summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2010-09-14 09:38:18 +0200
committerStefan Roese <sr@denx.de>2010-09-23 08:43:56 +0200
commitab25e880ca9d508b7a807aa969105af32c3e6e51 (patch)
treee62fc4dc3265d01915badb5001c4313404ee47ab
parent6aa9195daecf18f682a825213a08d28224644b93 (diff)
downloadu-boot-imx-ab25e880ca9d508b7a807aa969105af32c3e6e51.zip
u-boot-imx-ab25e880ca9d508b7a807aa969105af32c3e6e51.tar.gz
u-boot-imx-ab25e880ca9d508b7a807aa969105af32c3e6e51.tar.bz2
ppc4xx: POST UART: Use in/out_8() io-accessor functions
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@denx.de>
-rw-r--r--include/ppc4xx.h10
-rw-r--r--post/cpu/ppc4xx/uart.c105
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@emcraft.com>
*
+ * Copyright 2010, Stefan Roese, DENX Software Engineering, sr@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 ();