xref: /qemu/hw/misc/iotkit-sysctl.c (revision 75750e4d43c9c62d26d2b218a1e8c2f8efdf16c4)
1*75750e4dSPeter Maydell /*
2*75750e4dSPeter Maydell  * ARM IoTKit system control element
3*75750e4dSPeter Maydell  *
4*75750e4dSPeter Maydell  * Copyright (c) 2018 Linaro Limited
5*75750e4dSPeter Maydell  * Written by Peter Maydell
6*75750e4dSPeter Maydell  *
7*75750e4dSPeter Maydell  *  This program is free software; you can redistribute it and/or modify
8*75750e4dSPeter Maydell  *  it under the terms of the GNU General Public License version 2 or
9*75750e4dSPeter Maydell  *  (at your option) any later version.
10*75750e4dSPeter Maydell  */
11*75750e4dSPeter Maydell 
12*75750e4dSPeter Maydell /*
13*75750e4dSPeter Maydell  * This is a model of the "system control element" which is part of the
14*75750e4dSPeter Maydell  * Arm IoTKit and documented in
15*75750e4dSPeter Maydell  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
16*75750e4dSPeter Maydell  * Specifically, it implements the "system control register" blocks.
17*75750e4dSPeter Maydell  */
18*75750e4dSPeter Maydell 
19*75750e4dSPeter Maydell #include "qemu/osdep.h"
20*75750e4dSPeter Maydell #include "qemu/log.h"
21*75750e4dSPeter Maydell #include "trace.h"
22*75750e4dSPeter Maydell #include "qapi/error.h"
23*75750e4dSPeter Maydell #include "sysemu/sysemu.h"
24*75750e4dSPeter Maydell #include "hw/sysbus.h"
25*75750e4dSPeter Maydell #include "hw/registerfields.h"
26*75750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h"
27*75750e4dSPeter Maydell 
28*75750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0)
29*75750e4dSPeter Maydell REG32(SECDBGSET, 0x4)
30*75750e4dSPeter Maydell REG32(SECDBGCLR, 0x8)
31*75750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100)
32*75750e4dSPeter Maydell REG32(RESET_MASK, 0x104)
33*75750e4dSPeter Maydell REG32(SWRESET, 0x108)
34*75750e4dSPeter Maydell     FIELD(SWRESET, SWRESETREQ, 9, 1)
35*75750e4dSPeter Maydell REG32(GRETREG, 0x10c)
36*75750e4dSPeter Maydell REG32(INITSVRTOR0, 0x110)
37*75750e4dSPeter Maydell REG32(CPUWAIT, 0x118)
38*75750e4dSPeter Maydell REG32(BUSWAIT, 0x11c)
39*75750e4dSPeter Maydell REG32(WICCTRL, 0x120)
40*75750e4dSPeter Maydell REG32(PID4, 0xfd0)
41*75750e4dSPeter Maydell REG32(PID5, 0xfd4)
42*75750e4dSPeter Maydell REG32(PID6, 0xfd8)
43*75750e4dSPeter Maydell REG32(PID7, 0xfdc)
44*75750e4dSPeter Maydell REG32(PID0, 0xfe0)
45*75750e4dSPeter Maydell REG32(PID1, 0xfe4)
46*75750e4dSPeter Maydell REG32(PID2, 0xfe8)
47*75750e4dSPeter Maydell REG32(PID3, 0xfec)
48*75750e4dSPeter Maydell REG32(CID0, 0xff0)
49*75750e4dSPeter Maydell REG32(CID1, 0xff4)
50*75750e4dSPeter Maydell REG32(CID2, 0xff8)
51*75750e4dSPeter Maydell REG32(CID3, 0xffc)
52*75750e4dSPeter Maydell 
53*75750e4dSPeter Maydell /* PID/CID values */
54*75750e4dSPeter Maydell static const int sysctl_id[] = {
55*75750e4dSPeter Maydell     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
56*75750e4dSPeter Maydell     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
57*75750e4dSPeter Maydell     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
58*75750e4dSPeter Maydell };
59*75750e4dSPeter Maydell 
60*75750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
61*75750e4dSPeter Maydell                                     unsigned size)
62*75750e4dSPeter Maydell {
63*75750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
64*75750e4dSPeter Maydell     uint64_t r;
65*75750e4dSPeter Maydell 
66*75750e4dSPeter Maydell     switch (offset) {
67*75750e4dSPeter Maydell     case A_SECDBGSTAT:
68*75750e4dSPeter Maydell         r = s->secure_debug;
69*75750e4dSPeter Maydell         break;
70*75750e4dSPeter Maydell     case A_RESET_SYNDROME:
71*75750e4dSPeter Maydell         r = s->reset_syndrome;
72*75750e4dSPeter Maydell         break;
73*75750e4dSPeter Maydell     case A_RESET_MASK:
74*75750e4dSPeter Maydell         r = s->reset_mask;
75*75750e4dSPeter Maydell         break;
76*75750e4dSPeter Maydell     case A_GRETREG:
77*75750e4dSPeter Maydell         r = s->gretreg;
78*75750e4dSPeter Maydell         break;
79*75750e4dSPeter Maydell     case A_INITSVRTOR0:
80*75750e4dSPeter Maydell         r = s->initsvrtor0;
81*75750e4dSPeter Maydell         break;
82*75750e4dSPeter Maydell     case A_CPUWAIT:
83*75750e4dSPeter Maydell         r = s->cpuwait;
84*75750e4dSPeter Maydell         break;
85*75750e4dSPeter Maydell     case A_BUSWAIT:
86*75750e4dSPeter Maydell         /* In IoTKit BUSWAIT is reserved, R/O, zero */
87*75750e4dSPeter Maydell         r = 0;
88*75750e4dSPeter Maydell         break;
89*75750e4dSPeter Maydell     case A_WICCTRL:
90*75750e4dSPeter Maydell         r = s->wicctrl;
91*75750e4dSPeter Maydell         break;
92*75750e4dSPeter Maydell     case A_PID4 ... A_CID3:
93*75750e4dSPeter Maydell         r = sysctl_id[(offset - A_PID4) / 4];
94*75750e4dSPeter Maydell         break;
95*75750e4dSPeter Maydell     case A_SECDBGSET:
96*75750e4dSPeter Maydell     case A_SECDBGCLR:
97*75750e4dSPeter Maydell     case A_SWRESET:
98*75750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
99*75750e4dSPeter Maydell                       "IoTKit SysCtl read: read of WO offset %x\n",
100*75750e4dSPeter Maydell                       (int)offset);
101*75750e4dSPeter Maydell         r = 0;
102*75750e4dSPeter Maydell         break;
103*75750e4dSPeter Maydell     default:
104*75750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
105*75750e4dSPeter Maydell                       "IoTKit SysCtl read: bad offset %x\n", (int)offset);
106*75750e4dSPeter Maydell         r = 0;
107*75750e4dSPeter Maydell         break;
108*75750e4dSPeter Maydell     }
109*75750e4dSPeter Maydell     trace_iotkit_sysctl_read(offset, r, size);
110*75750e4dSPeter Maydell     return r;
111*75750e4dSPeter Maydell }
112*75750e4dSPeter Maydell 
113*75750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset,
114*75750e4dSPeter Maydell                                  uint64_t value, unsigned size)
115*75750e4dSPeter Maydell {
116*75750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
117*75750e4dSPeter Maydell 
118*75750e4dSPeter Maydell     trace_iotkit_sysctl_write(offset, value, size);
119*75750e4dSPeter Maydell 
120*75750e4dSPeter Maydell     /*
121*75750e4dSPeter Maydell      * Most of the state here has to do with control of reset and
122*75750e4dSPeter Maydell      * similar kinds of power up -- for instance the guest can ask
123*75750e4dSPeter Maydell      * what the reason for the last reset was, or forbid reset for
124*75750e4dSPeter Maydell      * some causes (like the non-secure watchdog). Most of this is
125*75750e4dSPeter Maydell      * not relevant to QEMU, which doesn't really model anything other
126*75750e4dSPeter Maydell      * than a full power-on reset.
127*75750e4dSPeter Maydell      * We just model the registers as reads-as-written.
128*75750e4dSPeter Maydell      */
129*75750e4dSPeter Maydell 
130*75750e4dSPeter Maydell     switch (offset) {
131*75750e4dSPeter Maydell     case A_RESET_SYNDROME:
132*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP,
133*75750e4dSPeter Maydell                       "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
134*75750e4dSPeter Maydell         s->reset_syndrome = value;
135*75750e4dSPeter Maydell         break;
136*75750e4dSPeter Maydell     case A_RESET_MASK:
137*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
138*75750e4dSPeter Maydell         s->reset_mask = value;
139*75750e4dSPeter Maydell         break;
140*75750e4dSPeter Maydell     case A_GRETREG:
141*75750e4dSPeter Maydell         /*
142*75750e4dSPeter Maydell          * General retention register, which is only reset by a power-on
143*75750e4dSPeter Maydell          * reset. Technically this implementation is complete, since
144*75750e4dSPeter Maydell          * QEMU only supports power-on resets...
145*75750e4dSPeter Maydell          */
146*75750e4dSPeter Maydell         s->gretreg = value;
147*75750e4dSPeter Maydell         break;
148*75750e4dSPeter Maydell     case A_INITSVRTOR0:
149*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\n");
150*75750e4dSPeter Maydell         s->initsvrtor0 = value;
151*75750e4dSPeter Maydell         break;
152*75750e4dSPeter Maydell     case A_CPUWAIT:
153*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n");
154*75750e4dSPeter Maydell         s->cpuwait = value;
155*75750e4dSPeter Maydell         break;
156*75750e4dSPeter Maydell     case A_WICCTRL:
157*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
158*75750e4dSPeter Maydell         s->wicctrl = value;
159*75750e4dSPeter Maydell         break;
160*75750e4dSPeter Maydell     case A_SECDBGSET:
161*75750e4dSPeter Maydell         /* write-1-to-set */
162*75750e4dSPeter Maydell         qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
163*75750e4dSPeter Maydell         s->secure_debug |= value;
164*75750e4dSPeter Maydell         break;
165*75750e4dSPeter Maydell     case A_SECDBGCLR:
166*75750e4dSPeter Maydell         /* write-1-to-clear */
167*75750e4dSPeter Maydell         s->secure_debug &= ~value;
168*75750e4dSPeter Maydell         break;
169*75750e4dSPeter Maydell     case A_SWRESET:
170*75750e4dSPeter Maydell         /* One w/o bit to request a reset; all other bits reserved */
171*75750e4dSPeter Maydell         if (value & R_SWRESET_SWRESETREQ_MASK) {
172*75750e4dSPeter Maydell             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
173*75750e4dSPeter Maydell         }
174*75750e4dSPeter Maydell         break;
175*75750e4dSPeter Maydell     case A_BUSWAIT:        /* In IoTKit BUSWAIT is reserved, R/O, zero */
176*75750e4dSPeter Maydell     case A_SECDBGSTAT:
177*75750e4dSPeter Maydell     case A_PID4 ... A_CID3:
178*75750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
179*75750e4dSPeter Maydell                       "IoTKit SysCtl write: write of RO offset %x\n",
180*75750e4dSPeter Maydell                       (int)offset);
181*75750e4dSPeter Maydell         break;
182*75750e4dSPeter Maydell     default:
183*75750e4dSPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
184*75750e4dSPeter Maydell                       "IoTKit SysCtl write: bad offset %x\n", (int)offset);
185*75750e4dSPeter Maydell         break;
186*75750e4dSPeter Maydell     }
187*75750e4dSPeter Maydell }
188*75750e4dSPeter Maydell 
189*75750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = {
190*75750e4dSPeter Maydell     .read = iotkit_sysctl_read,
191*75750e4dSPeter Maydell     .write = iotkit_sysctl_write,
192*75750e4dSPeter Maydell     .endianness = DEVICE_LITTLE_ENDIAN,
193*75750e4dSPeter Maydell     /* byte/halfword accesses are just zero-padded on reads and writes */
194*75750e4dSPeter Maydell     .impl.min_access_size = 4,
195*75750e4dSPeter Maydell     .impl.max_access_size = 4,
196*75750e4dSPeter Maydell     .valid.min_access_size = 1,
197*75750e4dSPeter Maydell     .valid.max_access_size = 4,
198*75750e4dSPeter Maydell };
199*75750e4dSPeter Maydell 
200*75750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev)
201*75750e4dSPeter Maydell {
202*75750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
203*75750e4dSPeter Maydell 
204*75750e4dSPeter Maydell     trace_iotkit_sysctl_reset();
205*75750e4dSPeter Maydell     s->secure_debug = 0;
206*75750e4dSPeter Maydell     s->reset_syndrome = 1;
207*75750e4dSPeter Maydell     s->reset_mask = 0;
208*75750e4dSPeter Maydell     s->gretreg = 0;
209*75750e4dSPeter Maydell     s->initsvrtor0 = 0x10000000;
210*75750e4dSPeter Maydell     s->cpuwait = 0;
211*75750e4dSPeter Maydell     s->wicctrl = 0;
212*75750e4dSPeter Maydell }
213*75750e4dSPeter Maydell 
214*75750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj)
215*75750e4dSPeter Maydell {
216*75750e4dSPeter Maydell     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
217*75750e4dSPeter Maydell     IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
218*75750e4dSPeter Maydell 
219*75750e4dSPeter Maydell     memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
220*75750e4dSPeter Maydell                           s, "iotkit-sysctl", 0x1000);
221*75750e4dSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem);
222*75750e4dSPeter Maydell }
223*75750e4dSPeter Maydell 
224*75750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = {
225*75750e4dSPeter Maydell     .name = "iotkit-sysctl",
226*75750e4dSPeter Maydell     .version_id = 1,
227*75750e4dSPeter Maydell     .minimum_version_id = 1,
228*75750e4dSPeter Maydell     .fields = (VMStateField[]) {
229*75750e4dSPeter Maydell         VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
230*75750e4dSPeter Maydell         VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
231*75750e4dSPeter Maydell         VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
232*75750e4dSPeter Maydell         VMSTATE_UINT32(gretreg, IoTKitSysCtl),
233*75750e4dSPeter Maydell         VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl),
234*75750e4dSPeter Maydell         VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
235*75750e4dSPeter Maydell         VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
236*75750e4dSPeter Maydell         VMSTATE_END_OF_LIST()
237*75750e4dSPeter Maydell     }
238*75750e4dSPeter Maydell };
239*75750e4dSPeter Maydell 
240*75750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
241*75750e4dSPeter Maydell {
242*75750e4dSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
243*75750e4dSPeter Maydell 
244*75750e4dSPeter Maydell     dc->vmsd = &iotkit_sysctl_vmstate;
245*75750e4dSPeter Maydell     dc->reset = iotkit_sysctl_reset;
246*75750e4dSPeter Maydell }
247*75750e4dSPeter Maydell 
248*75750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = {
249*75750e4dSPeter Maydell     .name = TYPE_IOTKIT_SYSCTL,
250*75750e4dSPeter Maydell     .parent = TYPE_SYS_BUS_DEVICE,
251*75750e4dSPeter Maydell     .instance_size = sizeof(IoTKitSysCtl),
252*75750e4dSPeter Maydell     .instance_init = iotkit_sysctl_init,
253*75750e4dSPeter Maydell     .class_init = iotkit_sysctl_class_init,
254*75750e4dSPeter Maydell };
255*75750e4dSPeter Maydell 
256*75750e4dSPeter Maydell static void iotkit_sysctl_register_types(void)
257*75750e4dSPeter Maydell {
258*75750e4dSPeter Maydell     type_register_static(&iotkit_sysctl_info);
259*75750e4dSPeter Maydell }
260*75750e4dSPeter Maydell 
261*75750e4dSPeter Maydell type_init(iotkit_sysctl_register_types);
262