From 2e27c020cb5b3064b5d13fe044caa58cf94f0e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Sun, 21 Apr 2013 03:28:01 +0200 Subject: [PATCH] U-Boot: Factor-out debug UART setup from FDT for kernel use --- src/system/boot/platform/u-boot/serial.cpp | 83 +----------------- src/system/kernel/arch/ppc/Jamfile | 2 + .../kernel/platform/u-boot/fdt_support.cpp | 85 +++++++++++++++++++ 3 files changed, 90 insertions(+), 80 deletions(-) diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index ef94710504..4bf1a548e5 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -24,6 +24,8 @@ extern "C" { }; +extern "C" DebugUART *debug_uart_from_fdt(const void *fdt); + DebugUART* gUART; static int32 sSerialEnabled = 0; @@ -96,90 +98,11 @@ serial_cleanup(void) } -static void -serial_init_fdt(const void *fdt) -{ - const char *name; - const char *type; - int node; - int len; - phys_addr_t regs; - int32 clock = 0; - int32 speed = 0; - const void *prop; - - if (fdt == NULL) - return; - - name = fdt_get_alias(fdt, "serial"); - if (name == NULL) - name = fdt_get_alias(fdt, "serial0"); - if (name == NULL) - name = fdt_get_alias(fdt, "serial1"); - // TODO: else use /chosen linux,stdout-path - if (name == NULL) - return; - - node = fdt_path_offset(fdt, name); - //dprintf("serial: using '%s', node %d\n", name, node); - if (node < 0) - return; - - type = (const char *)fdt_getprop(fdt, node, "device_type", &len); - //dprintf("serial: type: '%s'\n", type); - if (type == NULL || strcmp(type, "serial")) - return; - - // determine the MMIO address - // TODO: ppc460 use 64bit addressing, but U-Boot seems to map it below 4G, - // and the FDT is not very clear. libfdt is also getting 64bit addr support. - // so FIXME someday. - prop = fdt_getprop(fdt, node, "virtual-reg", &len); - if (prop && len == 4) { - regs = fdt32_to_cpu(*(uint32_t *)prop); - //dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs); - } else { - prop = fdt_getprop(fdt, node, "reg", &len); - if (prop && len >= 4) { - regs = fdt32_to_cpu(*(uint32_t *)prop); - //dprintf("serial: reg 0x%08llx\n", (int64)regs); - } else - return; - } - - // get the UART clock rate - prop = fdt_getprop(fdt, node, "clock-frequency", &len); - if (prop && len == 4) { - clock = fdt32_to_cpu(*(uint32_t *)prop); - //dprintf("serial: clock %ld\n", clock); - } - - // get current speed (XXX: not yet passed over) - prop = fdt_getprop(fdt, node, "current-speed", &len); - if (prop && len == 4) { - speed = fdt32_to_cpu(*(uint32_t *)prop); - //dprintf("serial: speed %ld\n", speed); - } - - if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1 - || fdt_node_check_compatible(fdt, node, "ns16550") == 1) { - gUART = arch_get_uart_8250(regs, clock); - //dprintf("serial: using 8250\n"); - // XXX:assume speed is already set - (void)speed; - return; - } - - // for when we can use U-Boot's console - panic("Unknown UART type %s", type); -} - - extern "C" void serial_init(const void *fdt) { // first try with hints from the FDT - serial_init_fdt(fdt); + gUART = debug_uart_from_fdt(fdt); #ifdef BOARD_UART_DEBUG // fallback to hardcoded board UART diff --git a/src/system/kernel/arch/ppc/Jamfile b/src/system/kernel/arch/ppc/Jamfile index 493d20caa0..075c70ee73 100644 --- a/src/system/kernel/arch/ppc/Jamfile +++ b/src/system/kernel/arch/ppc/Jamfile @@ -26,6 +26,8 @@ KernelMergeObject kernel_arch_ppc.o : arch_vm.cpp arch_vm_translation_map.cpp arch_asm.S + debug_uart_8250.cpp + arch_uart_8250.cpp generic_vm_physical_page_mapper.cpp generic_vm_physical_page_ops.cpp diff --git a/src/system/kernel/platform/u-boot/fdt_support.cpp b/src/system/kernel/platform/u-boot/fdt_support.cpp index fe05f6f9ad..df4c79bde9 100644 --- a/src/system/kernel/platform/u-boot/fdt_support.cpp +++ b/src/system/kernel/platform/u-boot/fdt_support.cpp @@ -9,6 +9,9 @@ #include #include +#include +#include + extern "C" { #include #include @@ -21,6 +24,7 @@ void *gFDT; #endif extern "C" void dump_fdt(const void *fdt); +extern "C" DebugUART *debug_uart_from_fdt(const void *fdt); //#define FDT_DUMP_NODES //#define FDT_DUMP_PROPS @@ -117,3 +121,84 @@ void dump_fdt(const void *fdt) } +DebugUART * +debug_uart_from_fdt(const void *fdt) +{ + const char *name; + const char *type; + int node; + int len; + phys_addr_t regs; + int32 clock = 0; + int32 speed = 0; + const void *prop; + DebugUART *uart = NULL; + + if (fdt == NULL) + return NULL; + + name = fdt_get_alias(fdt, "serial"); + if (name == NULL) + name = fdt_get_alias(fdt, "serial0"); + if (name == NULL) + name = fdt_get_alias(fdt, "serial1"); + // TODO: else use /chosen linux,stdout-path + if (name == NULL) + return NULL; + + node = fdt_path_offset(fdt, name); + //dprintf("serial: using '%s', node %d\n", name, node); + if (node < 0) + return NULL; + + type = (const char *)fdt_getprop(fdt, node, "device_type", &len); + //dprintf("serial: type: '%s'\n", type); + if (type == NULL || strcmp(type, "serial")) + return NULL; + + // determine the MMIO address + // TODO: ppc460 use 64bit addressing, but U-Boot seems to map it below 4G, + // and the FDT is not very clear. libfdt is also getting 64bit addr support. + // so FIXME someday. + prop = fdt_getprop(fdt, node, "virtual-reg", &len); + if (prop && len == 4) { + regs = fdt32_to_cpu(*(uint32_t *)prop); + //dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs); + } else { + prop = fdt_getprop(fdt, node, "reg", &len); + if (prop && len >= 4) { + regs = fdt32_to_cpu(*(uint32_t *)prop); + //dprintf("serial: reg 0x%08llx\n", (int64)regs); + } else + return NULL; + } + + // get the UART clock rate + prop = fdt_getprop(fdt, node, "clock-frequency", &len); + if (prop && len == 4) { + clock = fdt32_to_cpu(*(uint32_t *)prop); + //dprintf("serial: clock %ld\n", clock); + } + + // get current speed (XXX: not yet passed over) + prop = fdt_getprop(fdt, node, "current-speed", &len); + if (prop && len == 4) { + speed = fdt32_to_cpu(*(uint32_t *)prop); + //dprintf("serial: speed %ld\n", speed); + } + + if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1 + || fdt_node_check_compatible(fdt, node, "ns16550") == 1) { + uart = arch_get_uart_8250(regs, clock); + //dprintf("serial: using 8250\n"); + // XXX:assume speed is already set + (void)speed; + } else { + // TODO: handle more UART types + // for when we can use U-Boot's console + panic("Unknown UART type %s", type); + } + + return uart; +} +