[U-Boot] [PATCH] ppc4xx: POST UART: Use in/out_8() io-accessor functions

Stefan Roese sr at denx.de
Tue Sep 14 10:42:33 CEST 2010


This patch fixes a problem in the PPC4xx POST UART driver. This driver
incorrectly used the in/out8() io-accessor functions. This could lead to
problems since these functions don't guarantee execution ordering. This
patch now replaces these functions with the correct ones.

Additionally the driver is converted to using the NS16550 struct instead
of macros for the register offsets.

And some common code is factored out for better maintainability.

Signed-off-by: Stefan Roese <sr at denx.de>
---
 include/ppc4xx.h       |   10 +++++
 post/cpu/ppc4xx/uart.c |  105 +++++++++++++++++++-----------------------------
 2 files changed, 51 insertions(+), 64 deletions(-)

diff --git a/include/ppc4xx.h b/include/ppc4xx.h
index ee30a4c..5238d04 100644
--- a/include/ppc4xx.h
+++ b/include/ppc4xx.h
@@ -99,6 +99,16 @@
 
 #endif /* 440EP/EPX 440GR/GRX 440SP/SPE 460EX/GT/SX 405EX*/
 
+/*
+ * Define ns16550 register offset for all PPC4xx SoC's. Some
+ * mostly FPGA based PPC4xx implementations use a different
+ * offset. So let's give them a chance to define their offset
+ * in the board config header.
+ */
+#if !defined(CONFIG_SYS_NS16550_REG_SIZE)
+#define CONFIG_SYS_NS16550_REG_SIZE	1
+#endif
+
 #if defined(CONFIG_440)
 #include <ppc440.h>
 #else
diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c
index be217fc..6b61cc1 100644
--- a/post/cpu/ppc4xx/uart.c
+++ b/post/cpu/ppc4xx/uart.c
@@ -4,6 +4,8 @@
  *
  * Author: Igor Lisitsin <igor at emcraft.com>
  *
+ * Copyright 2010, Stefan Roese, DENX Software Engineering, sr at denx.de
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -24,6 +26,9 @@
  */
 
 #include <common.h>
+#include <ppc4xx.h>
+#include <ns16550.h>
+#include <asm/io.h>
 
 /*
  * UART test
@@ -119,32 +124,23 @@
 #define UDIV_MAX        32
 #endif
 
-#define UART_RBR    0x00
-#define UART_THR    0x00
-#define UART_IER    0x01
-#define UART_IIR    0x02
-#define UART_FCR    0x02
-#define UART_LCR    0x03
-#define UART_MCR    0x04
-#define UART_LSR    0x05
-#define UART_MSR    0x06
-#define UART_SCR    0x07
-#define UART_DLL    0x00
-#define UART_DLM    0x01
+DECLARE_GLOBAL_DATA_PTR;
 
-/*
- * Line Status Register.
- */
-#define asyncLSRDataReady1            0x01
-#define asyncLSROverrunError1         0x02
-#define asyncLSRParityError1          0x04
-#define asyncLSRFramingError1         0x08
-#define asyncLSRBreakInterrupt1       0x10
-#define asyncLSRTxHoldEmpty1          0x20
-#define asyncLSRTxShiftEmpty1         0x40
-#define asyncLSRRxFifoError1          0x80
+static void uart_post_init_common(struct NS16550 *com_port, unsigned short bdiv)
+{
+	volatile char val;
 
-DECLARE_GLOBAL_DATA_PTR;
+	out_8(&com_port->lcr, 0x80);	/* set DLAB bit */
+	out_8(&com_port->dll, bdiv);	/* set baudrate divisor */
+	out_8(&com_port->dlm, bdiv >> 8); /* set baudrate divisor */
+	out_8(&com_port->lcr, 0x03);	/* clear DLAB; set 8 bits, no parity */
+	out_8(&com_port->fcr, 0x00);	/* disable FIFO */
+	out_8(&com_port->mcr, 0x10);	/* enable loopback mode */
+	val = in_8(&com_port->lsr);	/* clear line status */
+	val = in_8(&com_port->rbr);	/* read receive buffer */
+	out_8(&com_port->scr, 0x00);	/* set scratchpad */
+	out_8(&com_port->ier, 0x00);	/* set interrupt enable reg */
+}
 
 #if defined(CONFIG_440) || defined(CONFIG_405EX)
 #if !defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
@@ -190,19 +186,18 @@ static void serial_divs (int baudrate, unsigned long *pudiv,
 }
 #endif
 
-static int uart_post_init (unsigned long dev_base)
+static int uart_post_init (struct NS16550 *com_port)
 {
 	unsigned long reg = 0;
 	unsigned long udiv;
 	unsigned short bdiv;
-	volatile char val;
 #ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
 	unsigned long tmp;
 #endif
 	int i;
 
 	for (i = 0; i < 3500; i++) {
-		if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1)
+		if (in_8(&com_port->lsr) & UART_LSR_THRE)
 			break;
 		udelay (100);
 	}
@@ -239,34 +234,24 @@ static int uart_post_init (unsigned long dev_base)
 	MTREG(UART3_SDR, reg);
 #endif
 
-	out8(dev_base + UART_LCR, 0x80);	/* set DLAB bit */
-	out8(dev_base + UART_DLL, bdiv);	/* set baudrate divisor */
-	out8(dev_base + UART_DLM, bdiv >> 8);	/* set baudrate divisor */
-	out8(dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */
-	out8(dev_base + UART_FCR, 0x00);	/* disable FIFO */
-	out8(dev_base + UART_MCR, 0x10);	/* enable loopback mode */
-	val = in8(dev_base + UART_LSR);		/* clear line status */
-	val = in8(dev_base + UART_RBR);		/* read receive buffer */
-	out8(dev_base + UART_SCR, 0x00);	/* set scratchpad */
-	out8(dev_base + UART_IER, 0x00);	/* set interrupt enable reg */
+	uart_post_init_common(com_port, bdiv);
 
 	return 0;
 }
 
 #else /* CONFIG_440 */
 
-static int uart_post_init (unsigned long dev_base)
+static int uart_post_init (struct NS16550 *com_port)
 {
 	unsigned long reg;
 	unsigned long tmp;
 	unsigned long clk;
 	unsigned long udiv;
 	unsigned short bdiv;
-	volatile char val;
 	int i;
 
 	for (i = 0; i < 3500; i++) {
-		if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1)
+		if (in_8(&com_port->lsr) & UART_LSR_THRE)
 			break;
 		udelay (100);
 	}
@@ -309,59 +294,51 @@ static int uart_post_init (unsigned long dev_base)
 	bdiv = (clk + tmp / 2) / tmp;
 #endif /* CONFIG_405EZ */
 
-	out8(dev_base + UART_LCR, 0x80);	/* set DLAB bit */
-	out8(dev_base + UART_DLL, bdiv);	/* set baudrate divisor */
-	out8(dev_base + UART_DLM, bdiv >> 8);	/* set baudrate divisor */
-	out8(dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */
-	out8(dev_base + UART_FCR, 0x00);	/* disable FIFO */
-	out8(dev_base + UART_MCR, 0x10);	/* enable loopback mode */
-	val = in8(dev_base + UART_LSR);	/* clear line status */
-	val = in8(dev_base + UART_RBR);	/* read receive buffer */
-	out8(dev_base + UART_SCR, 0x00);	/* set scratchpad */
-	out8(dev_base + UART_IER, 0x00);	/* set interrupt enable reg */
-
-	return (0);
+	uart_post_init_common(com_port, bdiv);
+
+	return 0;
 }
 #endif /* CONFIG_440 */
 
-static void uart_post_putc (unsigned long dev_base, char c)
+static void uart_post_putc (struct NS16550 *com_port, char c)
 {
 	int i;
 
-	out8 (dev_base + UART_THR, c);	/* put character out */
+	out_8(&com_port->thr, c);	/* put character out */
 
 	/* Wait for transfer completion */
 	for (i = 0; i < 3500; i++) {
-		if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1)
+		if (in_8(&com_port->lsr) & UART_LSR_THRE)
 			break;
 		udelay (100);
 	}
 }
 
-static int uart_post_getc (unsigned long dev_base)
+static int uart_post_getc (struct NS16550 *com_port)
 {
 	int i;
 
 	/* Wait for character available */
 	for (i = 0; i < 3500; i++) {
-		if (in8 (dev_base + UART_LSR) & asyncLSRDataReady1)
+		if (in_8(&com_port->lsr) & UART_LSR_DR)
 			break;
 		udelay (100);
 	}
-	return 0xff & in8 (dev_base + UART_RBR);
+
+	return 0xff & in_8(&com_port->rbr);
 }
 
-static int test_ctlr (unsigned long dev_base, int index)
+static int test_ctlr (struct NS16550 *com_port, int index)
 {
 	int res = -1;
 	char test_str[] = "*** UART Test String ***\r\n";
 	int i;
 
-	uart_post_init (dev_base);
+	uart_post_init (com_port);
 
 	for (i = 0; i < sizeof (test_str) - 1; i++) {
-		uart_post_putc (dev_base, test_str[i]);
-		if (uart_post_getc (dev_base) != test_str[i])
+		uart_post_putc (com_port, test_str[i]);
+		if (uart_post_getc (com_port) != test_str[i])
 			goto done;
 	}
 	res = 0;
@@ -377,8 +354,8 @@ int uart_post_test (int flags)
 	int i, res = 0;
 	static unsigned long base[] = CONFIG_SYS_POST_UART_TABLE;
 
-	for (i = 0; i < sizeof (base) / sizeof (base[0]); i++) {
-		if (test_ctlr (base[i], i))
+	for (i = 0; i < ARRAY_SIZE(base); i++) {
+		if (test_ctlr((struct NS16550 *)base[i], i))
 			res = -1;
 	}
 	serial_reinit_all ();
-- 
1.7.2.3



More information about the U-Boot mailing list