1 /*
2 * MAX78000 Global Control Registers
3 *
4 * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "qemu/log.h"
11 #include "trace.h"
12 #include "hw/irq.h"
13 #include "system/runstate.h"
14 #include "migration/vmstate.h"
15 #include "hw/qdev-properties.h"
16 #include "hw/char/max78000_uart.h"
17 #include "hw/misc/max78000_trng.h"
18 #include "hw/misc/max78000_aes.h"
19 #include "hw/misc/max78000_gcr.h"
20
21
max78000_gcr_reset_hold(Object * obj,ResetType type)22 static void max78000_gcr_reset_hold(Object *obj, ResetType type)
23 {
24 DeviceState *dev = DEVICE(obj);
25 Max78000GcrState *s = MAX78000_GCR(dev);
26 s->sysctrl = 0x21002;
27 s->rst0 = 0;
28 /* All clocks are always ready */
29 s->clkctrl = 0x3e140008;
30 s->pm = 0x3f000;
31 s->pclkdiv = 0;
32 s->pclkdis0 = 0xffffffff;
33 s->memctrl = 0x5;
34 s->memz = 0;
35 s->sysst = 0;
36 s->rst1 = 0;
37 s->pckdis1 = 0xffffffff;
38 s->eventen = 0;
39 s->revision = 0xa1;
40 s->sysie = 0;
41 s->eccerr = 0;
42 s->ecced = 0;
43 s->eccie = 0;
44 s->eccaddr = 0;
45 }
46
max78000_gcr_read(void * opaque,hwaddr addr,unsigned int size)47 static uint64_t max78000_gcr_read(void *opaque, hwaddr addr,
48 unsigned int size)
49 {
50 Max78000GcrState *s = opaque;
51
52 switch (addr) {
53 case SYSCTRL:
54 return s->sysctrl;
55
56 case RST0:
57 return s->rst0;
58
59 case CLKCTRL:
60 return s->clkctrl;
61
62 case PM:
63 return s->pm;
64
65 case PCLKDIV:
66 return s->pclkdiv;
67
68 case PCLKDIS0:
69 return s->pclkdis0;
70
71 case MEMCTRL:
72 return s->memctrl;
73
74 case MEMZ:
75 return s->memz;
76
77 case SYSST:
78 return s->sysst;
79
80 case RST1:
81 return s->rst1;
82
83 case PCKDIS1:
84 return s->pckdis1;
85
86 case EVENTEN:
87 return s->eventen;
88
89 case REVISION:
90 return s->revision;
91
92 case SYSIE:
93 return s->sysie;
94
95 case ECCERR:
96 return s->eccerr;
97
98 case ECCED:
99 return s->ecced;
100
101 case ECCIE:
102 return s->eccie;
103
104 case ECCADDR:
105 return s->eccaddr;
106
107 default:
108 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"
109 HWADDR_PRIx "\n", __func__, addr);
110 return 0;
111
112 }
113 }
114
max78000_gcr_write(void * opaque,hwaddr addr,uint64_t val64,unsigned int size)115 static void max78000_gcr_write(void *opaque, hwaddr addr,
116 uint64_t val64, unsigned int size)
117 {
118 Max78000GcrState *s = opaque;
119 uint32_t val = val64;
120 uint8_t zero[0xc000] = {0};
121 switch (addr) {
122 case SYSCTRL:
123 /* Checksum calculations always pass immediately */
124 s->sysctrl = (val & 0x30000) | 0x1002;
125 break;
126
127 case RST0:
128 if (val & SYSTEM_RESET) {
129 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
130 }
131 if (val & PERIPHERAL_RESET) {
132 /*
133 * Peripheral reset resets all peripherals. The CPU
134 * retains its state. The GPIO, watchdog timers, AoD,
135 * RAM retention, and general control registers (GCR),
136 * including the clock configuration, are unaffected.
137 */
138 val = UART2_RESET | UART1_RESET | UART0_RESET |
139 ADC_RESET | CNN_RESET | TRNG_RESET |
140 RTC_RESET | I2C0_RESET | SPI1_RESET |
141 TMR3_RESET | TMR2_RESET | TMR1_RESET |
142 TMR0_RESET | WDT0_RESET | DMA_RESET;
143 }
144 if (val & SOFT_RESET) {
145 /* Soft reset also resets GPIO */
146 val = UART2_RESET | UART1_RESET | UART0_RESET |
147 ADC_RESET | CNN_RESET | TRNG_RESET |
148 RTC_RESET | I2C0_RESET | SPI1_RESET |
149 TMR3_RESET | TMR2_RESET | TMR1_RESET |
150 TMR0_RESET | GPIO1_RESET | GPIO0_RESET |
151 DMA_RESET;
152 }
153 if (val & UART2_RESET) {
154 device_cold_reset(s->uart2);
155 }
156 if (val & UART1_RESET) {
157 device_cold_reset(s->uart1);
158 }
159 if (val & UART0_RESET) {
160 device_cold_reset(s->uart0);
161 }
162 if (val & TRNG_RESET) {
163 device_cold_reset(s->trng);
164 }
165 if (val & AES_RESET) {
166 device_cold_reset(s->aes);
167 }
168 /* TODO: As other devices are implemented, add them here */
169 break;
170
171 case CLKCTRL:
172 s->clkctrl = val | SYSCLK_RDY;
173 break;
174
175 case PM:
176 s->pm = val;
177 break;
178
179 case PCLKDIV:
180 s->pclkdiv = val;
181 break;
182
183 case PCLKDIS0:
184 s->pclkdis0 = val;
185 break;
186
187 case MEMCTRL:
188 s->memctrl = val;
189 break;
190
191 case MEMZ:
192 if (val & ram0) {
193 address_space_write(&s->sram_as, SYSRAM0_START,
194 MEMTXATTRS_UNSPECIFIED, zero, 0x8000);
195 }
196 if (val & ram1) {
197 address_space_write(&s->sram_as, SYSRAM1_START,
198 MEMTXATTRS_UNSPECIFIED, zero, 0x8000);
199 }
200 if (val & ram2) {
201 address_space_write(&s->sram_as, SYSRAM2_START,
202 MEMTXATTRS_UNSPECIFIED, zero, 0xC000);
203 }
204 if (val & ram3) {
205 address_space_write(&s->sram_as, SYSRAM3_START,
206 MEMTXATTRS_UNSPECIFIED, zero, 0x4000);
207 }
208 break;
209
210 case SYSST:
211 s->sysst = val;
212 break;
213
214 case RST1:
215 /* TODO: As other devices are implemented, add them here */
216 s->rst1 = val;
217 break;
218
219 case PCKDIS1:
220 s->pckdis1 = val;
221 break;
222
223 case EVENTEN:
224 s->eventen = val;
225 break;
226
227 case REVISION:
228 s->revision = val;
229 break;
230
231 case SYSIE:
232 s->sysie = val;
233 break;
234
235 case ECCERR:
236 s->eccerr = val;
237 break;
238
239 case ECCED:
240 s->ecced = val;
241 break;
242
243 case ECCIE:
244 s->eccie = val;
245 break;
246
247 case ECCADDR:
248 s->eccaddr = val;
249 break;
250
251 default:
252 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
253 __func__, addr);
254 break;
255
256 }
257 }
258
259 static const Property max78000_gcr_properties[] = {
260 DEFINE_PROP_LINK("sram", Max78000GcrState, sram,
261 TYPE_MEMORY_REGION, MemoryRegion*),
262 DEFINE_PROP_LINK("uart0", Max78000GcrState, uart0,
263 TYPE_MAX78000_UART, DeviceState*),
264 DEFINE_PROP_LINK("uart1", Max78000GcrState, uart1,
265 TYPE_MAX78000_UART, DeviceState*),
266 DEFINE_PROP_LINK("uart2", Max78000GcrState, uart2,
267 TYPE_MAX78000_UART, DeviceState*),
268 DEFINE_PROP_LINK("trng", Max78000GcrState, trng,
269 TYPE_MAX78000_TRNG, DeviceState*),
270 DEFINE_PROP_LINK("aes", Max78000GcrState, aes,
271 TYPE_MAX78000_AES, DeviceState*),
272 };
273
274 static const MemoryRegionOps max78000_gcr_ops = {
275 .read = max78000_gcr_read,
276 .write = max78000_gcr_write,
277 .endianness = DEVICE_LITTLE_ENDIAN,
278 .valid.min_access_size = 4,
279 .valid.max_access_size = 4,
280 };
281
282 static const VMStateDescription vmstate_max78000_gcr = {
283 .name = TYPE_MAX78000_GCR,
284 .version_id = 1,
285 .minimum_version_id = 1,
286 .fields = (const VMStateField[]) {
287 VMSTATE_UINT32(sysctrl, Max78000GcrState),
288 VMSTATE_UINT32(rst0, Max78000GcrState),
289 VMSTATE_UINT32(clkctrl, Max78000GcrState),
290 VMSTATE_UINT32(pm, Max78000GcrState),
291 VMSTATE_UINT32(pclkdiv, Max78000GcrState),
292 VMSTATE_UINT32(pclkdis0, Max78000GcrState),
293 VMSTATE_UINT32(memctrl, Max78000GcrState),
294 VMSTATE_UINT32(memz, Max78000GcrState),
295 VMSTATE_UINT32(sysst, Max78000GcrState),
296 VMSTATE_UINT32(rst1, Max78000GcrState),
297 VMSTATE_UINT32(pckdis1, Max78000GcrState),
298 VMSTATE_UINT32(eventen, Max78000GcrState),
299 VMSTATE_UINT32(revision, Max78000GcrState),
300 VMSTATE_UINT32(sysie, Max78000GcrState),
301 VMSTATE_UINT32(eccerr, Max78000GcrState),
302 VMSTATE_UINT32(ecced, Max78000GcrState),
303 VMSTATE_UINT32(eccie, Max78000GcrState),
304 VMSTATE_UINT32(eccaddr, Max78000GcrState),
305 VMSTATE_END_OF_LIST()
306 }
307 };
308
max78000_gcr_init(Object * obj)309 static void max78000_gcr_init(Object *obj)
310 {
311 Max78000GcrState *s = MAX78000_GCR(obj);
312
313 memory_region_init_io(&s->mmio, obj, &max78000_gcr_ops, s,
314 TYPE_MAX78000_GCR, 0x400);
315 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
316
317 }
318
max78000_gcr_realize(DeviceState * dev,Error ** errp)319 static void max78000_gcr_realize(DeviceState *dev, Error **errp)
320 {
321 Max78000GcrState *s = MAX78000_GCR(dev);
322
323 address_space_init(&s->sram_as, s->sram, "sram");
324 }
325
max78000_gcr_class_init(ObjectClass * klass,const void * data)326 static void max78000_gcr_class_init(ObjectClass *klass, const void *data)
327 {
328 DeviceClass *dc = DEVICE_CLASS(klass);
329 ResettableClass *rc = RESETTABLE_CLASS(klass);
330
331 device_class_set_props(dc, max78000_gcr_properties);
332
333 dc->realize = max78000_gcr_realize;
334 dc->vmsd = &vmstate_max78000_gcr;
335 rc->phases.hold = max78000_gcr_reset_hold;
336 }
337
338 static const TypeInfo max78000_gcr_info = {
339 .name = TYPE_MAX78000_GCR,
340 .parent = TYPE_SYS_BUS_DEVICE,
341 .instance_size = sizeof(Max78000GcrState),
342 .instance_init = max78000_gcr_init,
343 .class_init = max78000_gcr_class_init,
344 };
345
max78000_gcr_register_types(void)346 static void max78000_gcr_register_types(void)
347 {
348 type_register_static(&max78000_gcr_info);
349 }
350
351 type_init(max78000_gcr_register_types)
352