xref: /qemu/hw/misc/iotkit-sysctl.c (revision 0b8fa32f551e863bb548a11394239239270dd3dc)
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"
22*0b8fa32fSMarkus Armbruster #include "qemu/module.h"
2375750e4dSPeter Maydell #include "trace.h"
2475750e4dSPeter Maydell #include "qapi/error.h"
2575750e4dSPeter Maydell #include "sysemu/sysemu.h"
2675750e4dSPeter Maydell #include "hw/sysbus.h"
2775750e4dSPeter Maydell #include "hw/registerfields.h"
2875750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h"
290f862986SPeter Maydell #include "target/arm/arm-powerctl.h"
300f862986SPeter Maydell #include "target/arm/cpu.h"
3175750e4dSPeter Maydell 
3275750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0)
3375750e4dSPeter Maydell REG32(SECDBGSET, 0x4)
3475750e4dSPeter Maydell REG32(SECDBGCLR, 0x8)
3504836414SPeter Maydell REG32(SCSECCTRL, 0xc)
3604836414SPeter Maydell REG32(FCLK_DIV, 0x10)
3704836414SPeter Maydell REG32(SYSCLK_DIV, 0x14)
3804836414SPeter Maydell REG32(CLOCK_FORCE, 0x18)
3975750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100)
4075750e4dSPeter Maydell REG32(RESET_MASK, 0x104)
4175750e4dSPeter Maydell REG32(SWRESET, 0x108)
4275750e4dSPeter Maydell     FIELD(SWRESET, SWRESETREQ, 9, 1)
4375750e4dSPeter Maydell REG32(GRETREG, 0x10c)
44394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110)
4504836414SPeter Maydell REG32(INITSVTOR1, 0x114)
4675750e4dSPeter Maydell REG32(CPUWAIT, 0x118)
4704836414SPeter Maydell REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
4875750e4dSPeter Maydell REG32(WICCTRL, 0x120)
4904836414SPeter Maydell REG32(EWCTRL, 0x124)
5004836414SPeter Maydell REG32(PDCM_PD_SYS_SENSE, 0x200)
5104836414SPeter Maydell REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
5204836414SPeter Maydell REG32(PDCM_PD_SRAM1_SENSE, 0x210)
5304836414SPeter Maydell REG32(PDCM_PD_SRAM2_SENSE, 0x214)
5404836414SPeter Maydell REG32(PDCM_PD_SRAM3_SENSE, 0x218)
5575750e4dSPeter Maydell REG32(PID4, 0xfd0)
5675750e4dSPeter Maydell REG32(PID5, 0xfd4)
5775750e4dSPeter Maydell REG32(PID6, 0xfd8)
5875750e4dSPeter Maydell REG32(PID7, 0xfdc)
5975750e4dSPeter Maydell REG32(PID0, 0xfe0)
6075750e4dSPeter Maydell REG32(PID1, 0xfe4)
6175750e4dSPeter Maydell REG32(PID2, 0xfe8)
6275750e4dSPeter Maydell REG32(PID3, 0xfec)
6375750e4dSPeter Maydell REG32(CID0, 0xff0)
6475750e4dSPeter Maydell REG32(CID1, 0xff4)
6575750e4dSPeter Maydell REG32(CID2, 0xff8)
6675750e4dSPeter Maydell REG32(CID3, 0xffc)
6775750e4dSPeter Maydell 
6875750e4dSPeter Maydell /* PID/CID values */
6975750e4dSPeter Maydell static const int sysctl_id[] = {
7075750e4dSPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
7175750e4dSPeter Maydell     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
7275750e4dSPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
7375750e4dSPeter Maydell };
7475750e4dSPeter Maydell 
750f862986SPeter Maydell /*
760f862986SPeter Maydell  * Set the initial secure vector table offset address for the core.
770f862986SPeter Maydell  * This will take effect when the CPU next resets.
780f862986SPeter Maydell  */
790f862986SPeter Maydell static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
800f862986SPeter Maydell {
810f862986SPeter Maydell     Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
820f862986SPeter Maydell 
830f862986SPeter Maydell     if (cpuobj) {
840f862986SPeter Maydell         if (object_property_find(cpuobj, "init-svtor", NULL)) {
850f862986SPeter Maydell             object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort);
860f862986SPeter Maydell         }
870f862986SPeter Maydell     }
880f862986SPeter Maydell }
890f862986SPeter Maydell 
9075750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
9175750e4dSPeter Maydell                                     unsigned size)
9275750e4dSPeter Maydell {
9375750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
9475750e4dSPeter Maydell     uint64_t r;
9575750e4dSPeter Maydell 
9675750e4dSPeter Maydell     switch (offset) {
9775750e4dSPeter Maydell     case A_SECDBGSTAT:
9875750e4dSPeter Maydell         r = s->secure_debug;
9975750e4dSPeter Maydell         break;
10004836414SPeter Maydell     case A_SCSECCTRL:
10104836414SPeter Maydell         if (!s->is_sse200) {
10204836414SPeter Maydell             goto bad_offset;
10304836414SPeter Maydell         }
10404836414SPeter Maydell         r = s->scsecctrl;
10504836414SPeter Maydell         break;
10604836414SPeter Maydell     case A_FCLK_DIV:
10704836414SPeter Maydell         if (!s->is_sse200) {
10804836414SPeter Maydell             goto bad_offset;
10904836414SPeter Maydell         }
11004836414SPeter Maydell         r = s->fclk_div;
11104836414SPeter Maydell         break;
11204836414SPeter Maydell     case A_SYSCLK_DIV:
11304836414SPeter Maydell         if (!s->is_sse200) {
11404836414SPeter Maydell             goto bad_offset;
11504836414SPeter Maydell         }
11604836414SPeter Maydell         r = s->sysclk_div;
11704836414SPeter Maydell         break;
11804836414SPeter Maydell     case A_CLOCK_FORCE:
11904836414SPeter Maydell         if (!s->is_sse200) {
12004836414SPeter Maydell             goto bad_offset;
12104836414SPeter Maydell         }
12204836414SPeter Maydell         r = s->clock_force;
12304836414SPeter Maydell         break;
12475750e4dSPeter Maydell     case A_RESET_SYNDROME:
12575750e4dSPeter Maydell         r = s->reset_syndrome;
12675750e4dSPeter Maydell         break;
12775750e4dSPeter Maydell     case A_RESET_MASK:
12875750e4dSPeter Maydell         r = s->reset_mask;
12975750e4dSPeter Maydell         break;
13075750e4dSPeter Maydell     case A_GRETREG:
13175750e4dSPeter Maydell         r = s->gretreg;
13275750e4dSPeter Maydell         break;
133394e10d2SPeter Maydell     case A_INITSVTOR0:
134394e10d2SPeter Maydell         r = s->initsvtor0;
13575750e4dSPeter Maydell         break;
13604836414SPeter Maydell     case A_INITSVTOR1:
13704836414SPeter Maydell         if (!s->is_sse200) {
13804836414SPeter Maydell             goto bad_offset;
13904836414SPeter Maydell         }
14004836414SPeter Maydell         r = s->initsvtor1;
14104836414SPeter Maydell         break;
14275750e4dSPeter Maydell     case A_CPUWAIT:
14375750e4dSPeter Maydell         r = s->cpuwait;
14475750e4dSPeter Maydell         break;
14504836414SPeter Maydell     case A_NMI_ENABLE:
14604836414SPeter Maydell         /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
14704836414SPeter Maydell         if (!s->is_sse200) {
14875750e4dSPeter Maydell             r = 0;
14975750e4dSPeter Maydell             break;
15004836414SPeter Maydell         }
15104836414SPeter Maydell         r = s->nmi_enable;
15204836414SPeter Maydell         break;
15375750e4dSPeter Maydell     case A_WICCTRL:
15475750e4dSPeter Maydell         r = s->wicctrl;
15575750e4dSPeter Maydell         break;
15604836414SPeter Maydell     case A_EWCTRL:
15704836414SPeter Maydell         if (!s->is_sse200) {
15804836414SPeter Maydell             goto bad_offset;
15904836414SPeter Maydell         }
16004836414SPeter Maydell         r = s->ewctrl;
16104836414SPeter Maydell         break;
16204836414SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
16304836414SPeter Maydell         if (!s->is_sse200) {
16404836414SPeter Maydell             goto bad_offset;
16504836414SPeter Maydell         }
16604836414SPeter Maydell         r = s->pdcm_pd_sys_sense;
16704836414SPeter Maydell         break;
16804836414SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
16904836414SPeter Maydell         if (!s->is_sse200) {
17004836414SPeter Maydell             goto bad_offset;
17104836414SPeter Maydell         }
17204836414SPeter Maydell         r = s->pdcm_pd_sram0_sense;
17304836414SPeter Maydell         break;
17404836414SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
17504836414SPeter Maydell         if (!s->is_sse200) {
17604836414SPeter Maydell             goto bad_offset;
17704836414SPeter Maydell         }
17804836414SPeter Maydell         r = s->pdcm_pd_sram1_sense;
17904836414SPeter Maydell         break;
18004836414SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
18104836414SPeter Maydell         if (!s->is_sse200) {
18204836414SPeter Maydell             goto bad_offset;
18304836414SPeter Maydell         }
18404836414SPeter Maydell         r = s->pdcm_pd_sram2_sense;
18504836414SPeter Maydell         break;
18604836414SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
18704836414SPeter Maydell         if (!s->is_sse200) {
18804836414SPeter Maydell             goto bad_offset;
18904836414SPeter Maydell         }
19004836414SPeter Maydell         r = s->pdcm_pd_sram3_sense;
19104836414SPeter Maydell         break;
19275750e4dSPeter Maydell     case A_PID4 ... A_CID3:
19375750e4dSPeter Maydell         r = sysctl_id[(offset - A_PID4) / 4];
19475750e4dSPeter Maydell         break;
19575750e4dSPeter Maydell     case A_SECDBGSET:
19675750e4dSPeter Maydell     case A_SECDBGCLR:
19775750e4dSPeter Maydell     case A_SWRESET:
19875750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
19975750e4dSPeter Maydell                       "IoTKit SysCtl read: read of WO offset %x\n",
20075750e4dSPeter Maydell                       (int)offset);
20175750e4dSPeter Maydell         r = 0;
20275750e4dSPeter Maydell         break;
20375750e4dSPeter Maydell     default:
20404836414SPeter Maydell     bad_offset:
20575750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
20675750e4dSPeter Maydell                       "IoTKit SysCtl read: bad offset %x\n", (int)offset);
20775750e4dSPeter Maydell         r = 0;
20875750e4dSPeter Maydell         break;
20975750e4dSPeter Maydell     }
21075750e4dSPeter Maydell     trace_iotkit_sysctl_read(offset, r, size);
21175750e4dSPeter Maydell     return r;
21275750e4dSPeter Maydell }
21375750e4dSPeter Maydell 
21475750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset,
21575750e4dSPeter Maydell                                  uint64_t value, unsigned size)
21675750e4dSPeter Maydell {
21775750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
21875750e4dSPeter Maydell 
21975750e4dSPeter Maydell     trace_iotkit_sysctl_write(offset, value, size);
22075750e4dSPeter Maydell 
22175750e4dSPeter Maydell     /*
22275750e4dSPeter Maydell      * Most of the state here has to do with control of reset and
22375750e4dSPeter Maydell      * similar kinds of power up -- for instance the guest can ask
22475750e4dSPeter Maydell      * what the reason for the last reset was, or forbid reset for
22575750e4dSPeter Maydell      * some causes (like the non-secure watchdog). Most of this is
22675750e4dSPeter Maydell      * not relevant to QEMU, which doesn't really model anything other
22775750e4dSPeter Maydell      * than a full power-on reset.
22875750e4dSPeter Maydell      * We just model the registers as reads-as-written.
22975750e4dSPeter Maydell      */
23075750e4dSPeter Maydell 
23175750e4dSPeter Maydell     switch (offset) {
23275750e4dSPeter Maydell     case A_RESET_SYNDROME:
23375750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP,
23475750e4dSPeter Maydell                       "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
23575750e4dSPeter Maydell         s->reset_syndrome = value;
23675750e4dSPeter Maydell         break;
23775750e4dSPeter Maydell     case A_RESET_MASK:
23875750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
23975750e4dSPeter Maydell         s->reset_mask = value;
24075750e4dSPeter Maydell         break;
24175750e4dSPeter Maydell     case A_GRETREG:
24275750e4dSPeter Maydell         /*
24375750e4dSPeter Maydell          * General retention register, which is only reset by a power-on
24475750e4dSPeter Maydell          * reset. Technically this implementation is complete, since
24575750e4dSPeter Maydell          * QEMU only supports power-on resets...
24675750e4dSPeter Maydell          */
24775750e4dSPeter Maydell         s->gretreg = value;
24875750e4dSPeter Maydell         break;
249394e10d2SPeter Maydell     case A_INITSVTOR0:
250394e10d2SPeter Maydell         s->initsvtor0 = value;
2510f862986SPeter Maydell         set_init_vtor(0, s->initsvtor0);
25275750e4dSPeter Maydell         break;
25375750e4dSPeter Maydell     case A_CPUWAIT:
2540f862986SPeter Maydell         if ((s->cpuwait & 1) && !(value & 1)) {
2550f862986SPeter Maydell             /* Powering up CPU 0 */
2560f862986SPeter Maydell             arm_set_cpu_on_and_reset(0);
2570f862986SPeter Maydell         }
2580f862986SPeter Maydell         if ((s->cpuwait & 2) && !(value & 2)) {
2590f862986SPeter Maydell             /* Powering up CPU 1 */
2600f862986SPeter Maydell             arm_set_cpu_on_and_reset(1);
2610f862986SPeter Maydell         }
26275750e4dSPeter Maydell         s->cpuwait = value;
26375750e4dSPeter Maydell         break;
26475750e4dSPeter Maydell     case A_WICCTRL:
26575750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
26675750e4dSPeter Maydell         s->wicctrl = value;
26775750e4dSPeter Maydell         break;
26875750e4dSPeter Maydell     case A_SECDBGSET:
26975750e4dSPeter Maydell         /* write-1-to-set */
27075750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
27175750e4dSPeter Maydell         s->secure_debug |= value;
27275750e4dSPeter Maydell         break;
27375750e4dSPeter Maydell     case A_SECDBGCLR:
27475750e4dSPeter Maydell         /* write-1-to-clear */
27575750e4dSPeter Maydell         s->secure_debug &= ~value;
27675750e4dSPeter Maydell         break;
27775750e4dSPeter Maydell     case A_SWRESET:
27875750e4dSPeter Maydell         /* One w/o bit to request a reset; all other bits reserved */
27975750e4dSPeter Maydell         if (value & R_SWRESET_SWRESETREQ_MASK) {
28075750e4dSPeter Maydell             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
28175750e4dSPeter Maydell         }
28275750e4dSPeter Maydell         break;
28304836414SPeter Maydell     case A_SCSECCTRL:
28404836414SPeter Maydell         if (!s->is_sse200) {
28504836414SPeter Maydell             goto bad_offset;
28604836414SPeter Maydell         }
28704836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
28804836414SPeter Maydell         s->scsecctrl = value;
28904836414SPeter Maydell         break;
29004836414SPeter Maydell     case A_FCLK_DIV:
29104836414SPeter Maydell         if (!s->is_sse200) {
29204836414SPeter Maydell             goto bad_offset;
29304836414SPeter Maydell         }
29404836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
29504836414SPeter Maydell         s->fclk_div = value;
29604836414SPeter Maydell         break;
29704836414SPeter Maydell     case A_SYSCLK_DIV:
29804836414SPeter Maydell         if (!s->is_sse200) {
29904836414SPeter Maydell             goto bad_offset;
30004836414SPeter Maydell         }
30104836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
30204836414SPeter Maydell         s->sysclk_div = value;
30304836414SPeter Maydell         break;
30404836414SPeter Maydell     case A_CLOCK_FORCE:
30504836414SPeter Maydell         if (!s->is_sse200) {
30604836414SPeter Maydell             goto bad_offset;
30704836414SPeter Maydell         }
30804836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
30904836414SPeter Maydell         s->clock_force = value;
31004836414SPeter Maydell         break;
31104836414SPeter Maydell     case A_INITSVTOR1:
31204836414SPeter Maydell         if (!s->is_sse200) {
31304836414SPeter Maydell             goto bad_offset;
31404836414SPeter Maydell         }
31504836414SPeter Maydell         s->initsvtor1 = value;
3160f862986SPeter Maydell         set_init_vtor(1, s->initsvtor1);
31704836414SPeter Maydell         break;
31804836414SPeter Maydell     case A_EWCTRL:
31904836414SPeter Maydell         if (!s->is_sse200) {
32004836414SPeter Maydell             goto bad_offset;
32104836414SPeter Maydell         }
32204836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
32304836414SPeter Maydell         s->ewctrl = value;
32404836414SPeter Maydell         break;
32504836414SPeter Maydell     case A_PDCM_PD_SYS_SENSE:
32604836414SPeter Maydell         if (!s->is_sse200) {
32704836414SPeter Maydell             goto bad_offset;
32804836414SPeter Maydell         }
32904836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
33004836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
33104836414SPeter Maydell         s->pdcm_pd_sys_sense = value;
33204836414SPeter Maydell         break;
33304836414SPeter Maydell     case A_PDCM_PD_SRAM0_SENSE:
33404836414SPeter Maydell         if (!s->is_sse200) {
33504836414SPeter Maydell             goto bad_offset;
33604836414SPeter Maydell         }
33704836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
33804836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
33904836414SPeter Maydell         s->pdcm_pd_sram0_sense = value;
34004836414SPeter Maydell         break;
34104836414SPeter Maydell     case A_PDCM_PD_SRAM1_SENSE:
34204836414SPeter Maydell         if (!s->is_sse200) {
34304836414SPeter Maydell             goto bad_offset;
34404836414SPeter Maydell         }
34504836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
34604836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
34704836414SPeter Maydell         s->pdcm_pd_sram1_sense = value;
34804836414SPeter Maydell         break;
34904836414SPeter Maydell     case A_PDCM_PD_SRAM2_SENSE:
35004836414SPeter Maydell         if (!s->is_sse200) {
35104836414SPeter Maydell             goto bad_offset;
35204836414SPeter Maydell         }
35304836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
35404836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
35504836414SPeter Maydell         s->pdcm_pd_sram2_sense = value;
35604836414SPeter Maydell         break;
35704836414SPeter Maydell     case A_PDCM_PD_SRAM3_SENSE:
35804836414SPeter Maydell         if (!s->is_sse200) {
35904836414SPeter Maydell             goto bad_offset;
36004836414SPeter Maydell         }
36104836414SPeter Maydell         qemu_log_mask(LOG_UNIMP,
36204836414SPeter Maydell                       "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
36304836414SPeter Maydell         s->pdcm_pd_sram3_sense = value;
36404836414SPeter Maydell         break;
36504836414SPeter Maydell     case A_NMI_ENABLE:
36604836414SPeter Maydell         /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
36704836414SPeter Maydell         if (!s->is_sse200) {
36804836414SPeter Maydell             goto ro_offset;
36904836414SPeter Maydell         }
37004836414SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
37104836414SPeter Maydell         s->nmi_enable = value;
37204836414SPeter Maydell         break;
37375750e4dSPeter Maydell     case A_SECDBGSTAT:
37475750e4dSPeter Maydell     case A_PID4 ... A_CID3:
37504836414SPeter Maydell     ro_offset:
37675750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
37775750e4dSPeter Maydell                       "IoTKit SysCtl write: write of RO offset %x\n",
37875750e4dSPeter Maydell                       (int)offset);
37975750e4dSPeter Maydell         break;
38075750e4dSPeter Maydell     default:
38104836414SPeter Maydell     bad_offset:
38275750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
38375750e4dSPeter Maydell                       "IoTKit SysCtl write: bad offset %x\n", (int)offset);
38475750e4dSPeter Maydell         break;
38575750e4dSPeter Maydell     }
38675750e4dSPeter Maydell }
38775750e4dSPeter Maydell 
38875750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = {
38975750e4dSPeter Maydell     .read = iotkit_sysctl_read,
39075750e4dSPeter Maydell     .write = iotkit_sysctl_write,
39175750e4dSPeter Maydell     .endianness = DEVICE_LITTLE_ENDIAN,
39275750e4dSPeter Maydell     /* byte/halfword accesses are just zero-padded on reads and writes */
39375750e4dSPeter Maydell     .impl.min_access_size = 4,
39475750e4dSPeter Maydell     .impl.max_access_size = 4,
39575750e4dSPeter Maydell     .valid.min_access_size = 1,
39675750e4dSPeter Maydell     .valid.max_access_size = 4,
39775750e4dSPeter Maydell };
39875750e4dSPeter Maydell 
39975750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev)
40075750e4dSPeter Maydell {
40175750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
40275750e4dSPeter Maydell 
40375750e4dSPeter Maydell     trace_iotkit_sysctl_reset();
40475750e4dSPeter Maydell     s->secure_debug = 0;
40575750e4dSPeter Maydell     s->reset_syndrome = 1;
40675750e4dSPeter Maydell     s->reset_mask = 0;
40775750e4dSPeter Maydell     s->gretreg = 0;
408aab7a378SPeter Maydell     s->initsvtor0 = s->initsvtor0_rst;
409aab7a378SPeter Maydell     s->initsvtor1 = s->initsvtor1_rst;
410aab7a378SPeter Maydell     s->cpuwait = s->cpuwait_rst;
41175750e4dSPeter Maydell     s->wicctrl = 0;
41204836414SPeter Maydell     s->scsecctrl = 0;
41304836414SPeter Maydell     s->fclk_div = 0;
41404836414SPeter Maydell     s->sysclk_div = 0;
41504836414SPeter Maydell     s->clock_force = 0;
41604836414SPeter Maydell     s->nmi_enable = 0;
41704836414SPeter Maydell     s->ewctrl = 0;
41804836414SPeter Maydell     s->pdcm_pd_sys_sense = 0x7f;
41904836414SPeter Maydell     s->pdcm_pd_sram0_sense = 0;
42004836414SPeter Maydell     s->pdcm_pd_sram1_sense = 0;
42104836414SPeter Maydell     s->pdcm_pd_sram2_sense = 0;
42204836414SPeter Maydell     s->pdcm_pd_sram3_sense = 0;
42375750e4dSPeter Maydell }
42475750e4dSPeter Maydell 
42575750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj)
42675750e4dSPeter Maydell {
42775750e4dSPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
42875750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
42975750e4dSPeter Maydell 
43075750e4dSPeter Maydell     memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
43175750e4dSPeter Maydell                           s, "iotkit-sysctl", 0x1000);
43275750e4dSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem);
43375750e4dSPeter Maydell }
43475750e4dSPeter Maydell 
43504836414SPeter Maydell static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
43604836414SPeter Maydell {
43704836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
43804836414SPeter Maydell 
43904836414SPeter Maydell     /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
44004836414SPeter Maydell     if (extract32(s->sys_version, 28, 4) == 2) {
44104836414SPeter Maydell         s->is_sse200 = true;
44204836414SPeter Maydell     }
44304836414SPeter Maydell }
44404836414SPeter Maydell 
44504836414SPeter Maydell static bool sse200_needed(void *opaque)
44604836414SPeter Maydell {
44704836414SPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
44804836414SPeter Maydell 
44904836414SPeter Maydell     return s->is_sse200;
45004836414SPeter Maydell }
45104836414SPeter Maydell 
45204836414SPeter Maydell static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
45304836414SPeter Maydell     .name = "iotkit-sysctl/sse-200",
45404836414SPeter Maydell     .version_id = 1,
45504836414SPeter Maydell     .minimum_version_id = 1,
45604836414SPeter Maydell     .needed = sse200_needed,
45704836414SPeter Maydell     .fields = (VMStateField[]) {
45804836414SPeter Maydell         VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
45904836414SPeter Maydell         VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
46004836414SPeter Maydell         VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
46104836414SPeter Maydell         VMSTATE_UINT32(clock_force, IoTKitSysCtl),
46204836414SPeter Maydell         VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
46304836414SPeter Maydell         VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
46404836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
46504836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
46604836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
46704836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
46804836414SPeter Maydell         VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
46904836414SPeter Maydell         VMSTATE_END_OF_LIST()
47004836414SPeter Maydell     }
47104836414SPeter Maydell };
47204836414SPeter Maydell 
47375750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = {
47475750e4dSPeter Maydell     .name = "iotkit-sysctl",
47575750e4dSPeter Maydell     .version_id = 1,
47675750e4dSPeter Maydell     .minimum_version_id = 1,
47775750e4dSPeter Maydell     .fields = (VMStateField[]) {
47875750e4dSPeter Maydell         VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
47975750e4dSPeter Maydell         VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
48075750e4dSPeter Maydell         VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
48175750e4dSPeter Maydell         VMSTATE_UINT32(gretreg, IoTKitSysCtl),
482394e10d2SPeter Maydell         VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
48375750e4dSPeter Maydell         VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
48475750e4dSPeter Maydell         VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
48575750e4dSPeter Maydell         VMSTATE_END_OF_LIST()
48604836414SPeter Maydell     },
48704836414SPeter Maydell     .subsections = (const VMStateDescription*[]) {
48804836414SPeter Maydell         &iotkit_sysctl_sse200_vmstate,
48904836414SPeter Maydell         NULL
49075750e4dSPeter Maydell     }
49175750e4dSPeter Maydell };
49275750e4dSPeter Maydell 
49304836414SPeter Maydell static Property iotkit_sysctl_props[] = {
49404836414SPeter Maydell     DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
495aab7a378SPeter Maydell     DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
496aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
497aab7a378SPeter Maydell                        0x10000000),
498aab7a378SPeter Maydell     DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
499aab7a378SPeter Maydell                        0x10000000),
50004836414SPeter Maydell     DEFINE_PROP_END_OF_LIST()
50104836414SPeter Maydell };
50204836414SPeter Maydell 
50375750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
50475750e4dSPeter Maydell {
50575750e4dSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
50675750e4dSPeter Maydell 
50775750e4dSPeter Maydell     dc->vmsd = &iotkit_sysctl_vmstate;
50875750e4dSPeter Maydell     dc->reset = iotkit_sysctl_reset;
50904836414SPeter Maydell     dc->props = iotkit_sysctl_props;
51004836414SPeter Maydell     dc->realize = iotkit_sysctl_realize;
51175750e4dSPeter Maydell }
51275750e4dSPeter Maydell 
51375750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = {
51475750e4dSPeter Maydell     .name = TYPE_IOTKIT_SYSCTL,
51575750e4dSPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
51675750e4dSPeter Maydell     .instance_size = sizeof(IoTKitSysCtl),
51775750e4dSPeter Maydell     .instance_init = iotkit_sysctl_init,
51875750e4dSPeter Maydell     .class_init = iotkit_sysctl_class_init,
51975750e4dSPeter Maydell };
52075750e4dSPeter Maydell 
52175750e4dSPeter Maydell static void iotkit_sysctl_register_types(void)
52275750e4dSPeter Maydell {
52375750e4dSPeter Maydell     type_register_static(&iotkit_sysctl_info);
52475750e4dSPeter Maydell }
52575750e4dSPeter Maydell 
52675750e4dSPeter Maydell type_init(iotkit_sysctl_register_types);
527