hw/gpio: Add property for ASPEED GPIO in 32 bits basis

Added 32 bits property for ASPEED GPIO. Previously it can only be
access in bitwise manner.

The changes to qobject is to index gpios with array indices on top of
accessing with registers.  This allows for easier gpio access,
especially in tests with complex behaviors that requires large number
of gpios at a time, like fault injection and networking behaviors.

Indexing multiple gpios at once allows qmp/side band client to no
longer hardcode and populate register names and manipulate them
faster.

Signed-off-by: Felix Wu <flwu@google.com>
Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Link: https://lore.kernel.org/qemu-devel/20251015011830.1688468-2-lixiaoyan@google.com
[ clg: wrapped commit log lines ]
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Felix Wu 2025-10-15 01:18:25 +00:00 committed by Cédric Le Goater
parent d187d120d1
commit 42fa4bd01a

View file

@ -1308,6 +1308,57 @@ static void aspeed_gpio_2700_write(void *opaque, hwaddr offset,
}
/* Setup functions */
static void aspeed_gpio_set_set(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
uint32_t set_val = 0;
AspeedGPIOState *s = ASPEED_GPIO(obj);
AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
int set_idx = 0;
if (!visit_type_uint32(v, name, &set_val, errp)) {
return;
}
if (sscanf(name, "gpio-set[%d]", &set_idx) != 1) {
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
if (set_idx >= agc->nr_gpio_sets || set_idx < 0) {
error_setg(errp, "%s: invalid set_idx %s", __func__, name);
return;
}
aspeed_gpio_update(s, &s->sets[set_idx], set_val,
~s->sets[set_idx].direction);
}
static void aspeed_gpio_get_set(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
uint32_t set_val = 0;
AspeedGPIOState *s = ASPEED_GPIO(obj);
AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
int set_idx = 0;
if (sscanf(name, "gpio-set[%d]", &set_idx) != 1) {
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
if (set_idx >= agc->nr_gpio_sets || set_idx < 0) {
error_setg(errp, "%s: invalid set_idx %s", __func__, name);
return;
}
set_val = s->sets[set_idx].data_value;
visit_type_uint32(v, name, &set_val, errp);
}
/****************** Setup functions ******************/
static const GPIOSetProperties ast2400_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
[0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
[1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
@ -1435,6 +1486,12 @@ static void aspeed_gpio_init(Object *obj)
g_free(name);
}
}
for (int i = 0; i < agc->nr_gpio_sets; i++) {
char *name = g_strdup_printf("gpio-set[%d]", i);
object_property_add(obj, name, "uint32", aspeed_gpio_get_set,
aspeed_gpio_set_set, NULL, NULL);
}
}
static const VMStateDescription vmstate_gpio_regs = {