microblaze: Simplify early console binding from DT

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>
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index d0890d3..34c4e8b 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -26,8 +26,12 @@
 #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
 /*
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index 8f8384e..e21390d 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -127,45 +127,41 @@
 
 int __init setup_early_printk(char *opt)
 {
+	int version = 0;
+
 	if (early_console_initialized)
 		return 1;
 
+	base_addr = of_early_console(&version);
+	if (base_addr) {
+#ifdef CONFIG_MMU
+		early_console_reg_tlb_alloc(base_addr);
+#endif
+		switch (version) {
 #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
-	base_addr = early_uartlite_console();
-	if (base_addr) {
-		early_console_initialized = 1;
-#ifdef CONFIG_MMU
-		early_console_reg_tlb_alloc(base_addr);
+		case UARTLITE:
+			printk(KERN_INFO "Early console on uartlite "
+						"at 0x%08x\n", base_addr);
+			early_console = &early_serial_uartlite_console;
+			break;
 #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 */
-
 #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;
 }
 
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index b15cc21..18d9371 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -53,69 +53,57 @@
 }
 
 #ifdef CONFIG_EARLY_PRINTK
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial(unsigned long node,
+char *stdout;
+
+int __init early_init_dt_scan_chosen_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);
+	pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
 
-/* find all serial nodes */
-	if (strncmp(uname, "serial", 6) != 0)
-		return 0;
+	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 */
+	}
 
-/* 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;
+	if (stdout && strstr(stdout, uname)) {
+		p = of_get_flat_dt_prop(node, "compatible", &l);
+		pr_debug("Compatible string: %s\n", p);
 
-	addr = of_get_flat_dt_prop(node, "reg", &l);
-	return be32_to_cpup(addr); /* return address */
+		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_uartlite_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, NULL);
-}
-
-/* MS this is Microblaze specifig function */
-static int __init early_init_dt_scan_serial_full(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 */
-}
-
-/* this function is looking for early uartlite console - Microblaze specific */
-int __init early_uart16550_console(void)
-{
-	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