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 d567ec1155..32ba755bbf 100644
--- a/hw/riscv/tt_atlantis.c
+++ b/hw/riscv/tt_atlantis.c
@@ -420,6 +420,29 @@ 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_chosen = ams->uart_chosen ? ams->uart_chosen :
TT_ATL_UART1;
+ int uart_index = tt_atlantis_uart_index(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++));
+ }
+}
+
+
static void tt_atlantis_machine_done(Notifier *n, void *data)
{
TTAtlantisState *ams = container_of(n, TTAtlantisState,
machine_done);
@@ -482,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);
@@ -590,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)) {
@@ -661,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 */
@@ -678,6 +696,45 @@ static void
tt_atlantis_machine_init(MachineState *machine)
qemu_add_machine_init_done_notifier(&ams->machine_done);
}
+static char *tt_atlantis_get_console(Object *obj, Error **errp)
+{
+ TTAtlantisState *ams = TT_ATLANTIS_MACHINE(obj);
+
+ /* Default to Ascalon console */
+ int uart_chosen = ams->uart_chosen ? ams->uart_chosen :
TT_ATL_UART1;
+
+ return g_strdup_printf("uart%d",
tt_atlantis_uart_index(uart_chosen));
+}
+
+static void tt_atlantis_set_console(Object *obj, const char *value,
Error **errp)
+{
+ TTAtlantisState *ams = TT_ATLANTIS_MACHINE(obj);
+
+ int val;
+ int uart_first = tt_atlantis_uart_index(TT_ATL_UART0);
+ int uart_last = tt_atlantis_uart_index(TT_ATL_UART4);
+
+ if (sscanf(value, "uart%d", &val) != 1 || val < 0) {
+ error_setg(errp, "Bad value for \"uart\" property");
+ return;
+ }
+
+ if (val < uart_first || val > uart_last) {
+ error_setg(errp, "\"uart\" should be in range [%d - %d]",
+ uart_first, uart_last);
+ return;
+ }
+ ams->uart_chosen = val + TT_ATL_UART0;
+}
+
+static void tt_atlantis_machine_class_props_init(ObjectClass *oc)
+{
+ object_class_property_add_str(oc, "console",
tt_atlantis_get_console,
+ tt_atlantis_set_console);
+ object_class_property_set_description(oc, "console",
+ "Change the default UART to \"uartX\"");
+}
+
static void tt_atlantis_machine_class_init(ObjectClass *oc, const
void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -691,6 +748,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 {