On Wed, Jun 3, 2026 at 5:03 PM Joel Stanley <[email protected]> wrote:
>
> Add DesignWare I2C controllers to the tt-atlantis machine.
>
> Provide a fixed clock in the device tree so that the Linux driver probes
> without WARNing.
>
> Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
> Signed-off-by: Nicholas Piggin <[email protected]>
> Signed-off-by: Joel Stanley <[email protected]>

Acked-by: Alistair Francis <[email protected]>

Alistair

> ---
>  include/hw/riscv/tt_atlantis.h | 14 ++++++++
>  hw/riscv/tt_atlantis.c         | 59 ++++++++++++++++++++++++++++++++++
>  hw/riscv/Kconfig               |  1 +
>  3 files changed, 74 insertions(+)
>
> diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
> index a17732ce8114..7f7d4a5a5905 100644
> --- a/include/hw/riscv/tt_atlantis.h
> +++ b/include/hw/riscv/tt_atlantis.h
> @@ -11,12 +11,15 @@
>
>  #include "hw/core/boards.h"
>  #include "hw/core/sysbus.h"
> +#include "hw/i2c/designware_i2c.h"
>  #include "hw/intc/riscv_imsic.h"
>  #include "hw/riscv/riscv_hart.h"
>
>  #define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME("tt-atlantis")
>  OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE)
>
> +#define TT_ATL_NUM_I2C 5
> +
>  struct TTAtlantisState {
>      /*< private >*/
>      MachineState parent;
> @@ -27,11 +30,17 @@ struct TTAtlantisState {
>
>      RISCVHartArrayState soc;
>      DeviceState *irqchip;
> +    DesignWareI2CState i2c[TT_ATL_NUM_I2C];
>
>      int fdt_size;
>  };
>
>  enum {
> +    TT_ATL_I2C0_IRQ = 33,
> +    TT_ATL_I2C1_IRQ = 34,
> +    TT_ATL_I2C2_IRQ = 35,
> +    TT_ATL_I2C3_IRQ = 36,
> +    TT_ATL_I2C4_IRQ = 37,
>      TT_ATL_UART1_IRQ = 39,
>  };
>
> @@ -40,6 +49,11 @@ enum {
>      TT_ATL_BOOTROM,
>      TT_ATL_DDR_LO,
>      TT_ATL_DDR_HI,
> +    TT_ATL_I2C0,
> +    TT_ATL_I2C1,
> +    TT_ATL_I2C2,
> +    TT_ATL_I2C3,
> +    TT_ATL_I2C4,
>      TT_ATL_MAPLIC,
>      TT_ATL_MIMSIC,
>      TT_ATL_SAPLIC,
> diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
> index 5de138578b48..b1ff0cbe2f61 100644
> --- a/hw/riscv/tt_atlantis.c
> +++ b/hw/riscv/tt_atlantis.c
> @@ -53,6 +53,11 @@ static const MemMapEntry tt_atlantis_memmap[] = {
>      [TT_ATL_ACLINT] =           { 0xa2180000,       0x10000 },
>      [TT_ATL_SIMSIC] =           { 0xa4000000,      0x200000 },
>      [TT_ATL_MAPLIC] =           { 0xcc000000,     0x4000000 },
> +    [TT_ATL_I2C0] =             { 0xd4040000,       0x10000 },
> +    [TT_ATL_I2C1] =             { 0xd4050000,       0x10000 },
> +    [TT_ATL_I2C2] =             { 0xd4060000,       0x10000 },
> +    [TT_ATL_I2C3] =             { 0xd4070000,       0x10000 },
> +    [TT_ATL_I2C4] =             { 0xd4080000,       0x10000 },
>      [TT_ATL_UART1] =            { 0xd4110000,       0x10000 },
>      [TT_ATL_SAPLIC] =           { 0xe8000000,     0x4000000 },
>      [TT_ATL_DDR_HI] =          { 0x100000000,  0x1000000000 },
> @@ -333,10 +338,40 @@ static void create_fdt_rng(void *fdt)
>      qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
>  }
>
> +static void create_fdt_clk(void *fdt, const char *clock_name,
> +                           uint32_t freq, uint32_t phandle)
> +{
> +    g_autofree char *name = g_strdup_printf("/clocks/%s", clock_name);
> +
> +    qemu_fdt_add_path(fdt, name);
> +    qemu_fdt_setprop_string(fdt, name, "compatible", "fixed-clock");
> +    qemu_fdt_setprop_string(fdt, name, "clock-output-names", clock_name);
> +    qemu_fdt_setprop_cell(fdt, name, "#clock-cells", 0);
> +    qemu_fdt_setprop_cell(fdt, name, "clock-frequency", freq);
> +    qemu_fdt_setprop_cell(fdt, name, "phandle", phandle);
> +}
> +
> +static void create_fdt_i2c(void *fdt, const MemMapEntry *mem, uint32_t irq,
> +                           uint32_t irqchip_phandle, uint32_t clk_phandle)
> +{
> +    g_autofree char *name = g_strdup_printf("/soc/i2c@%"HWADDR_PRIX, 
> mem->base);
> +
> +    qemu_fdt_add_subnode(fdt, name);
> +    qemu_fdt_setprop_string(fdt, name, "compatible", "snps,designware-i2c");
> +    qemu_fdt_setprop_sized_cells(fdt, name, "reg", 2, mem->base, 2, 
> mem->size);
> +    qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irqchip_phandle);
> +    qemu_fdt_setprop_cells(fdt, name, "interrupts", irq, 0x4);
> +    qemu_fdt_setprop_cell(fdt, name, "clocks", clk_phandle);
> +    qemu_fdt_setprop_cell(fdt, name, "clock-frequency", 100000);
> +    qemu_fdt_setprop_cell(fdt, name, "#address-cells", 1);
> +    qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0);
> +}
> +
>  static void finalize_fdt(TTAtlantisState *s)
>  {
>      uint32_t aplic_s_phandle = next_phandle();
>      uint32_t imsic_s_phandle = next_phandle();
> +    uint32_t periph_clk_phandle = next_phandle();
>      void *fdt = MACHINE(s)->fdt;
>
>      create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle);
> @@ -350,6 +385,15 @@ static void finalize_fdt(TTAtlantisState *s)
>
>      create_fdt_uart(fdt, &s->memmap[TT_ATL_UART1], TT_ATL_UART1_IRQ,
>                      aplic_s_phandle);
> +
> +    create_fdt_clk(fdt, "periph-clk", 100000000, periph_clk_phandle);
> +
> +    for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
> +        create_fdt_i2c(fdt,
> +                       &s->memmap[TT_ATL_I2C0 + i],
> +                       TT_ATL_I2C0_IRQ + i,
> +                       aplic_s_phandle, periph_clk_phandle);
> +    }
>  }
>
>  static void create_fdt(TTAtlantisState *s)
> @@ -581,6 +625,21 @@ static void tt_atlantis_machine_init(MachineState 
> *machine)
>                                  s->memmap[TT_ATL_UART1].base,
>                                  s->memmap[TT_ATL_UART1].size);
>
> +    /* I2C */
> +    for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
> +        SysBusDevice *sbd;
> +
> +        object_initialize_child(OBJECT(s), "i2c[*]", &s->i2c[i],
> +                                TYPE_DESIGNWARE_I2C);
> +        sbd = SYS_BUS_DEVICE(&s->i2c[i]);
> +        sysbus_realize(sbd, &error_fatal);
> +        memory_region_add_subregion(system_memory,
> +                                    s->memmap[TT_ATL_I2C0 + i].base,
> +                                    sysbus_mmio_get_region(sbd, 0));
> +        sysbus_connect_irq(sbd, 0,
> +                           qdev_get_gpio_in(s->irqchip, TT_ATL_I2C0_IRQ + 
> i));
> +    }
> +
>      /* Load or create device tree */
>      if (machine->dtb) {
>          load_fdt(s);
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index aaf029c9ed5e..38180a903fbf 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -129,6 +129,7 @@ config TENSTORRENT
>      select RISCV_IMSIC
>      select SERIAL_MM
>      select DEVICE_TREE
> +    select DESIGNWARE_I2C
>
>  config XIANGSHAN_KUNMINGHU
>      bool
> --
> 2.47.3
>
>

Reply via email to