On Mon, Jan 12, 2026 at 12:38 AM Kane Chen via qemu development
<[email protected]> wrote:
>
> From: Kane-Chen-AS <[email protected]>
>
> On some Aspeed-based machines, multiple I2C controllers may exist
> across different components, such as the primary SoC and an external
> IO expander or co-processor (e.g., AST1700). Using the current static
> naming convention results in object name conflicts when multiple
> controllers attempt to instantiate buses with the same ID.
>
> This patch introduces a 'bus-label' property for the Aspeed I2C
> controller. This allows higher-level layers, such as the SoC realize
> function, to provide a unique identifier for the buses. The I2C bus
> object name is then constructed using this label (e.g., "ioexp0.0"
> instead of the default "aspeed.i2c.bus.0").
>
> This enhancement ensures unique bus identifiers across the system and
> resolves naming conflicts in multi-controller configurations.
>
> Signed-off-by: Kane-Chen-AS <[email protected]>

Signed-off-by: Nabih Estefan <[email protected]>
Tested-by: Nabih Estefan <[email protected]>

This is basically a rework of the bus-label patches I already tested
and we're carrying for AST1700, re-tested just in case, and everything
still looks good!

Thank you Kane!

-Nabih

> ---
>  include/hw/i2c/aspeed_i2c.h |  2 ++
>  hw/i2c/aspeed_i2c.c         | 27 +++++++++++++++++++++------
>  2 files changed, 23 insertions(+), 6 deletions(-)
>
> diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
> index ffcff2580f..68bd138026 100644
> --- a/include/hw/i2c/aspeed_i2c.h
> +++ b/include/hw/i2c/aspeed_i2c.h
> @@ -252,6 +252,7 @@ struct AspeedI2CBus {
>      MemoryRegion mr_pool;
>
>      I2CBus *bus;
> +    char *name;
>      uint8_t id;
>      qemu_irq irq;
>
> @@ -269,6 +270,7 @@ struct AspeedI2CState {
>      uint32_t intr_status;
>      uint32_t ctrl_global;
>      uint32_t new_clk_divider;
> +    char *bus_label;
>      MemoryRegion pool_iomem;
>      uint8_t share_pool[ASPEED_I2C_SHARE_POOL_SIZE];
>
> diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
> index 1b8ac561c3..7cf92423c7 100644
> --- a/hw/i2c/aspeed_i2c.c
> +++ b/hw/i2c/aspeed_i2c.c
> @@ -1215,9 +1215,16 @@ static void aspeed_i2c_realize(DeviceState *dev, Error 
> **errp)
>                            "aspeed.i2c", aic->mem_size);
>      sysbus_init_mmio(sbd, &s->iomem);
>
> +    /* default value */
> +    if (!s->bus_label) {
> +        s->bus_label = g_strdup(TYPE_ASPEED_I2C_BUS);
> +    }
> +
>      for (i = 0; i < aic->num_busses; i++) {
>          Object *bus = OBJECT(&s->busses[i]);
>          int offset = i < aic->gap ? 1 : 5;
> +        g_autofree char *name = g_strdup_printf("%s.%d",
> +                                                s->bus_label, i);
>
>          if (!object_property_set_link(bus, "controller", OBJECT(s), errp)) {
>              return;
> @@ -1227,6 +1234,10 @@ static void aspeed_i2c_realize(DeviceState *dev, Error 
> **errp)
>              return;
>          }
>
> +        if (!object_property_set_str(bus, "bus-name", name, errp)) {
> +            return;
> +        }
> +
>          if (!sysbus_realize(SYS_BUS_DEVICE(bus), errp)) {
>              return;
>          }
> @@ -1263,6 +1274,7 @@ static void aspeed_i2c_realize(DeviceState *dev, Error 
> **errp)
>  static const Property aspeed_i2c_properties[] = {
>      DEFINE_PROP_LINK("dram", AspeedI2CState, dram_mr,
>                       TYPE_MEMORY_REGION, MemoryRegion *),
> +    DEFINE_PROP_STRING("bus-label", AspeedI2CState, bus_label),
>  };
>
>  static void aspeed_i2c_class_init(ObjectClass *klass, const void *data)
> @@ -1423,24 +1435,26 @@ static void aspeed_i2c_bus_realize(DeviceState *dev, 
> Error **errp)
>  {
>      AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
>      AspeedI2CClass *aic;
> -    g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I2C_BUS ".%d", 
> s->id);
> -    g_autofree char *pool_name = g_strdup_printf("%s.pool", name);
> +    g_autofree char *pool_name = NULL;
>
> -    if (!s->controller) {
> -        error_setg(errp, TYPE_ASPEED_I2C_BUS ": 'controller' link not set");
> +    if (!s->controller || !s->name) {
> +        error_setg(errp, TYPE_ASPEED_I2C_BUS
> +                   ": 'controller' or 'bus-name' not set");
>          return;
>      }
>
> +    pool_name = g_strdup_printf("%s.pool", s->name);
> +
>      aic = ASPEED_I2C_GET_CLASS(s->controller);
>
>      sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
>
> -    s->bus = i2c_init_bus(dev, name);
> +    s->bus = i2c_init_bus(dev, s->name);
>      s->slave = i2c_slave_create_simple(s->bus, TYPE_ASPEED_I2C_BUS_SLAVE,
>                                         0xff);
>
>      memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i2c_bus_ops,
> -                          s, name, aic->reg_size);
> +                          s, s->name, aic->reg_size);
>      sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
>
>      memory_region_init_io(&s->mr_pool, OBJECT(s), &aspeed_i2c_bus_pool_ops,
> @@ -1452,6 +1466,7 @@ static const Property aspeed_i2c_bus_properties[] = {
>      DEFINE_PROP_UINT8("bus-id", AspeedI2CBus, id, 0),
>      DEFINE_PROP_LINK("controller", AspeedI2CBus, controller, TYPE_ASPEED_I2C,
>                       AspeedI2CState *),
> +    DEFINE_PROP_STRING("bus-name", AspeedI2CBus, name),
>  };
>
>  static void aspeed_i2c_bus_class_init(ObjectClass *klass, const void *data)
> --
> 2.43.0
>
>

Reply via email to