diff options
Diffstat (limited to 'post/cpu/ppc4xx')
-rw-r--r-- | post/cpu/ppc4xx/cache.c | 16 | ||||
-rw-r--r-- | post/cpu/ppc4xx/cache_4xx.S | 46 | ||||
-rw-r--r-- | post/cpu/ppc4xx/ether.c | 9 | ||||
-rw-r--r-- | post/cpu/ppc4xx/fpu.c | 4 | ||||
-rw-r--r-- | post/cpu/ppc4xx/spr.c | 13 | ||||
-rw-r--r-- | post/cpu/ppc4xx/uart.c | 176 |
6 files changed, 246 insertions, 18 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 785b8d6..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) */ @@ -438,7 +482,7 @@ cache_post_test6_reloc: blr /* Test instructions. - */ + */ cache_post_test_inst: li r3, 0 li r3, -1 diff --git a/post/cpu/ppc4xx/ether.c b/post/cpu/ppc4xx/ether.c index 391c815..ab23ca5 100644 --- a/post/cpu/ppc4xx/ether.c +++ b/post/cpu/ppc4xx/ether.c @@ -68,10 +68,10 @@ static char *rx_buf; static void ether_post_init (int devnum, int hw_addr) { int i; - unsigned mode_reg; #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_440SP) || defined(CONFIG_440SPE) + unsigned mode_reg; sys_info_t sysinfo; #endif #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) @@ -185,10 +185,17 @@ static void ether_post_init (int devnum, int hw_addr) mtdcr (malrxcasr, (MAL_TXRX_CASR >> devnum)); /* set internal loopback mode */ +#ifdef CFG_POST_ETHER_EXT_LOOPBACK + out32 (EMAC_M1 + hw_addr, EMAC_M1_FDE | 0 | + EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K | + EMAC_M1_MF_100MBPS | EMAC_M1_IST | + in32 (EMAC_M1)); +#else out32 (EMAC_M1 + hw_addr, EMAC_M1_FDE | EMAC_M1_ILE | EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K | EMAC_M1_MF_100MBPS | EMAC_M1_IST | in32 (EMAC_M1)); +#endif /* set transmit enable & receive enable */ out32 (EMAC_M0 + hw_addr, EMAC_M0_TXE | EMAC_M0_RXE); diff --git a/post/cpu/ppc4xx/fpu.c b/post/cpu/ppc4xx/fpu.c index c2eb4a9..0c26fe0 100644 --- a/post/cpu/ppc4xx/fpu.c +++ b/post/cpu/ppc4xx/fpu.c @@ -29,15 +29,15 @@ #if defined(CONFIG_440EP) || \ defined(CONFIG_440EPX) -#include <ppc4xx.h> #include <asm/processor.h> +#include <ppc4xx.h> int fpu_status(void) { if (mfspr(ccr0) & CCR0_DAPUIB) return 0; /* Disabled */ - else + else return 1; /* Enabled */ } diff --git a/post/cpu/ppc4xx/spr.c b/post/cpu/ppc4xx/spr.c index be5a701..3e74634 100644 --- a/post/cpu/ppc4xx/spr.c +++ b/post/cpu/ppc4xx/spr.c @@ -43,12 +43,11 @@ #include <asm/processor.h> -static struct -{ - int number; - char * name; - unsigned long mask; - unsigned long value; +static struct { + int number; + char * name; + unsigned long mask; + unsigned long value; } spr_test_list [] = { /* Standard Special-Purpose Registers */ @@ -65,7 +64,7 @@ static struct {0x11f, "PVR", 0x00000000, 0x00000000}, /* Additional Special-Purpose Registers. - * The values must match the initialization + * The values must match the initialization * values from cpu/ppc4xx/start.S */ {0x30, "PID", 0x00000000, 0x00000000}, diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index b047d42..7c3ed40 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 <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 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,50 @@ DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_440) +#if !defined(CFG_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 (unsigned long dev_base) { unsigned long reg; @@ -147,6 +244,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 +366,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)) |