microblaze: Simplify early console binding from DT
Michal Simek [Thu, 14 Apr 2011 09:48:43 +0000 (11:48 +0200)]
Recognize early Linux console from chosen - linux,stdout-path
instead of detecting the first console with appropriate
compatible strings.
This patch solved the problem on system with multiple
consoles.

Signed-off-by: Michal Simek <monstr@monstr.eu>

arch/microblaze/include/asm/prom.h
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/prom.c

index d0890d3..34c4e8b 100644 (file)
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
 /* Other Prototypes */
-extern int early_uartlite_console(void);
-extern int early_uart16550_console(void);
+enum early_consoles {
+       UARTLITE = 1,
+       UART16550 = 2,
+};
+
+extern int of_early_console(void *version);
 
 #ifdef CONFIG_PCI
 /*
index 8f8384e..e21390d 100644 (file)
@@ -127,45 +127,41 @@ void early_printk(const char *fmt, ...)
 
 int __init setup_early_printk(char *opt)
 {
+       int version = 0;
+
        if (early_console_initialized)
                return 1;
 
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-       base_addr = early_uartlite_console();
+       base_addr = of_early_console(&version);
        if (base_addr) {
-               early_console_initialized = 1;
 #ifdef CONFIG_MMU
                early_console_reg_tlb_alloc(base_addr);
 #endif
-               early_console = &early_serial_uartlite_console;
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
-
-               register_console(early_console);
-
-               return 0;
-       }
-#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-
+               switch (version) {
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+               case UARTLITE:
+                       printk(KERN_INFO "Early console on uartlite "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uartlite_console;
+                       break;
+#endif
 #ifdef CONFIG_SERIAL_8250_CONSOLE
-       base_addr = early_uart16550_console();
-       base_addr &= ~3; /* clear register offset */
-       if (base_addr) {
-               early_console_initialized = 1;
-#ifdef CONFIG_MMU
-               early_console_reg_tlb_alloc(base_addr);
+               case UART16550:
+                       printk(KERN_INFO "Early console on uart16650 "
+                                               "at 0x%08x\n", base_addr);
+                       early_console = &early_serial_uart16550_console;
+                       break;
 #endif
-               early_console = &early_serial_uart16550_console;
-
-               early_printk("early_printk_console is enabled at 0x%08x\n",
-                                                       base_addr);
+               default:
+                       printk(KERN_INFO  "Unsupported early console %d\n",
+                                                               version);
+                       return 1;
+               }
 
                register_console(early_console);
-
+               early_console_initialized = 1;
                return 0;
        }
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-
        return 1;
 }
 
index b15cc21..18d9371 100644 (file)
@@ -53,69 +53,57 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial(unsigned long node,
-                               const char *uname, int depth, void *data)
-{
-       unsigned long l;
-       char *p;
-       const __be32 *addr;
-
-       pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-       if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,axi-uartlite", 17) != 0))
-               return 0;
-
-       addr = of_get_flat_dt_prop(node, "reg", &l);
-       return be32_to_cpup(addr); /* return address */
-}
+char *stdout;
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uartlite_console(void)
-{
-       return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
-}
-
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial_full(unsigned long node,
+int __init early_init_dt_scan_chosen_serial(unsigned long node,
                                const char *uname, int depth, void *data)
 {
        unsigned long l;
        char *p;
-       unsigned int addr;
-
-       pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-/* find all serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
 
-       early_init_dt_check_for_initrd(node);
-
-/* find compatible node with uartlite */
-       p = of_get_flat_dt_prop(node, "compatible", &l);
-
-       if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
-               (strncmp(p, "xlnx,axi-uart16550", 18) != 0))
-               return 0;
-
-       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
-       addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
-       return be32_to_cpu(addr); /* return address */
+       pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
+
+       if (depth == 1 && (strcmp(uname, "chosen") == 0 ||
+                               strcmp(uname, "chosen@0") == 0)) {
+               p = of_get_flat_dt_prop(node, "linux,stdout-path", &l);
+               if (p != NULL && l > 0)
+                       stdout = p; /* store pointer to stdout-path */
+       }
+
+       if (stdout && strstr(stdout, uname)) {
+               p = of_get_flat_dt_prop(node, "compatible", &l);
+               pr_debug("Compatible string: %s\n", p);
+
+               if ((strncmp(p, "xlnx,xps-uart16550", 18) == 0) ||
+                       (strncmp(p, "xlnx,axi-uart16550", 18) == 0)) {
+                       unsigned int addr;
+
+                       *(u32 *)data = UART16550;
+
+                       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+                       addr += *(u32 *)of_get_flat_dt_prop(node,
+                                                       "reg-offset", &l);
+                       /* clear register offset */
+                       return be32_to_cpu(addr) & ~3;
+               }
+               if ((strncmp(p, "xlnx,xps-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,opb-uartlite", 17) == 0) ||
+                               (strncmp(p, "xlnx,axi-uartlite", 17) == 0)) {
+                       unsigned int *addrp;
+
+                       *(u32 *)data = UARTLITE;
+
+                       addrp = of_get_flat_dt_prop(node, "reg", &l);
+                       return be32_to_cpup(addrp); /* return address */
+               }
+       }
+       return 0;
 }
 
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uart16550_console(void)
+/* this function is looking for early console - Microblaze specific */
+int __init of_early_console(void *version)
 {
-       return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+       return of_scan_flat_dt(early_init_dt_scan_chosen_serial, version);
 }
 #endif