Add a common uart FDT helper to be used by 'virt' and the future 'riscv-server-ref' board.
The 'tt-atlantis' board is left out of this patch because it's going through UART related changes and its FDT might change soon, thus it's better to wait for the final DT to be determined and then we can evaluate whether it can share a common helper. The "/chosen" and "/alias" changes are UART0 only so we're keeping them out of the common helper. The board can set both manually as appropriate. No FDT changes intended. Signed-off-by: Daniel Henrique Barboza <[email protected]> Reviewed-by: Philippe Mathieu-Daudé <[email protected]> --- hw/riscv/fdt-common.c | 29 +++++++++++++++++++++++++++++ hw/riscv/virt.c | 35 +++++++++-------------------------- include/hw/riscv/fdt-common.h | 5 +++++ 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c index 76a783709d..e8186230b7 100644 --- a/hw/riscv/fdt-common.c +++ b/hw/riscv/fdt-common.c @@ -22,6 +22,8 @@ #include "hw/pci/pcie_host.h" #include "hw/riscv/aia.h" +#define UART_STD_CLOCK_FREQ 3686400 /* 3.6864 MHz */ + void *riscv_create_board_device_tree(const char *model, const char *compatible, int *fdt_size) { @@ -798,3 +800,30 @@ void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props, g_free(name); } } + +char *riscv_fdt_get_uart_nodename(hwaddr addr) +{ + return g_strdup_printf("/soc/serial@%"HWADDR_PRIx, addr); +} + +void riscv_create_fdt_uart(void *fdt, const MemMapEntry *uart_mem, + int uart_irq, int aia_type, + uint32_t irq_phandle) +{ + g_autofree char *name = riscv_fdt_get_uart_nodename(uart_mem->base); + + qemu_fdt_add_subnode(fdt, name); + qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a"); + qemu_fdt_setprop_sized_cells(fdt, name, "reg", + 2, uart_mem->base, + 2, uart_mem->size); + + qemu_fdt_setprop_cell(fdt, name, "clock-frequency", UART_STD_CLOCK_FREQ); + qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irq_phandle); + + if (aia_type == AIA_TYPE_NONE) { + qemu_fdt_setprop_cell(fdt, name, "interrupts", uart_irq); + } else { + qemu_fdt_setprop_cells(fdt, name, "interrupts", uart_irq, 0x4); + } +} diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 717a01da8d..3e40513dc1 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -418,39 +418,22 @@ static void create_fdt_virtio(RISCVVirtState *s, uint32_t irq_virtio_phandle) } } -static void create_fdt_uart(RISCVVirtState *s, - uint32_t irq_mmio_phandle, int memId, int irqNo) +static void create_fdt_uarts(RISCVVirtState *s, uint32_t irq_mmio_phandle) { g_autofree char *name = NULL; MachineState *ms = MACHINE(s); - name = g_strdup_printf("/soc/serial@%"HWADDR_PRIx, - s->memmap[memId].base); - qemu_fdt_add_subnode(ms->fdt, name); - qemu_fdt_setprop_string(ms->fdt, name, "compatible", "ns16550a"); - qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg", - 2, s->memmap[memId].base, - 2, s->memmap[memId].size); - qemu_fdt_setprop_cell(ms->fdt, name, "clock-frequency", 3686400); - qemu_fdt_setprop_cell(ms->fdt, name, "interrupt-parent", irq_mmio_phandle); - if (s->aia_type == VIRT_AIA_TYPE_NONE) { - qemu_fdt_setprop_cell(ms->fdt, name, "interrupts", irqNo); - } else { - qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", irqNo, 0x4); + if (s->uart1_present) { + riscv_create_fdt_uart(ms->fdt, &s->memmap[VIRT_UART1], + UART1_IRQ, s->aia_type, irq_mmio_phandle); } - if (VIRT_UART0 == memId) { - qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name); - qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name); - } -} + riscv_create_fdt_uart(ms->fdt, &s->memmap[VIRT_UART0], UART0_IRQ, + s->aia_type, irq_mmio_phandle); -static void create_fdt_uarts(RISCVVirtState *s, uint32_t irq_mmio_phandle) -{ - if (s->uart1_present) { - create_fdt_uart(s, irq_mmio_phandle, VIRT_UART1, UART1_IRQ); - } - create_fdt_uart(s, irq_mmio_phandle, VIRT_UART0, UART0_IRQ); + name = riscv_fdt_get_uart_nodename(s->memmap[VIRT_UART0].base); + qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name); + qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name); } static void create_fdt_rtc(RISCVVirtState *s, diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h index a45b063f66..c8b25348bd 100644 --- a/include/hw/riscv/fdt-common.h +++ b/include/hw/riscv/fdt-common.h @@ -128,4 +128,9 @@ void riscv_create_fdt_socket_aplic(void *fdt, APLICFdtProps *props, uint32_t *aplic_phandles); void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props, uint32_t *intc_phandles); +/* Caller must free the returned string. */ +char *riscv_fdt_get_uart_nodename(hwaddr addr); +void riscv_create_fdt_uart(void *fdt, const MemMapEntry *uart_mem, + int uart_irq, int aia_type, + uint32_t irq_phandle); #endif -- 2.43.0
