hw/misc/iotkit-sysctl.c: add SSE-310 support
Add SSE-310 case statements for reads and writes. Add new SSE-310 PIDR and CLIDR values. Add new SSE-310 PPUINTSTAT register as RAZ with LOG_UMIMP on reads and RO on writes. Reviewed-by: Owen Giles <owen.giles@hpe.com> Reviewed-by: Robert Elliott <elliott@hpe.com> Signed-off-by: Simon Xu <simonxhy0404@gmail.com> Message-Id: <20260805153005.9989-4-simonxhy0404@gmail.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Simon Xu committed
Aug 17, 2026 at 19:26 UTC
399ab98d0a37907ae2e2db095bf4d780a4a2747f
1 file changed
+79
-7
hw/misc/iotkit-sysctl.c
+79
-7
@@ -51,6 +51,7 @@ REG32(CPUWAIT, 0x118)
51
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
52
REG32(WICCTRL, 0x120)
53
REG32(EWCTRL, 0x124)
54
+REG32(PPUINTSTAT, 0x128)
55
REG32(PWRCTRL, 0x1fc)
56
FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
57
FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
@@ -87,6 +88,12 @@ static const int sse200_sysctl_id[] = {
88
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
89
};
90
91
+static const int sse310_sysctl_id[] = {
92
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
93
+ 0x54, 0xb8, 0x4b, 0x00, /* PID0..PID3 */
94
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
95
+};
96
+
97
/*
98
* Set the initial secure vector table offset address for the core.
99
* This will take effect when the CPU next resets.
@@ -118,6 +125,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
125
goto bad_offset;
126
case ARMSSE_SSE200:
127
case ARMSSE_SSE300:
128
+ case ARMSSE_SSE310:
129
r = s->scsecctrl;
130
break;
131
default:
@@ -130,6 +138,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
138
goto bad_offset;
139
case ARMSSE_SSE200:
140
case ARMSSE_SSE300:
141
+ case ARMSSE_SSE310:
142
r = s->fclk_div;
143
break;
144
default:
@@ -142,6 +151,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
151
goto bad_offset;
152
case ARMSSE_SSE200:
153
case ARMSSE_SSE300:
154
+ case ARMSSE_SSE310:
155
r = s->sysclk_div;
156
break;
157
default:
@@ -154,6 +164,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
164
goto bad_offset;
165
case ARMSSE_SSE200:
166
case ARMSSE_SSE300:
167
+ case ARMSSE_SSE310:
168
r = s->clock_force;
169
break;
170
default:
@@ -180,6 +191,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
191
r = s->initsvtor1;
192
break;
193
case ARMSSE_SSE300:
194
+ case ARMSSE_SSE310:
195
goto bad_offset;
196
default:
197
g_assert_not_reached();
@@ -192,6 +204,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
204
r = s->cpuwait;
205
break;
206
case ARMSSE_SSE300:
207
+ case ARMSSE_SSE310:
208
/* In SSE300 this is reserved (for INITSVTOR2) */
209
goto bad_offset;
210
default:
@@ -208,6 +221,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
221
r = s->nmi_enable;
222
break;
223
case ARMSSE_SSE300:
224
+ case ARMSSE_SSE310:
225
/* In SSE300 this is reserved (for INITSVTOR3) */
226
goto bad_offset;
227
default:
@@ -221,7 +235,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
235
r = s->wicctrl;
236
break;
237
case ARMSSE_SSE300:
224
- /* In SSE300 this offset is CPUWAIT */
238
+ case ARMSSE_SSE310:
239
+ /* In SSE300 and SSE310 this offset is CPUWAIT */
240
r = s->cpuwait;
241
break;
242
default:
@@ -236,19 +251,36 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
251
r = s->ewctrl;
252
break;
253
case ARMSSE_SSE300:
239
- /* In SSE300 this offset is NMI_ENABLE */
254
+ case ARMSSE_SSE310:
255
+ /* In SSE300 and SSE310 this offset is NMI_ENABLE */
256
r = s->nmi_enable;
257
break;
258
default:
259
g_assert_not_reached();
260
}
261
break;
262
+ case A_PPUINTSTAT:
263
+ switch (s->sse_version) {
264
+ case ARMSSE_IOTKIT:
265
+ case ARMSSE_SSE200:
266
+ case ARMSSE_SSE300:
267
+ goto bad_offset;
268
+ case ARMSSE_SSE310:
269
+ qemu_log_mask(LOG_UNIMP,
270
+ "IoTKit SysCtl PPUINTSTAT unimplemented\n");
271
+ r = 0;
272
+ break;
273
+ default:
274
+ g_assert_not_reached();
275
+ }
276
+ break;
277
case A_PWRCTRL:
278
switch (s->sse_version) {
279
case ARMSSE_IOTKIT:
280
case ARMSSE_SSE200:
281
goto bad_offset;
282
case ARMSSE_SSE300:
283
+ case ARMSSE_SSE310:
284
r = s->pwrctrl;
285
break;
286
default:
@@ -261,6 +293,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
293
goto bad_offset;
294
case ARMSSE_SSE200:
295
case ARMSSE_SSE300:
296
+ case ARMSSE_SSE310:
297
r = s->pdcm_pd_sys_sense;
298
break;
299
default:
@@ -273,6 +306,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
306
case ARMSSE_SSE200:
307
goto bad_offset;
308
case ARMSSE_SSE300:
309
+ case ARMSSE_SSE310:
310
r = s->pdcm_pd_cpu0_sense;
311
break;
312
default:
@@ -287,6 +321,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
321
r = s->pdcm_pd_sram0_sense;
322
break;
323
case ARMSSE_SSE300:
324
+ case ARMSSE_SSE310:
325
goto bad_offset;
326
default:
327
g_assert_not_reached();
@@ -300,6 +335,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
335
r = s->pdcm_pd_sram1_sense;
336
break;
337
case ARMSSE_SSE300:
338
+ case ARMSSE_SSE310:
339
goto bad_offset;
340
default:
341
g_assert_not_reached();
@@ -313,6 +349,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
349
r = s->pdcm_pd_sram2_sense;
350
break;
351
case ARMSSE_SSE300:
352
+ case ARMSSE_SSE310:
353
r = s->pdcm_pd_vmr0_sense;
354
break;
355
default:
@@ -327,6 +364,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
364
r = s->pdcm_pd_sram3_sense;
365
break;
366
case ARMSSE_SSE300:
367
+ case ARMSSE_SSE310:
368
r = s->pdcm_pd_vmr1_sense;
369
break;
370
default:
@@ -342,6 +380,9 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
380
case ARMSSE_SSE300:
381
r = sse200_sysctl_id[(offset - A_PID4) / 4];
382
break;
383
+ case ARMSSE_SSE310:
384
+ r = sse310_sysctl_id[(offset - A_PID4) / 4];
385
+ break;
386
default:
387
g_assert_not_reached();
388
}
@@ -367,7 +408,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
408
409
static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
410
{
370
- int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
411
+ int num_cpus = (s->sse_version == ARMSSE_SSE300 ||
412
+ s->sse_version == ARMSSE_SSE310) ? 1 : 2;
413
int i;
414
415
for (i = 0; i < num_cpus; i++) {
@@ -418,7 +460,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
460
case A_INITSVTOR0:
461
switch (s->sse_version) {
462
case ARMSSE_SSE300:
421
- /* SSE300 has a LOCK bit which prevents further writes when set */
463
+ case ARMSSE_SSE310:
464
+ /* SSE300, SSE310 have a LOCK bit which prevents further writes */
465
if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
466
qemu_log_mask(LOG_GUEST_ERROR,
467
"IoTKit INITSVTOR0 write when register locked\n");
@@ -443,6 +486,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
486
cpuwait_write(s, value);
487
break;
488
case ARMSSE_SSE300:
489
+ case ARMSSE_SSE310:
490
/* In SSE300 this is reserved (for INITSVTOR2) */
491
goto bad_offset;
492
default:
@@ -457,7 +501,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
501
s->wicctrl = value;
502
break;
503
case ARMSSE_SSE300:
460
- /* In SSE300 this offset is CPUWAIT */
504
+ case ARMSSE_SSE310:
505
+ /* In SSE300 and SSE310 this offset is CPUWAIT */
506
cpuwait_write(s, value);
507
break;
508
default:
@@ -485,6 +530,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
530
goto bad_offset;
531
case ARMSSE_SSE200:
532
case ARMSSE_SSE300:
533
+ case ARMSSE_SSE310:
534
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
535
s->scsecctrl = value;
536
break;
@@ -498,6 +544,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
544
goto bad_offset;
545
case ARMSSE_SSE200:
546
case ARMSSE_SSE300:
547
+ case ARMSSE_SSE310:
548
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
549
s->fclk_div = value;
550
break;
@@ -511,6 +558,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
558
goto bad_offset;
559
case ARMSSE_SSE200:
560
case ARMSSE_SSE300:
561
+ case ARMSSE_SSE310:
562
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
563
s->sysclk_div = value;
564
break;
@@ -524,6 +572,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
572
goto bad_offset;
573
case ARMSSE_SSE200:
574
case ARMSSE_SSE300:
575
+ case ARMSSE_SSE310:
576
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
577
s->clock_force = value;
578
break;
@@ -540,6 +589,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
589
set_init_vtor(1, s->initsvtor1);
590
break;
591
case ARMSSE_SSE300:
592
+ case ARMSSE_SSE310:
593
goto bad_offset;
594
default:
595
g_assert_not_reached();
@@ -554,7 +604,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
604
s->ewctrl = value;
605
break;
606
case ARMSSE_SSE300:
557
- /* In SSE300 this offset is NMI_ENABLE */
607
+ case ARMSSE_SSE310:
608
+ /* In SSE300 and SSE310 this offset is NMI_ENABLE */
609
qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
610
s->nmi_enable = value;
611
break;
@@ -562,12 +613,25 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
613
g_assert_not_reached();
614
}
615
break;
616
+ case A_PPUINTSTAT:
617
+ switch (s->sse_version) {
618
+ case ARMSSE_IOTKIT:
619
+ case ARMSSE_SSE200:
620
+ case ARMSSE_SSE300:
621
+ goto bad_offset;
622
+ case ARMSSE_SSE310:
623
+ goto ro_offset;
624
+ default:
625
+ g_assert_not_reached();
626
+ }
627
+ break;
628
case A_PWRCTRL:
629
switch (s->sse_version) {
630
case ARMSSE_IOTKIT:
631
case ARMSSE_SSE200:
632
goto bad_offset;
633
case ARMSSE_SSE300:
634
+ case ARMSSE_SSE310:
635
if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
636
qemu_log_mask(LOG_GUEST_ERROR,
637
"IoTKit PWRCTRL write when register locked\n");
@@ -585,6 +649,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
649
goto bad_offset;
650
case ARMSSE_SSE200:
651
case ARMSSE_SSE300:
652
+ case ARMSSE_SSE310:
653
qemu_log_mask(LOG_UNIMP,
654
"IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
655
s->pdcm_pd_sys_sense = value;
@@ -599,6 +664,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
664
case ARMSSE_SSE200:
665
goto bad_offset;
666
case ARMSSE_SSE300:
667
+ case ARMSSE_SSE310:
668
qemu_log_mask(LOG_UNIMP,
669
"IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
670
s->pdcm_pd_cpu0_sense = value;
@@ -617,6 +683,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
683
s->pdcm_pd_sram0_sense = value;
684
break;
685
case ARMSSE_SSE300:
686
+ case ARMSSE_SSE310:
687
goto bad_offset;
688
default:
689
g_assert_not_reached();
@@ -632,6 +699,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
699
s->pdcm_pd_sram1_sense = value;
700
break;
701
case ARMSSE_SSE300:
702
+ case ARMSSE_SSE310:
703
goto bad_offset;
704
default:
705
g_assert_not_reached();
@@ -647,6 +715,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
715
s->pdcm_pd_sram2_sense = value;
716
break;
717
case ARMSSE_SSE300:
718
+ case ARMSSE_SSE310:
719
qemu_log_mask(LOG_UNIMP,
720
"IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
721
s->pdcm_pd_vmr0_sense = value;
@@ -665,6 +734,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
734
s->pdcm_pd_sram3_sense = value;
735
break;
736
case ARMSSE_SSE300:
737
+ case ARMSSE_SSE310:
738
qemu_log_mask(LOG_UNIMP,
739
"IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
740
s->pdcm_pd_vmr1_sense = value;
@@ -683,6 +753,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
753
s->nmi_enable = value;
754
break;
755
case ARMSSE_SSE300:
756
+ case ARMSSE_SSE310:
757
/* In SSE300 this is reserved (for INITSVTOR3) */
758
goto bad_offset;
759
default:
@@ -769,7 +840,8 @@ static bool sse300_needed(void *opaque)
840
{
841
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
842
772
- return s->sse_version == ARMSSE_SSE300;
843
+ return s->sse_version == ARMSSE_SSE300 ||
844
+ s->sse_version == ARMSSE_SSE310;
845
}
846
847
static const VMStateDescription iotkit_sysctl_sse300_vmstate = {