From eb2b4010ae426245172988804ee8d9193fb41038 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 14 Aug 2007 14:39:44 +0200 Subject: [PATCH] POST: Add ppc405 support to cache and UART POST Signed-off-by: Stefan Roese --- post/cpu/ppc4xx/cache.c | 16 +++++- post/cpu/ppc4xx/cache_4xx.S | 44 +++++++++++++++ post/cpu/ppc4xx/uart.c | 133 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 186 insertions(+), 7 deletions(-) diff --git a/post/cpu/ppc4xx/cache.c b/post/cpu/ppc4xx/cache.c index e1f989e..109ca1f 100644 --- a/post/cpu/ppc4xx/cache.c +++ b/post/cpu/ppc4xx/cache.c @@ -53,14 +53,25 @@ int cache_post_test6 (int tlb, void *p, int size); static int tlb = -1; /* index to the victim TLB entry */ +#ifdef CONFIG_440 static unsigned char testarea[CACHE_POST_SIZE] __attribute__((__aligned__(CACHE_POST_SIZE))); +#endif int cache_post_test (int flags) { void* virt = (void*)CFG_POST_CACHE_ADDR; - int ints, i, res = 0; - u32 word0; + int ints; + int res = 0; + + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 + int word0, i; if (tlb < 0) { /* @@ -83,6 +94,7 @@ int cache_post_test (int flags) } } } +#endif ints = disable_interrupts (); WATCHDOG_RESET (); diff --git a/post/cpu/ppc4xx/cache_4xx.S b/post/cpu/ppc4xx/cache_4xx.S index dddd76b..d5cb075 100644 --- a/post/cpu/ppc4xx/cache_4xx.S +++ b/post/cpu/ppc4xx/cache_4xx.S @@ -37,6 +37,13 @@ .text + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 /* void cache_post_disable (int tlb) */ cache_post_disable: @@ -68,6 +75,43 @@ cache_post_wb: sync isync blr +#else +/* void cache_post_disable (int tlb) + */ +cache_post_disable: + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdccr r0 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr +#endif /* void cache_post_dinvalidate (void *p, int size) */ diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index b047d42..0cffda5 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -38,24 +38,77 @@ #if CONFIG_POST & CFG_POST_UART +/* + * This table defines the UART's that should be tested and can + * be overridden in the board config file + */ +#ifndef CFG_POST_UART_TABLE +#define CFG_POST_UART_TABLE {UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE} +#endif + #include #include +#if defined(CONFIG_440) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) #define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000300 #define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000400 #define UART2_BASE CFG_PERIPHERAL_BASE + 0x00000500 #define UART3_BASE CFG_PERIPHERAL_BASE + 0x00000600 +#else +#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000200 +#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300 +#endif +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#define UART2_BASE CFG_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 cntrl0 +#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 sdr_uart0 #define UART1_SDR sdr_uart1 +#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPe) #define UART2_SDR sdr_uart2 +#endif +#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRx) #define UART3_SDR sdr_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 +#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 +#endif #define UART_RBR 0x00 #define UART_THR 0x00 @@ -71,8 +124,8 @@ #define UART_DLM 0x01 /* - Line Status Register. -*/ + * Line Status Register. + */ #define asyncLSRDataReady1 0x01 #define asyncLSROverrunError1 0x02 #define asyncLSRParityError1 0x04 @@ -84,6 +137,7 @@ DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_440) static int uart_post_init (unsigned long dev_base) { unsigned long reg; @@ -147,6 +201,77 @@ static int uart_post_init (unsigned long dev_base) return 0; } +#else /* CONFIG_440 */ + +static int uart_post_init (unsigned long dev_base) +{ + 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) + 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 = CFG_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(cntrl0) & ~CR0_MASK; +#ifdef CFG_EXT_SERIAL_CLOCK + clk = CFG_EXT_SERIAL_CLOCK; + udiv = 1; + reg |= CR0_EXTCLK_ENA; +#else + clk = gd->cpu_clk; +#ifdef CFG_405_UART_ERRATA_59 + udiv = 31; /* Errata 59: stuck at 31 */ +#else + tmp = CFG_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 (cntrl0, reg); +#endif /* CONFIG_405EP */ + tmp = gd->baudrate * udiv * 16; + 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); +} +#endif /* CONFIG_440 */ + static void uart_post_putc (unsigned long dev_base, char c) { int i; @@ -198,9 +323,7 @@ done: int uart_post_test (int flags) { int i, res = 0; - static unsigned long base[] = { - UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE - }; + static unsigned long base[] = CFG_POST_UART_TABLE; for (i = 0; i < sizeof (base) / sizeof (base[0]); i++) { if (test_ctlr (base[i], i))