diff options
author | Stefan Roese <sr@denx.de> | 2010-09-29 16:58:38 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2010-10-04 11:20:02 +0200 |
commit | 5d7c73e65b518a63a861a1a9c4965b6e67ae89a6 (patch) | |
tree | a2a9e84d21ef0b60dc5ab204db2f39fa03a4b88b /post | |
parent | 98303292ad80245ef6707c89b2f16095ee1e1db3 (diff) | |
download | u-boot-5d7c73e65b518a63a861a1a9c4965b6e67ae89a6.tar.gz |
ppc4xx: Use common ns16550 functions in 4xx UART POST driver
This patch changes the PPC4xx POST UART driver to use the common
NS16550 functions for receiving and sending. Additionally the
local function for SoC divisor setup are removed. Instead the
functions from arch/powerpc/cpu/ppc4xx/4xx_uart.c are used. This
removes code duplication.
Also the common CONFIG_SYS_NS16550_COMx defines are now used
to describe the POST UART's.
And a compile breakage is fixed, introduced by a git merge of
the ppc4xx/next branch into master. Now "ppc4xx.h" is moved to
"asm/ppc4xx.h". Fixed as well with this patch.
Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'post')
-rw-r--r-- | post/cpu/ppc4xx/uart.c | 302 |
1 files changed, 22 insertions, 280 deletions
diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index 6b61cc191e..d76895696b 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -26,9 +26,10 @@ */ #include <common.h> -#include <ppc4xx.h> +#include <asm/ppc4xx.h> #include <ns16550.h> #include <asm/io.h> +#include <serial.h> /* * UART test @@ -46,299 +47,40 @@ * be overridden in the board config file */ #ifndef CONFIG_SYS_POST_UART_TABLE -#define CONFIG_SYS_POST_UART_TABLE {UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE} -#endif - -#include <asm/processor.h> -#include <serial.h> - -#if defined(CONFIG_440) -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define UART0_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000300 -#define UART1_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000400 -#define UART2_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000500 -#define UART3_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000600 -#else -#define UART0_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000200 -#define UART1_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000300 -#endif - -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) -#define UART2_BASE CONFIG_SYS_PERIPHERAL_BASE + 0x00000600 -#endif - -#if defined(CONFIG_440GP) -#define CR0_MASK 0x3fff0000 -#define CR0_EXTCLK_ENA 0x00600000 -#define CR0_UDIV_POS 16 -#define UDIV_SUBTRACT 1 -#define UART0_SDR CPC0_CR0 -#define MFREG(a, d) d = mfdcr(a) -#define MTREG(a, d) mtdcr(a, d) -#else /* #if defined(CONFIG_440GP) */ -/* all other 440 PPC's access clock divider via sdr register */ -#define CR0_MASK 0xdfffffff -#define CR0_EXTCLK_ENA 0x00800000 -#define CR0_UDIV_POS 0 -#define UDIV_SUBTRACT 0 -#define UART0_SDR SDR0_UART0 -#define UART1_SDR SDR0_UART1 -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) -#define UART2_SDR SDR0_UART2 -#endif -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) -#define UART3_SDR SDR0_UART3 -#endif -#define MFREG(a, d) mfsdr(a, d) -#define MTREG(a, d) mtsdr(a, d) -#endif /* #if defined(CONFIG_440GP) */ -#elif defined(CONFIG_405EP) || defined(CONFIG_405EZ) -#define UART0_BASE 0xef600300 -#define UART1_BASE 0xef600400 -#define UCR0_MASK 0x0000007f -#define UCR1_MASK 0x00007f00 -#define UCR0_UDIV_POS 0 -#define UCR1_UDIV_POS 8 -#define UDIV_MAX 127 -#elif defined(CONFIG_405EX) -#define UART0_BASE 0xef600200 -#define UART1_BASE 0xef600300 -#define CR0_MASK 0x000000ff -#define CR0_EXTCLK_ENA 0x00800000 -#define CR0_UDIV_POS 0 -#define UDIV_SUBTRACT 0 -#define UART0_SDR SDR0_UART0 -#define UART1_SDR SDR0_UART1 -#define MFREG(a, d) mfsdr(a, d) -#define MTREG(a, d) mtsdr(a, d) -#else /* CONFIG_405GP || CONFIG_405CR */ -#define UART0_BASE 0xef600300 -#define UART1_BASE 0xef600400 -#define CR0_MASK 0x00001fff -#define CR0_EXTCLK_ENA 0x000000c0 -#define CR0_UDIV_POS 1 -#define UDIV_MAX 32 +#define CONFIG_SYS_POST_UART_TABLE { CONFIG_SYS_NS16550_COM1, \ + CONFIG_SYS_NS16550_COM2, CONFIG_SYS_NS16550_COM3, \ + CONFIG_SYS_NS16550_COM4 } #endif DECLARE_GLOBAL_DATA_PTR; -static void uart_post_init_common(struct NS16550 *com_port, unsigned short bdiv) -{ - volatile char val; - - 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) -static void serial_divs (int baudrate, unsigned long *pudiv, - unsigned short *pbdiv) -{ - sys_info_t sysinfo; - unsigned long div; /* total divisor udiv * bdiv */ - unsigned long umin; /* minimum udiv */ - unsigned short diff; /* smallest diff */ - unsigned long udiv; /* best udiv */ - unsigned short idiff; /* current diff */ - unsigned short ibdiv; /* current bdiv */ - unsigned long i; - unsigned long est; /* current estimate */ - - get_sys_info(&sysinfo); - - udiv = 32; /* Assume lowest possible serial clk */ - div = sysinfo.freqPLB / (16 * baudrate); /* total divisor */ - umin = sysinfo.pllOpbDiv << 1; /* 2 x OPB divisor */ - diff = 32; /* highest possible */ - - /* i is the test udiv value -- start with the largest - * possible (32) to minimize serial clock and constrain - * search to umin. - */ - for (i = 32; i > umin; i--) { - ibdiv = div / i; - est = i * ibdiv; - idiff = (est > div) ? (est-div) : (div-est); - if (idiff == 0) { - udiv = i; - break; /* can't do better */ - } else if (idiff < diff) { - udiv = i; /* best so far */ - diff = idiff; /* update lowest diff*/ - } - } - - *pudiv = udiv; - *pbdiv = div / udiv; -} -#endif - -static int uart_post_init (struct NS16550 *com_port) +static int test_ctlr (struct NS16550 *com_port, int index) { - unsigned long reg = 0; - unsigned long udiv; - unsigned short bdiv; -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - unsigned long tmp; -#endif + int res = -1; + char test_str[] = "*** UART Test String ***\r\n"; int i; + int divisor; - for (i = 0; i < 3500; i++) { - if (in_8(&com_port->lsr) & UART_LSR_THRE) - break; - udelay (100); - } - MFREG(UART0_SDR, reg); - reg &= ~CR0_MASK; - -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - reg |= CR0_EXTCLK_ENA; - udiv = 1; - tmp = gd->baudrate * 16; - bdiv = (CONFIG_SYS_EXT_SERIAL_CLOCK + tmp / 2) / tmp; -#else - /* For 440, the cpu clock is on divider chain A, UART on divider - * chain B ... so cpu clock is irrelevant. Get the "optimized" - * values that are subject to the 1/2 opb clock constraint - */ - serial_divs (gd->baudrate, &udiv, &bdiv); -#endif - - reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */ + divisor = (get_serial_clock() + (gd->baudrate * (16 / 2))) / + (16 * gd->baudrate); + NS16550_init(com_port, divisor); /* - * Configure input clock to baudrate generator for all - * available serial ports here + * Set internal loopback mode in UART */ - MTREG(UART0_SDR, reg); -#if defined(UART1_SDR) - MTREG(UART1_SDR, reg); -#endif -#if defined(UART2_SDR) - MTREG(UART2_SDR, reg); -#endif -#if defined(UART3_SDR) - MTREG(UART3_SDR, reg); -#endif - - uart_post_init_common(com_port, bdiv); - - return 0; -} - -#else /* CONFIG_440 */ - -static int uart_post_init (struct NS16550 *com_port) -{ - unsigned long reg; - unsigned long tmp; - unsigned long clk; - unsigned long udiv; - unsigned short bdiv; - int i; - - for (i = 0; i < 3500; i++) { - if (in_8(&com_port->lsr) & UART_LSR_THRE) - break; - udelay (100); - } - -#if defined(CONFIG_405EZ) - serial_divs(gd->baudrate, &udiv, &bdiv); - clk = tmp = reg = 0; -#else -#ifdef CONFIG_405EP - reg = mfdcr(CPC0_UCR) & ~(UCR0_MASK | UCR1_MASK); - clk = gd->cpu_clk; - tmp = CONFIG_SYS_BASE_BAUD * 16; - udiv = (clk + tmp / 2) / tmp; - if (udiv > UDIV_MAX) /* max. n bits for udiv */ - udiv = UDIV_MAX; - reg |= (udiv) << UCR0_UDIV_POS; /* set the UART divisor */ - reg |= (udiv) << UCR1_UDIV_POS; /* set the UART divisor */ - mtdcr (CPC0_UCR, reg); -#else /* CONFIG_405EP */ - reg = mfdcr(CPC0_CR0) & ~CR0_MASK; -#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK - clk = CONFIG_SYS_EXT_SERIAL_CLOCK; - udiv = 1; - reg |= CR0_EXTCLK_ENA; -#else - clk = gd->cpu_clk; -#ifdef CONFIG_SYS_405_UART_ERRATA_59 - udiv = 31; /* Errata 59: stuck at 31 */ -#else - tmp = CONFIG_SYS_BASE_BAUD * 16; - udiv = (clk + tmp / 2) / tmp; - if (udiv > UDIV_MAX) /* max. n bits for udiv */ - udiv = UDIV_MAX; -#endif -#endif - reg |= (udiv - 1) << CR0_UDIV_POS; /* set the UART divisor */ - mtdcr (CPC0_CR0, reg); -#endif /* CONFIG_405EP */ - tmp = gd->baudrate * udiv * 16; - bdiv = (clk + tmp / 2) / tmp; -#endif /* CONFIG_405EZ */ - - uart_post_init_common(com_port, bdiv); + out_8(&com_port->mcr, in_8(&com_port->mcr) | UART_MCR_LOOP); - return 0; -} -#endif /* CONFIG_440 */ - -static void uart_post_putc (struct NS16550 *com_port, char c) -{ - int i; - - out_8(&com_port->thr, c); /* put character out */ - - /* Wait for transfer completion */ - for (i = 0; i < 3500; i++) { - if (in_8(&com_port->lsr) & UART_LSR_THRE) - break; - udelay (100); - } -} - -static int uart_post_getc (struct NS16550 *com_port) -{ - int i; - - /* Wait for character available */ - for (i = 0; i < 3500; i++) { - if (in_8(&com_port->lsr) & UART_LSR_DR) - break; - udelay (100); - } - - return 0xff & in_8(&com_port->rbr); -} - -static int test_ctlr (struct NS16550 *com_port, int index) -{ - int res = -1; - char test_str[] = "*** UART Test String ***\r\n"; - int i; + /* Reset FIFOs */ + out_8(&com_port->fcr, UART_FCR_RXSR | UART_FCR_TXSR); + udelay(100); - uart_post_init (com_port); + /* Flush RX-FIFO */ + while (NS16550_tstc(com_port)) + NS16550_getc(com_port); for (i = 0; i < sizeof (test_str) - 1; i++) { - uart_post_putc (com_port, test_str[i]); - if (uart_post_getc (com_port) != test_str[i]) + NS16550_putc(com_port, test_str[i]); + if (NS16550_getc(com_port) != test_str[i]) goto done; } res = 0; |