xref: /qemu/hw/misc/iotkit-sysctl.c (revision 394e10d2bb300e4445b0ce37f6d138302f2ff04e)
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"
2075750e4dSPeter Maydell #include "qemu/log.h"
2175750e4dSPeter Maydell #include "trace.h"
2275750e4dSPeter Maydell #include "qapi/error.h"
2375750e4dSPeter Maydell #include "sysemu/sysemu.h"
2475750e4dSPeter Maydell #include "hw/sysbus.h"
2575750e4dSPeter Maydell #include "hw/registerfields.h"
2675750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h"
2775750e4dSPeter Maydell 
2875750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0)
2975750e4dSPeter Maydell REG32(SECDBGSET, 0x4)
3075750e4dSPeter Maydell REG32(SECDBGCLR, 0x8)
3175750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100)
3275750e4dSPeter Maydell REG32(RESET_MASK, 0x104)
3375750e4dSPeter Maydell REG32(SWRESET, 0x108)
3475750e4dSPeter Maydell     FIELD(SWRESET, SWRESETREQ, 9, 1)
3575750e4dSPeter Maydell REG32(GRETREG, 0x10c)
36*394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110)
3775750e4dSPeter Maydell REG32(CPUWAIT, 0x118)
3875750e4dSPeter Maydell REG32(BUSWAIT, 0x11c)
3975750e4dSPeter Maydell REG32(WICCTRL, 0x120)
4075750e4dSPeter Maydell REG32(PID4, 0xfd0)
4175750e4dSPeter Maydell REG32(PID5, 0xfd4)
4275750e4dSPeter Maydell REG32(PID6, 0xfd8)
4375750e4dSPeter Maydell REG32(PID7, 0xfdc)
4475750e4dSPeter Maydell REG32(PID0, 0xfe0)
4575750e4dSPeter Maydell REG32(PID1, 0xfe4)
4675750e4dSPeter Maydell REG32(PID2, 0xfe8)
4775750e4dSPeter Maydell REG32(PID3, 0xfec)
4875750e4dSPeter Maydell REG32(CID0, 0xff0)
4975750e4dSPeter Maydell REG32(CID1, 0xff4)
5075750e4dSPeter Maydell REG32(CID2, 0xff8)
5175750e4dSPeter Maydell REG32(CID3, 0xffc)
5275750e4dSPeter Maydell 
5375750e4dSPeter Maydell /* PID/CID values */
5475750e4dSPeter Maydell static const int sysctl_id[] = {
5575750e4dSPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
5675750e4dSPeter Maydell     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
5775750e4dSPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
5875750e4dSPeter Maydell };
5975750e4dSPeter Maydell 
6075750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
6175750e4dSPeter Maydell                                     unsigned size)
6275750e4dSPeter Maydell {
6375750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
6475750e4dSPeter Maydell     uint64_t r;
6575750e4dSPeter Maydell 
6675750e4dSPeter Maydell     switch (offset) {
6775750e4dSPeter Maydell     case A_SECDBGSTAT:
6875750e4dSPeter Maydell         r = s->secure_debug;
6975750e4dSPeter Maydell         break;
7075750e4dSPeter Maydell     case A_RESET_SYNDROME:
7175750e4dSPeter Maydell         r = s->reset_syndrome;
7275750e4dSPeter Maydell         break;
7375750e4dSPeter Maydell     case A_RESET_MASK:
7475750e4dSPeter Maydell         r = s->reset_mask;
7575750e4dSPeter Maydell         break;
7675750e4dSPeter Maydell     case A_GRETREG:
7775750e4dSPeter Maydell         r = s->gretreg;
7875750e4dSPeter Maydell         break;
79*394e10d2SPeter Maydell     case A_INITSVTOR0:
80*394e10d2SPeter Maydell         r = s->initsvtor0;
8175750e4dSPeter Maydell         break;
8275750e4dSPeter Maydell     case A_CPUWAIT:
8375750e4dSPeter Maydell         r = s->cpuwait;
8475750e4dSPeter Maydell         break;
8575750e4dSPeter Maydell     case A_BUSWAIT:
8675750e4dSPeter Maydell         /* In IoTKit BUSWAIT is reserved, R/O, zero */
8775750e4dSPeter Maydell         r = 0;
8875750e4dSPeter Maydell         break;
8975750e4dSPeter Maydell     case A_WICCTRL:
9075750e4dSPeter Maydell         r = s->wicctrl;
9175750e4dSPeter Maydell         break;
9275750e4dSPeter Maydell     case A_PID4 ... A_CID3:
9375750e4dSPeter Maydell         r = sysctl_id[(offset - A_PID4) / 4];
9475750e4dSPeter Maydell         break;
9575750e4dSPeter Maydell     case A_SECDBGSET:
9675750e4dSPeter Maydell     case A_SECDBGCLR:
9775750e4dSPeter Maydell     case A_SWRESET:
9875750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
9975750e4dSPeter Maydell                       "IoTKit SysCtl read: read of WO offset %x\n",
10075750e4dSPeter Maydell                       (int)offset);
10175750e4dSPeter Maydell         r = 0;
10275750e4dSPeter Maydell         break;
10375750e4dSPeter Maydell     default:
10475750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
10575750e4dSPeter Maydell                       "IoTKit SysCtl read: bad offset %x\n", (int)offset);
10675750e4dSPeter Maydell         r = 0;
10775750e4dSPeter Maydell         break;
10875750e4dSPeter Maydell     }
10975750e4dSPeter Maydell     trace_iotkit_sysctl_read(offset, r, size);
11075750e4dSPeter Maydell     return r;
11175750e4dSPeter Maydell }
11275750e4dSPeter Maydell 
11375750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset,
11475750e4dSPeter Maydell                                  uint64_t value, unsigned size)
11575750e4dSPeter Maydell {
11675750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
11775750e4dSPeter Maydell 
11875750e4dSPeter Maydell     trace_iotkit_sysctl_write(offset, value, size);
11975750e4dSPeter Maydell 
12075750e4dSPeter Maydell     /*
12175750e4dSPeter Maydell      * Most of the state here has to do with control of reset and
12275750e4dSPeter Maydell      * similar kinds of power up -- for instance the guest can ask
12375750e4dSPeter Maydell      * what the reason for the last reset was, or forbid reset for
12475750e4dSPeter Maydell      * some causes (like the non-secure watchdog). Most of this is
12575750e4dSPeter Maydell      * not relevant to QEMU, which doesn't really model anything other
12675750e4dSPeter Maydell      * than a full power-on reset.
12775750e4dSPeter Maydell      * We just model the registers as reads-as-written.
12875750e4dSPeter Maydell      */
12975750e4dSPeter Maydell 
13075750e4dSPeter Maydell     switch (offset) {
13175750e4dSPeter Maydell     case A_RESET_SYNDROME:
13275750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP,
13375750e4dSPeter Maydell                       "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
13475750e4dSPeter Maydell         s->reset_syndrome = value;
13575750e4dSPeter Maydell         break;
13675750e4dSPeter Maydell     case A_RESET_MASK:
13775750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
13875750e4dSPeter Maydell         s->reset_mask = value;
13975750e4dSPeter Maydell         break;
14075750e4dSPeter Maydell     case A_GRETREG:
14175750e4dSPeter Maydell         /*
14275750e4dSPeter Maydell          * General retention register, which is only reset by a power-on
14375750e4dSPeter Maydell          * reset. Technically this implementation is complete, since
14475750e4dSPeter Maydell          * QEMU only supports power-on resets...
14575750e4dSPeter Maydell          */
14675750e4dSPeter Maydell         s->gretreg = value;
14775750e4dSPeter Maydell         break;
148*394e10d2SPeter Maydell     case A_INITSVTOR0:
149*394e10d2SPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVTOR0 unimplemented\n");
150*394e10d2SPeter Maydell         s->initsvtor0 = value;
15175750e4dSPeter Maydell         break;
15275750e4dSPeter Maydell     case A_CPUWAIT:
15375750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
15475750e4dSPeter Maydell         s->cpuwait = value;
15575750e4dSPeter Maydell         break;
15675750e4dSPeter Maydell     case A_WICCTRL:
15775750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
15875750e4dSPeter Maydell         s->wicctrl = value;
15975750e4dSPeter Maydell         break;
16075750e4dSPeter Maydell     case A_SECDBGSET:
16175750e4dSPeter Maydell         /* write-1-to-set */
16275750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
16375750e4dSPeter Maydell         s->secure_debug |= value;
16475750e4dSPeter Maydell         break;
16575750e4dSPeter Maydell     case A_SECDBGCLR:
16675750e4dSPeter Maydell         /* write-1-to-clear */
16775750e4dSPeter Maydell         s->secure_debug &= ~value;
16875750e4dSPeter Maydell         break;
16975750e4dSPeter Maydell     case A_SWRESET:
17075750e4dSPeter Maydell         /* One w/o bit to request a reset; all other bits reserved */
17175750e4dSPeter Maydell         if (value & R_SWRESET_SWRESETREQ_MASK) {
17275750e4dSPeter Maydell             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
17375750e4dSPeter Maydell         }
17475750e4dSPeter Maydell         break;
17575750e4dSPeter Maydell     case A_BUSWAIT:        /* In IoTKit BUSWAIT is reserved, R/O, zero */
17675750e4dSPeter Maydell     case A_SECDBGSTAT:
17775750e4dSPeter Maydell     case A_PID4 ... A_CID3:
17875750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
17975750e4dSPeter Maydell                       "IoTKit SysCtl write: write of RO offset %x\n",
18075750e4dSPeter Maydell                       (int)offset);
18175750e4dSPeter Maydell         break;
18275750e4dSPeter Maydell     default:
18375750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
18475750e4dSPeter Maydell                       "IoTKit SysCtl write: bad offset %x\n", (int)offset);
18575750e4dSPeter Maydell         break;
18675750e4dSPeter Maydell     }
18775750e4dSPeter Maydell }
18875750e4dSPeter Maydell 
18975750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = {
19075750e4dSPeter Maydell     .read = iotkit_sysctl_read,
19175750e4dSPeter Maydell     .write = iotkit_sysctl_write,
19275750e4dSPeter Maydell     .endianness = DEVICE_LITTLE_ENDIAN,
19375750e4dSPeter Maydell     /* byte/halfword accesses are just zero-padded on reads and writes */
19475750e4dSPeter Maydell     .impl.min_access_size = 4,
19575750e4dSPeter Maydell     .impl.max_access_size = 4,
19675750e4dSPeter Maydell     .valid.min_access_size = 1,
19775750e4dSPeter Maydell     .valid.max_access_size = 4,
19875750e4dSPeter Maydell };
19975750e4dSPeter Maydell 
20075750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev)
20175750e4dSPeter Maydell {
20275750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
20375750e4dSPeter Maydell 
20475750e4dSPeter Maydell     trace_iotkit_sysctl_reset();
20575750e4dSPeter Maydell     s->secure_debug = 0;
20675750e4dSPeter Maydell     s->reset_syndrome = 1;
20775750e4dSPeter Maydell     s->reset_mask = 0;
20875750e4dSPeter Maydell     s->gretreg = 0;
209*394e10d2SPeter Maydell     s->initsvtor0 = 0x10000000;
21075750e4dSPeter Maydell     s->cpuwait = 0;
21175750e4dSPeter Maydell     s->wicctrl = 0;
21275750e4dSPeter Maydell }
21375750e4dSPeter Maydell 
21475750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj)
21575750e4dSPeter Maydell {
21675750e4dSPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
21775750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
21875750e4dSPeter Maydell 
21975750e4dSPeter Maydell     memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
22075750e4dSPeter Maydell                           s, "iotkit-sysctl", 0x1000);
22175750e4dSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem);
22275750e4dSPeter Maydell }
22375750e4dSPeter Maydell 
22475750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = {
22575750e4dSPeter Maydell     .name = "iotkit-sysctl",
22675750e4dSPeter Maydell     .version_id = 1,
22775750e4dSPeter Maydell     .minimum_version_id = 1,
22875750e4dSPeter Maydell     .fields = (VMStateField[]) {
22975750e4dSPeter Maydell         VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
23075750e4dSPeter Maydell         VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
23175750e4dSPeter Maydell         VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
23275750e4dSPeter Maydell         VMSTATE_UINT32(gretreg, IoTKitSysCtl),
233*394e10d2SPeter Maydell         VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
23475750e4dSPeter Maydell         VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
23575750e4dSPeter Maydell         VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
23675750e4dSPeter Maydell         VMSTATE_END_OF_LIST()
23775750e4dSPeter Maydell     }
23875750e4dSPeter Maydell };
23975750e4dSPeter Maydell 
24075750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
24175750e4dSPeter Maydell {
24275750e4dSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
24375750e4dSPeter Maydell 
24475750e4dSPeter Maydell     dc->vmsd = &iotkit_sysctl_vmstate;
24575750e4dSPeter Maydell     dc->reset = iotkit_sysctl_reset;
24675750e4dSPeter Maydell }
24775750e4dSPeter Maydell 
24875750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = {
24975750e4dSPeter Maydell     .name = TYPE_IOTKIT_SYSCTL,
25075750e4dSPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
25175750e4dSPeter Maydell     .instance_size = sizeof(IoTKitSysCtl),
25275750e4dSPeter Maydell     .instance_init = iotkit_sysctl_init,
25375750e4dSPeter Maydell     .class_init = iotkit_sysctl_class_init,
25475750e4dSPeter Maydell };
25575750e4dSPeter Maydell 
25675750e4dSPeter Maydell static void iotkit_sysctl_register_types(void)
25775750e4dSPeter Maydell {
25875750e4dSPeter Maydell     type_register_static(&iotkit_sysctl_info);
25975750e4dSPeter Maydell }
26075750e4dSPeter Maydell 
26175750e4dSPeter Maydell type_init(iotkit_sysctl_register_types);
262