summaryrefslogtreecommitdiff
path: root/post
diff options
context:
space:
mode:
Diffstat (limited to 'post')
-rw-r--r--post/board/lwmon5/Makefile29
-rw-r--r--post/board/lwmon5/ecc.c267
-rw-r--r--post/cpu/ppc4xx/cache.c16
-rw-r--r--post/cpu/ppc4xx/cache_4xx.S44
-rw-r--r--post/cpu/ppc4xx/ether.c9
-rw-r--r--post/cpu/ppc4xx/fpu.c2
-rw-r--r--post/cpu/ppc4xx/uart.c176
-rw-r--r--post/tests.c13
8 files changed, 547 insertions, 9 deletions
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..3fa3ba6
--- /dev/null
+++ b/post/board/lwmon5/ecc.c
@@ -0,0 +1,267 @@
+/*
+ * (C) Copyright 2007
+ * Developed for DENX Software Engineering GmbH.
+ *
+ * Author: Pavel Kolesnikov <concord@emcraft.com>
+ *
+ * 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 <common.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_ECC
+
+/*
+ * MEMORY ECC test
+ *
+ * This test performs the checks ECC facility of memory.
+ */
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <ppc440.h>
+
+#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;
+ }
+
+ /* 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;
+
+}
+
+#endif /* CONFIG_POST & CFG_POST_ECC */
+#endif /* CONFIG_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/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 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 <ppc4xx.h>
#include <asm/processor.h>
+#include <ppc4xx.h>
int fpu_status(void)
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))
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);