Merged POST framework with the current TOT.
authorSergei Poselenov <sposelenov@emcraft.com>
Thu, 5 Jul 2007 06:17:37 +0000 (08:17 +0200)
committerStefan Roese <sr@denx.de>
Thu, 5 Jul 2007 06:17:37 +0000 (08:17 +0200)
Signed-off-by: Sergei Poselenov <sposelenov@emcraft.com>
26 files changed:
Makefile
cpu/ppc4xx/start.S
include/configs/sequoia.h
include/ppc440.h
post/cpu/mpc8xx/Makefile
post/cpu/mpc8xx/cache.c [new file with mode: 0644]
post/cpu/ppc4xx/Makefile
post/cpu/ppc4xx/cache.c [new file with mode: 0644]
post/cpu/ppc4xx/cache_4xx.S [new file with mode: 0644]
post/cpu/ppc4xx/ether.c [new file with mode: 0644]
post/cpu/ppc4xx/fpu.c
post/cpu/ppc4xx/spr.c
post/cpu/ppc4xx/uart.c
post/cpu/ppc4xx/watchdog.c
post/drivers/Makefile
post/drivers/cache.c [deleted file]
post/lib_ppc/Makefile
post/lib_ppc/fpu/20001122-1.c [new file with mode: 0644]
post/lib_ppc/fpu/20010114-2.c [new file with mode: 0644]
post/lib_ppc/fpu/20010226-1.c [new file with mode: 0644]
post/lib_ppc/fpu/980619-1.c [new file with mode: 0644]
post/lib_ppc/fpu/Makefile [new file with mode: 0644]
post/lib_ppc/fpu/acc1.c [new file with mode: 0644]
post/lib_ppc/fpu/compare-fp-1.c [new file with mode: 0644]
post/lib_ppc/fpu/fpu.c [new file with mode: 0644]
post/lib_ppc/fpu/mul-subnormal-single-1.c [new file with mode: 0644]

index 2d8cff3ffa4c5c522090b490f377671b7f0d961e..626283f708bc37367f33d35b4cf124c7b0073537 100644 (file)
--- 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 \
index dfe813c3f456866a91db946d704cfb6fae34ec0c..6086b6ceae472c76fd028cb6f189399ba7fffc5e 100644 (file)
@@ -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:
index 44bc955519485c35a6ede2997a5639593544c6c6..32199929a972cc6c9d2736fd2af451121dccdf73 100644 (file)
                                 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 */
 
index 61c937d9f9d3742dbe84f8cdc383d0da0266077b..93c10f1209960809941f06a3c78478ad8abeddfc 100644 (file)
 #define sdr_sdstp3     0x4003
 #endif /* CONFIG_440GX */
 
-#ifdef CONFIG_440
 /*----------------------------------------------------------------------------+
 | Core Configuration/MMU configuration for 440 (CCR1 for 440x5 only).
 +----------------------------------------------------------------------------*/
 #define MMUCR_IULXE            0x00400000
 #define MMUCR_STS              0x00100000
 #define MMUCR_STID_MASK                0x000000FF
-#endif /* CONFIG_440 */
 
 #ifdef CONFIG_440SPE
 #undef sdr_sdstp2
index 9dd3f0fce9b112683aed8fd27030baf330111aba..f871cbab6496cc367d950cf99a94a13c3adcdd02 100644 (file)
@@ -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/cpu/mpc8xx/cache.c b/post/cpu/mpc8xx/cache.c
new file mode 100644 (file)
index 0000000..501465c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * (C) Copyright 2002
+ * 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
+ */
+
+#include <common.h>
+
+/* Cache test
+ *
+ * This test verifies the CPU data and instruction cache using
+ * several test scenarios.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <watchdog.h>
+
+#if CONFIG_POST & CFG_POST_CACHE
+
+#define CACHE_POST_SIZE        1024
+
+extern int cache_post_test1 (char *, unsigned int);
+extern int cache_post_test2 (char *, unsigned int);
+extern int cache_post_test3 (char *, unsigned int);
+extern int cache_post_test4 (char *, unsigned int);
+extern int cache_post_test5 (void);
+extern int cache_post_test6 (void);
+
+int cache_post_test (int flags)
+{
+       int ints = disable_interrupts ();
+       int res = 0;
+       static char ta[CACHE_POST_SIZE + 0xf];
+       char *testarea = (char *) (((unsigned long) ta + 0xf) & ~0xf);
+
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test1 (testarea, CACHE_POST_SIZE);
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test2 (testarea, CACHE_POST_SIZE);
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test3 (testarea, CACHE_POST_SIZE);
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test4 (testarea, CACHE_POST_SIZE);
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test5 ();
+       WATCHDOG_RESET ();
+       if (res == 0)
+               res = cache_post_test6 ();
+
+       WATCHDOG_RESET ();
+       if (ints)
+               enable_interrupts ();
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_CACHE */
+#endif /* CONFIG_POST */
index 8e8ab50577ab11ae3036c3159dd33a411b311376..f1034dac249c12dbda31341816a4d1fb7704ba87 100644 (file)
@@ -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 (file)
index 0000000..e1f989e
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * (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 */
+
+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 (file)
index 0000000..785b8d6
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * (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
+
+/* 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 (file)
index 0000000..391c815
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * (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;
+       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 */
index 1935c011ba73a11bdd5fdf6bcbc8d3e1c895c27d..c2eb4a9bf0b5e03c4a0dc7bba7284b3ebc2ad884 100644 (file)
@@ -1,5 +1,8 @@
 /*
- *  Copyright (C) 2007 Wolfgang Denk <wd@denx.de>
+ * (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.
@@ -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 */
index f62526a1716e9f60f071228dedb8f00668894440..be5a701f317dbd90264a24f5c0a634177081e4f1 100644 (file)
@@ -2,6 +2,8 @@
  * (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.
  *
@@ -39,6 +41,8 @@
 
 #if CONFIG_POST & CFG_POST_SPR
 
+#include <asm/processor.h>
+
 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 */
index f220dba17abca59842bd8711b26a14c4346cbf17..b047d42dfd303675f57a1dc5204b74b2a5b3a717 100644 (file)
@@ -2,6 +2,8 @@
  * (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.
  *
@@ -210,5 +212,4 @@ int uart_post_test (int flags)
 }
 
 #endif /* CONFIG_POST & CFG_POST_UART */
-
 #endif /* CONFIG_POST */
index 3c76cfd3484b0eb0a25e4b3ec764cc7a33f99840..bd4f4c9856b2bf1c43d54e4942dacf44687da400 100644 (file)
@@ -2,6 +2,8 @@
  * (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.
  *
 #ifdef CONFIG_POST
 
 #include <post.h>
-#include <watchdog.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 {
+       }
+       else {
                /* 10-second delay */
                int ints = disable_interrupts ();
                ulong base = post_time_ms (0);
index 068fa98b14c349e769139d9754fd8ba060d55a18..cb2f1deacd7083f50238c571c8fcd90c2226c148 100644 (file)
@@ -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/cache.c b/post/drivers/cache.c
deleted file mode 100644 (file)
index 501465c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * (C) Copyright 2002
- * 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
- */
-
-#include <common.h>
-
-/* Cache test
- *
- * This test verifies the CPU data and instruction cache using
- * several test scenarios.
- */
-
-#ifdef CONFIG_POST
-
-#include <post.h>
-#include <watchdog.h>
-
-#if CONFIG_POST & CFG_POST_CACHE
-
-#define CACHE_POST_SIZE        1024
-
-extern int cache_post_test1 (char *, unsigned int);
-extern int cache_post_test2 (char *, unsigned int);
-extern int cache_post_test3 (char *, unsigned int);
-extern int cache_post_test4 (char *, unsigned int);
-extern int cache_post_test5 (void);
-extern int cache_post_test6 (void);
-
-int cache_post_test (int flags)
-{
-       int ints = disable_interrupts ();
-       int res = 0;
-       static char ta[CACHE_POST_SIZE + 0xf];
-       char *testarea = (char *) (((unsigned long) ta + 0xf) & ~0xf);
-
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test1 (testarea, CACHE_POST_SIZE);
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test2 (testarea, CACHE_POST_SIZE);
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test3 (testarea, CACHE_POST_SIZE);
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test4 (testarea, CACHE_POST_SIZE);
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test5 ();
-       WATCHDOG_RESET ();
-       if (res == 0)
-               res = cache_post_test6 ();
-
-       WATCHDOG_RESET ();
-       if (ints)
-               enable_interrupts ();
-       return res;
-}
-
-#endif /* CONFIG_POST & CFG_POST_CACHE */
-#endif /* CONFIG_POST */
index 14354a032363e449e380b27eabe945a15aa5e863..9f1b329d70be472c92b1a948c62f510521ca671c 100644 (file)
@@ -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 (file)
index 0000000..f689b82
--- /dev/null
@@ -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 (file)
index 0000000..6e60507
--- /dev/null
@@ -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 (file)
index 0000000..b2c47e3
--- /dev/null
@@ -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 (file)
index 0000000..990aa0c
--- /dev/null
@@ -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 (file)
index 0000000..82646c8
--- /dev/null
@@ -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 (file)
index 0000000..4cecbf6
--- /dev/null
@@ -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 (file)
index 0000000..d866ad5
--- /dev/null
@@ -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 (file)
index 0000000..07dcba8
--- /dev/null
@@ -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 (file)
index 0000000..67f48da
--- /dev/null
@@ -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 */