From 531e3e8b831f357056448fa573137d5fb37000fd Mon Sep 17 00:00:00 2001 From: Pavel Kolesnikov Date: Fri, 20 Jul 2007 15:03:03 +0200 Subject: POST: Add ECC POST for the lwmon5 board This patch adds ECC Post test for the Lwmon5 board based on PPC440EPx to U-Boot. Signed-off-by: Pavel Kolesnikov Acked-by: Yuri Tikhonov Acked-by: Stefan Roese --- post/board/lwmon5/Makefile | 29 +++++ post/board/lwmon5/ecc.c | 257 +++++++++++++++++++++++++++++++++++++++++++++ post/tests.c | 13 +++ 3 files changed, 299 insertions(+) create mode 100644 post/board/lwmon5/Makefile create mode 100644 post/board/lwmon5/ecc.c (limited to 'post') diff --git a/post/board/lwmon5/Makefile b/post/board/lwmon5/Makefile new file mode 100644 index 0000000..c3f54e3 --- /dev/null +++ b/post/board/lwmon5/Makefile @@ -0,0 +1,29 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + + +LIB = libpostlwmon5.a + +COBJS = ecc.o + +include $(TOPDIR)/post/rules.mk diff --git a/post/board/lwmon5/ecc.c b/post/board/lwmon5/ecc.c new file mode 100644 index 0000000..7f04f9a --- /dev/null +++ b/post/board/lwmon5/ecc.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2007 + * Developed for DENX Software Engineering GmbH. + * + * Author: Pavel Kolesnikov + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include +#include + +#ifdef CONFIG_POST + +#include + +#if CONFIG_POST & CFG_POST_ECC + +/* + * MEMORY ECC test + * + * This test performs the checks ECC facility of memory. + */ +#include +#include +#include +#include + +#include "../../../board/lwmon5/sdram.h" + +DECLARE_GLOBAL_DATA_PTR; + +const static unsigned char syndrome_codes[] = { + 0xF4, 0XF1, 0XEC ,0XEA, 0XE9, 0XE6, 0XE5, 0XE3, + 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB, + 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2, + 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A, + 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62, + 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A, + 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23, + 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +#define ECC_START_ADDR 0x10 +#define ECC_STOP_ADDR 0x2000 +#define ECC_PATTERN 0x0101010101010101ull +#define ECC_PATTERN_CORR 0x0101010101010100ull +#define ECC_PATTERN_UNCORR 0x010101010101010Full + +static int test_ecc_error(void) +{ + unsigned long value; + unsigned long hdata, ldata, haddr, laddr; + unsigned int bit; + + int ret = 0; + + mfsdram(DDR0_23, value); + + for (bit = 0; bit < sizeof(syndrome_codes); bit++) + if (syndrome_codes[bit] == ((value >> 16) & 0xff)) + break; + + mfsdram(DDR0_00, value); + + if (value & DDR0_00_INT_STATUS_BIT0) { + debug("Bit0. A single access outside the defined PHYSICAL" + " memory space detected\n"); + mfsdram(DDR0_32, laddr); + mfsdram(DDR0_33, haddr); + debug(" addr = 0x%08x%08x\n", haddr, laddr); + ret = 1; + } + if (value & DDR0_00_INT_STATUS_BIT1) { + debug("Bit1. Multiple accesses outside the defined PHYSICAL" + " memory space detected\n"); + ret = 2; + } + if (value & DDR0_00_INT_STATUS_BIT2) { + debug("Bit2. Single correctable ECC event detected\n"); + mfsdram(DDR0_38, laddr); + mfsdram(DDR0_39, haddr); + mfsdram(DDR0_40, ldata); + mfsdram(DDR0_41, hdata); + debug(" 0x%08x - 0x%08x%08x, bit - %d\n", + laddr, hdata, ldata, bit); + ret = 3; + } + if (value & DDR0_00_INT_STATUS_BIT3) { + debug("Bit3. Multiple correctable ECC events detected\n"); + mfsdram(DDR0_38, laddr); + mfsdram(DDR0_39, haddr); + mfsdram(DDR0_40, ldata); + mfsdram(DDR0_41, hdata); + debug(" 0x%08x - 0x%08x%08x, bit - %d\n", + laddr, hdata, ldata, bit); + ret = 4; + } + if (value & DDR0_00_INT_STATUS_BIT4) { + debug("Bit4. Single uncorrectable ECC event detected\n"); + mfsdram(DDR0_34, laddr); + mfsdram(DDR0_35, haddr); + mfsdram(DDR0_36, ldata); + mfsdram(DDR0_37, hdata); + debug(" 0x%08x - 0x%08x%08x, bit - %d\n", + laddr, hdata, ldata, bit); + ret = 5; + } + if (value & DDR0_00_INT_STATUS_BIT5) { + debug("Bit5. Multiple uncorrectable ECC events detected\n"); + mfsdram(DDR0_34, laddr); + mfsdram(DDR0_35, haddr); + mfsdram(DDR0_36, ldata); + mfsdram(DDR0_37, hdata); + debug(" 0x%08x - 0x%08x%08x, bit - %d\n", + laddr, hdata, ldata, bit); + ret = 6; + } + if (value & DDR0_00_INT_STATUS_BIT6) { + debug("Bit6. DRAM initialization complete\n"); + ret = 7; + } + + /* error status cleared */ + mfsdram(DDR0_00, value); + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); + + return ret; +} + +static int test_ecc(unsigned long ecc_addr) +{ + volatile unsigned long long *ecc_mem; + unsigned long value; + unsigned long ecc_data; + volatile unsigned long *lecc_mem; + int pret, ret = 0; + + sync(); + eieio(); + WATCHDOG_RESET(); + + ecc_mem = (unsigned long long *)ecc_addr; + lecc_mem = (ulong *)ecc_addr; + *ecc_mem = ECC_PATTERN; + pret = test_ecc_error(); + if (pret != 0) + ret = 1; + + /* disconnect ecc */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_DISABLE); + + /* injecting error */ + *ecc_mem = ECC_PATTERN_CORR; + + /* enable ecc */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_ENABLE); + + ecc_data = *lecc_mem; + pret = test_ecc_error(); + /* if read data ok, 1 correctable error must be fixed */ + if (pret != 3) + ret = 1; + + /* test for uncorrectable error */ + /* disconnect from ecc storage */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_NO_ECC_RAM); + + /* injecting multiply bit error */ + + *ecc_mem = ECC_PATTERN_UNCORR; + + /* enable ecc */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_ENABLE); + + ecc_data = *lecc_mem; + /* what the data should be read? */ + + pret = test_ecc_error(); + /* info about uncorrectable error must appear */ + if (pret != 5) + ret = 1; + + sync(); + eieio(); + + return ret; +} + +int ecc_post_test (int flags) +{ + int ret = 0; + unsigned long value; + unsigned long iaddr; + +#if CONFIG_DDR_ECC + sync(); + eieio(); + + /* mask all int */ + mfsdram(DDR0_01, value); + mtsdram(DDR0_01, (value &~ DDR0_01_INT_MASK_MASK) + | DDR0_01_INT_MASK_ALL_OFF); + + /* clear error status */ + mfsdram(DDR0_00, value); + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); + + + /* enable full support of ECC */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_ENABLE); + + for (iaddr = ECC_START_ADDR; iaddr < ECC_STOP_ADDR; iaddr += iaddr) { + ret = test_ecc(iaddr); + if (ret) + break; + } +#endif + + return ret; + +} + +#endif /* CONFIG_POST & CFG_POST_ECC */ +#endif /* CONFIG_POST */ diff --git a/post/tests.c b/post/tests.c index f3604b2..e1c3d28 100644 --- a/post/tests.c +++ b/post/tests.c @@ -46,6 +46,7 @@ extern int spr_post_test (int flags); extern int sysmon_post_test (int flags); extern int dsp_post_test (int flags); extern int codec_post_test (int flags); +extern int ecc_post_test (int flags); extern int sysmon_init_f (void); @@ -236,6 +237,18 @@ struct post_test post_list[] = CFG_POST_CODEC }, #endif +#if CONFIG_POST & CFG_POST_ECC + { + "ECC test", + "ecc", + "This test checks ECC facility of memory.", + POST_ROM | POST_ALWAYS, + &ecc_post_test, + NULL, + NULL, + CFG_POST_ECC + }, +#endif }; unsigned int post_list_size = sizeof (post_list) / sizeof (struct post_test); -- cgit v1.1 From ea9f6bce383cc9fbcdee28b5836109b1a6dba574 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 31 Jul 2007 08:37:01 +0200 Subject: ppc4xx: Update 440EPx lwmon5 board support - Clear ECC status regs after ECC POST test - Set dcbz for ECC generation with caches enabled as default - Code cleanup Signed-off-by: Stefan Roese --- post/board/lwmon5/ecc.c | 12 +++++++++++- post/cpu/ppc4xx/fpu.c | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'post') diff --git a/post/board/lwmon5/ecc.c b/post/board/lwmon5/ecc.c index 7f04f9a..3fa3ba6 100644 --- a/post/board/lwmon5/ecc.c +++ b/post/board/lwmon5/ecc.c @@ -236,7 +236,6 @@ int ecc_post_test (int flags) mfsdram(DDR0_00, value); mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); - /* enable full support of ECC */ mfsdram(DDR0_22, value); mtsdram(DDR0_22, (value &~ DDR0_22_CTRL_RAW_MASK) @@ -247,6 +246,17 @@ int ecc_post_test (int flags) if (ret) break; } + + /* clear error status */ + mfsdram(DDR0_00, value); + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); + + /* + * Clear possible errors resulting from ECC testing. + * If not done, then we could get an interrupt later on when + * exceptions are enabled. + */ + set_mcsr(get_mcsr()); #endif return ret; diff --git a/post/cpu/ppc4xx/fpu.c b/post/cpu/ppc4xx/fpu.c index 27e9ed0..0c26fe0 100644 --- a/post/cpu/ppc4xx/fpu.c +++ b/post/cpu/ppc4xx/fpu.c @@ -29,8 +29,8 @@ #if defined(CONFIG_440EP) || \ defined(CONFIG_440EPX) -#include #include +#include int fpu_status(void) -- cgit v1.1 From 29cb25da56afe18cf5e7072a92a9d98ea8af1fd4 Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Fri, 10 Aug 2007 08:25:22 +0200 Subject: POST: Add ppc4xx UART POST support without external uart clock (lwmon5) The patch adds support for UART POST on ppc44x-based boards with no external serial clocks installed. Signed-off-by: Yuri Tikhonov Acked-by: Stefan Roese --- post/cpu/ppc4xx/uart.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'post') diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index b047d42..0aeed75 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -84,6 +84,49 @@ DECLARE_GLOBAL_DATA_PTR; +#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; -- cgit v1.1 From eb2b4010ae426245172988804ee8d9193fb41038 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 14 Aug 2007 14:39:44 +0200 Subject: 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(-) (limited to 'post') 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)) -- cgit v1.1 From c5a172a5fd636c12467429e3f7910e53773979c6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 14 Aug 2007 14:41:55 +0200 Subject: POST: Add option for external ethernet loopback test When CFG_POST_ETHER_EXT_LOOPBACK is defined, the ethernet POST is not done using an internal loopback connection, but by assuming that an external loopback connector is plugged into the board. Signed-off-by: Stefan Roese --- post/cpu/ppc4xx/ether.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'post') 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); -- cgit v1.1 From 4ce846ec59f36b85d6644a769690ad3feb667575 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 14 Aug 2007 15:12:01 +0200 Subject: POST: Fix merge problem Signed-off-by: Stefan Roese --- post/cpu/ppc4xx/uart.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'post') diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index 5f14967..7c3ed40 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -137,7 +137,7 @@ DECLARE_GLOBAL_DATA_PTR; -<<<<<<< master +#if defined(CONFIG_440) #if !defined(CFG_EXT_SERIAL_CLOCK) static void serial_divs (int baudrate, unsigned long *pudiv, unsigned short *pbdiv) @@ -181,9 +181,6 @@ static void serial_divs (int baudrate, unsigned long *pudiv, } #endif -======= -#if defined(CONFIG_440) ->>>>>>> zeus static int uart_post_init (unsigned long dev_base) { unsigned long reg; -- cgit v1.1 From 9c02defc29b57945b600714cf61ddfd02b02fb14 Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Sat, 25 Aug 2007 05:07:16 +0200 Subject: POST: limit memory test area to not touch global data anymore As experienced on lwmon5, on some boards the POST memory test can corrupt the global data buffer (bd). This patch fixes this issue by checking and limiting this area. Signed-off-by: Yuri Tikhonov Signed-off-by: Stefan Roese --- post/drivers/memory.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'post') diff --git a/post/drivers/memory.c b/post/drivers/memory.c index a2c088b..fbc349a 100644 --- a/post/drivers/memory.c +++ b/post/drivers/memory.c @@ -461,6 +461,9 @@ int memory_post_test (int flags) unsigned long memsize = (bd->bi_memsize >= 256 << 20 ? 256 << 20 : bd->bi_memsize) - (1 << 20); + /* Limit area to be tested with the board info struct */ + if (CFG_SDRAM_BASE + memsize > (ulong)bd) + memsize = (ulong)bd - CFG_SDRAM_BASE; if (flags & POST_SLOWTEST) { ret = memory_post_tests (CFG_SDRAM_BASE, memsize); -- cgit v1.1