On Thu, 2026-10-08 at 09:02 +1000, Portia Stephens wrote:
> 
> On 6/10/2026 11:35 PM, Alistair wrote:
> > On Fri, 2026-10-02 at 09:33 +1000, Portia Stephens wrote:
> > > The Atlantis SoC has 5 UARTs. This adds a machine property to set
> > > which uart is on the first serial interface. This is the same
> > > pattern
> > > that is used by aspeed. The rest of the uart's will be added in
> > > sequential order starting at serial interface 1.
> > > 
> > > The default value is uart1 which means the Ascalon console will
> > > be on
> > > serial interface 0 by default.
> > > 
> > > Signed-off-by: Portia Stephens <[email protected]>
> > > Reviewed-by: Daniel Henrique Barboza
> > > <[email protected]>
> > > ---
> > >   hw/riscv/tt_atlantis.c         | 77
> > > ++++++++++++++++++++++++++++++--
> > > --
> > >   include/hw/riscv/tt_atlantis.h |  1 +
> > >   2 files changed, 69 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c
> > > index 2342edce93..7a5e1ddcd1 100644
> > > --- a/hw/riscv/tt_atlantis.c
> > > +++ b/hw/riscv/tt_atlantis.c
> > > @@ -12,6 +12,7 @@
> > >   #include "qemu/error-report.h"
> > >   #include "qemu/guest-random.h"
> > >   #include "qemu/units.h"
> > > +#include "qapi/visitor.h"
> > >   
> > >   #include "hw/core/boards.h"
> > >   #include "hw/core/loader.h"
> > > @@ -422,6 +423,26 @@ static void load_fdt(TTAtlantisState *ams)
> > >       create_fdt_memory(ms->fdt, &ams->soc);
> > >   }
> > >   
> > > +static inline int tt_atlantis_uart_index(int uart_dev)
> > > +{
> > > +    return uart_dev - TT_ATL_UART0;
> > > +}
> > > +
> > > +static void
> > > tt_atlantis_connect_serial_hds_to_uarts(TTAtlantisState
> > > *ams)
> > > +{
> > > +    TTAtlantisSoCState *s = &ams->soc;
> > > +    int uart_index = tt_atlantis_uart_index(ams->uart_chosen);
> > > +
> > > +    qdev_prop_set_chr(DEVICE(&s->uart[uart_index]), "chardev",
> > > serial_hd(0));
> > > +
> > > +    for (int i = 1, uart = 0; i < TT_ATL_NUM_UARTS; uart++) {
> > > +        if (uart == uart_index) {
> > > +            continue;
> > > +        }
> > > +        qdev_prop_set_chr(DEVICE(&s->uart[uart]), "chardev",
> > > serial_hd(i++));
> > > +    }
> > I don't like this. We shouldn't dynamically change the command line
> > API
> > based on a property
> 
> 
> Fair enough, can we just take the first 3 patches in the series and
> drop 
> this one? That will add modeling for all the uarts but only expose
> uart1 
> on command line.

This is path 3 though. Do you mean take the first 2 patches?

I can do that if you want

Alistair

> 
> 
> We will expose the remaining uarts as features as added to the model 
> that produce output that anyone would care to look at. For example, 
> uart0 is the system controller's console, when the system controller
> is 
> added to the model then we will expose uart0 on the command line.
> This 
> will prevent us from locking into a command line API before we need
> to.
> 
> 
> 
> > 
> > Alistair
> > 
> > > +}
> > > +
> > >   static void tt_atlantis_machine_done(Notifier *n, void *data)
> > >   {
> > >       TTAtlantisState *ams = container_of(n, TTAtlantisState,
> > > machine_done);
> > > @@ -484,11 +505,6 @@ 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);
> > > @@ -592,10 +608,6 @@ 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-
> > > > 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)) {
> > > @@ -663,6 +675,10 @@ static void
> > > tt_atlantis_machine_init(MachineState *machine)
> > >                                OBJECT(&ams->soc_memory),
> > > &error_abort);
> > >       object_property_set_link(OBJECT(&ams->soc), "dram",
> > > OBJECT(machine->ram),
> > >                                &error_abort);
> > > +
> > > +    /* Map serial interfaces to uart */
> > > +    tt_atlantis_connect_serial_hds_to_uarts(ams);
> > > +
> > >       qdev_realize(DEVICE(&ams->soc), NULL, &error_fatal);
> > >   
> > >       /* I2C peripherals: qemu specific */
> > > @@ -680,6 +696,47 @@ static void
> > > tt_atlantis_machine_init(MachineState *machine)
> > >       qemu_add_machine_init_done_notifier(&ams->machine_done);
> > >   }
> > >   
> > > +static void tt_atlantis_get_console(Object *obj, Visitor *v,
> > > const
> > > char *name,
> > > +                                    void *opaque, Error **errp)
> > > +{
> > > +    TTAtlantisState *ams = TT_ATLANTIS_MACHINE(obj);
> > > +    uint32_t uart_index = tt_atlantis_uart_index(ams-
> > > >uart_chosen);
> > > +
> > > +    visit_type_uint32(v, name, &uart_index, errp);
> > > +}
> > > +
> > > +static void tt_atlantis_set_console(Object *obj, Visitor *v,
> > > const
> > > char *name,
> > > +                                    void *opaque, Error **errp)
> > > +{
> > > +    TTAtlantisState *ams = TT_ATLANTIS_MACHINE(obj);
> > > +    uint32_t value;
> > > +
> > > +    if (!visit_type_uint32(v, name, &value, errp)) {
> > > +        return;
> > > +    }
> > > +
> > > +    if (value >= TT_ATL_NUM_UARTS) {
> > > +        error_setg(errp, "\"console\" should be in range [%d -
> > > %d]",
> > > +                   0, TT_ATL_NUM_UARTS - 1);
> > > +        return;
> > > +    }
> > > +    ams->uart_chosen = value + TT_ATL_UART0;
> > > +}
> > > +
> > > +static void tt_atlantis_machine_class_props_init(ObjectClass
> > > *oc)
> > > +{
> > > +    ObjectProperty *console;
> > > +
> > > +    console = object_class_property_add(oc, "console",
> > > "uint32_t",
> > > +                                        tt_atlantis_get_console,
> > > +                                        tt_atlantis_set_console,
> > > NULL, NULL);
> > > +    object_class_property_set_description(oc, "console",
> > > +            "Change the default UART index on -serial. Valid
> > > values
> > > are 0 " \
> > > +            "through 4");
> > > +    /* Default to UART1, the Ascalon console */
> > > +    object_property_set_default_uint(console, 1);
> > > +}
> > > +
> > >   static void tt_atlantis_machine_class_init(ObjectClass *oc,
> > > const
> > > void *data)
> > >   {
> > >       MachineClass *mc = MACHINE_CLASS(oc);
> > > @@ -693,6 +750,8 @@ static void
> > > tt_atlantis_machine_class_init(ObjectClass *oc, const void *data)
> > >       mc->block_default_type = IF_VIRTIO;
> > >       mc->no_cdrom = 1;
> > >       mc->default_ram_id = "tt_atlantis.ram";
> > > +
> > > +    tt_atlantis_machine_class_props_init(oc);
> > >   }
> > >   
> > >   static const TypeInfo tt_atlantis_types[] = {
> > > diff --git a/include/hw/riscv/tt_atlantis.h
> > > b/include/hw/riscv/tt_atlantis.h
> > > index b81b7c8abd..7bd46e9c9b 100644
> > > --- a/include/hw/riscv/tt_atlantis.h
> > > +++ b/include/hw/riscv/tt_atlantis.h
> > > @@ -56,6 +56,7 @@ struct TTAtlantisState {
> > >   
> > >       MemoryRegion soc_memory;
> > >       TTAtlantisSoCState soc;
> > > +    uint32_t uart_chosen;
> > >   };
> > >   
> > >   enum {

Reply via email to