1 | /* |
2 | * ARM IoTKit system control element |
3 | * |
4 | * Copyright (c) 2018 Linaro Limited |
5 | * Written by Peter Maydell |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 or |
9 | * (at your option) any later version. |
10 | */ |
11 | |
12 | /* |
13 | * This is a model of the "system control element" which is part of the |
14 | * Arm IoTKit and documented in |
15 | * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html |
16 | * Specifically, it implements the "system control register" blocks. |
17 | */ |
18 | |
19 | #include "qemu/osdep.h" |
20 | #include "qemu/bitops.h" |
21 | #include "qemu/log.h" |
22 | #include "qemu/module.h" |
23 | #include "sysemu/runstate.h" |
24 | #include "trace.h" |
25 | #include "qapi/error.h" |
26 | #include "hw/sysbus.h" |
27 | #include "migration/vmstate.h" |
28 | #include "hw/registerfields.h" |
29 | #include "hw/misc/iotkit-sysctl.h" |
30 | #include "hw/qdev-properties.h" |
31 | #include "target/arm/arm-powerctl.h" |
32 | #include "target/arm/cpu.h" |
33 | |
34 | REG32(SECDBGSTAT, 0x0) |
35 | REG32(SECDBGSET, 0x4) |
36 | REG32(SECDBGCLR, 0x8) |
37 | REG32(SCSECCTRL, 0xc) |
38 | REG32(FCLK_DIV, 0x10) |
39 | REG32(SYSCLK_DIV, 0x14) |
40 | REG32(CLOCK_FORCE, 0x18) |
41 | REG32(RESET_SYNDROME, 0x100) |
42 | REG32(RESET_MASK, 0x104) |
43 | REG32(SWRESET, 0x108) |
44 | FIELD(SWRESET, SWRESETREQ, 9, 1) |
45 | REG32(GRETREG, 0x10c) |
46 | REG32(INITSVTOR0, 0x110) |
47 | REG32(INITSVTOR1, 0x114) |
48 | REG32(CPUWAIT, 0x118) |
49 | REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */ |
50 | REG32(WICCTRL, 0x120) |
51 | REG32(EWCTRL, 0x124) |
52 | REG32(PDCM_PD_SYS_SENSE, 0x200) |
53 | REG32(PDCM_PD_SRAM0_SENSE, 0x20c) |
54 | REG32(PDCM_PD_SRAM1_SENSE, 0x210) |
55 | REG32(PDCM_PD_SRAM2_SENSE, 0x214) |
56 | REG32(PDCM_PD_SRAM3_SENSE, 0x218) |
57 | REG32(PID4, 0xfd0) |
58 | REG32(PID5, 0xfd4) |
59 | REG32(PID6, 0xfd8) |
60 | REG32(PID7, 0xfdc) |
61 | REG32(PID0, 0xfe0) |
62 | REG32(PID1, 0xfe4) |
63 | REG32(PID2, 0xfe8) |
64 | REG32(PID3, 0xfec) |
65 | REG32(CID0, 0xff0) |
66 | REG32(CID1, 0xff4) |
67 | REG32(CID2, 0xff8) |
68 | REG32(CID3, 0xffc) |
69 | |
70 | /* PID/CID values */ |
71 | static const int sysctl_id[] = { |
72 | 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ |
73 | 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ |
74 | 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ |
75 | }; |
76 | |
77 | /* |
78 | * Set the initial secure vector table offset address for the core. |
79 | * This will take effect when the CPU next resets. |
80 | */ |
81 | static void set_init_vtor(uint64_t cpuid, uint32_t vtor) |
82 | { |
83 | Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid)); |
84 | |
85 | if (cpuobj) { |
86 | if (object_property_find(cpuobj, "init-svtor" , NULL)) { |
87 | object_property_set_uint(cpuobj, vtor, "init-svtor" , &error_abort); |
88 | } |
89 | } |
90 | } |
91 | |
92 | static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, |
93 | unsigned size) |
94 | { |
95 | IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); |
96 | uint64_t r; |
97 | |
98 | switch (offset) { |
99 | case A_SECDBGSTAT: |
100 | r = s->secure_debug; |
101 | break; |
102 | case A_SCSECCTRL: |
103 | if (!s->is_sse200) { |
104 | goto bad_offset; |
105 | } |
106 | r = s->scsecctrl; |
107 | break; |
108 | case A_FCLK_DIV: |
109 | if (!s->is_sse200) { |
110 | goto bad_offset; |
111 | } |
112 | r = s->fclk_div; |
113 | break; |
114 | case A_SYSCLK_DIV: |
115 | if (!s->is_sse200) { |
116 | goto bad_offset; |
117 | } |
118 | r = s->sysclk_div; |
119 | break; |
120 | case A_CLOCK_FORCE: |
121 | if (!s->is_sse200) { |
122 | goto bad_offset; |
123 | } |
124 | r = s->clock_force; |
125 | break; |
126 | case A_RESET_SYNDROME: |
127 | r = s->reset_syndrome; |
128 | break; |
129 | case A_RESET_MASK: |
130 | r = s->reset_mask; |
131 | break; |
132 | case A_GRETREG: |
133 | r = s->gretreg; |
134 | break; |
135 | case A_INITSVTOR0: |
136 | r = s->initsvtor0; |
137 | break; |
138 | case A_INITSVTOR1: |
139 | if (!s->is_sse200) { |
140 | goto bad_offset; |
141 | } |
142 | r = s->initsvtor1; |
143 | break; |
144 | case A_CPUWAIT: |
145 | r = s->cpuwait; |
146 | break; |
147 | case A_NMI_ENABLE: |
148 | /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */ |
149 | if (!s->is_sse200) { |
150 | r = 0; |
151 | break; |
152 | } |
153 | r = s->nmi_enable; |
154 | break; |
155 | case A_WICCTRL: |
156 | r = s->wicctrl; |
157 | break; |
158 | case A_EWCTRL: |
159 | if (!s->is_sse200) { |
160 | goto bad_offset; |
161 | } |
162 | r = s->ewctrl; |
163 | break; |
164 | case A_PDCM_PD_SYS_SENSE: |
165 | if (!s->is_sse200) { |
166 | goto bad_offset; |
167 | } |
168 | r = s->pdcm_pd_sys_sense; |
169 | break; |
170 | case A_PDCM_PD_SRAM0_SENSE: |
171 | if (!s->is_sse200) { |
172 | goto bad_offset; |
173 | } |
174 | r = s->pdcm_pd_sram0_sense; |
175 | break; |
176 | case A_PDCM_PD_SRAM1_SENSE: |
177 | if (!s->is_sse200) { |
178 | goto bad_offset; |
179 | } |
180 | r = s->pdcm_pd_sram1_sense; |
181 | break; |
182 | case A_PDCM_PD_SRAM2_SENSE: |
183 | if (!s->is_sse200) { |
184 | goto bad_offset; |
185 | } |
186 | r = s->pdcm_pd_sram2_sense; |
187 | break; |
188 | case A_PDCM_PD_SRAM3_SENSE: |
189 | if (!s->is_sse200) { |
190 | goto bad_offset; |
191 | } |
192 | r = s->pdcm_pd_sram3_sense; |
193 | break; |
194 | case A_PID4 ... A_CID3: |
195 | r = sysctl_id[(offset - A_PID4) / 4]; |
196 | break; |
197 | case A_SECDBGSET: |
198 | case A_SECDBGCLR: |
199 | case A_SWRESET: |
200 | qemu_log_mask(LOG_GUEST_ERROR, |
201 | "IoTKit SysCtl read: read of WO offset %x\n" , |
202 | (int)offset); |
203 | r = 0; |
204 | break; |
205 | default: |
206 | bad_offset: |
207 | qemu_log_mask(LOG_GUEST_ERROR, |
208 | "IoTKit SysCtl read: bad offset %x\n" , (int)offset); |
209 | r = 0; |
210 | break; |
211 | } |
212 | trace_iotkit_sysctl_read(offset, r, size); |
213 | return r; |
214 | } |
215 | |
216 | static void iotkit_sysctl_write(void *opaque, hwaddr offset, |
217 | uint64_t value, unsigned size) |
218 | { |
219 | IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); |
220 | |
221 | trace_iotkit_sysctl_write(offset, value, size); |
222 | |
223 | /* |
224 | * Most of the state here has to do with control of reset and |
225 | * similar kinds of power up -- for instance the guest can ask |
226 | * what the reason for the last reset was, or forbid reset for |
227 | * some causes (like the non-secure watchdog). Most of this is |
228 | * not relevant to QEMU, which doesn't really model anything other |
229 | * than a full power-on reset. |
230 | * We just model the registers as reads-as-written. |
231 | */ |
232 | |
233 | switch (offset) { |
234 | case A_RESET_SYNDROME: |
235 | qemu_log_mask(LOG_UNIMP, |
236 | "IoTKit SysCtl RESET_SYNDROME unimplemented\n" ); |
237 | s->reset_syndrome = value; |
238 | break; |
239 | case A_RESET_MASK: |
240 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n" ); |
241 | s->reset_mask = value; |
242 | break; |
243 | case A_GRETREG: |
244 | /* |
245 | * General retention register, which is only reset by a power-on |
246 | * reset. Technically this implementation is complete, since |
247 | * QEMU only supports power-on resets... |
248 | */ |
249 | s->gretreg = value; |
250 | break; |
251 | case A_INITSVTOR0: |
252 | s->initsvtor0 = value; |
253 | set_init_vtor(0, s->initsvtor0); |
254 | break; |
255 | case A_CPUWAIT: |
256 | if ((s->cpuwait & 1) && !(value & 1)) { |
257 | /* Powering up CPU 0 */ |
258 | arm_set_cpu_on_and_reset(0); |
259 | } |
260 | if ((s->cpuwait & 2) && !(value & 2)) { |
261 | /* Powering up CPU 1 */ |
262 | arm_set_cpu_on_and_reset(1); |
263 | } |
264 | s->cpuwait = value; |
265 | break; |
266 | case A_WICCTRL: |
267 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n" ); |
268 | s->wicctrl = value; |
269 | break; |
270 | case A_SECDBGSET: |
271 | /* write-1-to-set */ |
272 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n" ); |
273 | s->secure_debug |= value; |
274 | break; |
275 | case A_SECDBGCLR: |
276 | /* write-1-to-clear */ |
277 | s->secure_debug &= ~value; |
278 | break; |
279 | case A_SWRESET: |
280 | /* One w/o bit to request a reset; all other bits reserved */ |
281 | if (value & R_SWRESET_SWRESETREQ_MASK) { |
282 | qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); |
283 | } |
284 | break; |
285 | case A_SCSECCTRL: |
286 | if (!s->is_sse200) { |
287 | goto bad_offset; |
288 | } |
289 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n" ); |
290 | s->scsecctrl = value; |
291 | break; |
292 | case A_FCLK_DIV: |
293 | if (!s->is_sse200) { |
294 | goto bad_offset; |
295 | } |
296 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n" ); |
297 | s->fclk_div = value; |
298 | break; |
299 | case A_SYSCLK_DIV: |
300 | if (!s->is_sse200) { |
301 | goto bad_offset; |
302 | } |
303 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n" ); |
304 | s->sysclk_div = value; |
305 | break; |
306 | case A_CLOCK_FORCE: |
307 | if (!s->is_sse200) { |
308 | goto bad_offset; |
309 | } |
310 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n" ); |
311 | s->clock_force = value; |
312 | break; |
313 | case A_INITSVTOR1: |
314 | if (!s->is_sse200) { |
315 | goto bad_offset; |
316 | } |
317 | s->initsvtor1 = value; |
318 | set_init_vtor(1, s->initsvtor1); |
319 | break; |
320 | case A_EWCTRL: |
321 | if (!s->is_sse200) { |
322 | goto bad_offset; |
323 | } |
324 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n" ); |
325 | s->ewctrl = value; |
326 | break; |
327 | case A_PDCM_PD_SYS_SENSE: |
328 | if (!s->is_sse200) { |
329 | goto bad_offset; |
330 | } |
331 | qemu_log_mask(LOG_UNIMP, |
332 | "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n" ); |
333 | s->pdcm_pd_sys_sense = value; |
334 | break; |
335 | case A_PDCM_PD_SRAM0_SENSE: |
336 | if (!s->is_sse200) { |
337 | goto bad_offset; |
338 | } |
339 | qemu_log_mask(LOG_UNIMP, |
340 | "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n" ); |
341 | s->pdcm_pd_sram0_sense = value; |
342 | break; |
343 | case A_PDCM_PD_SRAM1_SENSE: |
344 | if (!s->is_sse200) { |
345 | goto bad_offset; |
346 | } |
347 | qemu_log_mask(LOG_UNIMP, |
348 | "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n" ); |
349 | s->pdcm_pd_sram1_sense = value; |
350 | break; |
351 | case A_PDCM_PD_SRAM2_SENSE: |
352 | if (!s->is_sse200) { |
353 | goto bad_offset; |
354 | } |
355 | qemu_log_mask(LOG_UNIMP, |
356 | "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n" ); |
357 | s->pdcm_pd_sram2_sense = value; |
358 | break; |
359 | case A_PDCM_PD_SRAM3_SENSE: |
360 | if (!s->is_sse200) { |
361 | goto bad_offset; |
362 | } |
363 | qemu_log_mask(LOG_UNIMP, |
364 | "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n" ); |
365 | s->pdcm_pd_sram3_sense = value; |
366 | break; |
367 | case A_NMI_ENABLE: |
368 | /* In IoTKit this is BUSWAIT: reserved, R/O, zero */ |
369 | if (!s->is_sse200) { |
370 | goto ro_offset; |
371 | } |
372 | qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n" ); |
373 | s->nmi_enable = value; |
374 | break; |
375 | case A_SECDBGSTAT: |
376 | case A_PID4 ... A_CID3: |
377 | ro_offset: |
378 | qemu_log_mask(LOG_GUEST_ERROR, |
379 | "IoTKit SysCtl write: write of RO offset %x\n" , |
380 | (int)offset); |
381 | break; |
382 | default: |
383 | bad_offset: |
384 | qemu_log_mask(LOG_GUEST_ERROR, |
385 | "IoTKit SysCtl write: bad offset %x\n" , (int)offset); |
386 | break; |
387 | } |
388 | } |
389 | |
390 | static const MemoryRegionOps iotkit_sysctl_ops = { |
391 | .read = iotkit_sysctl_read, |
392 | .write = iotkit_sysctl_write, |
393 | .endianness = DEVICE_LITTLE_ENDIAN, |
394 | /* byte/halfword accesses are just zero-padded on reads and writes */ |
395 | .impl.min_access_size = 4, |
396 | .impl.max_access_size = 4, |
397 | .valid.min_access_size = 1, |
398 | .valid.max_access_size = 4, |
399 | }; |
400 | |
401 | static void iotkit_sysctl_reset(DeviceState *dev) |
402 | { |
403 | IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); |
404 | |
405 | trace_iotkit_sysctl_reset(); |
406 | s->secure_debug = 0; |
407 | s->reset_syndrome = 1; |
408 | s->reset_mask = 0; |
409 | s->gretreg = 0; |
410 | s->initsvtor0 = s->initsvtor0_rst; |
411 | s->initsvtor1 = s->initsvtor1_rst; |
412 | s->cpuwait = s->cpuwait_rst; |
413 | s->wicctrl = 0; |
414 | s->scsecctrl = 0; |
415 | s->fclk_div = 0; |
416 | s->sysclk_div = 0; |
417 | s->clock_force = 0; |
418 | s->nmi_enable = 0; |
419 | s->ewctrl = 0; |
420 | s->pdcm_pd_sys_sense = 0x7f; |
421 | s->pdcm_pd_sram0_sense = 0; |
422 | s->pdcm_pd_sram1_sense = 0; |
423 | s->pdcm_pd_sram2_sense = 0; |
424 | s->pdcm_pd_sram3_sense = 0; |
425 | } |
426 | |
427 | static void iotkit_sysctl_init(Object *obj) |
428 | { |
429 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
430 | IoTKitSysCtl *s = IOTKIT_SYSCTL(obj); |
431 | |
432 | memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops, |
433 | s, "iotkit-sysctl" , 0x1000); |
434 | sysbus_init_mmio(sbd, &s->iomem); |
435 | } |
436 | |
437 | static void iotkit_sysctl_realize(DeviceState *dev, Error **errp) |
438 | { |
439 | IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); |
440 | |
441 | /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */ |
442 | if (extract32(s->sys_version, 28, 4) == 2) { |
443 | s->is_sse200 = true; |
444 | } |
445 | } |
446 | |
447 | static bool sse200_needed(void *opaque) |
448 | { |
449 | IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); |
450 | |
451 | return s->is_sse200; |
452 | } |
453 | |
454 | static const VMStateDescription iotkit_sysctl_sse200_vmstate = { |
455 | .name = "iotkit-sysctl/sse-200" , |
456 | .version_id = 1, |
457 | .minimum_version_id = 1, |
458 | .needed = sse200_needed, |
459 | .fields = (VMStateField[]) { |
460 | VMSTATE_UINT32(scsecctrl, IoTKitSysCtl), |
461 | VMSTATE_UINT32(fclk_div, IoTKitSysCtl), |
462 | VMSTATE_UINT32(sysclk_div, IoTKitSysCtl), |
463 | VMSTATE_UINT32(clock_force, IoTKitSysCtl), |
464 | VMSTATE_UINT32(initsvtor1, IoTKitSysCtl), |
465 | VMSTATE_UINT32(nmi_enable, IoTKitSysCtl), |
466 | VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl), |
467 | VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl), |
468 | VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl), |
469 | VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl), |
470 | VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl), |
471 | VMSTATE_END_OF_LIST() |
472 | } |
473 | }; |
474 | |
475 | static const VMStateDescription iotkit_sysctl_vmstate = { |
476 | .name = "iotkit-sysctl" , |
477 | .version_id = 1, |
478 | .minimum_version_id = 1, |
479 | .fields = (VMStateField[]) { |
480 | VMSTATE_UINT32(secure_debug, IoTKitSysCtl), |
481 | VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl), |
482 | VMSTATE_UINT32(reset_mask, IoTKitSysCtl), |
483 | VMSTATE_UINT32(gretreg, IoTKitSysCtl), |
484 | VMSTATE_UINT32(initsvtor0, IoTKitSysCtl), |
485 | VMSTATE_UINT32(cpuwait, IoTKitSysCtl), |
486 | VMSTATE_UINT32(wicctrl, IoTKitSysCtl), |
487 | VMSTATE_END_OF_LIST() |
488 | }, |
489 | .subsections = (const VMStateDescription*[]) { |
490 | &iotkit_sysctl_sse200_vmstate, |
491 | NULL |
492 | } |
493 | }; |
494 | |
495 | static Property iotkit_sysctl_props[] = { |
496 | DEFINE_PROP_UINT32("SYS_VERSION" , IoTKitSysCtl, sys_version, 0), |
497 | DEFINE_PROP_UINT32("CPUWAIT_RST" , IoTKitSysCtl, cpuwait_rst, 0), |
498 | DEFINE_PROP_UINT32("INITSVTOR0_RST" , IoTKitSysCtl, initsvtor0_rst, |
499 | 0x10000000), |
500 | DEFINE_PROP_UINT32("INITSVTOR1_RST" , IoTKitSysCtl, initsvtor1_rst, |
501 | 0x10000000), |
502 | DEFINE_PROP_END_OF_LIST() |
503 | }; |
504 | |
505 | static void iotkit_sysctl_class_init(ObjectClass *klass, void *data) |
506 | { |
507 | DeviceClass *dc = DEVICE_CLASS(klass); |
508 | |
509 | dc->vmsd = &iotkit_sysctl_vmstate; |
510 | dc->reset = iotkit_sysctl_reset; |
511 | dc->props = iotkit_sysctl_props; |
512 | dc->realize = iotkit_sysctl_realize; |
513 | } |
514 | |
515 | static const TypeInfo iotkit_sysctl_info = { |
516 | .name = TYPE_IOTKIT_SYSCTL, |
517 | .parent = TYPE_SYS_BUS_DEVICE, |
518 | .instance_size = sizeof(IoTKitSysCtl), |
519 | .instance_init = iotkit_sysctl_init, |
520 | .class_init = iotkit_sysctl_class_init, |
521 | }; |
522 | |
523 | static void iotkit_sysctl_register_types(void) |
524 | { |
525 | type_register_static(&iotkit_sysctl_info); |
526 | } |
527 | |
528 | type_init(iotkit_sysctl_register_types); |
529 | |