xref: /qemu/hw/misc/iotkit-sysctl.c (revision 6069bbc904503dd4f4c2cfd7ff883300a6bddeeb)
175750e4dSPeter Maydell /*
275750e4dSPeter Maydell  * ARM IoTKit system control element
375750e4dSPeter Maydell  *
475750e4dSPeter Maydell  * Copyright (c) 2018 Linaro Limited
575750e4dSPeter Maydell  * Written by Peter Maydell
675750e4dSPeter Maydell  *
775750e4dSPeter Maydell  *  This program is free software; you can redistribute it and/or modify
875750e4dSPeter Maydell  *  it under the terms of the GNU General Public License version 2 or
975750e4dSPeter Maydell  *  (at your option) any later version.
1075750e4dSPeter Maydell  */
1175750e4dSPeter Maydell 
1275750e4dSPeter Maydell /*
1375750e4dSPeter Maydell  * This is a model of the "system control element" which is part of the
1475750e4dSPeter Maydell  * Arm IoTKit and documented in
1550b52b18SPeter Maydell  * https://developer.arm.com/documentation/ecm0601256/latest
1675750e4dSPeter Maydell  * Specifically, it implements the "system control register" blocks.
1775750e4dSPeter Maydell  */
1875750e4dSPeter Maydell 
1975750e4dSPeter Maydell #include "qemu/osdep.h"
2004836414SPeter Maydell #include "qemu/bitops.h"
2175750e4dSPeter Maydell #include "qemu/log.h"
220b8fa32fSMarkus Armbruster #include "qemu/module.h"
2354d31236SMarkus Armbruster #include "sysemu/runstate.h"
2475750e4dSPeter Maydell #include "trace.h"
2575750e4dSPeter Maydell #include "qapi/error.h"
2675750e4dSPeter Maydell #include "hw/sysbus.h"
27d6454270SMarkus Armbruster #include "migration/vmstate.h"
2875750e4dSPeter Maydell #include "hw/registerfields.h"
2975750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h"
30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
31419a7f80SPeter Maydell #include "hw/arm/armsse-version.h"
320f862986SPeter Maydell #include "target/arm/arm-powerctl.h"
330f862986SPeter Maydell #include "target/arm/cpu.h"
3475750e4dSPeter Maydell 
3575750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0)
3675750e4dSPeter Maydell REG32(SECDBGSET, 0x4)
3775750e4dSPeter Maydell REG32(SECDBGCLR, 0x8)
3804836414SPeter Maydell REG32(SCSECCTRL, 0xc)
3904836414SPeter Maydell REG32(FCLK_DIV, 0x10)
4004836414SPeter Maydell REG32(SYSCLK_DIV, 0x14)
4104836414SPeter Maydell REG32(CLOCK_FORCE, 0x18)
4275750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100)
4375750e4dSPeter Maydell REG32(RESET_MASK, 0x104)
4475750e4dSPeter Maydell REG32(SWRESET, 0x108)
4575750e4dSPeter Maydell     FIELD(SWRESET, SWRESETREQ, 9, 1)
4675750e4dSPeter Maydell REG32(GRETREG, 0x10c)
47394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110)
48246dbeb7SPeter Maydell     FIELD(INITSVTOR0, LOCK, 0, 1)
49246dbeb7SPeter Maydell     FIELD(INITSVTOR0, VTOR, 7, 25)
5004836414SPeter Maydell REG32(INITSVTOR1, 0x114)
5175750e4dSPeter Maydell REG32(CPUWAIT, 0x118)
5204836414SPeter Maydell REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
5375750e4dSPeter Maydell REG32(WICCTRL, 0x120)
5404836414SPeter Maydell REG32(EWCTRL, 0x124)
552672a6caSPeter Maydell REG32(PWRCTRL, 0x1fc)
562672a6caSPeter Maydell     FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
572672a6caSPeter Maydell     FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
5804836414SPeter Maydell REG32(PDCM_PD_SYS_SENSE, 0x200)
59c5ffe6c8SPeter Maydell REG32(PDCM_PD_CPU0_SENSE, 0x204)
6004836414SPeter Maydell REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
6104836414SPeter Maydell REG32(PDCM_PD_SRAM1_SENSE, 0x210)
62c5ffe6c8SPeter Maydell REG32(PDCM_PD_SRAM2_SENSE, 0x214) /* PDCM_PD_VMR0_SENSE on SSE300 */
63c5ffe6c8SPeter Maydell REG32(PDCM_PD_SRAM3_SENSE, 0x218) /* PDCM_PD_VMR1_SENSE on SSE300 */
6475750e4dSPeter Maydell REG32(PID4, 0xfd0)
6575750e4dSPeter Maydell REG32(PID5, 0xfd4)
6675750e4dSPeter Maydell REG32(PID6, 0xfd8)
6775750e4dSPeter Maydell REG32(PID7, 0xfdc)
6875750e4dSPeter Maydell REG32(PID0, 0xfe0)
6975750e4dSPeter Maydell REG32(PID1, 0xfe4)
7075750e4dSPeter Maydell REG32(PID2, 0xfe8)
7175750e4dSPeter Maydell REG32(PID3, 0xfec)
7275750e4dSPeter Maydell REG32(CID0, 0xff0)
7375750e4dSPeter Maydell REG32(CID1, 0xff4)
7475750e4dSPeter Maydell REG32(CID2, 0xff8)
7575750e4dSPeter Maydell REG32(CID3, 0xffc)
7675750e4dSPeter Maydell 
7775750e4dSPeter Maydell /* PID/CID values */
78*6069bbc9SPeter Maydell static const int iotkit_sysctl_id[] = {
7975750e4dSPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
8075750e4dSPeter Maydell     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
8175750e4dSPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
8275750e4dSPeter Maydell };
8375750e4dSPeter Maydell 
84*6069bbc9SPeter Maydell /* Also used by the SSE300 */
85*6069bbc9SPeter Maydell static const int sse200_sysctl_id[] = {
86*6069bbc9SPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
87*6069bbc9SPeter Maydell     0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
88*6069bbc9SPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
89*6069bbc9SPeter Maydell };
90*6069bbc9SPeter Maydell 
910f862986SPeter Maydell /*
920f862986SPeter Maydell  * Set the initial secure vector table offset address for the core.
930f862986SPeter Maydell  * This will take effect when the CPU next resets.
940f862986SPeter Maydell  */
950f862986SPeter Maydell static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
960f862986SPeter Maydell {
970f862986SPeter Maydell     Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
980f862986SPeter Maydell 
990f862986SPeter Maydell     if (cpuobj) {
100efba1595SDaniel P. Berrangé         if (object_property_find(cpuobj, "init-svtor")) {
1015325cc34SMarkus Armbruster             object_property_set_uint(cpuobj, "init-svtor", vtor, &error_abort);
1020f862986SPeter Maydell         }
1030f862986SPeter Maydell     }
1040f862986SPeter Maydell }
1050f862986SPeter Maydell 
10675750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
10775750e4dSPeter Maydell                                     unsigned size)
10875750e4dSPeter Maydell {
10975750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
11075750e4dSPeter Maydell     uint64_t r;
11175750e4dSPeter Maydell 
11275750e4dSPeter Maydell     switch (offset) {
11375750e4dSPeter Maydell     case A_SECDBGSTAT:
11475750e4dSPeter Maydell         r = s->secure_debug;
11575750e4dSPeter Maydell         break;
11604836414SPeter Maydell     case A_SCSECCTRL:
1171cbd6fe4SPeter Maydell         switch (s->sse_version) {
1181cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
11904836414SPeter Maydell             goto bad_offset;
1201cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
12131b0c6b1SPeter Maydell         case ARMSSE_SSE300:
12204836414SPeter Maydell             r = s->scsecctrl;
12304836414SPeter Maydell             break;
1241cbd6fe4SPeter Maydell         default:
1251cbd6fe4SPeter Maydell             g_assert_not_reached();
12604836414SPeter Maydell         }
1271cbd6fe4SPeter Maydell         break;
1281cbd6fe4SPeter Maydell     case A_FCLK_DIV:
1291cbd6fe4SPeter Maydell         switch (s->sse_version) {
1301cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
1311cbd6fe4SPeter Maydell             goto bad_offset;
1321cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
13331b0c6b1SPeter Maydell         case ARMSSE_SSE300:
13404836414SPeter Maydell             r = s->fclk_div;
13504836414SPeter Maydell             break;
1361cbd6fe4SPeter Maydell         default:
1371cbd6fe4SPeter Maydell             g_assert_not_reached();
13804836414SPeter Maydell         }
1391cbd6fe4SPeter Maydell         break;
1401cbd6fe4SPeter Maydell     case A_SYSCLK_DIV:
1411cbd6fe4SPeter Maydell         switch (s->sse_version) {
1421cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
1431cbd6fe4SPeter Maydell             goto bad_offset;
1441cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
14531b0c6b1SPeter Maydell         case ARMSSE_SSE300:
14604836414SPeter Maydell             r = s->sysclk_div;
14704836414SPeter Maydell             break;
1481cbd6fe4SPeter Maydell         default:
1491cbd6fe4SPeter Maydell             g_assert_not_reached();
15004836414SPeter Maydell         }
1511cbd6fe4SPeter Maydell         break;
1521cbd6fe4SPeter Maydell     case A_CLOCK_FORCE:
1531cbd6fe4SPeter Maydell         switch (s->sse_version) {
1541cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
1551cbd6fe4SPeter Maydell             goto bad_offset;
1561cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
15731b0c6b1SPeter Maydell         case ARMSSE_SSE300:
15804836414SPeter Maydell             r = s->clock_force;
15904836414SPeter Maydell             break;
1601cbd6fe4SPeter Maydell         default:
1611cbd6fe4SPeter Maydell             g_assert_not_reached();
1621cbd6fe4SPeter Maydell         }
1631cbd6fe4SPeter Maydell         break;
16475750e4dSPeter Maydell     case A_RESET_SYNDROME:
16575750e4dSPeter Maydell         r = s->reset_syndrome;
16675750e4dSPeter Maydell         break;
16775750e4dSPeter Maydell     case A_RESET_MASK:
16875750e4dSPeter Maydell         r = s->reset_mask;
16975750e4dSPeter Maydell         break;
17075750e4dSPeter Maydell     case A_GRETREG:
17175750e4dSPeter Maydell         r = s->gretreg;
17275750e4dSPeter Maydell         break;
173394e10d2SPeter Maydell     case A_INITSVTOR0:
174394e10d2SPeter Maydell         r = s->initsvtor0;
17575750e4dSPeter Maydell         break;
17604836414SPeter Maydell     case A_INITSVTOR1:
1771cbd6fe4SPeter Maydell         switch (s->sse_version) {
1781cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
17904836414SPeter Maydell             goto bad_offset;
1801cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
18104836414SPeter Maydell             r = s->initsvtor1;
18204836414SPeter Maydell             break;
183246dbeb7SPeter Maydell         case ARMSSE_SSE300:
184246dbeb7SPeter Maydell             goto bad_offset;
1851cbd6fe4SPeter Maydell         default:
1861cbd6fe4SPeter Maydell             g_assert_not_reached();
1871cbd6fe4SPeter Maydell         }
1881cbd6fe4SPeter Maydell         break;
18975750e4dSPeter Maydell     case A_CPUWAIT:
19092ecf2d5SPeter Maydell         switch (s->sse_version) {
19192ecf2d5SPeter Maydell         case ARMSSE_IOTKIT:
19292ecf2d5SPeter Maydell         case ARMSSE_SSE200:
19375750e4dSPeter Maydell             r = s->cpuwait;
19475750e4dSPeter Maydell             break;
19592ecf2d5SPeter Maydell         case ARMSSE_SSE300:
19692ecf2d5SPeter Maydell             /* In SSE300 this is reserved (for INITSVTOR2) */
19792ecf2d5SPeter Maydell             goto bad_offset;
19892ecf2d5SPeter Maydell         default:
19992ecf2d5SPeter Maydell             g_assert_not_reached();
20092ecf2d5SPeter Maydell         }
20192ecf2d5SPeter Maydell         break;
20204836414SPeter Maydell     case A_NMI_ENABLE:
2031cbd6fe4SPeter Maydell         switch (s->sse_version) {
2041cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
2051cbd6fe4SPeter Maydell             /* In IoTKit this is named BUSWAIT but marked reserved, R/O, zero */
20675750e4dSPeter Maydell             r = 0;
20775750e4dSPeter Maydell             break;
2081cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
20904836414SPeter Maydell             r = s->nmi_enable;
21004836414SPeter Maydell             break;
21192ecf2d5SPeter Maydell         case ARMSSE_SSE300:
21292ecf2d5SPeter Maydell             /* In SSE300 this is reserved (for INITSVTOR3) */
21392ecf2d5SPeter Maydell             goto bad_offset;
2141cbd6fe4SPeter Maydell         default:
2151cbd6fe4SPeter Maydell             g_assert_not_reached();
2161cbd6fe4SPeter Maydell         }
2171cbd6fe4SPeter Maydell         break;
21875750e4dSPeter Maydell     case A_WICCTRL:
21992ecf2d5SPeter Maydell         switch (s->sse_version) {
22092ecf2d5SPeter Maydell         case ARMSSE_IOTKIT:
22192ecf2d5SPeter Maydell         case ARMSSE_SSE200:
22275750e4dSPeter Maydell             r = s->wicctrl;
22375750e4dSPeter Maydell             break;
22492ecf2d5SPeter Maydell         case ARMSSE_SSE300:
22592ecf2d5SPeter Maydell             /* In SSE300 this offset is CPUWAIT */
22692ecf2d5SPeter Maydell             r = s->cpuwait;
22792ecf2d5SPeter Maydell             break;
22892ecf2d5SPeter Maydell         default:
22992ecf2d5SPeter Maydell             g_assert_not_reached();
23092ecf2d5SPeter Maydell         }
23192ecf2d5SPeter Maydell         break;
23204836414SPeter Maydell     case A_EWCTRL:
2331cbd6fe4SPeter Maydell         switch (s->sse_version) {
2341cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
23504836414SPeter Maydell             goto bad_offset;
2361cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
23704836414SPeter Maydell             r = s->ewctrl;
23804836414SPeter Maydell             break;
23992ecf2d5SPeter Maydell         case ARMSSE_SSE300:
24092ecf2d5SPeter Maydell             /* In SSE300 this offset is is NMI_ENABLE */
24192ecf2d5SPeter Maydell             r = s->nmi_enable;
24292ecf2d5SPeter Maydell             break;
2431cbd6fe4SPeter Maydell         default:
2441cbd6fe4SPeter Maydell             g_assert_not_reached();
24504836414SPeter Maydell         }
2461cbd6fe4SPeter Maydell         break;
2472672a6caSPeter Maydell     case A_PWRCTRL:
2482672a6caSPeter Maydell         switch (s->sse_version) {
2492672a6caSPeter Maydell         case ARMSSE_IOTKIT:
2502672a6caSPeter Maydell         case ARMSSE_SSE200:
2512672a6caSPeter Maydell             goto bad_offset;
2522672a6caSPeter Maydell         case ARMSSE_SSE300:
2532672a6caSPeter Maydell             r = s->pwrctrl;
2542672a6caSPeter Maydell             break;
2552672a6caSPeter Maydell         default:
2562672a6caSPeter Maydell             g_assert_not_reached();
2572672a6caSPeter Maydell         }
2582672a6caSPeter Maydell         break;
2591cbd6fe4SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
2601cbd6fe4SPeter Maydell         switch (s->sse_version) {
2611cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
2621cbd6fe4SPeter Maydell             goto bad_offset;
2631cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
26431b0c6b1SPeter Maydell         case ARMSSE_SSE300:
26504836414SPeter Maydell             r = s->pdcm_pd_sys_sense;
26604836414SPeter Maydell             break;
2671cbd6fe4SPeter Maydell         default:
2681cbd6fe4SPeter Maydell             g_assert_not_reached();
26904836414SPeter Maydell         }
2701cbd6fe4SPeter Maydell         break;
271c5ffe6c8SPeter Maydell     case A_PDCM_PD_CPU0_SENSE:
272c5ffe6c8SPeter Maydell         switch (s->sse_version) {
273c5ffe6c8SPeter Maydell         case ARMSSE_IOTKIT:
274c5ffe6c8SPeter Maydell         case ARMSSE_SSE200:
275c5ffe6c8SPeter Maydell             goto bad_offset;
276c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
277c5ffe6c8SPeter Maydell             r = s->pdcm_pd_cpu0_sense;
278c5ffe6c8SPeter Maydell             break;
279c5ffe6c8SPeter Maydell         default:
280c5ffe6c8SPeter Maydell             g_assert_not_reached();
281c5ffe6c8SPeter Maydell         }
282c5ffe6c8SPeter Maydell         break;
2831cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
2841cbd6fe4SPeter Maydell         switch (s->sse_version) {
2851cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
2861cbd6fe4SPeter Maydell             goto bad_offset;
2871cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
28804836414SPeter Maydell             r = s->pdcm_pd_sram0_sense;
28904836414SPeter Maydell             break;
290c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
291c5ffe6c8SPeter Maydell             goto bad_offset;
2921cbd6fe4SPeter Maydell         default:
2931cbd6fe4SPeter Maydell             g_assert_not_reached();
29404836414SPeter Maydell         }
2951cbd6fe4SPeter Maydell         break;
2961cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
2971cbd6fe4SPeter Maydell         switch (s->sse_version) {
2981cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
2991cbd6fe4SPeter Maydell             goto bad_offset;
3001cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
30104836414SPeter Maydell             r = s->pdcm_pd_sram1_sense;
30204836414SPeter Maydell             break;
303c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
304c5ffe6c8SPeter Maydell             goto bad_offset;
3051cbd6fe4SPeter Maydell         default:
3061cbd6fe4SPeter Maydell             g_assert_not_reached();
30704836414SPeter Maydell         }
3081cbd6fe4SPeter Maydell         break;
3091cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
3101cbd6fe4SPeter Maydell         switch (s->sse_version) {
3111cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
3121cbd6fe4SPeter Maydell             goto bad_offset;
3131cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
31404836414SPeter Maydell             r = s->pdcm_pd_sram2_sense;
31504836414SPeter Maydell             break;
316c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
317c5ffe6c8SPeter Maydell             r = s->pdcm_pd_vmr0_sense;
318c5ffe6c8SPeter Maydell             break;
3191cbd6fe4SPeter Maydell         default:
3201cbd6fe4SPeter Maydell             g_assert_not_reached();
32104836414SPeter Maydell         }
3221cbd6fe4SPeter Maydell         break;
3231cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
3241cbd6fe4SPeter Maydell         switch (s->sse_version) {
3251cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
3261cbd6fe4SPeter Maydell             goto bad_offset;
3271cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
32804836414SPeter Maydell             r = s->pdcm_pd_sram3_sense;
32904836414SPeter Maydell             break;
330c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
331c5ffe6c8SPeter Maydell             r = s->pdcm_pd_vmr1_sense;
332c5ffe6c8SPeter Maydell             break;
3331cbd6fe4SPeter Maydell         default:
3341cbd6fe4SPeter Maydell             g_assert_not_reached();
3351cbd6fe4SPeter Maydell         }
3361cbd6fe4SPeter Maydell         break;
33775750e4dSPeter Maydell     case A_PID4 ... A_CID3:
338*6069bbc9SPeter Maydell         switch (s->sse_version) {
339*6069bbc9SPeter Maydell         case ARMSSE_IOTKIT:
340*6069bbc9SPeter Maydell             r = iotkit_sysctl_id[(offset - A_PID4) / 4];
341*6069bbc9SPeter Maydell             break;
342*6069bbc9SPeter Maydell         case ARMSSE_SSE200:
343*6069bbc9SPeter Maydell         case ARMSSE_SSE300:
344*6069bbc9SPeter Maydell             r = sse200_sysctl_id[(offset - A_PID4) / 4];
345*6069bbc9SPeter Maydell             break;
346*6069bbc9SPeter Maydell         default:
347*6069bbc9SPeter Maydell             g_assert_not_reached();
348*6069bbc9SPeter Maydell         }
34975750e4dSPeter Maydell         break;
35075750e4dSPeter Maydell     case A_SECDBGSET:
35175750e4dSPeter Maydell     case A_SECDBGCLR:
35275750e4dSPeter Maydell     case A_SWRESET:
35375750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
35475750e4dSPeter Maydell                       "IoTKit SysCtl read: read of WO offset %x\n",
35575750e4dSPeter Maydell                       (int)offset);
35675750e4dSPeter Maydell         r = 0;
35775750e4dSPeter Maydell         break;
35875750e4dSPeter Maydell     default:
35904836414SPeter Maydell     bad_offset:
36075750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
36175750e4dSPeter Maydell                       "IoTKit SysCtl read: bad offset %x\n", (int)offset);
36275750e4dSPeter Maydell         r = 0;
36375750e4dSPeter Maydell         break;
36475750e4dSPeter Maydell     }
36575750e4dSPeter Maydell     trace_iotkit_sysctl_read(offset, r, size);
36675750e4dSPeter Maydell     return r;
36775750e4dSPeter Maydell }
36875750e4dSPeter Maydell 
36992ecf2d5SPeter Maydell static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
37092ecf2d5SPeter Maydell {
37192ecf2d5SPeter Maydell     int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
37292ecf2d5SPeter Maydell     int i;
37392ecf2d5SPeter Maydell 
37492ecf2d5SPeter Maydell     for (i = 0; i < num_cpus; i++) {
37592ecf2d5SPeter Maydell         uint32_t mask = 1 << i;
37692ecf2d5SPeter Maydell         if ((s->cpuwait & mask) && !(value & mask)) {
37792ecf2d5SPeter Maydell             /* Powering up CPU 0 */
37892ecf2d5SPeter Maydell             arm_set_cpu_on_and_reset(i);
37992ecf2d5SPeter Maydell         }
38092ecf2d5SPeter Maydell     }
38192ecf2d5SPeter Maydell     s->cpuwait = value;
38292ecf2d5SPeter Maydell }
38392ecf2d5SPeter Maydell 
38475750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset,
38575750e4dSPeter Maydell                                  uint64_t value, unsigned size)
38675750e4dSPeter Maydell {
38775750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
38875750e4dSPeter Maydell 
38975750e4dSPeter Maydell     trace_iotkit_sysctl_write(offset, value, size);
39075750e4dSPeter Maydell 
39175750e4dSPeter Maydell     /*
39275750e4dSPeter Maydell      * Most of the state here has to do with control of reset and
39375750e4dSPeter Maydell      * similar kinds of power up -- for instance the guest can ask
39475750e4dSPeter Maydell      * what the reason for the last reset was, or forbid reset for
39575750e4dSPeter Maydell      * some causes (like the non-secure watchdog). Most of this is
39675750e4dSPeter Maydell      * not relevant to QEMU, which doesn't really model anything other
39775750e4dSPeter Maydell      * than a full power-on reset.
39875750e4dSPeter Maydell      * We just model the registers as reads-as-written.
39975750e4dSPeter Maydell      */
40075750e4dSPeter Maydell 
40175750e4dSPeter Maydell     switch (offset) {
40275750e4dSPeter Maydell     case A_RESET_SYNDROME:
40375750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP,
40475750e4dSPeter Maydell                       "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
40575750e4dSPeter Maydell         s->reset_syndrome = value;
40675750e4dSPeter Maydell         break;
40775750e4dSPeter Maydell     case A_RESET_MASK:
40875750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
40975750e4dSPeter Maydell         s->reset_mask = value;
41075750e4dSPeter Maydell         break;
41175750e4dSPeter Maydell     case A_GRETREG:
41275750e4dSPeter Maydell         /*
41375750e4dSPeter Maydell          * General retention register, which is only reset by a power-on
41475750e4dSPeter Maydell          * reset. Technically this implementation is complete, since
41575750e4dSPeter Maydell          * QEMU only supports power-on resets...
41675750e4dSPeter Maydell          */
41775750e4dSPeter Maydell         s->gretreg = value;
41875750e4dSPeter Maydell         break;
419394e10d2SPeter Maydell     case A_INITSVTOR0:
420246dbeb7SPeter Maydell         switch (s->sse_version) {
421246dbeb7SPeter Maydell         case ARMSSE_SSE300:
422246dbeb7SPeter Maydell             /* SSE300 has a LOCK bit which prevents further writes when set */
423246dbeb7SPeter Maydell             if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
424246dbeb7SPeter Maydell                 qemu_log_mask(LOG_GUEST_ERROR,
425246dbeb7SPeter Maydell                               "IoTKit INITSVTOR0 write when register locked\n");
426246dbeb7SPeter Maydell                 break;
427246dbeb7SPeter Maydell             }
428246dbeb7SPeter Maydell             s->initsvtor0 = value;
429246dbeb7SPeter Maydell             set_init_vtor(0, s->initsvtor0 & R_INITSVTOR0_VTOR_MASK);
430246dbeb7SPeter Maydell             break;
431246dbeb7SPeter Maydell         case ARMSSE_IOTKIT:
432246dbeb7SPeter Maydell         case ARMSSE_SSE200:
433394e10d2SPeter Maydell             s->initsvtor0 = value;
4340f862986SPeter Maydell             set_init_vtor(0, s->initsvtor0);
43575750e4dSPeter Maydell             break;
436246dbeb7SPeter Maydell         default:
437246dbeb7SPeter Maydell             g_assert_not_reached();
438246dbeb7SPeter Maydell         }
439246dbeb7SPeter Maydell         break;
44075750e4dSPeter Maydell     case A_CPUWAIT:
44192ecf2d5SPeter Maydell         switch (s->sse_version) {
44292ecf2d5SPeter Maydell         case ARMSSE_IOTKIT:
44392ecf2d5SPeter Maydell         case ARMSSE_SSE200:
44492ecf2d5SPeter Maydell             cpuwait_write(s, value);
44592ecf2d5SPeter Maydell             break;
44692ecf2d5SPeter Maydell         case ARMSSE_SSE300:
44792ecf2d5SPeter Maydell             /* In SSE300 this is reserved (for INITSVTOR2) */
44892ecf2d5SPeter Maydell             goto bad_offset;
44992ecf2d5SPeter Maydell         default:
45092ecf2d5SPeter Maydell             g_assert_not_reached();
4510f862986SPeter Maydell         }
45275750e4dSPeter Maydell         break;
45375750e4dSPeter Maydell     case A_WICCTRL:
45492ecf2d5SPeter Maydell         switch (s->sse_version) {
45592ecf2d5SPeter Maydell         case ARMSSE_IOTKIT:
45692ecf2d5SPeter Maydell         case ARMSSE_SSE200:
45775750e4dSPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
45875750e4dSPeter Maydell             s->wicctrl = value;
45975750e4dSPeter Maydell             break;
46092ecf2d5SPeter Maydell         case ARMSSE_SSE300:
46192ecf2d5SPeter Maydell             /* In SSE300 this offset is CPUWAIT */
46292ecf2d5SPeter Maydell             cpuwait_write(s, value);
46392ecf2d5SPeter Maydell             break;
46492ecf2d5SPeter Maydell         default:
46592ecf2d5SPeter Maydell             g_assert_not_reached();
46692ecf2d5SPeter Maydell         }
46792ecf2d5SPeter Maydell         break;
46875750e4dSPeter Maydell     case A_SECDBGSET:
46975750e4dSPeter Maydell         /* write-1-to-set */
47075750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
47175750e4dSPeter Maydell         s->secure_debug |= value;
47275750e4dSPeter Maydell         break;
47375750e4dSPeter Maydell     case A_SECDBGCLR:
47475750e4dSPeter Maydell         /* write-1-to-clear */
47575750e4dSPeter Maydell         s->secure_debug &= ~value;
47675750e4dSPeter Maydell         break;
47775750e4dSPeter Maydell     case A_SWRESET:
47875750e4dSPeter Maydell         /* One w/o bit to request a reset; all other bits reserved */
47975750e4dSPeter Maydell         if (value & R_SWRESET_SWRESETREQ_MASK) {
48075750e4dSPeter Maydell             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
48175750e4dSPeter Maydell         }
48275750e4dSPeter Maydell         break;
48304836414SPeter Maydell     case A_SCSECCTRL:
4841cbd6fe4SPeter Maydell         switch (s->sse_version) {
4851cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
48604836414SPeter Maydell             goto bad_offset;
4871cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
48831b0c6b1SPeter Maydell         case ARMSSE_SSE300:
48904836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
49004836414SPeter Maydell             s->scsecctrl = value;
49104836414SPeter Maydell             break;
4921cbd6fe4SPeter Maydell         default:
4931cbd6fe4SPeter Maydell             g_assert_not_reached();
49404836414SPeter Maydell         }
4951cbd6fe4SPeter Maydell         break;
4961cbd6fe4SPeter Maydell     case A_FCLK_DIV:
4971cbd6fe4SPeter Maydell         switch (s->sse_version) {
4981cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
4991cbd6fe4SPeter Maydell             goto bad_offset;
5001cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
50131b0c6b1SPeter Maydell         case ARMSSE_SSE300:
50204836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
50304836414SPeter Maydell             s->fclk_div = value;
50404836414SPeter Maydell             break;
5051cbd6fe4SPeter Maydell         default:
5061cbd6fe4SPeter Maydell             g_assert_not_reached();
50704836414SPeter Maydell         }
5081cbd6fe4SPeter Maydell         break;
5091cbd6fe4SPeter Maydell     case A_SYSCLK_DIV:
5101cbd6fe4SPeter Maydell         switch (s->sse_version) {
5111cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
5121cbd6fe4SPeter Maydell             goto bad_offset;
5131cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
51431b0c6b1SPeter Maydell         case ARMSSE_SSE300:
51504836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
51604836414SPeter Maydell             s->sysclk_div = value;
51704836414SPeter Maydell             break;
5181cbd6fe4SPeter Maydell         default:
5191cbd6fe4SPeter Maydell             g_assert_not_reached();
52004836414SPeter Maydell         }
5211cbd6fe4SPeter Maydell         break;
5221cbd6fe4SPeter Maydell     case A_CLOCK_FORCE:
5231cbd6fe4SPeter Maydell         switch (s->sse_version) {
5241cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
5251cbd6fe4SPeter Maydell             goto bad_offset;
5261cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
52731b0c6b1SPeter Maydell         case ARMSSE_SSE300:
52804836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
52904836414SPeter Maydell             s->clock_force = value;
53004836414SPeter Maydell             break;
5311cbd6fe4SPeter Maydell         default:
5321cbd6fe4SPeter Maydell             g_assert_not_reached();
53304836414SPeter Maydell         }
5341cbd6fe4SPeter Maydell         break;
5351cbd6fe4SPeter Maydell     case A_INITSVTOR1:
5361cbd6fe4SPeter Maydell         switch (s->sse_version) {
5371cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
5381cbd6fe4SPeter Maydell             goto bad_offset;
5391cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
54004836414SPeter Maydell             s->initsvtor1 = value;
5410f862986SPeter Maydell             set_init_vtor(1, s->initsvtor1);
54204836414SPeter Maydell             break;
543246dbeb7SPeter Maydell         case ARMSSE_SSE300:
544246dbeb7SPeter Maydell             goto bad_offset;
5451cbd6fe4SPeter Maydell         default:
5461cbd6fe4SPeter Maydell             g_assert_not_reached();
54704836414SPeter Maydell         }
5481cbd6fe4SPeter Maydell         break;
5491cbd6fe4SPeter Maydell     case A_EWCTRL:
5501cbd6fe4SPeter Maydell         switch (s->sse_version) {
5511cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
5521cbd6fe4SPeter Maydell             goto bad_offset;
5531cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
55404836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
55504836414SPeter Maydell             s->ewctrl = value;
55604836414SPeter Maydell             break;
55792ecf2d5SPeter Maydell         case ARMSSE_SSE300:
55892ecf2d5SPeter Maydell             /* In SSE300 this offset is is NMI_ENABLE */
55992ecf2d5SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
56092ecf2d5SPeter Maydell             s->nmi_enable = value;
56192ecf2d5SPeter Maydell             break;
5621cbd6fe4SPeter Maydell         default:
5631cbd6fe4SPeter Maydell             g_assert_not_reached();
56404836414SPeter Maydell         }
5651cbd6fe4SPeter Maydell         break;
5662672a6caSPeter Maydell     case A_PWRCTRL:
5672672a6caSPeter Maydell         switch (s->sse_version) {
5682672a6caSPeter Maydell         case ARMSSE_IOTKIT:
5692672a6caSPeter Maydell         case ARMSSE_SSE200:
5702672a6caSPeter Maydell             goto bad_offset;
5712672a6caSPeter Maydell         case ARMSSE_SSE300:
5722672a6caSPeter Maydell             if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
5732672a6caSPeter Maydell                 qemu_log_mask(LOG_GUEST_ERROR,
5742672a6caSPeter Maydell                               "IoTKit PWRCTRL write when register locked\n");
5752672a6caSPeter Maydell                 break;
5762672a6caSPeter Maydell             }
5772672a6caSPeter Maydell             s->pwrctrl = value;
5782672a6caSPeter Maydell             break;
5792672a6caSPeter Maydell         default:
5802672a6caSPeter Maydell             g_assert_not_reached();
5812672a6caSPeter Maydell         }
5822672a6caSPeter Maydell         break;
5831cbd6fe4SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
5841cbd6fe4SPeter Maydell         switch (s->sse_version) {
5851cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
5861cbd6fe4SPeter Maydell             goto bad_offset;
5871cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
58831b0c6b1SPeter Maydell         case ARMSSE_SSE300:
58904836414SPeter Maydell             qemu_log_mask(LOG_UNIMP,
59004836414SPeter Maydell                           "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
59104836414SPeter Maydell             s->pdcm_pd_sys_sense = value;
59204836414SPeter Maydell             break;
5931cbd6fe4SPeter Maydell         default:
5941cbd6fe4SPeter Maydell             g_assert_not_reached();
59504836414SPeter Maydell         }
5961cbd6fe4SPeter Maydell         break;
597c5ffe6c8SPeter Maydell     case A_PDCM_PD_CPU0_SENSE:
598c5ffe6c8SPeter Maydell         switch (s->sse_version) {
599c5ffe6c8SPeter Maydell         case ARMSSE_IOTKIT:
600c5ffe6c8SPeter Maydell         case ARMSSE_SSE200:
601c5ffe6c8SPeter Maydell             goto bad_offset;
602c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
603c5ffe6c8SPeter Maydell             qemu_log_mask(LOG_UNIMP,
604c5ffe6c8SPeter Maydell                           "IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
605c5ffe6c8SPeter Maydell             s->pdcm_pd_cpu0_sense = value;
606c5ffe6c8SPeter Maydell             break;
607c5ffe6c8SPeter Maydell         default:
608c5ffe6c8SPeter Maydell             g_assert_not_reached();
609c5ffe6c8SPeter Maydell         }
610c5ffe6c8SPeter Maydell         break;
6111cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
6121cbd6fe4SPeter Maydell         switch (s->sse_version) {
6131cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
6141cbd6fe4SPeter Maydell             goto bad_offset;
6151cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
61604836414SPeter Maydell             qemu_log_mask(LOG_UNIMP,
61704836414SPeter Maydell                           "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
61804836414SPeter Maydell             s->pdcm_pd_sram0_sense = value;
61904836414SPeter Maydell             break;
620c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
621c5ffe6c8SPeter Maydell             goto bad_offset;
6221cbd6fe4SPeter Maydell         default:
6231cbd6fe4SPeter Maydell             g_assert_not_reached();
62404836414SPeter Maydell         }
6251cbd6fe4SPeter Maydell         break;
6261cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
6271cbd6fe4SPeter Maydell         switch (s->sse_version) {
6281cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
6291cbd6fe4SPeter Maydell             goto bad_offset;
6301cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
63104836414SPeter Maydell             qemu_log_mask(LOG_UNIMP,
63204836414SPeter Maydell                           "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
63304836414SPeter Maydell             s->pdcm_pd_sram1_sense = value;
63404836414SPeter Maydell             break;
635c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
636c5ffe6c8SPeter Maydell             goto bad_offset;
6371cbd6fe4SPeter Maydell         default:
6381cbd6fe4SPeter Maydell             g_assert_not_reached();
63904836414SPeter Maydell         }
6401cbd6fe4SPeter Maydell         break;
6411cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
6421cbd6fe4SPeter Maydell         switch (s->sse_version) {
6431cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
6441cbd6fe4SPeter Maydell             goto bad_offset;
6451cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
64604836414SPeter Maydell             qemu_log_mask(LOG_UNIMP,
64704836414SPeter Maydell                           "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
64804836414SPeter Maydell             s->pdcm_pd_sram2_sense = value;
64904836414SPeter Maydell             break;
650c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
651c5ffe6c8SPeter Maydell             qemu_log_mask(LOG_UNIMP,
652c5ffe6c8SPeter Maydell                           "IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
653c5ffe6c8SPeter Maydell             s->pdcm_pd_vmr0_sense = value;
654c5ffe6c8SPeter Maydell             break;
6551cbd6fe4SPeter Maydell         default:
6561cbd6fe4SPeter Maydell             g_assert_not_reached();
65704836414SPeter Maydell         }
6581cbd6fe4SPeter Maydell         break;
6591cbd6fe4SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
6601cbd6fe4SPeter Maydell         switch (s->sse_version) {
6611cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
6621cbd6fe4SPeter Maydell             goto bad_offset;
6631cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
66404836414SPeter Maydell             qemu_log_mask(LOG_UNIMP,
66504836414SPeter Maydell                           "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
66604836414SPeter Maydell             s->pdcm_pd_sram3_sense = value;
66704836414SPeter Maydell             break;
668c5ffe6c8SPeter Maydell         case ARMSSE_SSE300:
669c5ffe6c8SPeter Maydell             qemu_log_mask(LOG_UNIMP,
670c5ffe6c8SPeter Maydell                           "IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
671c5ffe6c8SPeter Maydell             s->pdcm_pd_vmr1_sense = value;
672c5ffe6c8SPeter Maydell             break;
6731cbd6fe4SPeter Maydell         default:
6741cbd6fe4SPeter Maydell             g_assert_not_reached();
6751cbd6fe4SPeter Maydell         }
6761cbd6fe4SPeter Maydell         break;
67704836414SPeter Maydell     case A_NMI_ENABLE:
67804836414SPeter Maydell         /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
6791cbd6fe4SPeter Maydell         switch (s->sse_version) {
6801cbd6fe4SPeter Maydell         case ARMSSE_IOTKIT:
68104836414SPeter Maydell             goto ro_offset;
6821cbd6fe4SPeter Maydell         case ARMSSE_SSE200:
68304836414SPeter Maydell             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
68404836414SPeter Maydell             s->nmi_enable = value;
68504836414SPeter Maydell             break;
68692ecf2d5SPeter Maydell         case ARMSSE_SSE300:
68792ecf2d5SPeter Maydell             /* In SSE300 this is reserved (for INITSVTOR3) */
68892ecf2d5SPeter Maydell             goto bad_offset;
6891cbd6fe4SPeter Maydell         default:
6901cbd6fe4SPeter Maydell             g_assert_not_reached();
6911cbd6fe4SPeter Maydell         }
6921cbd6fe4SPeter Maydell         break;
69375750e4dSPeter Maydell     case A_SECDBGSTAT:
69475750e4dSPeter Maydell     case A_PID4 ... A_CID3:
69504836414SPeter Maydell     ro_offset:
69675750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
69775750e4dSPeter Maydell                       "IoTKit SysCtl write: write of RO offset %x\n",
69875750e4dSPeter Maydell                       (int)offset);
69975750e4dSPeter Maydell         break;
70075750e4dSPeter Maydell     default:
70104836414SPeter Maydell     bad_offset:
70275750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
70375750e4dSPeter Maydell                       "IoTKit SysCtl write: bad offset %x\n", (int)offset);
70475750e4dSPeter Maydell         break;
70575750e4dSPeter Maydell     }
70675750e4dSPeter Maydell }
70775750e4dSPeter Maydell 
70875750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = {
70975750e4dSPeter Maydell     .read = iotkit_sysctl_read,
71075750e4dSPeter Maydell     .write = iotkit_sysctl_write,
71175750e4dSPeter Maydell     .endianness = DEVICE_LITTLE_ENDIAN,
71275750e4dSPeter Maydell     /* byte/halfword accesses are just zero-padded on reads and writes */
71375750e4dSPeter Maydell     .impl.min_access_size = 4,
71475750e4dSPeter Maydell     .impl.max_access_size = 4,
71575750e4dSPeter Maydell     .valid.min_access_size = 1,
71675750e4dSPeter Maydell     .valid.max_access_size = 4,
71775750e4dSPeter Maydell };
71875750e4dSPeter Maydell 
71975750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev)
72075750e4dSPeter Maydell {
72175750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
72275750e4dSPeter Maydell 
72375750e4dSPeter Maydell     trace_iotkit_sysctl_reset();
72475750e4dSPeter Maydell     s->secure_debug = 0;
72575750e4dSPeter Maydell     s->reset_syndrome = 1;
72675750e4dSPeter Maydell     s->reset_mask = 0;
72775750e4dSPeter Maydell     s->gretreg = 0;
728aab7a378SPeter Maydell     s->initsvtor0 = s->initsvtor0_rst;
729aab7a378SPeter Maydell     s->initsvtor1 = s->initsvtor1_rst;
730aab7a378SPeter Maydell     s->cpuwait = s->cpuwait_rst;
73175750e4dSPeter Maydell     s->wicctrl = 0;
73204836414SPeter Maydell     s->scsecctrl = 0;
73304836414SPeter Maydell     s->fclk_div = 0;
73404836414SPeter Maydell     s->sysclk_div = 0;
73504836414SPeter Maydell     s->clock_force = 0;
73604836414SPeter Maydell     s->nmi_enable = 0;
73704836414SPeter Maydell     s->ewctrl = 0;
7382672a6caSPeter Maydell     s->pwrctrl = 0x3;
73904836414SPeter Maydell     s->pdcm_pd_sys_sense = 0x7f;
74004836414SPeter Maydell     s->pdcm_pd_sram0_sense = 0;
74104836414SPeter Maydell     s->pdcm_pd_sram1_sense = 0;
74204836414SPeter Maydell     s->pdcm_pd_sram2_sense = 0;
74304836414SPeter Maydell     s->pdcm_pd_sram3_sense = 0;
744c5ffe6c8SPeter Maydell     s->pdcm_pd_cpu0_sense = 0;
745c5ffe6c8SPeter Maydell     s->pdcm_pd_vmr0_sense = 0;
746c5ffe6c8SPeter Maydell     s->pdcm_pd_vmr1_sense = 0;
74775750e4dSPeter Maydell }
74875750e4dSPeter Maydell 
74975750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj)
75075750e4dSPeter Maydell {
75175750e4dSPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
75275750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
75375750e4dSPeter Maydell 
75475750e4dSPeter Maydell     memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
75575750e4dSPeter Maydell                           s, "iotkit-sysctl", 0x1000);
75675750e4dSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem);
75775750e4dSPeter Maydell }
75875750e4dSPeter Maydell 
75904836414SPeter Maydell static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
76004836414SPeter Maydell {
76104836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
76204836414SPeter Maydell 
763419a7f80SPeter Maydell     if (!armsse_version_valid(s->sse_version)) {
764419a7f80SPeter Maydell         error_setg(errp, "invalid sse-version value %d", s->sse_version);
765419a7f80SPeter Maydell         return;
76604836414SPeter Maydell     }
76704836414SPeter Maydell }
76804836414SPeter Maydell 
7692672a6caSPeter Maydell static bool sse300_needed(void *opaque)
7702672a6caSPeter Maydell {
7712672a6caSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
7722672a6caSPeter Maydell 
7732672a6caSPeter Maydell     return s->sse_version == ARMSSE_SSE300;
7742672a6caSPeter Maydell }
7752672a6caSPeter Maydell 
7762672a6caSPeter Maydell static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
7772672a6caSPeter Maydell     .name = "iotkit-sysctl/sse-300",
7782672a6caSPeter Maydell     .version_id = 1,
7792672a6caSPeter Maydell     .minimum_version_id = 1,
7802672a6caSPeter Maydell     .needed = sse300_needed,
7812672a6caSPeter Maydell     .fields = (VMStateField[]) {
7822672a6caSPeter Maydell         VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
783c5ffe6c8SPeter Maydell         VMSTATE_UINT32(pdcm_pd_cpu0_sense, IoTKitSysCtl),
784c5ffe6c8SPeter Maydell         VMSTATE_UINT32(pdcm_pd_vmr0_sense, IoTKitSysCtl),
785c5ffe6c8SPeter Maydell         VMSTATE_UINT32(pdcm_pd_vmr1_sense, IoTKitSysCtl),
7862672a6caSPeter Maydell         VMSTATE_END_OF_LIST()
7872672a6caSPeter Maydell     }
7882672a6caSPeter Maydell };
7892672a6caSPeter Maydell 
79004836414SPeter Maydell static bool sse200_needed(void *opaque)
79104836414SPeter Maydell {
79204836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
79304836414SPeter Maydell 
79431b0c6b1SPeter Maydell     return s->sse_version != ARMSSE_IOTKIT;
79504836414SPeter Maydell }
79604836414SPeter Maydell 
79704836414SPeter Maydell static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
79804836414SPeter Maydell     .name = "iotkit-sysctl/sse-200",
79904836414SPeter Maydell     .version_id = 1,
80004836414SPeter Maydell     .minimum_version_id = 1,
80104836414SPeter Maydell     .needed = sse200_needed,
80204836414SPeter Maydell     .fields = (VMStateField[]) {
80304836414SPeter Maydell         VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
80404836414SPeter Maydell         VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
80504836414SPeter Maydell         VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
80604836414SPeter Maydell         VMSTATE_UINT32(clock_force, IoTKitSysCtl),
80704836414SPeter Maydell         VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
80804836414SPeter Maydell         VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
80904836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
81004836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
81104836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
81204836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
81304836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
81404836414SPeter Maydell         VMSTATE_END_OF_LIST()
81504836414SPeter Maydell     }
81604836414SPeter Maydell };
81704836414SPeter Maydell 
81875750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = {
81975750e4dSPeter Maydell     .name = "iotkit-sysctl",
82075750e4dSPeter Maydell     .version_id = 1,
82175750e4dSPeter Maydell     .minimum_version_id = 1,
82275750e4dSPeter Maydell     .fields = (VMStateField[]) {
82375750e4dSPeter Maydell         VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
82475750e4dSPeter Maydell         VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
82575750e4dSPeter Maydell         VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
82675750e4dSPeter Maydell         VMSTATE_UINT32(gretreg, IoTKitSysCtl),
827394e10d2SPeter Maydell         VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
82875750e4dSPeter Maydell         VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
82975750e4dSPeter Maydell         VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
83075750e4dSPeter Maydell         VMSTATE_END_OF_LIST()
83104836414SPeter Maydell     },
83204836414SPeter Maydell     .subsections = (const VMStateDescription*[]) {
83304836414SPeter Maydell         &iotkit_sysctl_sse200_vmstate,
8342672a6caSPeter Maydell         &iotkit_sysctl_sse300_vmstate,
83504836414SPeter Maydell         NULL
83675750e4dSPeter Maydell     }
83775750e4dSPeter Maydell };
83875750e4dSPeter Maydell 
83904836414SPeter Maydell static Property iotkit_sysctl_props[] = {
840419a7f80SPeter Maydell     DEFINE_PROP_UINT32("sse-version", IoTKitSysCtl, sse_version, 0),
841aab7a378SPeter Maydell     DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
842aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
843aab7a378SPeter Maydell                        0x10000000),
844aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
845aab7a378SPeter Maydell                        0x10000000),
84604836414SPeter Maydell     DEFINE_PROP_END_OF_LIST()
84704836414SPeter Maydell };
84804836414SPeter Maydell 
84975750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
85075750e4dSPeter Maydell {
85175750e4dSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
85275750e4dSPeter Maydell 
85375750e4dSPeter Maydell     dc->vmsd = &iotkit_sysctl_vmstate;
85475750e4dSPeter Maydell     dc->reset = iotkit_sysctl_reset;
8554f67d30bSMarc-André Lureau     device_class_set_props(dc, iotkit_sysctl_props);
85604836414SPeter Maydell     dc->realize = iotkit_sysctl_realize;
85775750e4dSPeter Maydell }
85875750e4dSPeter Maydell 
85975750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = {
86075750e4dSPeter Maydell     .name = TYPE_IOTKIT_SYSCTL,
86175750e4dSPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
86275750e4dSPeter Maydell     .instance_size = sizeof(IoTKitSysCtl),
86375750e4dSPeter Maydell     .instance_init = iotkit_sysctl_init,
86475750e4dSPeter Maydell     .class_init = iotkit_sysctl_class_init,
86575750e4dSPeter Maydell };
86675750e4dSPeter Maydell 
86775750e4dSPeter Maydell static void iotkit_sysctl_register_types(void)
86875750e4dSPeter Maydell {
86975750e4dSPeter Maydell     type_register_static(&iotkit_sysctl_info);
87075750e4dSPeter Maydell }
87175750e4dSPeter Maydell 
87275750e4dSPeter Maydell type_init(iotkit_sysctl_register_types);
873