1 | /* |
2 | * Status and system control registers for Xilinx Zynq Platform |
3 | * |
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 |
7 | * |
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. |
12 | * |
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/>. |
15 | */ |
16 | |
17 | #include "qemu/osdep.h" |
18 | #include "qemu/timer.h" |
19 | #include "sysemu/runstate.h" |
20 | #include "hw/sysbus.h" |
21 | #include "migration/vmstate.h" |
22 | #include "qemu/log.h" |
23 | #include "qemu/module.h" |
24 | #include "hw/registerfields.h" |
25 | |
26 | #ifndef ZYNQ_SLCR_ERR_DEBUG |
27 | #define ZYNQ_SLCR_ERR_DEBUG 0 |
28 | #endif |
29 | |
30 | #define DB_PRINT(...) do { \ |
31 | if (ZYNQ_SLCR_ERR_DEBUG) { \ |
32 | fprintf(stderr, ": %s: ", __func__); \ |
33 | fprintf(stderr, ## __VA_ARGS__); \ |
34 | } \ |
35 | } while (0) |
36 | |
37 | #define XILINX_LOCK_KEY 0x767b |
38 | #define XILINX_UNLOCK_KEY 0xdf0d |
39 | |
40 | REG32(SCL, 0x000) |
41 | REG32(LOCK, 0x004) |
42 | REG32(UNLOCK, 0x008) |
43 | REG32(LOCKSTA, 0x00c) |
44 | |
45 | REG32(ARM_PLL_CTRL, 0x100) |
46 | REG32(DDR_PLL_CTRL, 0x104) |
47 | REG32(IO_PLL_CTRL, 0x108) |
48 | REG32(PLL_STATUS, 0x10c) |
49 | REG32(ARM_PLL_CFG, 0x110) |
50 | REG32(DDR_PLL_CFG, 0x114) |
51 | REG32(IO_PLL_CFG, 0x118) |
52 | |
53 | REG32(ARM_CLK_CTRL, 0x120) |
54 | REG32(DDR_CLK_CTRL, 0x124) |
55 | REG32(DCI_CLK_CTRL, 0x128) |
56 | REG32(APER_CLK_CTRL, 0x12c) |
57 | REG32(USB0_CLK_CTRL, 0x130) |
58 | REG32(USB1_CLK_CTRL, 0x134) |
59 | REG32(GEM0_RCLK_CTRL, 0x138) |
60 | REG32(GEM1_RCLK_CTRL, 0x13c) |
61 | REG32(GEM0_CLK_CTRL, 0x140) |
62 | REG32(GEM1_CLK_CTRL, 0x144) |
63 | REG32(SMC_CLK_CTRL, 0x148) |
64 | REG32(LQSPI_CLK_CTRL, 0x14c) |
65 | REG32(SDIO_CLK_CTRL, 0x150) |
66 | REG32(UART_CLK_CTRL, 0x154) |
67 | REG32(SPI_CLK_CTRL, 0x158) |
68 | REG32(CAN_CLK_CTRL, 0x15c) |
69 | REG32(CAN_MIOCLK_CTRL, 0x160) |
70 | REG32(DBG_CLK_CTRL, 0x164) |
71 | REG32(PCAP_CLK_CTRL, 0x168) |
72 | REG32(TOPSW_CLK_CTRL, 0x16c) |
73 | |
74 | #define FPGA_CTRL_REGS(n, start) \ |
75 | REG32(FPGA ## n ## _CLK_CTRL, (start)) \ |
76 | REG32(FPGA ## n ## _THR_CTRL, (start) + 0x4)\ |
77 | REG32(FPGA ## n ## _THR_CNT, (start) + 0x8)\ |
78 | REG32(FPGA ## n ## _THR_STA, (start) + 0xc) |
79 | FPGA_CTRL_REGS(0, 0x170) |
80 | FPGA_CTRL_REGS(1, 0x180) |
81 | FPGA_CTRL_REGS(2, 0x190) |
82 | FPGA_CTRL_REGS(3, 0x1a0) |
83 | |
84 | REG32(BANDGAP_TRIP, 0x1b8) |
85 | REG32(PLL_PREDIVISOR, 0x1c0) |
86 | REG32(CLK_621_TRUE, 0x1c4) |
87 | |
88 | REG32(PSS_RST_CTRL, 0x200) |
89 | FIELD(PSS_RST_CTRL, SOFT_RST, 0, 1) |
90 | REG32(DDR_RST_CTRL, 0x204) |
91 | REG32(TOPSW_RESET_CTRL, 0x208) |
92 | REG32(DMAC_RST_CTRL, 0x20c) |
93 | REG32(USB_RST_CTRL, 0x210) |
94 | REG32(GEM_RST_CTRL, 0x214) |
95 | REG32(SDIO_RST_CTRL, 0x218) |
96 | REG32(SPI_RST_CTRL, 0x21c) |
97 | REG32(CAN_RST_CTRL, 0x220) |
98 | REG32(I2C_RST_CTRL, 0x224) |
99 | REG32(UART_RST_CTRL, 0x228) |
100 | REG32(GPIO_RST_CTRL, 0x22c) |
101 | REG32(LQSPI_RST_CTRL, 0x230) |
102 | REG32(SMC_RST_CTRL, 0x234) |
103 | REG32(OCM_RST_CTRL, 0x238) |
104 | REG32(FPGA_RST_CTRL, 0x240) |
105 | REG32(A9_CPU_RST_CTRL, 0x244) |
106 | |
107 | REG32(RS_AWDT_CTRL, 0x24c) |
108 | REG32(RST_REASON, 0x250) |
109 | |
110 | REG32(REBOOT_STATUS, 0x258) |
111 | REG32(BOOT_MODE, 0x25c) |
112 | |
113 | REG32(APU_CTRL, 0x300) |
114 | REG32(WDT_CLK_SEL, 0x304) |
115 | |
116 | REG32(TZ_DMA_NS, 0x440) |
117 | REG32(TZ_DMA_IRQ_NS, 0x444) |
118 | REG32(TZ_DMA_PERIPH_NS, 0x448) |
119 | |
120 | REG32(PSS_IDCODE, 0x530) |
121 | |
122 | REG32(DDR_URGENT, 0x600) |
123 | REG32(DDR_CAL_START, 0x60c) |
124 | REG32(DDR_REF_START, 0x614) |
125 | REG32(DDR_CMD_STA, 0x618) |
126 | REG32(DDR_URGENT_SEL, 0x61c) |
127 | REG32(DDR_DFI_STATUS, 0x620) |
128 | |
129 | REG32(MIO, 0x700) |
130 | #define MIO_LENGTH 54 |
131 | |
132 | REG32(MIO_LOOPBACK, 0x804) |
133 | REG32(MIO_MST_TRI0, 0x808) |
134 | REG32(MIO_MST_TRI1, 0x80c) |
135 | |
136 | REG32(SD0_WP_CD_SEL, 0x830) |
137 | REG32(SD1_WP_CD_SEL, 0x834) |
138 | |
139 | REG32(LVL_SHFTR_EN, 0x900) |
140 | REG32(OCM_CFG, 0x910) |
141 | |
142 | REG32(CPU_RAM, 0xa00) |
143 | |
144 | REG32(IOU, 0xa30) |
145 | |
146 | REG32(DMAC_RAM, 0xa50) |
147 | |
148 | REG32(AFI0, 0xa60) |
149 | REG32(AFI1, 0xa6c) |
150 | REG32(AFI2, 0xa78) |
151 | REG32(AFI3, 0xa84) |
152 | #define AFI_LENGTH 3 |
153 | |
154 | REG32(OCM, 0xa90) |
155 | |
156 | REG32(DEVCI_RAM, 0xaa0) |
157 | |
158 | REG32(CSG_RAM, 0xab0) |
159 | |
160 | REG32(GPIOB_CTRL, 0xb00) |
161 | REG32(GPIOB_CFG_CMOS18, 0xb04) |
162 | REG32(GPIOB_CFG_CMOS25, 0xb08) |
163 | REG32(GPIOB_CFG_CMOS33, 0xb0c) |
164 | REG32(GPIOB_CFG_HSTL, 0xb14) |
165 | REG32(GPIOB_DRVR_BIAS_CTRL, 0xb18) |
166 | |
167 | REG32(DDRIOB, 0xb40) |
168 | #define DDRIOB_LENGTH 14 |
169 | |
170 | #define ZYNQ_SLCR_MMIO_SIZE 0x1000 |
171 | #define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4) |
172 | |
173 | #define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr" |
174 | #define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR) |
175 | |
176 | typedef struct ZynqSLCRState { |
177 | SysBusDevice parent_obj; |
178 | |
179 | MemoryRegion iomem; |
180 | |
181 | uint32_t regs[ZYNQ_SLCR_NUM_REGS]; |
182 | } ZynqSLCRState; |
183 | |
184 | static void zynq_slcr_reset(DeviceState *d) |
185 | { |
186 | ZynqSLCRState *s = ZYNQ_SLCR(d); |
187 | int i; |
188 | |
189 | DB_PRINT("RESET\n" ); |
190 | |
191 | s->regs[R_LOCKSTA] = 1; |
192 | /* 0x100 - 0x11C */ |
193 | s->regs[R_ARM_PLL_CTRL] = 0x0001A008; |
194 | s->regs[R_DDR_PLL_CTRL] = 0x0001A008; |
195 | s->regs[R_IO_PLL_CTRL] = 0x0001A008; |
196 | s->regs[R_PLL_STATUS] = 0x0000003F; |
197 | s->regs[R_ARM_PLL_CFG] = 0x00014000; |
198 | s->regs[R_DDR_PLL_CFG] = 0x00014000; |
199 | s->regs[R_IO_PLL_CFG] = 0x00014000; |
200 | |
201 | /* 0x120 - 0x16C */ |
202 | s->regs[R_ARM_CLK_CTRL] = 0x1F000400; |
203 | s->regs[R_DDR_CLK_CTRL] = 0x18400003; |
204 | s->regs[R_DCI_CLK_CTRL] = 0x01E03201; |
205 | s->regs[R_APER_CLK_CTRL] = 0x01FFCCCD; |
206 | s->regs[R_USB0_CLK_CTRL] = s->regs[R_USB1_CLK_CTRL] = 0x00101941; |
207 | s->regs[R_GEM0_RCLK_CTRL] = s->regs[R_GEM1_RCLK_CTRL] = 0x00000001; |
208 | s->regs[R_GEM0_CLK_CTRL] = s->regs[R_GEM1_CLK_CTRL] = 0x00003C01; |
209 | s->regs[R_SMC_CLK_CTRL] = 0x00003C01; |
210 | s->regs[R_LQSPI_CLK_CTRL] = 0x00002821; |
211 | s->regs[R_SDIO_CLK_CTRL] = 0x00001E03; |
212 | s->regs[R_UART_CLK_CTRL] = 0x00003F03; |
213 | s->regs[R_SPI_CLK_CTRL] = 0x00003F03; |
214 | s->regs[R_CAN_CLK_CTRL] = 0x00501903; |
215 | s->regs[R_DBG_CLK_CTRL] = 0x00000F03; |
216 | s->regs[R_PCAP_CLK_CTRL] = 0x00000F01; |
217 | |
218 | /* 0x170 - 0x1AC */ |
219 | s->regs[R_FPGA0_CLK_CTRL] = s->regs[R_FPGA1_CLK_CTRL] |
220 | = s->regs[R_FPGA2_CLK_CTRL] |
221 | = s->regs[R_FPGA3_CLK_CTRL] = 0x00101800; |
222 | s->regs[R_FPGA0_THR_STA] = s->regs[R_FPGA1_THR_STA] |
223 | = s->regs[R_FPGA2_THR_STA] |
224 | = s->regs[R_FPGA3_THR_STA] = 0x00010000; |
225 | |
226 | /* 0x1B0 - 0x1D8 */ |
227 | s->regs[R_BANDGAP_TRIP] = 0x0000001F; |
228 | s->regs[R_PLL_PREDIVISOR] = 0x00000001; |
229 | s->regs[R_CLK_621_TRUE] = 0x00000001; |
230 | |
231 | /* 0x200 - 0x25C */ |
232 | s->regs[R_FPGA_RST_CTRL] = 0x01F33F0F; |
233 | s->regs[R_RST_REASON] = 0x00000040; |
234 | |
235 | s->regs[R_BOOT_MODE] = 0x00000001; |
236 | |
237 | /* 0x700 - 0x7D4 */ |
238 | for (i = 0; i < 54; i++) { |
239 | s->regs[R_MIO + i] = 0x00001601; |
240 | } |
241 | for (i = 2; i <= 8; i++) { |
242 | s->regs[R_MIO + i] = 0x00000601; |
243 | } |
244 | |
245 | s->regs[R_MIO_MST_TRI0] = s->regs[R_MIO_MST_TRI1] = 0xFFFFFFFF; |
246 | |
247 | s->regs[R_CPU_RAM + 0] = s->regs[R_CPU_RAM + 1] = s->regs[R_CPU_RAM + 3] |
248 | = s->regs[R_CPU_RAM + 4] = s->regs[R_CPU_RAM + 7] |
249 | = 0x00010101; |
250 | s->regs[R_CPU_RAM + 2] = s->regs[R_CPU_RAM + 5] = 0x01010101; |
251 | s->regs[R_CPU_RAM + 6] = 0x00000001; |
252 | |
253 | s->regs[R_IOU + 0] = s->regs[R_IOU + 1] = s->regs[R_IOU + 2] |
254 | = s->regs[R_IOU + 3] = 0x09090909; |
255 | s->regs[R_IOU + 4] = s->regs[R_IOU + 5] = 0x00090909; |
256 | s->regs[R_IOU + 6] = 0x00000909; |
257 | |
258 | s->regs[R_DMAC_RAM] = 0x00000009; |
259 | |
260 | s->regs[R_AFI0 + 0] = s->regs[R_AFI0 + 1] = 0x09090909; |
261 | s->regs[R_AFI1 + 0] = s->regs[R_AFI1 + 1] = 0x09090909; |
262 | s->regs[R_AFI2 + 0] = s->regs[R_AFI2 + 1] = 0x09090909; |
263 | s->regs[R_AFI3 + 0] = s->regs[R_AFI3 + 1] = 0x09090909; |
264 | s->regs[R_AFI0 + 2] = s->regs[R_AFI1 + 2] = s->regs[R_AFI2 + 2] |
265 | = s->regs[R_AFI3 + 2] = 0x00000909; |
266 | |
267 | s->regs[R_OCM + 0] = 0x01010101; |
268 | s->regs[R_OCM + 1] = s->regs[R_OCM + 2] = 0x09090909; |
269 | |
270 | s->regs[R_DEVCI_RAM] = 0x00000909; |
271 | s->regs[R_CSG_RAM] = 0x00000001; |
272 | |
273 | s->regs[R_DDRIOB + 0] = s->regs[R_DDRIOB + 1] = s->regs[R_DDRIOB + 2] |
274 | = s->regs[R_DDRIOB + 3] = 0x00000e00; |
275 | s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6] |
276 | = 0x00000e00; |
277 | s->regs[R_DDRIOB + 12] = 0x00000021; |
278 | } |
279 | |
280 | |
281 | static bool zynq_slcr_check_offset(hwaddr offset, bool rnw) |
282 | { |
283 | switch (offset) { |
284 | case R_LOCK: |
285 | case R_UNLOCK: |
286 | case R_DDR_CAL_START: |
287 | case R_DDR_REF_START: |
288 | return !rnw; /* Write only */ |
289 | case R_LOCKSTA: |
290 | case R_FPGA0_THR_STA: |
291 | case R_FPGA1_THR_STA: |
292 | case R_FPGA2_THR_STA: |
293 | case R_FPGA3_THR_STA: |
294 | case R_BOOT_MODE: |
295 | case R_PSS_IDCODE: |
296 | case R_DDR_CMD_STA: |
297 | case R_DDR_DFI_STATUS: |
298 | case R_PLL_STATUS: |
299 | return rnw;/* read only */ |
300 | case R_SCL: |
301 | case R_ARM_PLL_CTRL ... R_IO_PLL_CTRL: |
302 | case R_ARM_PLL_CFG ... R_IO_PLL_CFG: |
303 | case R_ARM_CLK_CTRL ... R_TOPSW_CLK_CTRL: |
304 | case R_FPGA0_CLK_CTRL ... R_FPGA0_THR_CNT: |
305 | case R_FPGA1_CLK_CTRL ... R_FPGA1_THR_CNT: |
306 | case R_FPGA2_CLK_CTRL ... R_FPGA2_THR_CNT: |
307 | case R_FPGA3_CLK_CTRL ... R_FPGA3_THR_CNT: |
308 | case R_BANDGAP_TRIP: |
309 | case R_PLL_PREDIVISOR: |
310 | case R_CLK_621_TRUE: |
311 | case R_PSS_RST_CTRL ... R_A9_CPU_RST_CTRL: |
312 | case R_RS_AWDT_CTRL: |
313 | case R_RST_REASON: |
314 | case R_REBOOT_STATUS: |
315 | case R_APU_CTRL: |
316 | case R_WDT_CLK_SEL: |
317 | case R_TZ_DMA_NS ... R_TZ_DMA_PERIPH_NS: |
318 | case R_DDR_URGENT: |
319 | case R_DDR_URGENT_SEL: |
320 | case R_MIO ... R_MIO + MIO_LENGTH - 1: |
321 | case R_MIO_LOOPBACK ... R_MIO_MST_TRI1: |
322 | case R_SD0_WP_CD_SEL: |
323 | case R_SD1_WP_CD_SEL: |
324 | case R_LVL_SHFTR_EN: |
325 | case R_OCM_CFG: |
326 | case R_CPU_RAM: |
327 | case R_IOU: |
328 | case R_DMAC_RAM: |
329 | case R_AFI0 ... R_AFI3 + AFI_LENGTH - 1: |
330 | case R_OCM: |
331 | case R_DEVCI_RAM: |
332 | case R_CSG_RAM: |
333 | case R_GPIOB_CTRL ... R_GPIOB_CFG_CMOS33: |
334 | case R_GPIOB_CFG_HSTL: |
335 | case R_GPIOB_DRVR_BIAS_CTRL: |
336 | case R_DDRIOB ... R_DDRIOB + DDRIOB_LENGTH - 1: |
337 | return true; |
338 | default: |
339 | return false; |
340 | } |
341 | } |
342 | |
343 | static uint64_t zynq_slcr_read(void *opaque, hwaddr offset, |
344 | unsigned size) |
345 | { |
346 | ZynqSLCRState *s = opaque; |
347 | offset /= 4; |
348 | uint32_t ret = s->regs[offset]; |
349 | |
350 | if (!zynq_slcr_check_offset(offset, true)) { |
351 | qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to " |
352 | " addr %" HWADDR_PRIx "\n" , offset * 4); |
353 | } |
354 | |
355 | DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n" , offset * 4, ret); |
356 | return ret; |
357 | } |
358 | |
359 | static void zynq_slcr_write(void *opaque, hwaddr offset, |
360 | uint64_t val, unsigned size) |
361 | { |
362 | ZynqSLCRState *s = (ZynqSLCRState *)opaque; |
363 | offset /= 4; |
364 | |
365 | DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n" , offset * 4, val); |
366 | |
367 | if (!zynq_slcr_check_offset(offset, false)) { |
368 | qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to " |
369 | "addr %" HWADDR_PRIx "\n" , offset * 4); |
370 | return; |
371 | } |
372 | |
373 | switch (offset) { |
374 | case R_SCL: |
375 | s->regs[R_SCL] = val & 0x1; |
376 | return; |
377 | case R_LOCK: |
378 | if ((val & 0xFFFF) == XILINX_LOCK_KEY) { |
379 | DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n" , (int)offset, |
380 | (unsigned)val & 0xFFFF); |
381 | s->regs[R_LOCKSTA] = 1; |
382 | } else { |
383 | DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n" , |
384 | (int)offset, (unsigned)val & 0xFFFF); |
385 | } |
386 | return; |
387 | case R_UNLOCK: |
388 | if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) { |
389 | DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n" , (int)offset, |
390 | (unsigned)val & 0xFFFF); |
391 | s->regs[R_LOCKSTA] = 0; |
392 | } else { |
393 | DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n" , |
394 | (int)offset, (unsigned)val & 0xFFFF); |
395 | } |
396 | return; |
397 | } |
398 | |
399 | if (s->regs[R_LOCKSTA]) { |
400 | qemu_log_mask(LOG_GUEST_ERROR, |
401 | "SCLR registers are locked. Unlock them first\n" ); |
402 | return; |
403 | } |
404 | s->regs[offset] = val; |
405 | |
406 | switch (offset) { |
407 | case R_PSS_RST_CTRL: |
408 | if (FIELD_EX32(val, PSS_RST_CTRL, SOFT_RST)) { |
409 | qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); |
410 | } |
411 | break; |
412 | } |
413 | } |
414 | |
415 | static const MemoryRegionOps slcr_ops = { |
416 | .read = zynq_slcr_read, |
417 | .write = zynq_slcr_write, |
418 | .endianness = DEVICE_NATIVE_ENDIAN, |
419 | }; |
420 | |
421 | static void zynq_slcr_init(Object *obj) |
422 | { |
423 | ZynqSLCRState *s = ZYNQ_SLCR(obj); |
424 | |
425 | memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr" , |
426 | ZYNQ_SLCR_MMIO_SIZE); |
427 | sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); |
428 | } |
429 | |
430 | static const VMStateDescription vmstate_zynq_slcr = { |
431 | .name = "zynq_slcr" , |
432 | .version_id = 2, |
433 | .minimum_version_id = 2, |
434 | .fields = (VMStateField[]) { |
435 | VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS), |
436 | VMSTATE_END_OF_LIST() |
437 | } |
438 | }; |
439 | |
440 | static void zynq_slcr_class_init(ObjectClass *klass, void *data) |
441 | { |
442 | DeviceClass *dc = DEVICE_CLASS(klass); |
443 | |
444 | dc->vmsd = &vmstate_zynq_slcr; |
445 | dc->reset = zynq_slcr_reset; |
446 | } |
447 | |
448 | static const TypeInfo zynq_slcr_info = { |
449 | .class_init = zynq_slcr_class_init, |
450 | .name = TYPE_ZYNQ_SLCR, |
451 | .parent = TYPE_SYS_BUS_DEVICE, |
452 | .instance_size = sizeof(ZynqSLCRState), |
453 | .instance_init = zynq_slcr_init, |
454 | }; |
455 | |
456 | static void zynq_slcr_register_types(void) |
457 | { |
458 | type_register_static(&zynq_slcr_info); |
459 | } |
460 | |
461 | type_init(zynq_slcr_register_types) |
462 | |