2 * Status and system control registers for Xilinx Zynq Platform
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/>.
18 #include "qemu/timer.h"
22 #ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
23 #define DB_PRINT(...) do { \
24 fprintf(stderr, ": %s: ", __func__); \
25 fprintf(stderr, ## __VA_ARGS__); \
31 #define XILINX_LOCK_KEY 0x767b
32 #define XILINX_UNLOCK_KEY 0xdf0d
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];
159 static void zynq_slcr_reset(DeviceState *d)
163 FROM_SYSBUS(ZynqSLCRState, sysbus_from_qdev(d));
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;
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;
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;
201 s->misc[BANDGAP_TRIP] = 0x0000001F;
202 s->misc[PLL_PREDIVISOR] = 0x00000001;
203 s->misc[CLK_621_TRUE] = 0x00000001;
206 s->reset[FPGA] = 0x01F33F0F;
207 s->reset[RST_REASON] = 0x00000040;
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,
251 ZynqSLCRState *s = (ZynqSLCRState *)opaque;
257 case 0x8: /* UNLOCK */
258 DB_PRINT("Reading SCLR_LOCK/UNLOCK is not enabled\n");
260 case 0x0C: /* LOCKSTA */
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];
277 return s->wdt_clk_sel;
278 case 0x400 ... 0x408:
279 return s->tz_ocm[(offset - 0x400) / 4];
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];
291 return s->pss_idcode;
292 case 0x600 ... 0x620:
293 if (offset == 0x604) {
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];
304 return s->lvl_shftr_en;
307 case 0xA00 ... 0xA1C:
308 return s->cpu_ram[(offset - 0xA00) / 4];
309 case 0xA30 ... 0xA48:
310 return s->iou[(offset - 0xA30) / 4];
313 case 0xA60 ... 0xA8C:
314 return s->afi[0][(offset - 0xA60) / 4];
315 case 0xA90 ... 0xA98:
316 return s->ocm[(offset - 0xA90) / 4];
321 case 0xB00 ... 0xB2C:
322 return s->gpiob[(offset - 0xB00) / 4];
323 case 0xB40 ... 0xB74:
324 return s->ddriob[(offset - 0xB40) / 4];
327 DB_PRINT("Bad register offset 0x%x\n", (int)offset);
332 static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
335 uint32_t ret = zynq_slcr_read_imp(opaque, offset);
337 DB_PRINT("addr: %08x data: %08x\n", offset, ret);
341 static void zynq_slcr_write(void *opaque, hwaddr offset,
342 uint64_t val, unsigned size)
344 ZynqSLCRState *s = (ZynqSLCRState *)opaque;
346 DB_PRINT("offset: %08x data: %08x\n", offset, (unsigned)val);
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);
358 DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
359 (int)offset, (unsigned)val & 0xFFFF);
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);
368 DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
369 (int)offset, (unsigned)val & 0xFFFF);
372 case 0xc: /* LOCKSTA */
373 DB_PRINT("Writing SCLR_LOCKSTA is not enabled\n");
379 case 0x100 ... 0x11C:
380 if (offset == 0x10C) {
383 s->pll[(offset - 0x100) / 4] = val;
385 case 0x120 ... 0x16C:
386 s->clk[(offset - 0x120) / 4] = val;
388 case 0x170 ... 0x1AC:
389 s->fpga[0][(offset - 0x170) / 4] = val;
391 case 0x1B0 ... 0x1D8:
392 s->misc[(offset - 0x1B0) / 4] = val;
394 case 0x200 ... 0x25C:
395 if (offset == 0x250) {
398 s->reset[(offset - 0x200) / 4] = val;
404 s->wdt_clk_sel = val;
406 case 0x400 ... 0x408:
407 s->tz_ocm[(offset - 0x400) / 4] = val;
412 case 0x440 ... 0x448:
413 s->tz_dma[(offset - 0x440) / 4] = val;
415 case 0x450 ... 0x458:
416 s->tz_misc[(offset - 0x450) / 4] = val;
418 case 0x484 ... 0x488:
419 s->tz_fpga[(offset - 0x484) / 4] = val;
427 case 0x600 ... 0x620:
428 if (offset == 0x604) {
431 s->ddr[(offset - 0x600) / 4] = val;
433 case 0x700 ... 0x7D4:
434 s->mio[(offset - 0x700) / 4] = val;
436 case 0x800 ... 0x810:
437 s->mio_func[(offset - 0x800) / 4] = val;
439 case 0x830 ... 0x834:
440 s->sd[(offset - 0x830) / 4] = val;
443 s->lvl_shftr_en = val;
447 case 0xA00 ... 0xA1C:
448 s->cpu_ram[(offset - 0xA00) / 4] = val;
450 case 0xA30 ... 0xA48:
451 s->iou[(offset - 0xA30) / 4] = val;
456 case 0xA60 ... 0xA8C:
457 s->afi[0][(offset - 0xA60) / 4] = val;
468 case 0xB00 ... 0xB2C:
469 if (offset == 0xB20 || offset == 0xB2C) {
472 s->gpiob[(offset - 0xB00) / 4] = val;
474 case 0xB40 ... 0xB74:
475 s->ddriob[(offset - 0xB40) / 4] = val;
479 DB_PRINT("Bad register write %x <= %08x\n", (int)offset, val);
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);
502 static const VMStateDescription vmstate_zynq_slcr = {
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)