On 9/29/2026 12:16 AM, [email protected] wrote:
From: Portia Stephens <[email protected]>

Previously only the Ascalon console UART was enabled, this enables all 5
UARTs on the SoC. Only UART1 is added to the serial interface for now.
The next change will handle adding the rest of the UARTs.

Signed-off-by: Portia Stephens <[email protected]>
---

Reviewed-by: Daniel Henrique Barboza <[email protected]>

  hw/riscv/tt_atlantis.c         | 54 +++++++++++++++++++++++++---------
  include/hw/riscv/tt_atlantis.h | 11 ++++++-
  2 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
index e889951677..d567ec1155 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -63,7 +63,11 @@ static const MemMapEntry tt_atlantis_memmap[] = {
      [TT_ATL_I2C2] =             { 0xd4060000,       0x10000 },
      [TT_ATL_I2C3] =             { 0xd4070000,       0x10000 },
      [TT_ATL_I2C4] =             { 0xd4080000,       0x10000 },
+    [TT_ATL_UART0] =            { 0xd4100000,       0x10000 },
      [TT_ATL_UART1] =            { 0xd4110000,       0x10000 },
+    [TT_ATL_UART2] =            { 0xd4120000,       0x10000 },
+    [TT_ATL_UART3] =            { 0xd4130000,       0x10000 },
+    [TT_ATL_UART4] =            { 0xd4140000,       0x10000 },
      [TT_ATL_SAPLIC] =           { 0xe8000000,     0x4000000 },
      [TT_ATL_DDR_HI] =          { 0x100000000,  0x1000000000 },
  };
@@ -260,11 +264,12 @@ static void create_fdt_cpu(void *fdt, TTAtlantisSoCState 
*s,
  }
static void create_fdt_uart(void *fdt, const MemMapEntry *mem, int irq,
-                            int irqchip_phandle)
+                            int irqchip_phandle, int index)
  {
      static const char compat[] = "snps,dw-apb-uart\0ns16550a";
      g_autofree char *name = g_strdup_printf("/soc/serial@%"HWADDR_PRIX,
                                              mem->base);
+    g_autofree char *alias = g_strdup_printf("serial%d", index);
qemu_fdt_add_subnode(fdt, name);
      qemu_fdt_setprop(fdt, name, "compatible", compat, sizeof(compat));
@@ -275,8 +280,10 @@ static void create_fdt_uart(void *fdt, const MemMapEntry 
*mem, int irq,
      qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irqchip_phandle);
      qemu_fdt_setprop_cells(fdt, name, "interrupts", irq, 0x4);
- qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name);
-    qemu_fdt_setprop_string(fdt, "/aliases", "serial0", name);
+    if (index == 0) {
+        qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name);
+    }
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, name);
  }
static void create_fdt_rng(void *fdt)
@@ -345,8 +352,11 @@ static void finalize_fdt(void *fdt, TTAtlantisSoCState *s)
       *                       aplic_s_phandle);
       */
- create_fdt_uart(fdt, &s->memmap[TT_ATL_UART1], TT_ATL_UART1_IRQ,
-                    aplic_s_phandle);
+    /* Skip UART0 since it is the RCPU console, UART1 is the Ascalon console */
+    for (int i = 0; i < TT_ATL_NUM_UARTS - 1; i++) {
+        create_fdt_uart(fdt, &s->memmap[TT_ATL_UART1 + i], TT_ATL_UART1_IRQ + 
i,
+                        aplic_s_phandle, i);
+    }
create_fdt_clk(fdt, "periph-clk", 100000000, periph_clk_phandle); @@ -472,13 +482,21 @@ static void tt_atlantis_machine_done(Notifier *n, void *data)
                                fdt_load_addr);
  }
+static inline int tt_atlantis_uart_index(int uart_dev)
+{
+    return uart_dev - TT_ATL_UART0;
+}
+
  static void tt_atlantis_soc_init(Object *obj)
  {
      TTAtlantisSoCState *s = TT_ATLANTIS_SOC(obj);
object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); - object_initialize_child(obj, "uart1", &s->uart1, TYPE_DW8250);
+    for (int i = 0; i < TT_ATL_NUM_UARTS; i++) {
+        object_initialize_child(OBJECT(s), "uart[*]", &s->uart[i],
+                                TYPE_DW8250);
+    }
for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
          object_initialize_child(obj, "i2c[*]", &s->i2c[i],
@@ -572,14 +590,22 @@ static void tt_atlantis_soc_realize(DeviceState *dev, 
Error **errp)
      memory_region_add_subregion(s->memory, s->memmap[TT_ATL_BOOTROM].base,
                                  &s->bootrom);
- /* UART1, the soc console (UART0 is for the boot microcontroller) */
-    qdev_prop_set_chr(DEVICE(&s->uart1), "chardev", serial_hd(0));
-    sysbus_realize(SYS_BUS_DEVICE(&s->uart1), &error_fatal);
-    memory_region_add_subregion(s->memory,
-                                s->memmap[TT_ATL_UART1].base,
-                                
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart1), 0));
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart1), 0,
-                       qdev_get_gpio_in(s->irqchip, TT_ATL_UART1_IRQ));
+    /* UART1, the soc console (UART0 is for the boot microcontroller */
+    qdev_prop_set_chr(DEVICE(&s->uart[tt_atlantis_uart_index(TT_ATL_UART1)]),
+                      "chardev", serial_hd(0));
+
+    for (int i = 0; i < TT_ATL_NUM_UARTS; i++) {
+        SysBusDevice *sbd = SYS_BUS_DEVICE(&s->uart[i]);
+        if (!sysbus_realize(sbd, errp)) {
+            return;
+        }
+
+        memory_region_add_subregion(s->memory,
+                                    s->memmap[TT_ATL_UART0 + i].base,
+                                    sysbus_mmio_get_region(sbd, 0));
+        sysbus_connect_irq(sbd, 0,
+                           qdev_get_gpio_in(s->irqchip, TT_ATL_UART0_IRQ + i));
+    }
/* I2C */
      for (int i = 0; i < TT_ATL_NUM_I2C; i++) {
diff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h
index 000988c037..b81b7c8abd 100644
--- a/include/hw/riscv/tt_atlantis.h
+++ b/include/hw/riscv/tt_atlantis.h
@@ -23,6 +23,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, 
TT_ATLANTIS_MACHINE)
  OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisSoCState, TT_ATLANTIS_SOC)
#define TT_ATL_NUM_I2C 5
+#define TT_ATL_NUM_UARTS 5
struct TTAtlantisSoCState {
      /*< private >*/
@@ -39,7 +40,7 @@ struct TTAtlantisSoCState {
      RISCVHartArrayState cpus;
      DeviceState *irqchip;
      DesignWareI2CState i2c[TT_ATL_NUM_I2C];
-    DW8250State uart1;
+    DW8250State uart[TT_ATL_NUM_UARTS];
      MemoryRegion bootrom;
uint32_t num_harts;
@@ -63,7 +64,11 @@ enum {
      TT_ATL_I2C2_IRQ = 35,
      TT_ATL_I2C3_IRQ = 36,
      TT_ATL_I2C4_IRQ = 37,
+    TT_ATL_UART0_IRQ = 38,
      TT_ATL_UART1_IRQ = 39,
+    TT_ATL_UART2_IRQ = 40,
+    TT_ATL_UART3_IRQ = 41,
+    TT_ATL_UART4_IRQ = 42,
  };
enum {
@@ -80,7 +85,11 @@ enum {
      TT_ATL_MIMSIC,
      TT_ATL_SAPLIC,
      TT_ATL_SIMSIC,
+    TT_ATL_UART0,
      TT_ATL_UART1,
+    TT_ATL_UART2,
+    TT_ATL_UART3,
+    TT_ATL_UART4,
  };
#endif


Reply via email to