target-i386: Add API to get note's size
[qemu/ar7.git] / hw / zynq_slcr.c
blob4f97575770a0991c4adfcb99ad700cdb93abb4ee
1 /*
2 * Status and system control registers for Xilinx Zynq Platform
4 * Copyright (c) 2011 Michal Simek <monstr@monstr.eu>
5 * Copyright (c) 2012 PetaLogix Pty Ltd.
6 * Based on hw/arm_sysctl.c, written by Paul Brook
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, see <http://www.gnu.org/licenses/>.
17 #include "hw.h"
18 #include "qemu-timer.h"
19 #include "sysbus.h"
20 #include "sysemu.h"
22 #ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
23 #define DB_PRINT(...) do { \
24 fprintf(stderr, ": %s: ", __func__); \
25 fprintf(stderr, ## __VA_ARGS__); \
26 } while (0);
27 #else
28 #define DB_PRINT(...)
29 #endif
31 #define XILINX_LOCK_KEY 0x767b
32 #define XILINX_UNLOCK_KEY 0xdf0d
34 typedef enum {
35 ARM_PLL_CTRL,
36 DDR_PLL_CTRL,
37 IO_PLL_CTRL,
38 PLL_STATUS,
39 ARM_PPL_CFG,
40 DDR_PLL_CFG,
41 IO_PLL_CFG,
42 PLL_BG_CTRL,
43 PLL_MAX
44 } PLLValues;
46 typedef enum {
47 ARM_CLK_CTRL,
48 DDR_CLK_CTRL,
49 DCI_CLK_CTRL,
50 APER_CLK_CTRL,
51 USB0_CLK_CTRL,
52 USB1_CLK_CTRL,
53 GEM0_RCLK_CTRL,
54 GEM1_RCLK_CTRL,
55 GEM0_CLK_CTRL,
56 GEM1_CLK_CTRL,
57 SMC_CLK_CTRL,
58 LQSPI_CLK_CTRL,
59 SDIO_CLK_CTRL,
60 UART_CLK_CTRL,
61 SPI_CLK_CTRL,
62 CAN_CLK_CTRL,
63 CAN_MIOCLK_CTRL,
64 DBG_CLK_CTRL,
65 PCAP_CLK_CTRL,
66 TOPSW_CLK_CTRL,
67 CLK_MAX
68 } ClkValues;
70 typedef enum {
71 CLK_CTRL,
72 THR_CTRL,
73 THR_CNT,
74 THR_STA,
75 FPGA_MAX
76 } FPGAValues;
78 typedef enum {
79 SYNC_CTRL,
80 SYNC_STATUS,
81 BANDGAP_TRIP,
82 CC_TEST,
83 PLL_PREDIVISOR,
84 CLK_621_TRUE,
85 PICTURE_DBG,
86 PICTURE_DBG_UCNT,
87 PICTURE_DBG_LCNT,
88 MISC_MAX
89 } MiscValues;
91 typedef enum {
92 PSS,
93 DDDR,
94 DMAC,
95 USB,
96 GEM,
97 SDIO,
98 SPI,
99 CAN,
100 I2C,
101 UART,
102 GPIO,
103 LQSPI,
104 SMC,
105 OCM,
106 DEVCI,
107 FPGA,
108 A9_CPU,
109 RS_AWDT,
110 RST_REASON,
111 RST_REASON_CLR,
112 REBOOT_STATUS,
113 BOOT_MODE,
114 RESET_MAX
115 } ResetValues;
117 typedef struct {
118 SysBusDevice busdev;
119 MemoryRegion iomem;
121 union {
122 struct {
123 uint16_t scl;
124 uint16_t lockval;
125 uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
126 uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
127 uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
128 uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
129 uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
130 uint32_t apu_ctrl; /* 0x300 */
131 uint32_t wdt_clk_sel; /* 0x304 */
132 uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
133 uint32_t tz_ddr; /* 0x430 */
134 uint32_t tz_dma[3]; /* 0x440 - 0x448 */
135 uint32_t tz_misc[3]; /* 0x450 - 0x458 */
136 uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
137 uint32_t dbg_ctrl; /* 0x500 */
138 uint32_t pss_idcode; /* 0x530 */
139 uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
140 uint32_t mio[54]; /* 0x700 - 0x7D4 */
141 uint32_t mio_func[4]; /* 0x800 - 0x810 */
142 uint32_t sd[2]; /* 0x830 - 0x834 */
143 uint32_t lvl_shftr_en; /* 0x900 */
144 uint32_t ocm_cfg; /* 0x910 */
145 uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
146 uint32_t iou[7]; /* 0xA30 - 0xA48 */
147 uint32_t dmac_ram; /* 0xA50 */
148 uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
149 uint32_t ocm[3]; /* 0xA90 - 0xA98 */
150 uint32_t devci_ram; /* 0xAA0 */
151 uint32_t csg_ram; /* 0xAB0 */
152 uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
153 uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
155 uint8_t data[0x1000];
157 } ZynqSLCRState;
159 static void zynq_slcr_reset(DeviceState *d)
161 int i;
162 ZynqSLCRState *s =
163 FROM_SYSBUS(ZynqSLCRState, sysbus_from_qdev(d));
165 DB_PRINT("RESET\n");
167 s->lockval = 1;
168 /* 0x100 - 0x11C */
169 s->pll[ARM_PLL_CTRL] = 0x0001A008;
170 s->pll[DDR_PLL_CTRL] = 0x0001A008;
171 s->pll[IO_PLL_CTRL] = 0x0001A008;
172 s->pll[PLL_STATUS] = 0x0000003F;
173 s->pll[ARM_PPL_CFG] = 0x00014000;
174 s->pll[DDR_PLL_CFG] = 0x00014000;
175 s->pll[IO_PLL_CFG] = 0x00014000;
177 /* 0x120 - 0x16C */
178 s->clk[ARM_CLK_CTRL] = 0x1F000400;
179 s->clk[DDR_CLK_CTRL] = 0x18400003;
180 s->clk[DCI_CLK_CTRL] = 0x01E03201;
181 s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
182 s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
183 s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
184 s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
185 s->clk[SMC_CLK_CTRL] = 0x00003C01;
186 s->clk[LQSPI_CLK_CTRL] = 0x00002821;
187 s->clk[SDIO_CLK_CTRL] = 0x00001E03;
188 s->clk[UART_CLK_CTRL] = 0x00003F03;
189 s->clk[SPI_CLK_CTRL] = 0x00003F03;
190 s->clk[CAN_CLK_CTRL] = 0x00501903;
191 s->clk[DBG_CLK_CTRL] = 0x00000F03;
192 s->clk[PCAP_CLK_CTRL] = 0x00000F01;
194 /* 0x170 - 0x1AC */
195 s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
196 s->fpga[3][CLK_CTRL] = 0x00101800;
197 s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
198 s->fpga[3][THR_STA] = 0x00010000;
200 /* 0x1B0 - 0x1D8 */
201 s->misc[BANDGAP_TRIP] = 0x0000001F;
202 s->misc[PLL_PREDIVISOR] = 0x00000001;
203 s->misc[CLK_621_TRUE] = 0x00000001;
205 /* 0x200 - 0x25C */
206 s->reset[FPGA] = 0x01F33F0F;
207 s->reset[RST_REASON] = 0x00000040;
209 /* 0x700 - 0x7D4 */
210 for (i = 0; i < 54; i++) {
211 s->mio[i] = 0x00001601;
213 for (i = 2; i <= 8; i++) {
214 s->mio[i] = 0x00000601;
217 /* MIO_MST_TRI0, MIO_MST_TRI1 */
218 s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
220 s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
221 s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
222 s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
223 s->cpu_ram[6] = 0x00000001;
225 s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
226 s->iou[4] = s->iou[5] = 0x00090909;
227 s->iou[6] = 0x00000909;
229 s->dmac_ram = 0x00000009;
231 s->afi[0][0] = s->afi[0][1] = 0x09090909;
232 s->afi[1][0] = s->afi[1][1] = 0x09090909;
233 s->afi[2][0] = s->afi[2][1] = 0x09090909;
234 s->afi[3][0] = s->afi[3][1] = 0x09090909;
235 s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
237 s->ocm[0] = 0x01010101;
238 s->ocm[1] = s->ocm[2] = 0x09090909;
240 s->devci_ram = 0x00000909;
241 s->csg_ram = 0x00000001;
243 s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
244 s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
245 s->ddriob[12] = 0x00000021;
248 static inline uint32_t zynq_slcr_read_imp(void *opaque,
249 target_phys_addr_t offset)
251 ZynqSLCRState *s = (ZynqSLCRState *)opaque;
253 switch (offset) {
254 case 0x0: /* SCL */
255 return s->scl;
256 case 0x4: /* LOCK */
257 case 0x8: /* UNLOCK */
258 DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
259 return 0;
260 case 0x0C: /* LOCKSTA */
261 return s->lockval;
262 case 0x100 ... 0x11C:
263 return s->pll[(offset - 0x100) / 4];
264 case 0x120 ... 0x16C:
265 return s->clk[(offset - 0x120) / 4];
266 case 0x170 ... 0x1AC:
267 return s->fpga[0][(offset - 0x170) / 4];
268 case 0x1B0 ... 0x1D8:
269 return s->misc[(offset - 0x1B0) / 4];
270 case 0x200 ... 0x258:
271 return s->reset[(offset - 0x200) / 4];
272 case 0x25c:
273 return 1;
274 case 0x300:
275 return s->apu_ctrl;
276 case 0x304:
277 return s->wdt_clk_sel;
278 case 0x400 ... 0x408:
279 return s->tz_ocm[(offset - 0x400) / 4];
280 case 0x430:
281 return s->tz_ddr;
282 case 0x440 ... 0x448:
283 return s->tz_dma[(offset - 0x440) / 4];
284 case 0x450 ... 0x458:
285 return s->tz_misc[(offset - 0x450) / 4];
286 case 0x484 ... 0x488:
287 return s->tz_fpga[(offset - 0x484) / 4];
288 case 0x500:
289 return s->dbg_ctrl;
290 case 0x530:
291 return s->pss_idcode;
292 case 0x600 ... 0x620:
293 if (offset == 0x604) {
294 goto bad_reg;
296 return s->ddr[(offset - 0x600) / 4];
297 case 0x700 ... 0x7D4:
298 return s->mio[(offset - 0x700) / 4];
299 case 0x800 ... 0x810:
300 return s->mio_func[(offset - 0x800) / 4];
301 case 0x830 ... 0x834:
302 return s->sd[(offset - 0x830) / 4];
303 case 0x900:
304 return s->lvl_shftr_en;
305 case 0x910:
306 return s->ocm_cfg;
307 case 0xA00 ... 0xA1C:
308 return s->cpu_ram[(offset - 0xA00) / 4];
309 case 0xA30 ... 0xA48:
310 return s->iou[(offset - 0xA30) / 4];
311 case 0xA50:
312 return s->dmac_ram;
313 case 0xA60 ... 0xA8C:
314 return s->afi[0][(offset - 0xA60) / 4];
315 case 0xA90 ... 0xA98:
316 return s->ocm[(offset - 0xA90) / 4];
317 case 0xAA0:
318 return s->devci_ram;
319 case 0xAB0:
320 return s->csg_ram;
321 case 0xB00 ... 0xB2C:
322 return s->gpiob[(offset - 0xB00) / 4];
323 case 0xB40 ... 0xB74:
324 return s->ddriob[(offset - 0xB40) / 4];
325 default:
326 bad_reg:
327 DB_PRINT("Bad register offset 0x%x\n", (int)offset);
328 return 0;
332 static uint64_t zynq_slcr_read(void *opaque, target_phys_addr_t offset,
333 unsigned size)
335 uint32_t ret = zynq_slcr_read_imp(opaque, offset);
337 DB_PRINT("addr: %08x data: %08x\n", offset, ret);
338 return ret;
341 static void zynq_slcr_write(void *opaque, target_phys_addr_t offset,
342 uint64_t val, unsigned size)
344 ZynqSLCRState *s = (ZynqSLCRState *)opaque;
346 DB_PRINT("offset: %08x data: %08x\n", offset, (unsigned)val);
348 switch (offset) {
349 case 0x00: /* SCL */
350 s->scl = val & 0x1;
351 return;
352 case 0x4: /* SLCR_LOCK */
353 if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
354 DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
355 (unsigned)val & 0xFFFF);
356 s->lockval = 1;
357 } else {
358 DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
359 (int)offset, (unsigned)val & 0xFFFF);
361 return;
362 case 0x8: /* SLCR_UNLOCK */
363 if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
364 DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
365 (unsigned)val & 0xFFFF);
366 s->lockval = 0;
367 } else {
368 DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
369 (int)offset, (unsigned)val & 0xFFFF);
371 return;
372 case 0xc: /* LOCKSTA */
373 DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
374 return;
377 if (!s->lockval) {
378 switch (offset) {
379 case 0x100 ... 0x11C:
380 if (offset == 0x10C) {
381 goto bad_reg;
383 s->pll[(offset - 0x100) / 4] = val;
384 break;
385 case 0x120 ... 0x16C:
386 s->clk[(offset - 0x120) / 4] = val;
387 break;
388 case 0x170 ... 0x1AC:
389 s->fpga[0][(offset - 0x170) / 4] = val;
390 break;
391 case 0x1B0 ... 0x1D8:
392 s->misc[(offset - 0x1B0) / 4] = val;
393 break;
394 case 0x200 ... 0x25C:
395 if (offset == 0x250) {
396 goto bad_reg;
398 s->reset[(offset - 0x200) / 4] = val;
399 break;
400 case 0x300:
401 s->apu_ctrl = val;
402 break;
403 case 0x304:
404 s->wdt_clk_sel = val;
405 break;
406 case 0x400 ... 0x408:
407 s->tz_ocm[(offset - 0x400) / 4] = val;
408 break;
409 case 0x430:
410 s->tz_ddr = val;
411 break;
412 case 0x440 ... 0x448:
413 s->tz_dma[(offset - 0x440) / 4] = val;
414 break;
415 case 0x450 ... 0x458:
416 s->tz_misc[(offset - 0x450) / 4] = val;
417 break;
418 case 0x484 ... 0x488:
419 s->tz_fpga[(offset - 0x484) / 4] = val;
420 break;
421 case 0x500:
422 s->dbg_ctrl = val;
423 break;
424 case 0x530:
425 s->pss_idcode = val;
426 break;
427 case 0x600 ... 0x620:
428 if (offset == 0x604) {
429 goto bad_reg;
431 s->ddr[(offset - 0x600) / 4] = val;
432 break;
433 case 0x700 ... 0x7D4:
434 s->mio[(offset - 0x700) / 4] = val;
435 break;
436 case 0x800 ... 0x810:
437 s->mio_func[(offset - 0x800) / 4] = val;
438 break;
439 case 0x830 ... 0x834:
440 s->sd[(offset - 0x830) / 4] = val;
441 break;
442 case 0x900:
443 s->lvl_shftr_en = val;
444 break;
445 case 0x910:
446 break;
447 case 0xA00 ... 0xA1C:
448 s->cpu_ram[(offset - 0xA00) / 4] = val;
449 break;
450 case 0xA30 ... 0xA48:
451 s->iou[(offset - 0xA30) / 4] = val;
452 break;
453 case 0xA50:
454 s->dmac_ram = val;
455 break;
456 case 0xA60 ... 0xA8C:
457 s->afi[0][(offset - 0xA60) / 4] = val;
458 break;
459 case 0xA90:
460 s->ocm[0] = val;
461 break;
462 case 0xAA0:
463 s->devci_ram = val;
464 break;
465 case 0xAB0:
466 s->csg_ram = val;
467 break;
468 case 0xB00 ... 0xB2C:
469 if (offset == 0xB20 || offset == 0xB2C) {
470 goto bad_reg;
472 s->gpiob[(offset - 0xB00) / 4] = val;
473 break;
474 case 0xB40 ... 0xB74:
475 s->ddriob[(offset - 0xB40) / 4] = val;
476 break;
477 default:
478 bad_reg:
479 DB_PRINT("Bad register write %x <= %08x\n", (int)offset, val);
481 } else {
482 DB_PRINT("SCLR registers are locked. Unlock them first\n");
486 static const MemoryRegionOps slcr_ops = {
487 .read = zynq_slcr_read,
488 .write = zynq_slcr_write,
489 .endianness = DEVICE_NATIVE_ENDIAN,
492 static int zynq_slcr_init(SysBusDevice *dev)
494 ZynqSLCRState *s = FROM_SYSBUS(ZynqSLCRState, dev);
496 memory_region_init_io(&s->iomem, &slcr_ops, s, "slcr", 0x1000);
497 sysbus_init_mmio(dev, &s->iomem);
499 return 0;
502 static const VMStateDescription vmstate_zynq_slcr = {
503 .name = "zynq_slcr",
504 .version_id = 1,
505 .minimum_version_id = 1,
506 .minimum_version_id_old = 1,
507 .fields = (VMStateField[]) {
508 VMSTATE_UINT8_ARRAY(data, ZynqSLCRState, 0x1000),
509 VMSTATE_END_OF_LIST()
513 static void zynq_slcr_class_init(ObjectClass *klass, void *data)
515 DeviceClass *dc = DEVICE_CLASS(klass);
516 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
518 sdc->init = zynq_slcr_init;
519 dc->vmsd = &vmstate_zynq_slcr;
520 dc->reset = zynq_slcr_reset;
523 static TypeInfo zynq_slcr_info = {
524 .class_init = zynq_slcr_class_init,
525 .name = "xilinx,zynq_slcr",
526 .parent = TYPE_SYS_BUS_DEVICE,
527 .instance_size = sizeof(ZynqSLCRState),
530 static void zynq_slcr_register_types(void)
532 type_register_static(&zynq_slcr_info);
535 type_init(zynq_slcr_register_types)