Subject: [PATCH 3/3] [POWERPC] Xilinx: boot support for Xilinx uart 16550.

From: John Linn <[email-masked]>
Date: Thu, 20 Mar 2008 07:43:52 -0700

The Xilinx 16550 uart core is not a standard 16550, because it uses
word-based addressing rather than byte-based addressing.  As a result,
it is not compatible with the open firmware 'ns16550' compatible
binding.

This code adds the Xilinx uart 16550 to the serial console
of the boot. A new initialization function for the Xilinx 16550 uart
is added to the ns16550 driver. It sets up the correct register base
and regshift properties specific to the Xilinx 16550.

Signed-off-by: John Linn <[email-masked]>
---
 arch/powerpc/boot/ns16550.c |   24 ++++++++++++++++++++++++
 arch/powerpc/boot/ops.h     |    1 +
 arch/powerpc/boot/serial.c  |    8 ++++++++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
index f8f1b2f..5385255 100644
--- a/arch/powerpc/boot/ns16550.c
+++ b/arch/powerpc/boot/ns16550.c
@@ -77,3 +77,27 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp)
 
 	return 0;
 }
+
+int xilinx16550_console_init(void *devp, struct serial_console_data *scdp)
+{
+	int n;
+	unsigned long reg_phys;
+
+	n = getprop(devp, "virtual-reg", &reg_base, sizeof(reg_base));
+	if (n != sizeof(reg_base)) {
+		if (!dt_xlate_reg(devp, 0, &reg_phys, NULL))
+			return -1;
+
+		reg_base = (void *)reg_phys + 3;
+	}
+
+	reg_shift = 2;
+
+	scdp->open = ns16550_open;
+	scdp->putc = ns16550_putc;
+	scdp->getc = ns16550_getc;
+	scdp->tstc = ns16550_tstc;
+	scdp->close = NULL;
+
+	return 0;
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index a180b65..d8b864b 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -86,6 +86,7 @@ int mpsc_console_init(void *devp, struct serial_console_data *scdp);
 int cpm_console_init(void *devp, struct serial_console_data *scdp);
 int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp);
 int uartlite_console_init(void *devp, struct serial_console_data *scdp);
+int xilinx16550_console_init(void *devp, struct serial_console_data *scdp);
 void *simple_alloc_init(char *base, unsigned long heap_size,
 			unsigned long granularity, unsigned long max_allocs);
 extern void flush_cache(void *, unsigned long);
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index 7fa5078..fb5c91e 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -131,6 +131,14 @@ int serial_console_init(void)
 	else if (dt_is_compatible(devp, "xlnx,opb-uartlite-1.00.b") ||
                  dt_is_compatible(devp, "xlnx,xps-uartlite-1.00.a"))
 		rc = uartlite_console_init(devp, &serial_cd);
+	else if (dt_is_compatible(devp, "xlnx,opb-uart16550-1.00.c") ||
+		 dt_is_compatible(devp, "xlnx,opb-uart16550-1.00.d") ||
+		 dt_is_compatible(devp, "xlnx,opb-uart16550-1.00.e") ||
+		 dt_is_compatible(devp, "xlnx,plb-uart16550-1.00.c") ||
+		 dt_is_compatible(devp, "xlnx,xps-uart16550-1.00.a") ||
+		 dt_is_compatible(devp, "xlnx,xps-uart16550-2.00.a") ||
+		 dt_is_compatible(devp, "xlnx,xps-uart16550-2.00.b"))
+		rc = xilinx16550_console_init(devp, &serial_cd);
 
 	/* Add other serial console driver calls here */
 
-- 
1.5.2.1