diff options
Diffstat (limited to 'post')
28 files changed, 2841 insertions, 13 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/mpc8xx/Makefile b/post/cpu/mpc8xx/Makefile index 9dd3f0f..f871cba 100644 --- a/post/cpu/mpc8xx/Makefile +++ b/post/cpu/mpc8xx/Makefile @@ -24,6 +24,6 @@ LIB = libpostmpc8xx.a AOBJS = cache_8xx.o -COBJS = ether.o spr.o uart.o usb.o watchdog.o +COBJS = cache.o ether.o spr.o uart.o usb.o watchdog.o include $(TOPDIR)/post/rules.mk diff --git a/post/drivers/cache.c b/post/cpu/mpc8xx/cache.c index 501465c..501465c 100644 --- a/post/drivers/cache.c +++ b/post/cpu/mpc8xx/cache.c diff --git a/post/cpu/ppc4xx/Makefile b/post/cpu/ppc4xx/Makefile new file mode 100644 index 0000000..f1034da --- /dev/null +++ b/post/cpu/ppc4xx/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 = libpostppc4xx.a + +AOBJS = cache_4xx.o +COBJS = cache.o ether.o fpu.o spr.o uart.o watchdog.o + +include $(TOPDIR)/post/rules.mk diff --git a/post/cpu/ppc4xx/cache.c b/post/cpu/ppc4xx/cache.c new file mode 100644 index 0000000..109ca1f --- /dev/null +++ b/post/cpu/ppc4xx/cache.c @@ -0,0 +1,126 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_CACHE + +#include <asm/mmu.h> +#include <watchdog.h> + +#define CACHE_POST_SIZE 1024 + +void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value); + +int cache_post_test1 (int tlb, void *p, int size); +int cache_post_test2 (int tlb, void *p, int size); +int cache_post_test3 (int tlb, void *p, int size); +int cache_post_test4 (int tlb, void *p, int size); +int cache_post_test5 (int tlb, void *p, int size); +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; + 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) { + /* + * Allocate a new TLB entry, since we are going to modify + * the write-through and caching inhibited storage attributes. + */ + program_tlb((u32)testarea, (u32)virt, + CACHE_POST_SIZE, TLB_WORD2_I_ENABLE); + + /* Find the TLB entry */ + for (i = 0;; i++) { + if (i >= PPC4XX_TLB_SIZE) { + printf ("Failed to program tlb entry\n"); + return -1; + } + word0 = mftlb1(i); + if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) { + tlb = i; + break; + } + } + } +#endif + ints = disable_interrupts (); + + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE); + + if (ints) + enable_interrupts (); + + return res; +} + +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/cache_4xx.S b/post/cpu/ppc4xx/cache_4xx.S new file mode 100644 index 0000000..d5cb075 --- /dev/null +++ b/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,492 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <config.h> + +#ifdef CONFIG_POST + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CFG_POST_CACHE + + .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: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + tlbre r0, r3, 0x0002 + andi. r0, r0, ~TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + 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) + */ +cache_post_dinvalidate: + dcbi r0, r3 + addi r3, r3, CFG_CACHELINE_SIZE + subic. r4, r4, CFG_CACHELINE_SIZE + bgt cache_post_dinvalidate + sync + blr + +/* void cache_post_dstore (void *p, int size) + */ +cache_post_dstore: + dcbst r0, r3 + addi r3, r3, CFG_CACHELINE_SIZE + subic. r4, r4, CFG_CACHELINE_SIZE + bgt cache_post_dstore + sync + blr + +/* void cache_post_dtouch (void *p, int size) + */ +cache_post_dtouch: + dcbt r0, r3 + addi r3, r3, CFG_CACHELINE_SIZE + subic. r4, r4, CFG_CACHELINE_SIZE + bgt cache_post_dtouch + sync + blr + +/* void cache_post_iinvalidate (void) + */ +cache_post_iinvalidate: + iccci r0, r0 + sync + blr + +/* void cache_post_memset (void *p, int val, int size) + */ +cache_post_memset: + mtctr r5 +1: + stb r4, 0(r3) + addi r3, r3, 1 + bdnz 1b + blr + +/* int cache_post_check (void *p, int size) + */ +cache_post_check: + mtctr r4 +1: + lbz r0, 0(r3) + addi r3, r3, 1 + cmpwi r0, 0xff + bne 2f + bdnz 1b + li r3, 0 + blr +2: + li r3, -1 + blr + +#define CACHE_POST_DISABLE() \ + mr r3, r10; \ + bl cache_post_disable + +#define CACHE_POST_WT() \ + mr r3, r10; \ + bl cache_post_wt + +#define CACHE_POST_WB() \ + mr r3, r10; \ + bl cache_post_wb + +#define CACHE_POST_DINVALIDATE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dinvalidate + +#define CACHE_POST_DFLUSH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dflush + +#define CACHE_POST_DSTORE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dstore + +#define CACHE_POST_DTOUCH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dtouch + +#define CACHE_POST_IINVALIDATE() \ + bl cache_post_iinvalidate + +#define CACHE_POST_MEMSET(val) \ + mr r3, r11; \ + li r4, val; \ + mr r5, r12; \ + bl cache_post_memset + +#define CACHE_POST_CHECK() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_check; \ + mr r13, r3 + +/* + * Write and read 0xff pattern with caching enabled. + */ + .global cache_post_test1 +cache_post_test1: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write zeroes with caching enabled. + * Write 0xff pattern with caching disabled. + * Read 0xff pattern with caching enabled. + */ + .global cache_post_test2 +cache_post_test2: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_WB() + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-through mode test. + * Write zeroes, store the cache, write 0xff pattern. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test3 +cache_post_test3: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DSTORE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-back mode test. + * Write 0xff pattern, store the cache, write zeroes. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test4 +cache_post_test4: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DSTORE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions. + * Check that the original instructions are executed. + */ + .global cache_post_test5 +cache_post_test5: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test5_reloc +cache_post_test5_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test5_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 0(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 4(r13) + stw r0, 0(r11) + sync + + /* Do not invalidate the cache line */ + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions and invalidate the cache. + * Check that the replaced instructions are executed. + */ + .global cache_post_test6 +cache_post_test6: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test6_reloc +cache_post_test6_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test6_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 4(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 0(r13) + stw r0, 0(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* Test instructions. + */ +cache_post_test_inst: + li r3, 0 + li r3, -1 + blr + +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/ether.c b/post/cpu/ppc4xx/ether.c new file mode 100644 index 0000000..ab23ca5 --- /dev/null +++ b/post/cpu/ppc4xx/ether.c @@ -0,0 +1,402 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <common.h> + +/* + * Ethernet test + * + * The Ethernet Media Access Controllers (EMAC) are tested in the + * internal loopback mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + * MIN_PACKET_LENGTH - minimum size of packet to transmit + * MAX_PACKET_LENGTH - maximum size of packet to transmit + * TEST_NUM - number of tests + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_ETHER + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <405_mal.h> +#include <ppc4xx_enet.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) +#endif + +#define MIN_PACKET_LENGTH 64 +#define MAX_PACKET_LENGTH 256 +#define TEST_NUM 1 + +static volatile mal_desc_t tx __cacheline_aligned; +static volatile mal_desc_t rx __cacheline_aligned; +static char *tx_buf; +static char *rx_buf; + +static void ether_post_init (int devnum, int hw_addr) +{ + int i; +#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) + unsigned long mfr; +#endif + +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Need to get the OPB frequency so we can access the PHY */ + get_sys_info (&sysinfo); +#endif + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* provide clocks for EMAC internal loopback */ + mfsdr (sdr_mfr, mfr); + mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (sdr_mfr, mfr); + sync (); +#endif + /* reset emac */ + out32 (EMAC_M0 + hw_addr, EMAC_M0_SRST); + sync (); + + for (i = 0;; i++) { + if (!(in32 (EMAC_M0 + hw_addr) & EMAC_M0_SRST)) + break; + if (i >= 1000) { + printf ("Timeout resetting EMAC\n"); + break; + } + udelay (1000); + } +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Whack the M1 register */ + mode_reg = 0x0; + if (sysinfo.freqOPB <= 50000000); + else if (sysinfo.freqOPB <= 66666667) + mode_reg |= EMAC_M1_OBCI_66; + else if (sysinfo.freqOPB <= 83333333) + mode_reg |= EMAC_M1_OBCI_83; + else if (sysinfo.freqOPB <= 100000000) + mode_reg |= EMAC_M1_OBCI_100; + else + mode_reg |= EMAC_M1_OBCI_GT100; + + out32 (EMAC_M1 + hw_addr, mode_reg); + +#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ + + /* set the Mal configuration reg */ +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | + MAL_CR_PLBLT_DEFAULT | 0x00330000); +#else + mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); + /* Errata 1.12: MAL_1 -- Disable MAL bursting */ + if (get_pvr() == PVR_440GP_RB) { + mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB); + } +#endif + /* setup buffer descriptors */ + tx.ctrl = MAL_TX_CTRL_WRAP; + tx.data_len = 0; + tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf); + + rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY; + rx.data_len = 0; + rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf); + + switch (devnum) { + case 1: + /* setup MAL tx & rx channel pointers */ +#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) + mtdcr (maltxctp2r, &tx); +#else + mtdcr (maltxctp1r, &tx); +#endif +#if defined(CONFIG_440) + mtdcr (maltxbattr, 0x0); + mtdcr (malrxbattr, 0x0); +#endif + mtdcr (malrxctp1r, &rx); + /* set RX buffer size */ + mtdcr (malrcbs1, PKTSIZE_ALIGN / 16); + break; + case 0: + default: + /* setup MAL tx & rx channel pointers */ +#if defined(CONFIG_440) + mtdcr (maltxbattr, 0x0); + mtdcr (malrxbattr, 0x0); +#endif + mtdcr (maltxctp0r, &tx); + mtdcr (malrxctp0r, &rx); + /* set RX buffer size */ + mtdcr (malrcbs0, PKTSIZE_ALIGN / 16); + break; + } + + /* Enable MAL transmit and receive channels */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (maltxcasr, (MAL_TXRX_CASR >> (devnum*2))); +#else + mtdcr (maltxcasr, (MAL_TXRX_CASR >> devnum)); +#endif + 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); + + /* enable broadcast address */ + out32 (EMAC_RXM + hw_addr, EMAC_RMR_BAE); + + /* set transmit request threshold register */ + out32 (EMAC_TRTR + hw_addr, 0x18000000); /* 256 byte threshold */ + + /* set receive low/high water mark register */ +#if defined(CONFIG_440) + /* 440s has a 64 byte burst length */ + out32 (EMAC_RX_HI_LO_WMARK + hw_addr, 0x80009000); +#else + /* 405s have a 16 byte burst length */ + out32 (EMAC_RX_HI_LO_WMARK + hw_addr, 0x0f002000); +#endif /* defined(CONFIG_440) */ + out32 (EMAC_TXM1 + hw_addr, 0xf8640000); + + /* Set fifo limit entry in tx mode 0 */ + out32 (EMAC_TXM0 + hw_addr, 0x00000003); + /* Frame gap set */ + out32 (EMAC_I_FRAME_GAP_REG + hw_addr, 0x00000008); + sync (); +} + +static void ether_post_halt (int devnum, int hw_addr) +{ + int i = 0; +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + unsigned long mfr; +#endif + + /* 1st reset MAL channel */ + /* Note: writing a 0 to a channel has no effect */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (maltxcarr, MAL_TXRX_CASR >> (devnum * 2)); +#else + mtdcr (maltxcarr, MAL_TXRX_CASR >> devnum); +#endif + mtdcr (malrxcarr, MAL_TXRX_CASR >> devnum); + + /* wait for reset */ + while (mfdcr (malrxcasr) & (MAL_TXRX_CASR >> devnum)) { + if (i++ >= 1000) + break; + udelay (1000); + } + /* emac reset */ + out32 (EMAC_M0 + hw_addr, EMAC_M0_SRST); + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* remove clocks for EMAC internal loopback */ + mfsdr (sdr_mfr, mfr); + mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (sdr_mfr, mfr); +#endif +} + +static void ether_post_send (int devnum, int hw_addr, void *packet, int length) +{ + int i = 0; + + while (tx.ctrl & MAL_TX_CTRL_READY) { + if (i++ > 100) { + printf ("TX timeout\n"); + return; + } + udelay (1000); + } + tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST | + EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP; + tx.data_len = length; + memcpy (tx.data_ptr, packet, length); + sync (); + + out32 (EMAC_TXM0 + hw_addr, in32 (EMAC_TXM0 + hw_addr) | EMAC_TXM0_GNP0); + sync (); +} + +static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length) +{ + int length; + int i = 0; + + while (rx.ctrl & MAL_RX_CTRL_EMPTY) { + if (i++ > 100) { + printf ("RX timeout\n"); + return 0; + } + udelay (1000); + } + length = rx.data_len - 4; + if (length <= max_length) + memcpy(packet, rx.data_ptr, length); + sync (); + + rx.ctrl |= MAL_RX_CTRL_EMPTY; + sync (); + + return length; +} + + /* + * Test routines + */ + +static void packet_fill (char *packet, int length) +{ + char c = (char) length; + int i; + + /* set up ethernet header */ + memset (packet, 0xff, 14); + + for (i = 14; i < length; i++) { + packet[i] = c++; + } +} + +static int packet_check (char *packet, int length) +{ + char c = (char) length; + int i; + + for (i = 14; i < length; i++) { + if (packet[i] != c++) + return -1; + } + + return 0; +} + +static int test_ctlr (int devnum, int hw_addr) +{ + int res = -1; + char packet_send[MAX_PACKET_LENGTH]; + char packet_recv[MAX_PACKET_LENGTH]; + int length; + int i; + int l; + + ether_post_init (devnum, hw_addr); + + for (i = 0; i < TEST_NUM; i++) { + for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) { + packet_fill (packet_send, l); + + ether_post_send (devnum, hw_addr, packet_send, l); + + length = ether_post_recv (devnum, hw_addr, packet_recv, + sizeof (packet_recv)); + + if (length != l || packet_check (packet_recv, length) < 0) { + goto Done; + } + } + } + + res = 0; + +Done: + + ether_post_halt (devnum, hw_addr); + + if (res != 0) { + post_log ("EMAC%d test failed\n", devnum); + } + + return res; +} + +int ether_post_test (int flags) +{ + int res = 0; + + /* Allocate tx & rx packet buffers */ + tx_buf = malloc (PKTSIZE_ALIGN + CFG_CACHELINE_SIZE); + rx_buf = malloc (PKTSIZE_ALIGN + CFG_CACHELINE_SIZE); + + if (!tx_buf || !rx_buf) { + printf ("Failed to allocate packet buffers\n"); + res = -1; + goto out_free; + } + + /* EMAC0 */ + if (test_ctlr (0, 0)) + res = -1; + + /* EMAC1 */ + if (test_ctlr (1, 0x100)) + res = -1; + +out_free: + free (tx_buf); + free (rx_buf); + + return res; +} + +#endif /* CONFIG_POST & CFG_POST_ETHER */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/fpu.c b/post/cpu/ppc4xx/fpu.c new file mode 100644 index 0000000..0c26fe0 --- /dev/null +++ b/post/cpu/ppc4xx/fpu.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@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 + */ + +#include <config.h> + +#ifdef CONFIG_POST +#if defined(CONFIG_440EP) || \ + defined(CONFIG_440EPX) + +#include <asm/processor.h> +#include <ppc4xx.h> + + +int fpu_status(void) +{ + if (mfspr(ccr0) & CCR0_DAPUIB) + return 0; /* Disabled */ + else + return 1; /* Enabled */ +} + + +void fpu_disable(void) +{ + mtspr(ccr0, mfspr(ccr0) | CCR0_DAPUIB); + mtmsr(mfmsr() & ~MSR_FP); +} + + +void fpu_enable(void) +{ + mtspr(ccr0, mfspr(ccr0) & ~CCR0_DAPUIB); + mtmsr(mfmsr() | MSR_FP); +} + +#endif +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/spr.c b/post/cpu/ppc4xx/spr.c new file mode 100644 index 0000000..3e74634 --- /dev/null +++ b/post/cpu/ppc4xx/spr.c @@ -0,0 +1,182 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <common.h> + +/* + * SPR test + * + * The test checks the contents of Special Purpose Registers (SPR) listed + * in the spr_test_list array below. + * Each SPR value is read using mfspr instruction, some bits are masked + * according to the table and the resulting value is compared to the + * corresponding table value. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_SPR + +#include <asm/processor.h> + +static struct { + int number; + char * name; + unsigned long mask; + unsigned long value; +} spr_test_list [] = { + /* Standard Special-Purpose Registers */ + + {0x001, "XER", 0x00000000, 0x00000000}, + {0x008, "LR", 0x00000000, 0x00000000}, + {0x009, "CTR", 0x00000000, 0x00000000}, + {0x016, "DEC", 0x00000000, 0x00000000}, + {0x01a, "SRR0", 0x00000000, 0x00000000}, + {0x01b, "SRR1", 0x00000000, 0x00000000}, + {0x110, "SPRG0", 0x00000000, 0x00000000}, + {0x111, "SPRG1", 0x00000000, 0x00000000}, + {0x112, "SPRG2", 0x00000000, 0x00000000}, + {0x113, "SPRG3", 0x00000000, 0x00000000}, + {0x11f, "PVR", 0x00000000, 0x00000000}, + + /* Additional Special-Purpose Registers. + * The values must match the initialization + * values from cpu/ppc4xx/start.S + */ + {0x30, "PID", 0x00000000, 0x00000000}, + {0x3a, "CSRR0", 0x00000000, 0x00000000}, + {0x3b, "CSRR1", 0x00000000, 0x00000000}, + {0x3d, "DEAR", 0x00000000, 0x00000000}, + {0x3e, "ESR", 0x00000000, 0x00000000}, + {0x3f, "IVPR", 0xffff0000, 0x00000000}, + {0x100, "USPRG0", 0x00000000, 0x00000000}, + {0x104, "SPRG4", 0x00000000, 0x00000000}, + {0x105, "SPRG5", 0x00000000, 0x00000000}, + {0x106, "SPRG6", 0x00000000, 0x00000000}, + {0x107, "SPRG7", 0x00000000, 0x00000000}, + {0x10c, "TBL", 0x00000000, 0x00000000}, + {0x10d, "TBU", 0x00000000, 0x00000000}, + {0x11e, "PIR", 0x0000000f, 0x00000000}, + {0x130, "DBSR", 0x00000000, 0x00000000}, + {0x134, "DBCR0", 0x00000000, 0x00000000}, + {0x135, "DBCR1", 0x00000000, 0x00000000}, + {0x136, "DBCR2", 0x00000000, 0x00000000}, + {0x138, "IAC1", 0x00000000, 0x00000000}, + {0x139, "IAC2", 0x00000000, 0x00000000}, + {0x13a, "IAC3", 0x00000000, 0x00000000}, + {0x13b, "IAC4", 0x00000000, 0x00000000}, + {0x13c, "DAC1", 0x00000000, 0x00000000}, + {0x13d, "DAC2", 0x00000000, 0x00000000}, + {0x13e, "DVC1", 0x00000000, 0x00000000}, + {0x13f, "DVC2", 0x00000000, 0x00000000}, + {0x150, "TSR", 0x00000000, 0x00000000}, + {0x154, "TCR", 0x00000000, 0x00000000}, + {0x190, "IVOR0", 0x0000fff0, 0x00000100}, + {0x191, "IVOR1", 0x0000fff0, 0x00000200}, + {0x192, "IVOR2", 0x0000fff0, 0x00000300}, + {0x193, "IVOR3", 0x0000fff0, 0x00000400}, + {0x194, "IVOR4", 0x0000fff0, 0x00000500}, + {0x195, "IVOR5", 0x0000fff0, 0x00000600}, + {0x196, "IVOR6", 0x0000fff0, 0x00000700}, + {0x197, "IVOR7", 0x0000fff0, 0x00000800}, + {0x198, "IVOR8", 0x0000fff0, 0x00000c00}, + {0x199, "IVOR9", 0x00000000, 0x00000000}, + {0x19a, "IVOR10", 0x0000fff0, 0x00000900}, + {0x19b, "IVOR11", 0x00000000, 0x00000000}, + {0x19c, "IVOR12", 0x00000000, 0x00000000}, + {0x19d, "IVOR13", 0x0000fff0, 0x00001300}, + {0x19e, "IVOR14", 0x0000fff0, 0x00001400}, + {0x19f, "IVOR15", 0x0000fff0, 0x00002000}, + {0x23a, "MCSRR0", 0x00000000, 0x00000000}, + {0x23b, "MCSRR1", 0x00000000, 0x00000000}, + {0x23c, "MCSR", 0x00000000, 0x00000000}, + {0x370, "INV0", 0x00000000, 0x00000000}, + {0x371, "INV1", 0x00000000, 0x00000000}, + {0x372, "INV2", 0x00000000, 0x00000000}, + {0x373, "INV3", 0x00000000, 0x00000000}, + {0x374, "ITV0", 0x00000000, 0x00000000}, + {0x375, "ITV1", 0x00000000, 0x00000000}, + {0x376, "ITV2", 0x00000000, 0x00000000}, + {0x377, "ITV3", 0x00000000, 0x00000000}, + {0x378, "CCR1", 0x00000000, 0x00000000}, + {0x390, "DNV0", 0x00000000, 0x00000000}, + {0x391, "DNV1", 0x00000000, 0x00000000}, + {0x392, "DNV2", 0x00000000, 0x00000000}, + {0x393, "DNV3", 0x00000000, 0x00000000}, + {0x394, "DTV0", 0x00000000, 0x00000000}, + {0x395, "DTV1", 0x00000000, 0x00000000}, + {0x396, "DTV2", 0x00000000, 0x00000000}, + {0x397, "DTV3", 0x00000000, 0x00000000}, + {0x398, "DVLIM", 0x0fc1f83f, 0x0001f800}, + {0x399, "IVLIM", 0x0fc1f83f, 0x0001f800}, + {0x39b, "RSTCFG", 0x00000000, 0x00000000}, + {0x39c, "DCDBTRL", 0x00000000, 0x00000000}, + {0x39d, "DCDBTRH", 0x00000000, 0x00000000}, + {0x39e, "ICDBTRL", 0x00000000, 0x00000000}, + {0x39f, "ICDBTRH", 0x00000000, 0x00000000}, + {0x3b2, "MMUCR", 0x00000000, 0x00000000}, + {0x3b3, "CCR0", 0x00000000, 0x00000000}, + {0x3d3, "ICDBDR", 0x00000000, 0x00000000}, + {0x3f3, "DBDR", 0x00000000, 0x00000000}, +}; + +static int spr_test_list_size = + sizeof (spr_test_list) / sizeof (spr_test_list[0]); + +int spr_post_test (int flags) +{ + int ret = 0; + int i; + + unsigned long code[] = { + 0x7c6002a6, /* mfspr r3,SPR */ + 0x4e800020 /* blr */ + }; + unsigned long (*get_spr) (void) = (void *) code; + + for (i = 0; i < spr_test_list_size; i++) { + int num = spr_test_list[i].number; + + /* mfspr r3,num */ + code[0] = 0x7c6002a6 | ((num & 0x1F) << 16) | ((num & 0x3E0) << 6); + + asm volatile ("isync"); + + if ((get_spr () & spr_test_list[i].mask) != + (spr_test_list[i].value & spr_test_list[i].mask)) { + post_log ("The value of %s special register " + "is incorrect: 0x%08X\n", + spr_test_list[i].name, get_spr ()); + ret = -1; + } + } + + return ret; +} + +#endif /* CONFIG_POST & CFG_POST_SPR */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c new file mode 100644 index 0000000..7c3ed40 --- /dev/null +++ b/post/cpu/ppc4xx/uart.c @@ -0,0 +1,381 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <common.h> + +/* + * UART test + * + * The controllers are configured to loopback mode and several + * characters are transmitted. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#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 +#define UART_IER 0x01 +#define UART_IIR 0x02 +#define UART_FCR 0x02 +#define UART_LCR 0x03 +#define UART_MCR 0x04 +#define UART_LSR 0x05 +#define UART_MSR 0x06 +#define UART_SCR 0x07 +#define UART_DLL 0x00 +#define UART_DLM 0x01 + +/* + * Line Status Register. + */ +#define asyncLSRDataReady1 0x01 +#define asyncLSROverrunError1 0x02 +#define asyncLSRParityError1 0x04 +#define asyncLSRFramingError1 0x08 +#define asyncLSRBreakInterrupt1 0x10 +#define asyncLSRTxHoldEmpty1 0x20 +#define asyncLSRTxShiftEmpty1 0x40 +#define asyncLSRRxFifoError1 0x80 + +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; + unsigned long udiv; + unsigned short bdiv; + volatile char val; +#ifdef CFG_EXT_SERIAL_CLOCK + unsigned long tmp; +#endif + int i; + + for (i = 0; i < 3500; i++) { + if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1) + break; + udelay (100); + } + MFREG(UART0_SDR, reg); + reg &= ~CR0_MASK; + +#ifdef CFG_EXT_SERIAL_CLOCK + reg |= CR0_EXTCLK_ENA; + udiv = 1; + tmp = gd->baudrate * 16; + bdiv = (CFG_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 */ + + /* + * Configure input clock to baudrate generator for all + * available serial ports here + */ + 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 + + 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; +} + +#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; + + out8 (dev_base + UART_THR, c); /* put character out */ + + /* Wait for transfer completion */ + for (i = 0; i < 3500; i++) { + if (in8 (dev_base + UART_LSR) & asyncLSRTxHoldEmpty1) + break; + udelay (100); + } +} + +static int uart_post_getc (unsigned long dev_base) +{ + int i; + + /* Wait for character available */ + for (i = 0; i < 3500; i++) { + if (in8 (dev_base + UART_LSR) & asyncLSRDataReady1) + break; + udelay (100); + } + return 0xff & in8 (dev_base + UART_RBR); +} + +static int test_ctlr (unsigned long dev_base, int index) +{ + int res = -1; + char test_str[] = "*** UART Test String ***\r\n"; + int i; + + uart_post_init (dev_base); + + for (i = 0; i < sizeof (test_str) - 1; i++) { + uart_post_putc (dev_base, test_str[i]); + if (uart_post_getc (dev_base) != test_str[i]) + goto done; + } + res = 0; +done: + if (res) + post_log ("uart%d test failed\n", index); + + return res; +} + +int uart_post_test (int flags) +{ + int i, res = 0; + static unsigned long base[] = CFG_POST_UART_TABLE; + + for (i = 0; i < sizeof (base) / sizeof (base[0]); i++) { + if (test_ctlr (base[i], i)) + res = -1; + } + serial_reinit_all (); + + return res; +} + +#endif /* CONFIG_POST & CFG_POST_UART */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/watchdog.c b/post/cpu/ppc4xx/watchdog.c new file mode 100644 index 0000000..bd4f4c9 --- /dev/null +++ b/post/cpu/ppc4xx/watchdog.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@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 + */ + +#include <common.h> + +/* + * Watchdog test + * + * The test verifies the watchdog timer operation. + * On the first iteration, the test routine disables interrupts and + * makes a 10-second delay. If the system does not reboot during this delay, + * the watchdog timer is not operational and the test fails. If the system + * reboots, on the second iteration the test routine reports a success. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_WATCHDOG + +#include <watchdog.h> + +int watchdog_post_test (int flags) +{ + if (flags & POST_REBOOT) { + /* Test passed */ + return 0; + } + else { + /* 10-second delay */ + int ints = disable_interrupts (); + ulong base = post_time_ms (0); + + while (post_time_ms (base) < 10000) + ; + if (ints) + enable_interrupts (); + + /* + * If we have reached this point, the watchdog timer + * does not work + */ + return -1; + } +} + +#endif /* CONFIG_POST & CFG_POST_WATCHDOG */ +#endif /* CONFIG_POST */ diff --git a/post/drivers/Makefile b/post/drivers/Makefile index 068fa98..cb2f1de 100644 --- a/post/drivers/Makefile +++ b/post/drivers/Makefile @@ -26,6 +26,6 @@ SUBDIRS = LIB = libpostdrivers.a -COBJS = cache.o i2c.o memory.o rtc.o +COBJS = i2c.o memory.o rtc.o include $(TOPDIR)/post/rules.mk 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); diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile index 14354a0..9f1b329 100644 --- a/post/lib_ppc/Makefile +++ b/post/lib_ppc/Makefile @@ -21,6 +21,7 @@ # MA 02111-1307 USA # +SUBDIRS = fpu LIB = libpostppc.a diff --git a/post/lib_ppc/asm.S b/post/lib_ppc/asm.S index a0815a4..5e72b34 100644 --- a/post/lib_ppc/asm.S +++ b/post/lib_ppc/asm.S @@ -34,6 +34,7 @@ /* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */ .global cpu_post_exec_02 cpu_post_exec_02: + isync mflr r0 stwu r0, -4(r1) @@ -56,6 +57,7 @@ cpu_post_exec_02: /* void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, ulong op4); */ .global cpu_post_exec_04 cpu_post_exec_04: + isync mflr r0 stwu r0, -4(r1) @@ -80,6 +82,7 @@ cpu_post_exec_04: /* void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); */ .global cpu_post_exec_12 cpu_post_exec_12: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -100,6 +103,7 @@ cpu_post_exec_12: /* void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); */ .global cpu_post_exec_11 cpu_post_exec_11: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -119,6 +123,7 @@ cpu_post_exec_11: /* void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); */ .global cpu_post_exec_21 cpu_post_exec_21: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -148,6 +153,7 @@ cpu_post_exec_21: ulong op2); */ .global cpu_post_exec_22 cpu_post_exec_22: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -177,6 +183,7 @@ cpu_post_exec_22: /* void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); */ .global cpu_post_exec_12w cpu_post_exec_12w: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -198,6 +205,7 @@ cpu_post_exec_12w: /* void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); */ .global cpu_post_exec_11w cpu_post_exec_11w: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -218,6 +226,7 @@ cpu_post_exec_11w: /* void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); */ .global cpu_post_exec_22w cpu_post_exec_22w: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -241,6 +250,7 @@ cpu_post_exec_22w: /* void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); */ .global cpu_post_exec_21w cpu_post_exec_21w: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -263,6 +273,7 @@ cpu_post_exec_21w: /* void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); */ .global cpu_post_exec_21x cpu_post_exec_21x: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) @@ -286,6 +297,7 @@ cpu_post_exec_21x: ulong cr); */ .global cpu_post_exec_31 cpu_post_exec_31: + isync mflr r0 stwu r0, -4(r1) stwu r4, -4(r1) diff --git a/post/lib_ppc/b.c b/post/lib_ppc/b.c index b4b17c8..6e276c4 100644 --- a/post/lib_ppc/b.c +++ b/post/lib_ppc/b.c @@ -49,7 +49,7 @@ extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, ulong cr); static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, - int pjump, int dec, int link, ulong pctr, ulong cr) + int pjump, int decr, int link, ulong pctr, ulong cr) { int ret = 0; ulong lr = 0; @@ -77,7 +77,7 @@ static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, ret = pjump == jump ? 0 : -1; if (ret == 0) { - if (dec) + if (decr) ret = pctr == ctr + 1 ? 0 : -1; else ret = pctr == ctr ? 0 : -1; @@ -163,7 +163,7 @@ int cpu_post_test_b (void) { for (ctr = 1; ctr <= 2 && ret == 0; ctr++) { - int dec = cd < 2; + int decr = cd < 2; int cr = cond ? 0x80000000 : 0x00000000; int jumpc = cc >= 2 || (cc == 0 && !cond) || @@ -174,7 +174,7 @@ int cpu_post_test_b (void) int jump = jumpc && jumpd; ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, - (cc << 3) + (cd << 1), 0, jump, dec, link, + (cc << 3) + (cd << 1), 0, jump, decr, link, ctr, cr); if (ret != 0) diff --git a/post/lib_ppc/fpu/20001122-1.c b/post/lib_ppc/fpu/20001122-1.c new file mode 100644 index 0000000..f689b82 --- /dev/null +++ b/post/lib_ppc/fpu/20001122-1.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math1 (void) +{ + volatile double a, *p; + double c, d; + volatile double b; + + d = 1.0; + p = &b; + + do + { + c = d; + d = c * 0.5; + b = 1 + d; + } while (b != 1.0); + + a = 1.0 + c; + + if (a == 1.0) { + post_log ("Error in FPU math1 test\n"); + return -1; + } + + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/20010114-2.c b/post/lib_ppc/fpu/20010114-2.c new file mode 100644 index 0000000..6e60507 --- /dev/null +++ b/post/lib_ppc/fpu/20010114-2.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static float rintf (float x) +{ + volatile float TWO23 = 8388608.0; + + if (__builtin_fabs (x) < TWO23) + { + if (x > 0.0) + { + x += TWO23; + x -= TWO23; + } + else if (x < 0.0) + { + x = TWO23 - x; + x = -(x - TWO23); + } + } + + return x; +} + +int fpu_post_test_math2 (void) +{ + if (rintf (-1.5) != -2.0) { + post_log ("Error in FPU math2 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/20010226-1.c b/post/lib_ppc/fpu/20010226-1.c new file mode 100644 index 0000000..b2c47e3 --- /dev/null +++ b/post/lib_ppc/fpu/20010226-1.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math3 (void) +{ + volatile long double dfrom = 1.1; + volatile long double m1; + volatile long double m2; + volatile unsigned long mant_long; + + m1 = dfrom / 2.0; + m2 = m1 * 4294967296.0; + mant_long = ((unsigned long) m2) & 0xffffffff; + + if (mant_long != 0x8ccccccc) { + post_log ("Error in FPU math3 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/980619-1.c b/post/lib_ppc/fpu/980619-1.c new file mode 100644 index 0000000..990aa0c --- /dev/null +++ b/post/lib_ppc/fpu/980619-1.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math4 (void) +{ + volatile float reale = 1.0f; + volatile float oneplus; + int i; + + if (sizeof (float) != 4) + return 0; + + for (i = 0; ; i++) + { + oneplus = 1.0f + reale; + if (oneplus == 1.0f) + break; + reale = reale / 2.0f; + } + /* Assumes ieee754 accurate arithmetic above. */ + if (i != 24) { + post_log ("Error in FPU math4 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/Makefile b/post/lib_ppc/fpu/Makefile new file mode 100644 index 0000000..82646c8 --- /dev/null +++ b/post/lib_ppc/fpu/Makefile @@ -0,0 +1,32 @@ +# +# (C) Copyright 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 = libpostppcfpu.a + +COBJS += fpu.o 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o +COBJS += acc1.o compare-fp-1.o mul-subnormal-single-1.o + +include $(TOPDIR)/post/rules.mk + +CFLAGS += -mhard-float -fkeep-inline-functions diff --git a/post/lib_ppc/fpu/acc1.c b/post/lib_ppc/fpu/acc1.c new file mode 100644 index 0000000..4cecbf6 --- /dev/null +++ b/post/lib_ppc/fpu/acc1.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static double func (const double *array) +{ + double d = *array; + + if (d == 0.0) + return d; + else + return d + func (array + 1); +} + +int fpu_post_test_math5 (void) +{ + double values[] = { 0.1e-100, 1.0, -1.0, 0.0 }; + + if (func (values) != 0.1e-100) { + post_log ("Error in FPU math5 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/compare-fp-1.c b/post/lib_ppc/fpu/compare-fp-1.c new file mode 100644 index 0000000..d866ad5 --- /dev/null +++ b/post/lib_ppc/fpu/compare-fp-1.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 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 + */ +/* + * Test for correctness of composite floating-point comparisons. + * Written by Paolo Bonzini, 26th May 2004. + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static int failed; + +#define TEST(c) if ((c) != ok) failed++ +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b))) +#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b))) +#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b))) +#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b))) +#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b))) +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) + +static float pinf; +static float ninf; +static float NaN; + +static void iuneq (float x, float y, int ok) +{ + TEST (UNEQ (x, y)); + TEST (!LTGT (x, y)); + TEST (UNLE (x, y) && UNGE (x,y)); +} + +static void ieq (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNEQ (x, y)); +} + +static void iltgt (float x, float y, int ok) +{ + TEST (!UNEQ (x, y)); /* Not optimizable. */ + TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */ + TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y))); +} + +static void ine (float x, float y, int ok) +{ + TEST (UNLT (x, y) || UNGT (x, y)); +} + +static void iunlt (float x, float y, int ok) +{ + TEST (UNLT (x, y)); + TEST (UNORD (x, y) || (x < y)); +} + +static void ilt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */ + TEST ((x <= y) && (x != y)); + TEST ((x <= y) && (y != x)); + TEST ((x != y) && (x <= y)); /* Not optimized */ + TEST ((y != x) && (x <= y)); /* Not optimized */ +} + +static void iunle (float x, float y, int ok) +{ + TEST (UNLE (x, y)); + TEST (UNORD (x, y) || (x <= y)); +} + +static void ile (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */ + TEST ((x < y) || (x == y)); + TEST ((y > x) || (x == y)); + TEST ((x == y) || (x < y)); /* Not optimized */ + TEST ((y == x) || (x < y)); /* Not optimized */ +} + +static void iungt (float x, float y, int ok) +{ + TEST (UNGT (x, y)); + TEST (UNORD (x, y) || (x > y)); +} + +static void igt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */ + TEST ((x >= y) && (x != y)); + TEST ((x >= y) && (y != x)); + TEST ((x != y) && (x >= y)); /* Not optimized */ + TEST ((y != x) && (x >= y)); /* Not optimized */ +} + +static void iunge (float x, float y, int ok) +{ + TEST (UNGE (x, y)); + TEST (UNORD (x, y) || (x >= y)); +} + +static void ige (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */ + TEST ((x > y) || (x == y)); + TEST ((y < x) || (x == y)); + TEST ((x == y) || (x > y)); /* Not optimized */ + TEST ((y == x) || (x > y)); /* Not optimized */ +} + +int fpu_post_test_math6 (void) +{ + pinf = __builtin_inf (); + ninf = -__builtin_inf (); + NaN = __builtin_nan (""); + + iuneq (ninf, pinf, 0); + iuneq (NaN, NaN, 1); + iuneq (pinf, ninf, 0); + iuneq (1, 4, 0); + iuneq (3, 3, 1); + iuneq (5, 2, 0); + + ieq (1, 4, 0); + ieq (3, 3, 1); + ieq (5, 2, 0); + + iltgt (ninf, pinf, 1); + iltgt (NaN, NaN, 0); + iltgt (pinf, ninf, 1); + iltgt (1, 4, 1); + iltgt (3, 3, 0); + iltgt (5, 2, 1); + + ine (1, 4, 1); + ine (3, 3, 0); + ine (5, 2, 1); + + iunlt (NaN, ninf, 1); + iunlt (pinf, NaN, 1); + iunlt (pinf, ninf, 0); + iunlt (pinf, pinf, 0); + iunlt (ninf, ninf, 0); + iunlt (1, 4, 1); + iunlt (3, 3, 0); + iunlt (5, 2, 0); + + ilt (1, 4, 1); + ilt (3, 3, 0); + ilt (5, 2, 0); + + iunle (NaN, ninf, 1); + iunle (pinf, NaN, 1); + iunle (pinf, ninf, 0); + iunle (pinf, pinf, 1); + iunle (ninf, ninf, 1); + iunle (1, 4, 1); + iunle (3, 3, 1); + iunle (5, 2, 0); + + ile (1, 4, 1); + ile (3, 3, 1); + ile (5, 2, 0); + + iungt (NaN, ninf, 1); + iungt (pinf, NaN, 1); + iungt (pinf, ninf, 1); + iungt (pinf, pinf, 0); + iungt (ninf, ninf, 0); + iungt (1, 4, 0); + iungt (3, 3, 0); + iungt (5, 2, 1); + + igt (1, 4, 0); + igt (3, 3, 0); + igt (5, 2, 1); + + iunge (NaN, ninf, 1); + iunge (pinf, NaN, 1); + iunge (ninf, pinf, 0); + iunge (pinf, pinf, 1); + iunge (ninf, ninf, 1); + iunge (1, 4, 0); + iunge (3, 3, 1); + iunge (5, 2, 1); + + ige (1, 4, 0); + ige (3, 3, 1); + ige (5, 2, 1); + + if (failed) { + post_log ("Error in FPU math6 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/fpu.c b/post/lib_ppc/fpu/fpu.c new file mode 100644 index 0000000..07dcba8 --- /dev/null +++ b/post/lib_ppc/fpu/fpu.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@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 + */ + +#include <common.h> + +/* + * FPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +#include <watchdog.h> + +extern int fpu_status (void); +extern void fpu_enable (void); +extern void fpu_disable (void); + +extern int fpu_post_test_math1 (void); +extern int fpu_post_test_math2 (void); +extern int fpu_post_test_math3 (void); +extern int fpu_post_test_math4 (void); +extern int fpu_post_test_math5 (void); +extern int fpu_post_test_math6 (void); +extern int fpu_post_test_math7 (void); + +int fpu_post_test (int flags) +{ + int fpu = fpu_status (); + + int ret = 0; + + WATCHDOG_RESET (); + + if (!fpu) + fpu_enable (); + + if (ret == 0) + ret = fpu_post_test_math1 (); + if (ret == 0) + ret = fpu_post_test_math2 (); + if (ret == 0) + ret = fpu_post_test_math3 (); + if (ret == 0) + ret = fpu_post_test_math4 (); + if (ret == 0) + ret = fpu_post_test_math5 (); + if (ret == 0) + ret = fpu_post_test_math6 (); + if (ret == 0) + ret = fpu_post_test_math7 (); + + if (!fpu) + fpu_disable (); + + WATCHDOG_RESET (); + + return ret; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/mul-subnormal-single-1.c b/post/lib_ppc/fpu/mul-subnormal-single-1.c new file mode 100644 index 0000000..67f48da --- /dev/null +++ b/post/lib_ppc/fpu/mul-subnormal-single-1.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 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 + */ +/* + * This file is originally a part of the GCC testsuite. + * Check that certain subnormal numbers (formerly known as denormalized + * numbers) are rounded to within 0.5 ulp. PR other/14354. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +union uf +{ + unsigned int u; + float f; +}; + +static float +u2f (unsigned int v) +{ + union uf u; + u.u = v; + return u.f; +} + +static unsigned int +f2u (float v) +{ + union uf u; + u.f = v; + return u.u; +} + +static int ok = 1; + +static void +tstmul (unsigned int ux, unsigned int uy, unsigned int ur) +{ + float x = u2f (ux); + float y = u2f (uy); + + if (f2u (x * y) != ur) + /* Set a variable rather than aborting here, to simplify tracing when + several computations are wrong. */ + ok = 0; +} + +/* We don't want to make this const and static, or else we risk inlining + causing the test to fold as constants at compile-time. */ +struct +{ + unsigned int p1, p2, res; +} static volatile expected[] = +{ + {0xfff, 0x3f800400, 0xfff}, + {0xf, 0x3fc88888, 0x17}, + {0xf, 0x3f844444, 0xf} +}; + +int fpu_post_test_math7 (void) +{ + unsigned int i; + + for (i = 0; i < sizeof (expected) / sizeof (expected[0]); i++) + { + tstmul (expected[i].p1, expected[i].p2, expected[i].res); + tstmul (expected[i].p2, expected[i].p1, expected[i].res); + } + + if (!ok) { + post_log ("Error in FPU math7 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/post.c b/post/post.c index ac41990..4ff75ee 100644 --- a/post/post.c +++ b/post/post.c @@ -129,9 +129,7 @@ void post_output_backlog ( void ) post_log ("PASSED\n"); else { post_log ("FAILED\n"); -#ifdef CONFIG_SHOW_BOOT_PROGRESS - show_boot_progress(-31); -#endif + show_boot_progress (-31); } } } @@ -241,9 +239,7 @@ static int post_run_single (struct post_test *test, } else { if ((*test->test) (flags) != 0) { post_log ("FAILED\n"); -#ifdef CONFIG_SHOW_BOOT_PROGRESS - show_boot_progress(-32); -#endif + show_boot_progress (-32); } else post_log ("PASSED\n"); @@ -428,7 +424,7 @@ void post_reloc (void) unsigned long post_time_ms (unsigned long base) { #ifdef CONFIG_PPC - return (unsigned long)get_ticks () / (get_tbclk () / CFG_HZ) - base; + return (unsigned long)(get_ticks () / (get_tbclk () / CFG_HZ)) - base; #else #warning "Not implemented yet" return 0; /* Not implemented yet */ diff --git a/post/tests.c b/post/tests.c index 3bccd1a..e1c3d28 100644 --- a/post/tests.c +++ b/post/tests.c @@ -37,6 +37,7 @@ extern int i2c_post_test (int flags); extern int rtc_post_test (int flags); extern int memory_post_test (int flags); extern int cpu_post_test (int flags); +extern int fpu_post_test (int flags); extern int uart_post_test (int flags); extern int ether_post_test (int flags); extern int spi_post_test (int flags); @@ -45,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); @@ -126,6 +128,19 @@ struct post_test post_list[] = CFG_POST_CPU }, #endif +#if CONFIG_POST & CFG_POST_FPU + { + "FPU test", + "fpu", + "This test verifies the arithmetic logic unit of" + " FPU.", + POST_RAM | POST_ALWAYS, + &fpu_post_test, + NULL, + NULL, + CFG_POST_FPU + }, +#endif #if CONFIG_POST & CFG_POST_UART { "UART test", @@ -222,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); |