hw/misc/mps2-fpgaio.c: add GPIOALT2 register
Add GPIOALT2 register for new an555 board. Implement register access as RW with LOG_UNIMP for writes. Add "has-gpioalt2" property to make each board configurable. Add gpioalt2 vmstate subsection for device state migration. 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-10-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
64eef0e6c3bbfd56ed559bad63724c393ecdf684
3 files changed
+43
hw/arm/mps2-tz.c
+6
@@ -122,6 +122,7 @@ struct MPS2TZMachineClass {
122
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
123
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
124
bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
125
+ bool fpgaio_has_gpioalt2; /* Does FPGAIO have GPIOALT2 register? */
126
int numirq; /* Number of external interrupts */
127
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
128
uint32_t init_svtor; /* init-svtor setting for SSE */
@@ -494,6 +495,7 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
495
qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
496
qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
497
qdev_prop_set_bit(DEVICE(fpgaio), "has-dbgctrl", mmc->fpgaio_has_dbgctrl);
498
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-gpioalt2", mmc->fpgaio_has_gpioalt2);
499
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
500
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
501
}
@@ -1350,6 +1352,7 @@ static void mps2tz_an505_class_init(ObjectClass *oc, const void *data)
1352
mmc->fpgaio_num_leds = 2;
1353
mmc->fpgaio_has_switches = false;
1354
mmc->fpgaio_has_dbgctrl = false;
1355
+ mmc->fpgaio_has_gpioalt2 = false;
1356
mmc->numirq = 92;
1357
mmc->uart_overflow_irq = 47;
1358
mmc->init_svtor = 0x10000000;
@@ -1384,6 +1387,7 @@ static void mps2tz_an521_class_init(ObjectClass *oc, const void *data)
1387
mmc->fpgaio_num_leds = 2;
1388
mmc->fpgaio_has_switches = false;
1389
mmc->fpgaio_has_dbgctrl = false;
1390
+ mmc->fpgaio_has_gpioalt2 = false;
1391
mmc->numirq = 92;
1392
mmc->uart_overflow_irq = 47;
1393
mmc->init_svtor = 0x10000000;
@@ -1418,6 +1422,7 @@ static void mps3tz_an524_class_init(ObjectClass *oc, const void *data)
1422
mmc->fpgaio_num_leds = 10;
1423
mmc->fpgaio_has_switches = true;
1424
mmc->fpgaio_has_dbgctrl = false;
1425
+ mmc->fpgaio_has_gpioalt2 = false;
1426
mmc->numirq = 95;
1427
mmc->uart_overflow_irq = 47;
1428
mmc->init_svtor = 0x10000000;
@@ -1457,6 +1462,7 @@ static void mps3tz_an547_class_init(ObjectClass *oc, const void *data)
1462
mmc->fpgaio_num_leds = 10;
1463
mmc->fpgaio_has_switches = true;
1464
mmc->fpgaio_has_dbgctrl = true;
1465
+ mmc->fpgaio_has_gpioalt2 = false;
1466
mmc->numirq = 96;
1467
mmc->uart_overflow_irq = 48;
1468
mmc->init_svtor = 0x00000000;
hw/misc/mps2-fpgaio.c
+35
@@ -31,6 +31,7 @@
31
REG32(LED0, 0)
32
REG32(DBGCTRL, 4)
33
REG32(BUTTON, 8)
34
+REG32(GPIOALT2, 0xc)
35
REG32(CLK1HZ, 0x10)
36
REG32(CLK100HZ, 0x14)
37
REG32(COUNTER, 0x18)
@@ -142,6 +143,9 @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
143
*/
144
r = 0;
145
break;
146
+ case A_GPIOALT2:
147
+ r = s->gpioalt2;
148
+ break;
149
case A_PRESCALE:
150
r = s->prescale;
151
break;
@@ -210,6 +214,14 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
214
"MPS2 FPGAIO: DBGCTRL unimplemented\n");
215
s->dbgctrl = value;
216
break;
217
+ case A_GPIOALT2:
218
+ if (!s->has_gpioalt2) {
219
+ goto bad_offset;
220
+ }
221
+ qemu_log_mask(LOG_UNIMP,
222
+ "MPS2 FPGAIO: GPIOALT2 unimplemented\n");
223
+ s->gpioalt2 = value;
224
+ break;
225
case A_PRESCALE:
226
resync_counter(s);
227
s->prescale = value;
@@ -301,6 +313,24 @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
313
}
314
}
315
316
+static bool needed_gpioalt2(void *opaque)
317
+{
318
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
319
+
320
+ return s->has_gpioalt2;
321
+}
322
+
323
+static const VMStateDescription mps2_fpgaio_gpioalt2_vmstate = {
324
+ .name = "mps2-fpgaio/gpioalt2",
325
+ .version_id = 1,
326
+ .minimum_version_id = 1,
327
+ .needed = needed_gpioalt2,
328
+ .fields = (const VMStateField[]) {
329
+ VMSTATE_UINT32(gpioalt2, MPS2FPGAIO),
330
+ VMSTATE_END_OF_LIST()
331
+ }
332
+};
333
+
334
static const VMStateDescription mps2_fpgaio_vmstate = {
335
.name = "mps2-fpgaio",
336
.version_id = 3,
@@ -317,6 +347,10 @@ static const VMStateDescription mps2_fpgaio_vmstate = {
347
VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
348
VMSTATE_END_OF_LIST()
349
},
350
+ .subsections = (const VMStateDescription * const []) {
351
+ &mps2_fpgaio_gpioalt2_vmstate,
352
+ NULL
353
+ }
354
};
355
356
static const Property mps2_fpgaio_properties[] = {
@@ -326,6 +360,7 @@ static const Property mps2_fpgaio_properties[] = {
360
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
361
DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
362
DEFINE_PROP_BOOL("has-dbgctrl", MPS2FPGAIO, has_dbgctrl, false),
363
+ DEFINE_PROP_BOOL("has-gpioalt2", MPS2FPGAIO, has_gpioalt2, false),
364
};
365
366
static void mps2_fpgaio_class_init(ObjectClass *klass, const void *data)
include/hw/misc/mps2-fpgaio.h
+2
@@ -40,11 +40,13 @@ struct MPS2FPGAIO {
40
uint32_t num_leds;
41
bool has_switches;
42
bool has_dbgctrl;
43
+ bool has_gpioalt2;
44
45
uint32_t led0;
46
uint32_t prescale;
47
uint32_t misc;
48
uint32_t dbgctrl;
49
+ uint32_t gpioalt2;
50
51
/* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
52
int64_t pscntr_sync_ticks;