The `aspeed_sgpio_get_pin` and `aspeed_sgpio_set_pin` functions are implemented to get and set the level of individual SGPIO pins. These are then exposed as boolean properties on the SGPIO device object.
Signed-off-by: Yubin Zou <[email protected]> Reviewed-by: Kane Chen <[email protected]> --- hw/gpio/aspeed_sgpio.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/hw/gpio/aspeed_sgpio.c b/hw/gpio/aspeed_sgpio.c index 167a72c41e96c67bd1867a19e2b1706f5bd074e4..927c711cb3aef889c47c9a9156fe4241981c5efa 100644 --- a/hw/gpio/aspeed_sgpio.c +++ b/hw/gpio/aspeed_sgpio.c @@ -51,6 +51,8 @@ static uint64_t aspeed_sgpio_2700_read(void *opaque, hwaddr offset, reg = offset >> 2; switch (reg) { + case R_SGPIO_INT_STATUS_0 ... R_SGPIO_INT_STATUS_7: + break; case R_SGPIO_0_CONTROL ... R_SGPIO_255_CONTROL: value = aspeed_sgpio_2700_read_control_reg(s, reg); break; @@ -82,6 +84,73 @@ static void aspeed_sgpio_2700_write(void *opaque, hwaddr offset, uint64_t data, } } +static bool aspeed_sgpio_get_pin_level(AspeedSGPIOState *s, int pin) +{ + uint32_t value = s->ctrl_regs[pin >> 1]; + bool is_input = !(pin % 2); + uint32_t bit_mask = 0; + + if (is_input) { + bit_mask = SGPIO_SERIAL_IN_VAL_MASK; + } else { + bit_mask = SGPIO_SERIAL_OUT_VAL_MASK; + } + + return value & bit_mask; +} + +static void aspeed_sgpio_set_pin_level(AspeedSGPIOState *s, int pin, bool level) +{ + uint32_t value = s->ctrl_regs[pin >> 1]; + bool is_input = !(pin % 2); + uint32_t bit_mask = 0; + + if (is_input) { + bit_mask = SGPIO_SERIAL_IN_VAL_MASK; + } else { + bit_mask = SGPIO_SERIAL_OUT_VAL_MASK; + } + + if (level) { + value |= bit_mask; + } else { + value &= ~bit_mask; + } + s->ctrl_regs[pin >> 1] = value; +} + +static void aspeed_sgpio_get_pin(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + bool level = true; + int pin = 0xfff; + AspeedSGPIOState *s = ASPEED_SGPIO(obj); + + if (sscanf(name, "sgpio%03d", &pin) != 1) { + error_setg(errp, "%s: error reading %s", __func__, name); + return; + } + level = aspeed_sgpio_get_pin_level(s, pin); + visit_type_bool(v, name, &level, errp); +} + +static void aspeed_sgpio_set_pin(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + bool level; + int pin = 0xfff; + AspeedSGPIOState *s = ASPEED_SGPIO(obj); + + if (!visit_type_bool(v, name, &level, errp)) { + return; + } + if (sscanf(name, "sgpio%03d", &pin) != 1) { + error_setg(errp, "%s: error reading %s", __func__, name); + return; + } + aspeed_sgpio_set_pin_level(s, pin, level); +} + static const MemoryRegionOps aspeed_sgpio_2700_ops = { .read = aspeed_sgpio_2700_read, .write = aspeed_sgpio_2700_write, @@ -105,6 +174,15 @@ static void aspeed_sgpio_realize(DeviceState *dev, Error **errp) sysbus_init_mmio(sbd, &s->iomem); } +static void aspeed_sgpio_init(Object *obj) +{ + for (int i = 0; i < ASPEED_SGPIO_MAX_PIN_PAIR * 2; i++) { + g_autofree char *name = g_strdup_printf("sgpio%03d", i); + object_property_add(obj, name, "bool", aspeed_sgpio_get_pin, + aspeed_sgpio_set_pin, NULL, NULL); + } +} + static void aspeed_sgpio_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -134,6 +212,7 @@ static const TypeInfo aspeed_sgpio_ast2700_info = { .name = TYPE_ASPEED_SGPIO "-ast2700", .parent = TYPE_ASPEED_SGPIO, .class_init = aspeed_sgpio_2700_class_init, + .instance_init = aspeed_sgpio_init, }; static void aspeed_sgpio_register_types(void) -- 2.52.0.351.gbe84eed79e-goog
