From: Sergei Poselenov Date: Thu, 5 Jul 2007 06:17:37 +0000 (+0200) Subject: Merged POST framework with the current TOT. X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=b44896215a09c60fa40cae906f7ed207bbc2c492;p=u-boot.git Merged POST framework with the current TOT. Signed-off-by: Sergei Poselenov --- diff --git a/Makefile b/Makefile index 2d8cff3ffa..626283f708 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,8 @@ LIBS += drivers/sk98lin/libsk98lin.a LIBS += post/libpost.a post/drivers/libpostdrivers.a LIBS += $(shell if [ -d post/lib_$(ARCH) ]; then echo \ "post/lib_$(ARCH)/libpost$(ARCH).a"; fi) +LIBS += $(shell if [ -d post/lib_$(ARCH)/fpu ]; then echo \ + "post/lib_$(ARCH)/fpu/libpost$(ARCH)fpu.a"; fi) LIBS += $(shell if [ -d post/cpu/$(CPU) ]; then echo \ "post/cpu/$(CPU)/libpost$(CPU).a"; fi) LIBS += $(shell if [ -d post/board/$(BOARDDIR) ]; then echo \ diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index dfe813c3f4..6086b6ceae 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -1217,15 +1217,23 @@ mck_return: * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, * although for some cache-ralated calls stubs have to be provided to satisfy * symbols resolution. + * Icache-related functions are used in POST framework. * */ #ifdef CONFIG_440 .globl dcache_disable + .globl icache_disable + .globl icache_enable dcache_disable: +icache_disable: +icache_enable: blr .globl dcache_status + .globl icache_status dcache_status: +icache_status: + mr r3, 0 blr #else flush_dcache: diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index 44bc955519..32199929a9 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -334,10 +334,14 @@ CFG_POST_CPU | \ CFG_POST_UART | \ CFG_POST_I2C | \ + CFG_POST_CACHE | \ + CFG_POST_FPU | \ + CFG_POST_ETHER | \ CFG_POST_SPR) #define CFG_POST_WORD_ADDR (CFG_GBL_DATA_OFFSET - 0x4) #define CONFIG_LOGBUFFER +#define CFG_POST_CACHE_ADDR 0x10000000 /* free virtual address */ #define CFG_CONSOLE_IS_IN_ENV /* Otherwise it catches logbuffer as output */ diff --git a/include/ppc440.h b/include/ppc440.h index 61c937d9f9..93c10f1209 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -282,7 +282,6 @@ #define sdr_sdstp3 0x4003 #endif /* CONFIG_440GX */ -#ifdef CONFIG_440 /*----------------------------------------------------------------------------+ | Core Configuration/MMU configuration for 440 (CCR1 for 440x5 only). +----------------------------------------------------------------------------*/ @@ -306,7 +305,6 @@ #define MMUCR_IULXE 0x00400000 #define MMUCR_STS 0x00100000 #define MMUCR_STID_MASK 0x000000FF -#endif /* CONFIG_440 */ #ifdef CONFIG_440SPE #undef sdr_sdstp2 diff --git a/post/cpu/mpc8xx/Makefile b/post/cpu/mpc8xx/Makefile index 9dd3f0fce9..f871cbab64 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 similarity index 100% rename from post/drivers/cache.c rename to post/cpu/mpc8xx/cache.c diff --git a/post/cpu/ppc4xx/Makefile b/post/cpu/ppc4xx/Makefile index 8e8ab50577..f1034dac24 100644 --- a/post/cpu/ppc4xx/Makefile +++ b/post/cpu/ppc4xx/Makefile @@ -23,6 +23,7 @@ LIB = libpostppc4xx.a -COBJS = fpu.o spr.o uart.o watchdog.o +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 0000000000..e1f989ed93 --- /dev/null +++ b/post/cpu/ppc4xx/cache.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin + * + * 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 + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#ifdef CONFIG_POST + +#include + +#if CONFIG_POST & CFG_POST_CACHE + +#include +#include + +#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 */ + +static unsigned char testarea[CACHE_POST_SIZE] +__attribute__((__aligned__(CACHE_POST_SIZE))); + +int cache_post_test (int flags) +{ + void* virt = (void*)CFG_POST_CACHE_ADDR; + int ints, i, res = 0; + u32 word0; + + 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; + } + } + } + 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 0000000000..785b8d60b9 --- /dev/null +++ b/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,448 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin + * + * 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 + +#ifdef CONFIG_POST + +#include +#include +#include +#include +#include + +#if CONFIG_POST & CFG_POST_CACHE + + .text + +/* 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 + +/* 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 0000000000..391c815d7a --- /dev/null +++ b/post/cpu/ppc4xx/ether.c @@ -0,0 +1,395 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin + * + * 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 + +/* + * 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 + +#if CONFIG_POST & CFG_POST_ETHER + +#include +#include +#include +#include <405_mal.h> +#include +#include + +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; + unsigned mode_reg; +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + 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 */ + 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)); + + /* 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 index 1935c011ba..c2eb4a9bf0 100644 --- a/post/cpu/ppc4xx/fpu.c +++ b/post/cpu/ppc4xx/fpu.c @@ -1,5 +1,8 @@ /* - * Copyright (C) 2007 Wolfgang Denk + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov * * See file CREDITS for list of people who contributed to this * project. @@ -34,7 +37,7 @@ int fpu_status(void) { if (mfspr(ccr0) & CCR0_DAPUIB) return 0; /* Disabled */ - else + else return 1; /* Enabled */ } @@ -51,5 +54,6 @@ void fpu_enable(void) mtspr(ccr0, mfspr(ccr0) & ~CCR0_DAPUIB); mtmsr(mfmsr() | MSR_FP); } + #endif -#endif +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/spr.c b/post/cpu/ppc4xx/spr.c index f62526a171..be5a701f31 100644 --- a/post/cpu/ppc4xx/spr.c +++ b/post/cpu/ppc4xx/spr.c @@ -2,6 +2,8 @@ * (C) Copyright 2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * + * Author: Igor Lisitsin + * * See file CREDITS for list of people who contributed to this * project. * @@ -39,6 +41,8 @@ #if CONFIG_POST & CFG_POST_SPR +#include + static struct { int number; @@ -60,8 +64,10 @@ static struct {0x113, "SPRG3", 0x00000000, 0x00000000}, {0x11f, "PVR", 0x00000000, 0x00000000}, - /* Additional Special-Purpose Registers */ - + /* 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}, @@ -90,22 +96,22 @@ static struct {0x13f, "DVC2", 0x00000000, 0x00000000}, {0x150, "TSR", 0x00000000, 0x00000000}, {0x154, "TCR", 0x00000000, 0x00000000}, - {0x190, "IVOR0", 0x00000000, 0x00000000}, - {0x191, "IVOR1", 0x00000000, 0x00000000}, - {0x192, "IVOR2", 0x00000000, 0x00000000}, - {0x193, "IVOR3", 0x00000000, 0x00000000}, - {0x194, "IVOR4", 0x00000000, 0x00000000}, - {0x195, "IVOR5", 0x00000000, 0x00000000}, - {0x196, "IVOR6", 0x00000000, 0x00000000}, - {0x197, "IVOR7", 0x00000000, 0x00000000}, - {0x198, "IVOR8", 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", 0x00000000, 0x00000000}, + {0x19a, "IVOR10", 0x0000fff0, 0x00000900}, {0x19b, "IVOR11", 0x00000000, 0x00000000}, {0x19c, "IVOR12", 0x00000000, 0x00000000}, - {0x19d, "IVOR13", 0x00000000, 0x00000000}, - {0x19e, "IVOR14", 0x00000000, 0x00000000}, - {0x19f, "IVOR15", 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}, @@ -126,8 +132,8 @@ static struct {0x395, "DTV1", 0x00000000, 0x00000000}, {0x396, "DTV2", 0x00000000, 0x00000000}, {0x397, "DTV3", 0x00000000, 0x00000000}, - {0x398, "DVLIM", 0x00000000, 0x00000000}, - {0x399, "IVLIM", 0x00000000, 0x00000000}, + {0x398, "DVLIM", 0x0fc1f83f, 0x0001f800}, + {0x399, "IVLIM", 0x0fc1f83f, 0x0001f800}, {0x39b, "RSTCFG", 0x00000000, 0x00000000}, {0x39c, "DCDBTRL", 0x00000000, 0x00000000}, {0x39d, "DCDBTRH", 0x00000000, 0x00000000}, @@ -172,5 +178,6 @@ int spr_post_test (int flags) 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 index f220dba17a..b047d42dfd 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -2,6 +2,8 @@ * (C) Copyright 2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * + * Author: Igor Lisitsin + * * See file CREDITS for list of people who contributed to this * project. * @@ -210,5 +212,4 @@ int uart_post_test (int flags) } #endif /* CONFIG_POST & CFG_POST_UART */ - #endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/watchdog.c b/post/cpu/ppc4xx/watchdog.c index 3c76cfd348..bd4f4c9856 100644 --- a/post/cpu/ppc4xx/watchdog.c +++ b/post/cpu/ppc4xx/watchdog.c @@ -2,6 +2,8 @@ * (C) Copyright 2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * + * Author: Igor Lisitsin + * * See file CREDITS for list of people who contributed to this * project. * @@ -36,17 +38,18 @@ #ifdef CONFIG_POST #include -#include #if CONFIG_POST & CFG_POST_WATCHDOG +#include + int watchdog_post_test (int flags) { if (flags & POST_REBOOT) { /* Test passed */ - return 0; - } else { + } + else { /* 10-second delay */ int ints = disable_interrupts (); ulong base = post_time_ms (0); diff --git a/post/drivers/Makefile b/post/drivers/Makefile index 068fa98b14..cb2f1deacd 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/lib_ppc/Makefile b/post/lib_ppc/Makefile index 14354a0323..9f1b329d70 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/fpu/20001122-1.c b/post/lib_ppc/fpu/20001122-1.c new file mode 100644 index 0000000000..f689b8232f --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..6e60507f9c --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..b2c47e3658 --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..990aa0c989 --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..82646c80d6 --- /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 0000000000..4cecbf6a4f --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..d866ad5a36 --- /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 + +#ifdef CONFIG_POST + +#include + +#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 0000000000..07dcba8cc9 --- /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 + * + * 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 + +/* + * 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 + +#if CONFIG_POST & CFG_POST_FPU + +#include + +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 0000000000..67f48da335 --- /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 + +#ifdef CONFIG_POST + +#include + +#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 */