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 "qemu/osdep.h"
19 #include "qemu/timer.h"
20 #include "hw/sysbus.h"
21 #include "sysemu/sysemu.h"
24 #ifndef ZYNQ_SLCR_ERR_DEBUG
25 #define ZYNQ_SLCR_ERR_DEBUG 0
28 #define DB_PRINT(...) do { \
29 if (ZYNQ_SLCR_ERR_DEBUG) { \
30 fprintf(stderr, ": %s: ", __func__); \
31 fprintf(stderr, ## __VA_ARGS__); \
35 #define XILINX_LOCK_KEY 0x767b
36 #define XILINX_UNLOCK_KEY 0xdf0d
38 #define R_PSS_RST_CTRL_SOFT_RST 0x1
46 ARM_PLL_CTRL
= 0x100 / 4,
54 ARM_CLK_CTRL
= 0x120 / 4,
75 #define FPGA_CTRL_REGS(n, start) \
76 FPGA ## n ## _CLK_CTRL = (start) / 4, \
77 FPGA ## n ## _THR_CTRL, \
78 FPGA ## n ## _THR_CNT, \
79 FPGA ## n ## _THR_STA,
80 FPGA_CTRL_REGS(0, 0x170)
81 FPGA_CTRL_REGS(1, 0x180)
82 FPGA_CTRL_REGS(2, 0x190)
83 FPGA_CTRL_REGS(3, 0x1a0)
85 BANDGAP_TRIP
= 0x1b8 / 4,
86 PLL_PREDIVISOR
= 0x1c0 / 4,
89 PSS_RST_CTRL
= 0x200 / 4,
104 FPGA_RST_CTRL
= 0x240 / 4,
107 RS_AWDT_CTRL
= 0x24c / 4,
110 REBOOT_STATUS
= 0x258 / 4,
113 APU_CTRL
= 0x300 / 4,
116 TZ_DMA_NS
= 0x440 / 4,
120 PSS_IDCODE
= 0x530 / 4,
122 DDR_URGENT
= 0x600 / 4,
123 DDR_CAL_START
= 0x60c / 4,
124 DDR_REF_START
= 0x614 / 4,
130 #define MIO_LENGTH 54
132 MIO_LOOPBACK
= 0x804 / 4,
136 SD0_WP_CD_SEL
= 0x830 / 4,
139 LVL_SHFTR_EN
= 0x900 / 4,
146 DMAC_RAM
= 0xa50 / 4,
156 DEVCI_RAM
= 0xaa0 / 4,
160 GPIOB_CTRL
= 0xb00 / 4,
164 GPIOB_CFG_HSTL
= 0xb14 / 4,
165 GPIOB_DRVR_BIAS_CTRL
,
168 #define DDRIOB_LENGTH 14
171 #define ZYNQ_SLCR_MMIO_SIZE 0x1000
172 #define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4)
174 #define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
175 #define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
177 typedef struct ZynqSLCRState
{
178 SysBusDevice parent_obj
;
182 uint32_t regs
[ZYNQ_SLCR_NUM_REGS
];
185 static void zynq_slcr_reset(DeviceState
*d
)
187 ZynqSLCRState
*s
= ZYNQ_SLCR(d
);
192 s
->regs
[LOCKSTA
] = 1;
194 s
->regs
[ARM_PLL_CTRL
] = 0x0001A008;
195 s
->regs
[DDR_PLL_CTRL
] = 0x0001A008;
196 s
->regs
[IO_PLL_CTRL
] = 0x0001A008;
197 s
->regs
[PLL_STATUS
] = 0x0000003F;
198 s
->regs
[ARM_PLL_CFG
] = 0x00014000;
199 s
->regs
[DDR_PLL_CFG
] = 0x00014000;
200 s
->regs
[IO_PLL_CFG
] = 0x00014000;
203 s
->regs
[ARM_CLK_CTRL
] = 0x1F000400;
204 s
->regs
[DDR_CLK_CTRL
] = 0x18400003;
205 s
->regs
[DCI_CLK_CTRL
] = 0x01E03201;
206 s
->regs
[APER_CLK_CTRL
] = 0x01FFCCCD;
207 s
->regs
[USB0_CLK_CTRL
] = s
->regs
[USB1_CLK_CTRL
] = 0x00101941;
208 s
->regs
[GEM0_RCLK_CTRL
] = s
->regs
[GEM1_RCLK_CTRL
] = 0x00000001;
209 s
->regs
[GEM0_CLK_CTRL
] = s
->regs
[GEM1_CLK_CTRL
] = 0x00003C01;
210 s
->regs
[SMC_CLK_CTRL
] = 0x00003C01;
211 s
->regs
[LQSPI_CLK_CTRL
] = 0x00002821;
212 s
->regs
[SDIO_CLK_CTRL
] = 0x00001E03;
213 s
->regs
[UART_CLK_CTRL
] = 0x00003F03;
214 s
->regs
[SPI_CLK_CTRL
] = 0x00003F03;
215 s
->regs
[CAN_CLK_CTRL
] = 0x00501903;
216 s
->regs
[DBG_CLK_CTRL
] = 0x00000F03;
217 s
->regs
[PCAP_CLK_CTRL
] = 0x00000F01;
220 s
->regs
[FPGA0_CLK_CTRL
] = s
->regs
[FPGA1_CLK_CTRL
] = s
->regs
[FPGA2_CLK_CTRL
]
221 = s
->regs
[FPGA3_CLK_CTRL
] = 0x00101800;
222 s
->regs
[FPGA0_THR_STA
] = s
->regs
[FPGA1_THR_STA
] = s
->regs
[FPGA2_THR_STA
]
223 = s
->regs
[FPGA3_THR_STA
] = 0x00010000;
226 s
->regs
[BANDGAP_TRIP
] = 0x0000001F;
227 s
->regs
[PLL_PREDIVISOR
] = 0x00000001;
228 s
->regs
[CLK_621_TRUE
] = 0x00000001;
231 s
->regs
[FPGA_RST_CTRL
] = 0x01F33F0F;
232 s
->regs
[RST_REASON
] = 0x00000040;
234 s
->regs
[BOOT_MODE
] = 0x00000001;
237 for (i
= 0; i
< 54; i
++) {
238 s
->regs
[MIO
+ i
] = 0x00001601;
240 for (i
= 2; i
<= 8; i
++) {
241 s
->regs
[MIO
+ i
] = 0x00000601;
244 s
->regs
[MIO_MST_TRI0
] = s
->regs
[MIO_MST_TRI1
] = 0xFFFFFFFF;
246 s
->regs
[CPU_RAM
+ 0] = s
->regs
[CPU_RAM
+ 1] = s
->regs
[CPU_RAM
+ 3]
247 = s
->regs
[CPU_RAM
+ 4] = s
->regs
[CPU_RAM
+ 7]
249 s
->regs
[CPU_RAM
+ 2] = s
->regs
[CPU_RAM
+ 5] = 0x01010101;
250 s
->regs
[CPU_RAM
+ 6] = 0x00000001;
252 s
->regs
[IOU
+ 0] = s
->regs
[IOU
+ 1] = s
->regs
[IOU
+ 2] = s
->regs
[IOU
+ 3]
254 s
->regs
[IOU
+ 4] = s
->regs
[IOU
+ 5] = 0x00090909;
255 s
->regs
[IOU
+ 6] = 0x00000909;
257 s
->regs
[DMAC_RAM
] = 0x00000009;
259 s
->regs
[AFI0
+ 0] = s
->regs
[AFI0
+ 1] = 0x09090909;
260 s
->regs
[AFI1
+ 0] = s
->regs
[AFI1
+ 1] = 0x09090909;
261 s
->regs
[AFI2
+ 0] = s
->regs
[AFI2
+ 1] = 0x09090909;
262 s
->regs
[AFI3
+ 0] = s
->regs
[AFI3
+ 1] = 0x09090909;
263 s
->regs
[AFI0
+ 2] = s
->regs
[AFI1
+ 2] = s
->regs
[AFI2
+ 2]
264 = s
->regs
[AFI3
+ 2] = 0x00000909;
266 s
->regs
[OCM
+ 0] = 0x01010101;
267 s
->regs
[OCM
+ 1] = s
->regs
[OCM
+ 2] = 0x09090909;
269 s
->regs
[DEVCI_RAM
] = 0x00000909;
270 s
->regs
[CSG_RAM
] = 0x00000001;
272 s
->regs
[DDRIOB
+ 0] = s
->regs
[DDRIOB
+ 1] = s
->regs
[DDRIOB
+ 2]
273 = s
->regs
[DDRIOB
+ 3] = 0x00000e00;
274 s
->regs
[DDRIOB
+ 4] = s
->regs
[DDRIOB
+ 5] = s
->regs
[DDRIOB
+ 6]
276 s
->regs
[DDRIOB
+ 12] = 0x00000021;
280 static bool zynq_slcr_check_offset(hwaddr offset
, bool rnw
)
287 return !rnw
; /* Write only */
298 return rnw
;/* read only */
300 case ARM_PLL_CTRL
... IO_PLL_CTRL
:
301 case ARM_PLL_CFG
... IO_PLL_CFG
:
302 case ARM_CLK_CTRL
... TOPSW_CLK_CTRL
:
303 case FPGA0_CLK_CTRL
... FPGA0_THR_CNT
:
304 case FPGA1_CLK_CTRL
... FPGA1_THR_CNT
:
305 case FPGA2_CLK_CTRL
... FPGA2_THR_CNT
:
306 case FPGA3_CLK_CTRL
... FPGA3_THR_CNT
:
310 case PSS_RST_CTRL
... A9_CPU_RST_CTRL
:
316 case TZ_DMA_NS
... TZ_DMA_PERIPH_NS
:
319 case MIO
... MIO
+ MIO_LENGTH
- 1:
320 case MIO_LOOPBACK
... MIO_MST_TRI1
:
328 case AFI0
... AFI3
+ AFI_LENGTH
- 1:
332 case GPIOB_CTRL
... GPIOB_CFG_CMOS33
:
334 case GPIOB_DRVR_BIAS_CTRL
:
335 case DDRIOB
... DDRIOB
+ DDRIOB_LENGTH
- 1:
342 static uint64_t zynq_slcr_read(void *opaque
, hwaddr offset
,
345 ZynqSLCRState
*s
= opaque
;
347 uint32_t ret
= s
->regs
[offset
];
349 if (!zynq_slcr_check_offset(offset
, true)) {
350 qemu_log_mask(LOG_GUEST_ERROR
, "zynq_slcr: Invalid read access to "
351 " addr %" HWADDR_PRIx
"\n", offset
* 4);
354 DB_PRINT("addr: %08" HWADDR_PRIx
" data: %08" PRIx32
"\n", offset
* 4, ret
);
358 static void zynq_slcr_write(void *opaque
, hwaddr offset
,
359 uint64_t val
, unsigned size
)
361 ZynqSLCRState
*s
= (ZynqSLCRState
*)opaque
;
364 DB_PRINT("addr: %08" HWADDR_PRIx
" data: %08" PRIx64
"\n", offset
* 4, val
);
366 if (!zynq_slcr_check_offset(offset
, false)) {
367 qemu_log_mask(LOG_GUEST_ERROR
, "zynq_slcr: Invalid write access to "
368 "addr %" HWADDR_PRIx
"\n", offset
* 4);
374 s
->regs
[SCL
] = val
& 0x1;
377 if ((val
& 0xFFFF) == XILINX_LOCK_KEY
) {
378 DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset
,
379 (unsigned)val
& 0xFFFF);
380 s
->regs
[LOCKSTA
] = 1;
382 DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
383 (int)offset
, (unsigned)val
& 0xFFFF);
387 if ((val
& 0xFFFF) == XILINX_UNLOCK_KEY
) {
388 DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset
,
389 (unsigned)val
& 0xFFFF);
390 s
->regs
[LOCKSTA
] = 0;
392 DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
393 (int)offset
, (unsigned)val
& 0xFFFF);
398 if (s
->regs
[LOCKSTA
]) {
399 qemu_log_mask(LOG_GUEST_ERROR
,
400 "SCLR registers are locked. Unlock them first\n");
403 s
->regs
[offset
] = val
;
407 if (val
& R_PSS_RST_CTRL_SOFT_RST
) {
408 qemu_system_reset_request();
414 static const MemoryRegionOps slcr_ops
= {
415 .read
= zynq_slcr_read
,
416 .write
= zynq_slcr_write
,
417 .endianness
= DEVICE_NATIVE_ENDIAN
,
420 static void zynq_slcr_init(Object
*obj
)
422 ZynqSLCRState
*s
= ZYNQ_SLCR(obj
);
424 memory_region_init_io(&s
->iomem
, obj
, &slcr_ops
, s
, "slcr",
425 ZYNQ_SLCR_MMIO_SIZE
);
426 sysbus_init_mmio(SYS_BUS_DEVICE(obj
), &s
->iomem
);
429 static const VMStateDescription vmstate_zynq_slcr
= {
432 .minimum_version_id
= 2,
433 .fields
= (VMStateField
[]) {
434 VMSTATE_UINT32_ARRAY(regs
, ZynqSLCRState
, ZYNQ_SLCR_NUM_REGS
),
435 VMSTATE_END_OF_LIST()
439 static void zynq_slcr_class_init(ObjectClass
*klass
, void *data
)
441 DeviceClass
*dc
= DEVICE_CLASS(klass
);
443 dc
->vmsd
= &vmstate_zynq_slcr
;
444 dc
->reset
= zynq_slcr_reset
;
447 static const TypeInfo zynq_slcr_info
= {
448 .class_init
= zynq_slcr_class_init
,
449 .name
= TYPE_ZYNQ_SLCR
,
450 .parent
= TYPE_SYS_BUS_DEVICE
,
451 .instance_size
= sizeof(ZynqSLCRState
),
452 .instance_init
= zynq_slcr_init
,
455 static void zynq_slcr_register_types(void)
457 type_register_static(&zynq_slcr_info
);
460 type_init(zynq_slcr_register_types
)