xref: /qemu/hw/misc/iotkit-sysctl.c (revision 4f67d30b5e74e060b8dbe10528829b47345cd6e8)
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
1575750e4dSPeter Maydell  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
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"
310f862986SPeter Maydell #include "target/arm/arm-powerctl.h"
320f862986SPeter Maydell #include "target/arm/cpu.h"
3375750e4dSPeter Maydell 
3475750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0)
3575750e4dSPeter Maydell REG32(SECDBGSET, 0x4)
3675750e4dSPeter Maydell REG32(SECDBGCLR, 0x8)
3704836414SPeter Maydell REG32(SCSECCTRL, 0xc)
3804836414SPeter Maydell REG32(FCLK_DIV, 0x10)
3904836414SPeter Maydell REG32(SYSCLK_DIV, 0x14)
4004836414SPeter Maydell REG32(CLOCK_FORCE, 0x18)
4175750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100)
4275750e4dSPeter Maydell REG32(RESET_MASK, 0x104)
4375750e4dSPeter Maydell REG32(SWRESET, 0x108)
4475750e4dSPeter Maydell     FIELD(SWRESET, SWRESETREQ, 9, 1)
4575750e4dSPeter Maydell REG32(GRETREG, 0x10c)
46394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110)
4704836414SPeter Maydell REG32(INITSVTOR1, 0x114)
4875750e4dSPeter Maydell REG32(CPUWAIT, 0x118)
4904836414SPeter Maydell REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
5075750e4dSPeter Maydell REG32(WICCTRL, 0x120)
5104836414SPeter Maydell REG32(EWCTRL, 0x124)
5204836414SPeter Maydell REG32(PDCM_PD_SYS_SENSE, 0x200)
5304836414SPeter Maydell REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
5404836414SPeter Maydell REG32(PDCM_PD_SRAM1_SENSE, 0x210)
5504836414SPeter Maydell REG32(PDCM_PD_SRAM2_SENSE, 0x214)
5604836414SPeter Maydell REG32(PDCM_PD_SRAM3_SENSE, 0x218)
5775750e4dSPeter Maydell REG32(PID4, 0xfd0)
5875750e4dSPeter Maydell REG32(PID5, 0xfd4)
5975750e4dSPeter Maydell REG32(PID6, 0xfd8)
6075750e4dSPeter Maydell REG32(PID7, 0xfdc)
6175750e4dSPeter Maydell REG32(PID0, 0xfe0)
6275750e4dSPeter Maydell REG32(PID1, 0xfe4)
6375750e4dSPeter Maydell REG32(PID2, 0xfe8)
6475750e4dSPeter Maydell REG32(PID3, 0xfec)
6575750e4dSPeter Maydell REG32(CID0, 0xff0)
6675750e4dSPeter Maydell REG32(CID1, 0xff4)
6775750e4dSPeter Maydell REG32(CID2, 0xff8)
6875750e4dSPeter Maydell REG32(CID3, 0xffc)
6975750e4dSPeter Maydell 
7075750e4dSPeter Maydell /* PID/CID values */
7175750e4dSPeter Maydell static const int sysctl_id[] = {
7275750e4dSPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
7375750e4dSPeter Maydell     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
7475750e4dSPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
7575750e4dSPeter Maydell };
7675750e4dSPeter Maydell 
770f862986SPeter Maydell /*
780f862986SPeter Maydell  * Set the initial secure vector table offset address for the core.
790f862986SPeter Maydell  * This will take effect when the CPU next resets.
800f862986SPeter Maydell  */
810f862986SPeter Maydell static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
820f862986SPeter Maydell {
830f862986SPeter Maydell     Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
840f862986SPeter Maydell 
850f862986SPeter Maydell     if (cpuobj) {
860f862986SPeter Maydell         if (object_property_find(cpuobj, "init-svtor", NULL)) {
870f862986SPeter Maydell             object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort);
880f862986SPeter Maydell         }
890f862986SPeter Maydell     }
900f862986SPeter Maydell }
910f862986SPeter Maydell 
9275750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
9375750e4dSPeter Maydell                                     unsigned size)
9475750e4dSPeter Maydell {
9575750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
9675750e4dSPeter Maydell     uint64_t r;
9775750e4dSPeter Maydell 
9875750e4dSPeter Maydell     switch (offset) {
9975750e4dSPeter Maydell     case A_SECDBGSTAT:
10075750e4dSPeter Maydell         r = s->secure_debug;
10175750e4dSPeter Maydell         break;
10204836414SPeter Maydell     case A_SCSECCTRL:
10304836414SPeter Maydell         if (!s->is_sse200) {
10404836414SPeter Maydell             goto bad_offset;
10504836414SPeter Maydell         }
10604836414SPeter Maydell         r = s->scsecctrl;
10704836414SPeter Maydell         break;
10804836414SPeter Maydell     case A_FCLK_DIV:
10904836414SPeter Maydell         if (!s->is_sse200) {
11004836414SPeter Maydell             goto bad_offset;
11104836414SPeter Maydell         }
11204836414SPeter Maydell         r = s->fclk_div;
11304836414SPeter Maydell         break;
11404836414SPeter Maydell     case A_SYSCLK_DIV:
11504836414SPeter Maydell         if (!s->is_sse200) {
11604836414SPeter Maydell             goto bad_offset;
11704836414SPeter Maydell         }
11804836414SPeter Maydell         r = s->sysclk_div;
11904836414SPeter Maydell         break;
12004836414SPeter Maydell     case A_CLOCK_FORCE:
12104836414SPeter Maydell         if (!s->is_sse200) {
12204836414SPeter Maydell             goto bad_offset;
12304836414SPeter Maydell         }
12404836414SPeter Maydell         r = s->clock_force;
12504836414SPeter Maydell         break;
12675750e4dSPeter Maydell     case A_RESET_SYNDROME:
12775750e4dSPeter Maydell         r = s->reset_syndrome;
12875750e4dSPeter Maydell         break;
12975750e4dSPeter Maydell     case A_RESET_MASK:
13075750e4dSPeter Maydell         r = s->reset_mask;
13175750e4dSPeter Maydell         break;
13275750e4dSPeter Maydell     case A_GRETREG:
13375750e4dSPeter Maydell         r = s->gretreg;
13475750e4dSPeter Maydell         break;
135394e10d2SPeter Maydell     case A_INITSVTOR0:
136394e10d2SPeter Maydell         r = s->initsvtor0;
13775750e4dSPeter Maydell         break;
13804836414SPeter Maydell     case A_INITSVTOR1:
13904836414SPeter Maydell         if (!s->is_sse200) {
14004836414SPeter Maydell             goto bad_offset;
14104836414SPeter Maydell         }
14204836414SPeter Maydell         r = s->initsvtor1;
14304836414SPeter Maydell         break;
14475750e4dSPeter Maydell     case A_CPUWAIT:
14575750e4dSPeter Maydell         r = s->cpuwait;
14675750e4dSPeter Maydell         break;
14704836414SPeter Maydell     case A_NMI_ENABLE:
14804836414SPeter Maydell         /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
14904836414SPeter Maydell         if (!s->is_sse200) {
15075750e4dSPeter Maydell             r = 0;
15175750e4dSPeter Maydell             break;
15204836414SPeter Maydell         }
15304836414SPeter Maydell         r = s->nmi_enable;
15404836414SPeter Maydell         break;
15575750e4dSPeter Maydell     case A_WICCTRL:
15675750e4dSPeter Maydell         r = s->wicctrl;
15775750e4dSPeter Maydell         break;
15804836414SPeter Maydell     case A_EWCTRL:
15904836414SPeter Maydell         if (!s->is_sse200) {
16004836414SPeter Maydell             goto bad_offset;
16104836414SPeter Maydell         }
16204836414SPeter Maydell         r = s->ewctrl;
16304836414SPeter Maydell         break;
16404836414SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
16504836414SPeter Maydell         if (!s->is_sse200) {
16604836414SPeter Maydell             goto bad_offset;
16704836414SPeter Maydell         }
16804836414SPeter Maydell         r = s->pdcm_pd_sys_sense;
16904836414SPeter Maydell         break;
17004836414SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
17104836414SPeter Maydell         if (!s->is_sse200) {
17204836414SPeter Maydell             goto bad_offset;
17304836414SPeter Maydell         }
17404836414SPeter Maydell         r = s->pdcm_pd_sram0_sense;
17504836414SPeter Maydell         break;
17604836414SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
17704836414SPeter Maydell         if (!s->is_sse200) {
17804836414SPeter Maydell             goto bad_offset;
17904836414SPeter Maydell         }
18004836414SPeter Maydell         r = s->pdcm_pd_sram1_sense;
18104836414SPeter Maydell         break;
18204836414SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
18304836414SPeter Maydell         if (!s->is_sse200) {
18404836414SPeter Maydell             goto bad_offset;
18504836414SPeter Maydell         }
18604836414SPeter Maydell         r = s->pdcm_pd_sram2_sense;
18704836414SPeter Maydell         break;
18804836414SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
18904836414SPeter Maydell         if (!s->is_sse200) {
19004836414SPeter Maydell             goto bad_offset;
19104836414SPeter Maydell         }
19204836414SPeter Maydell         r = s->pdcm_pd_sram3_sense;
19304836414SPeter Maydell         break;
19475750e4dSPeter Maydell     case A_PID4 ... A_CID3:
19575750e4dSPeter Maydell         r = sysctl_id[(offset - A_PID4) / 4];
19675750e4dSPeter Maydell         break;
19775750e4dSPeter Maydell     case A_SECDBGSET:
19875750e4dSPeter Maydell     case A_SECDBGCLR:
19975750e4dSPeter Maydell     case A_SWRESET:
20075750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
20175750e4dSPeter Maydell                       "IoTKit SysCtl read: read of WO offset %x\n",
20275750e4dSPeter Maydell                       (int)offset);
20375750e4dSPeter Maydell         r = 0;
20475750e4dSPeter Maydell         break;
20575750e4dSPeter Maydell     default:
20604836414SPeter Maydell     bad_offset:
20775750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
20875750e4dSPeter Maydell                       "IoTKit SysCtl read: bad offset %x\n", (int)offset);
20975750e4dSPeter Maydell         r = 0;
21075750e4dSPeter Maydell         break;
21175750e4dSPeter Maydell     }
21275750e4dSPeter Maydell     trace_iotkit_sysctl_read(offset, r, size);
21375750e4dSPeter Maydell     return r;
21475750e4dSPeter Maydell }
21575750e4dSPeter Maydell 
21675750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset,
21775750e4dSPeter Maydell                                  uint64_t value, unsigned size)
21875750e4dSPeter Maydell {
21975750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
22075750e4dSPeter Maydell 
22175750e4dSPeter Maydell     trace_iotkit_sysctl_write(offset, value, size);
22275750e4dSPeter Maydell 
22375750e4dSPeter Maydell     /*
22475750e4dSPeter Maydell      * Most of the state here has to do with control of reset and
22575750e4dSPeter Maydell      * similar kinds of power up -- for instance the guest can ask
22675750e4dSPeter Maydell      * what the reason for the last reset was, or forbid reset for
22775750e4dSPeter Maydell      * some causes (like the non-secure watchdog). Most of this is
22875750e4dSPeter Maydell      * not relevant to QEMU, which doesn't really model anything other
22975750e4dSPeter Maydell      * than a full power-on reset.
23075750e4dSPeter Maydell      * We just model the registers as reads-as-written.
23175750e4dSPeter Maydell      */
23275750e4dSPeter Maydell 
23375750e4dSPeter Maydell     switch (offset) {
23475750e4dSPeter Maydell     case A_RESET_SYNDROME:
23575750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP,
23675750e4dSPeter Maydell                       "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
23775750e4dSPeter Maydell         s->reset_syndrome = value;
23875750e4dSPeter Maydell         break;
23975750e4dSPeter Maydell     case A_RESET_MASK:
24075750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
24175750e4dSPeter Maydell         s->reset_mask = value;
24275750e4dSPeter Maydell         break;
24375750e4dSPeter Maydell     case A_GRETREG:
24475750e4dSPeter Maydell         /*
24575750e4dSPeter Maydell          * General retention register, which is only reset by a power-on
24675750e4dSPeter Maydell          * reset. Technically this implementation is complete, since
24775750e4dSPeter Maydell          * QEMU only supports power-on resets...
24875750e4dSPeter Maydell          */
24975750e4dSPeter Maydell         s->gretreg = value;
25075750e4dSPeter Maydell         break;
251394e10d2SPeter Maydell     case A_INITSVTOR0:
252394e10d2SPeter Maydell         s->initsvtor0 = value;
2530f862986SPeter Maydell         set_init_vtor(0, s->initsvtor0);
25475750e4dSPeter Maydell         break;
25575750e4dSPeter Maydell     case A_CPUWAIT:
2560f862986SPeter Maydell         if ((s->cpuwait & 1) && !(value & 1)) {
2570f862986SPeter Maydell             /* Powering up CPU 0 */
2580f862986SPeter Maydell             arm_set_cpu_on_and_reset(0);
2590f862986SPeter Maydell         }
2600f862986SPeter Maydell         if ((s->cpuwait & 2) && !(value & 2)) {
2610f862986SPeter Maydell             /* Powering up CPU 1 */
2620f862986SPeter Maydell             arm_set_cpu_on_and_reset(1);
2630f862986SPeter Maydell         }
26475750e4dSPeter Maydell         s->cpuwait = value;
26575750e4dSPeter Maydell         break;
26675750e4dSPeter Maydell     case A_WICCTRL:
26775750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
26875750e4dSPeter Maydell         s->wicctrl = value;
26975750e4dSPeter Maydell         break;
27075750e4dSPeter Maydell     case A_SECDBGSET:
27175750e4dSPeter Maydell         /* write-1-to-set */
27275750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
27375750e4dSPeter Maydell         s->secure_debug |= value;
27475750e4dSPeter Maydell         break;
27575750e4dSPeter Maydell     case A_SECDBGCLR:
27675750e4dSPeter Maydell         /* write-1-to-clear */
27775750e4dSPeter Maydell         s->secure_debug &= ~value;
27875750e4dSPeter Maydell         break;
27975750e4dSPeter Maydell     case A_SWRESET:
28075750e4dSPeter Maydell         /* One w/o bit to request a reset; all other bits reserved */
28175750e4dSPeter Maydell         if (value & R_SWRESET_SWRESETREQ_MASK) {
28275750e4dSPeter Maydell             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
28375750e4dSPeter Maydell         }
28475750e4dSPeter Maydell         break;
28504836414SPeter Maydell     case A_SCSECCTRL:
28604836414SPeter Maydell         if (!s->is_sse200) {
28704836414SPeter Maydell             goto bad_offset;
28804836414SPeter Maydell         }
28904836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
29004836414SPeter Maydell         s->scsecctrl = value;
29104836414SPeter Maydell         break;
29204836414SPeter Maydell     case A_FCLK_DIV:
29304836414SPeter Maydell         if (!s->is_sse200) {
29404836414SPeter Maydell             goto bad_offset;
29504836414SPeter Maydell         }
29604836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
29704836414SPeter Maydell         s->fclk_div = value;
29804836414SPeter Maydell         break;
29904836414SPeter Maydell     case A_SYSCLK_DIV:
30004836414SPeter Maydell         if (!s->is_sse200) {
30104836414SPeter Maydell             goto bad_offset;
30204836414SPeter Maydell         }
30304836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
30404836414SPeter Maydell         s->sysclk_div = value;
30504836414SPeter Maydell         break;
30604836414SPeter Maydell     case A_CLOCK_FORCE:
30704836414SPeter Maydell         if (!s->is_sse200) {
30804836414SPeter Maydell             goto bad_offset;
30904836414SPeter Maydell         }
31004836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
31104836414SPeter Maydell         s->clock_force = value;
31204836414SPeter Maydell         break;
31304836414SPeter Maydell     case A_INITSVTOR1:
31404836414SPeter Maydell         if (!s->is_sse200) {
31504836414SPeter Maydell             goto bad_offset;
31604836414SPeter Maydell         }
31704836414SPeter Maydell         s->initsvtor1 = value;
3180f862986SPeter Maydell         set_init_vtor(1, s->initsvtor1);
31904836414SPeter Maydell         break;
32004836414SPeter Maydell     case A_EWCTRL:
32104836414SPeter Maydell         if (!s->is_sse200) {
32204836414SPeter Maydell             goto bad_offset;
32304836414SPeter Maydell         }
32404836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
32504836414SPeter Maydell         s->ewctrl = value;
32604836414SPeter Maydell         break;
32704836414SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
32804836414SPeter Maydell         if (!s->is_sse200) {
32904836414SPeter Maydell             goto bad_offset;
33004836414SPeter Maydell         }
33104836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
33204836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
33304836414SPeter Maydell         s->pdcm_pd_sys_sense = value;
33404836414SPeter Maydell         break;
33504836414SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
33604836414SPeter Maydell         if (!s->is_sse200) {
33704836414SPeter Maydell             goto bad_offset;
33804836414SPeter Maydell         }
33904836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
34004836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
34104836414SPeter Maydell         s->pdcm_pd_sram0_sense = value;
34204836414SPeter Maydell         break;
34304836414SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
34404836414SPeter Maydell         if (!s->is_sse200) {
34504836414SPeter Maydell             goto bad_offset;
34604836414SPeter Maydell         }
34704836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
34804836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
34904836414SPeter Maydell         s->pdcm_pd_sram1_sense = value;
35004836414SPeter Maydell         break;
35104836414SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
35204836414SPeter Maydell         if (!s->is_sse200) {
35304836414SPeter Maydell             goto bad_offset;
35404836414SPeter Maydell         }
35504836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
35604836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
35704836414SPeter Maydell         s->pdcm_pd_sram2_sense = value;
35804836414SPeter Maydell         break;
35904836414SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
36004836414SPeter Maydell         if (!s->is_sse200) {
36104836414SPeter Maydell             goto bad_offset;
36204836414SPeter Maydell         }
36304836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
36404836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
36504836414SPeter Maydell         s->pdcm_pd_sram3_sense = value;
36604836414SPeter Maydell         break;
36704836414SPeter Maydell     case A_NMI_ENABLE:
36804836414SPeter Maydell         /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
36904836414SPeter Maydell         if (!s->is_sse200) {
37004836414SPeter Maydell             goto ro_offset;
37104836414SPeter Maydell         }
37204836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
37304836414SPeter Maydell         s->nmi_enable = value;
37404836414SPeter Maydell         break;
37575750e4dSPeter Maydell     case A_SECDBGSTAT:
37675750e4dSPeter Maydell     case A_PID4 ... A_CID3:
37704836414SPeter Maydell     ro_offset:
37875750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
37975750e4dSPeter Maydell                       "IoTKit SysCtl write: write of RO offset %x\n",
38075750e4dSPeter Maydell                       (int)offset);
38175750e4dSPeter Maydell         break;
38275750e4dSPeter Maydell     default:
38304836414SPeter Maydell     bad_offset:
38475750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
38575750e4dSPeter Maydell                       "IoTKit SysCtl write: bad offset %x\n", (int)offset);
38675750e4dSPeter Maydell         break;
38775750e4dSPeter Maydell     }
38875750e4dSPeter Maydell }
38975750e4dSPeter Maydell 
39075750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = {
39175750e4dSPeter Maydell     .read = iotkit_sysctl_read,
39275750e4dSPeter Maydell     .write = iotkit_sysctl_write,
39375750e4dSPeter Maydell     .endianness = DEVICE_LITTLE_ENDIAN,
39475750e4dSPeter Maydell     /* byte/halfword accesses are just zero-padded on reads and writes */
39575750e4dSPeter Maydell     .impl.min_access_size = 4,
39675750e4dSPeter Maydell     .impl.max_access_size = 4,
39775750e4dSPeter Maydell     .valid.min_access_size = 1,
39875750e4dSPeter Maydell     .valid.max_access_size = 4,
39975750e4dSPeter Maydell };
40075750e4dSPeter Maydell 
40175750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev)
40275750e4dSPeter Maydell {
40375750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
40475750e4dSPeter Maydell 
40575750e4dSPeter Maydell     trace_iotkit_sysctl_reset();
40675750e4dSPeter Maydell     s->secure_debug = 0;
40775750e4dSPeter Maydell     s->reset_syndrome = 1;
40875750e4dSPeter Maydell     s->reset_mask = 0;
40975750e4dSPeter Maydell     s->gretreg = 0;
410aab7a378SPeter Maydell     s->initsvtor0 = s->initsvtor0_rst;
411aab7a378SPeter Maydell     s->initsvtor1 = s->initsvtor1_rst;
412aab7a378SPeter Maydell     s->cpuwait = s->cpuwait_rst;
41375750e4dSPeter Maydell     s->wicctrl = 0;
41404836414SPeter Maydell     s->scsecctrl = 0;
41504836414SPeter Maydell     s->fclk_div = 0;
41604836414SPeter Maydell     s->sysclk_div = 0;
41704836414SPeter Maydell     s->clock_force = 0;
41804836414SPeter Maydell     s->nmi_enable = 0;
41904836414SPeter Maydell     s->ewctrl = 0;
42004836414SPeter Maydell     s->pdcm_pd_sys_sense = 0x7f;
42104836414SPeter Maydell     s->pdcm_pd_sram0_sense = 0;
42204836414SPeter Maydell     s->pdcm_pd_sram1_sense = 0;
42304836414SPeter Maydell     s->pdcm_pd_sram2_sense = 0;
42404836414SPeter Maydell     s->pdcm_pd_sram3_sense = 0;
42575750e4dSPeter Maydell }
42675750e4dSPeter Maydell 
42775750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj)
42875750e4dSPeter Maydell {
42975750e4dSPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
43075750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
43175750e4dSPeter Maydell 
43275750e4dSPeter Maydell     memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
43375750e4dSPeter Maydell                           s, "iotkit-sysctl", 0x1000);
43475750e4dSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem);
43575750e4dSPeter Maydell }
43675750e4dSPeter Maydell 
43704836414SPeter Maydell static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
43804836414SPeter Maydell {
43904836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
44004836414SPeter Maydell 
44104836414SPeter Maydell     /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
44204836414SPeter Maydell     if (extract32(s->sys_version, 28, 4) == 2) {
44304836414SPeter Maydell         s->is_sse200 = true;
44404836414SPeter Maydell     }
44504836414SPeter Maydell }
44604836414SPeter Maydell 
44704836414SPeter Maydell static bool sse200_needed(void *opaque)
44804836414SPeter Maydell {
44904836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
45004836414SPeter Maydell 
45104836414SPeter Maydell     return s->is_sse200;
45204836414SPeter Maydell }
45304836414SPeter Maydell 
45404836414SPeter Maydell static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
45504836414SPeter Maydell     .name = "iotkit-sysctl/sse-200",
45604836414SPeter Maydell     .version_id = 1,
45704836414SPeter Maydell     .minimum_version_id = 1,
45804836414SPeter Maydell     .needed = sse200_needed,
45904836414SPeter Maydell     .fields = (VMStateField[]) {
46004836414SPeter Maydell         VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
46104836414SPeter Maydell         VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
46204836414SPeter Maydell         VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
46304836414SPeter Maydell         VMSTATE_UINT32(clock_force, IoTKitSysCtl),
46404836414SPeter Maydell         VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
46504836414SPeter Maydell         VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
46604836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
46704836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
46804836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
46904836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
47004836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
47104836414SPeter Maydell         VMSTATE_END_OF_LIST()
47204836414SPeter Maydell     }
47304836414SPeter Maydell };
47404836414SPeter Maydell 
47575750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = {
47675750e4dSPeter Maydell     .name = "iotkit-sysctl",
47775750e4dSPeter Maydell     .version_id = 1,
47875750e4dSPeter Maydell     .minimum_version_id = 1,
47975750e4dSPeter Maydell     .fields = (VMStateField[]) {
48075750e4dSPeter Maydell         VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
48175750e4dSPeter Maydell         VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
48275750e4dSPeter Maydell         VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
48375750e4dSPeter Maydell         VMSTATE_UINT32(gretreg, IoTKitSysCtl),
484394e10d2SPeter Maydell         VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
48575750e4dSPeter Maydell         VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
48675750e4dSPeter Maydell         VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
48775750e4dSPeter Maydell         VMSTATE_END_OF_LIST()
48804836414SPeter Maydell     },
48904836414SPeter Maydell     .subsections = (const VMStateDescription*[]) {
49004836414SPeter Maydell         &iotkit_sysctl_sse200_vmstate,
49104836414SPeter Maydell         NULL
49275750e4dSPeter Maydell     }
49375750e4dSPeter Maydell };
49475750e4dSPeter Maydell 
49504836414SPeter Maydell static Property iotkit_sysctl_props[] = {
49604836414SPeter Maydell     DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
497aab7a378SPeter Maydell     DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
498aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
499aab7a378SPeter Maydell                        0x10000000),
500aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
501aab7a378SPeter Maydell                        0x10000000),
50204836414SPeter Maydell     DEFINE_PROP_END_OF_LIST()
50304836414SPeter Maydell };
50404836414SPeter Maydell 
50575750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
50675750e4dSPeter Maydell {
50775750e4dSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
50875750e4dSPeter Maydell 
50975750e4dSPeter Maydell     dc->vmsd = &iotkit_sysctl_vmstate;
51075750e4dSPeter Maydell     dc->reset = iotkit_sysctl_reset;
511*4f67d30bSMarc-André Lureau     device_class_set_props(dc, iotkit_sysctl_props);
51204836414SPeter Maydell     dc->realize = iotkit_sysctl_realize;
51375750e4dSPeter Maydell }
51475750e4dSPeter Maydell 
51575750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = {
51675750e4dSPeter Maydell     .name = TYPE_IOTKIT_SYSCTL,
51775750e4dSPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
51875750e4dSPeter Maydell     .instance_size = sizeof(IoTKitSysCtl),
51975750e4dSPeter Maydell     .instance_init = iotkit_sysctl_init,
52075750e4dSPeter Maydell     .class_init = iotkit_sysctl_class_init,
52175750e4dSPeter Maydell };
52275750e4dSPeter Maydell 
52375750e4dSPeter Maydell static void iotkit_sysctl_register_types(void)
52475750e4dSPeter Maydell {
52575750e4dSPeter Maydell     type_register_static(&iotkit_sysctl_info);
52675750e4dSPeter Maydell }
52775750e4dSPeter Maydell 
52875750e4dSPeter Maydell type_init(iotkit_sysctl_register_types);
529