Restructure POST directory to support of other CPUs, boards, etc.
authorWolfgang Denk <wd@pollux.denx.de>
Tue, 6 Mar 2007 17:08:43 +0000 (18:08 +0100)
committerWolfgang Denk <wd@denx.de>
Tue, 6 Mar 2007 17:08:43 +0000 (18:08 +0100)
45 files changed:
Makefile
cpu/ppc4xx/44x_spd_ddr2.c
cpu/ppc4xx/start.S
post/Makefile
post/board/lwmon/Makefile [new file with mode: 0644]
post/board/lwmon/sysmon.c [new file with mode: 0644]
post/board/netta/Makefile [new file with mode: 0644]
post/board/netta/codec.c [new file with mode: 0644]
post/board/netta/dsp.c [new file with mode: 0644]
post/cpu/mpc8xx/Makefile [new file with mode: 0644]
post/cpu/mpc8xx/cache_8xx.S [new file with mode: 0644]
post/cpu/mpc8xx/ether.c [new file with mode: 0644]
post/cpu/mpc8xx/spr.c [new file with mode: 0644]
post/cpu/mpc8xx/uart.c [new file with mode: 0644]
post/cpu/mpc8xx/usb.c [new file with mode: 0644]
post/cpu/mpc8xx/watchdog.c [new file with mode: 0644]
post/drivers/Makefile [new file with mode: 0644]
post/drivers/cache.c [new file with mode: 0644]
post/drivers/i2c.c [new file with mode: 0644]
post/drivers/memory.c [new file with mode: 0644]
post/drivers/rtc.c [new file with mode: 0644]
post/lib_ppc/Makefile [new file with mode: 0644]
post/lib_ppc/andi.c [new file with mode: 0644]
post/lib_ppc/asm.S [new file with mode: 0644]
post/lib_ppc/b.c [new file with mode: 0644]
post/lib_ppc/cmp.c [new file with mode: 0644]
post/lib_ppc/cmpi.c [new file with mode: 0644]
post/lib_ppc/complex.c [new file with mode: 0644]
post/lib_ppc/cpu.c [new file with mode: 0644]
post/lib_ppc/cpu_asm.h [new file with mode: 0644]
post/lib_ppc/cr.c [new file with mode: 0644]
post/lib_ppc/load.c [new file with mode: 0644]
post/lib_ppc/multi.c [new file with mode: 0644]
post/lib_ppc/rlwimi.c [new file with mode: 0644]
post/lib_ppc/rlwinm.c [new file with mode: 0644]
post/lib_ppc/rlwnm.c [new file with mode: 0644]
post/lib_ppc/srawi.c [new file with mode: 0644]
post/lib_ppc/store.c [new file with mode: 0644]
post/lib_ppc/string.c [new file with mode: 0644]
post/lib_ppc/three.c [new file with mode: 0644]
post/lib_ppc/threei.c [new file with mode: 0644]
post/lib_ppc/threex.c [new file with mode: 0644]
post/lib_ppc/two.c [new file with mode: 0644]
post/lib_ppc/twox.c [new file with mode: 0644]
post/post.c

index 3809de0a411b9f2d6e2fdd1b2558c309eec0d725..fec114ff6b011d709881e34a421ff058b594a4b1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -203,7 +203,13 @@ ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/qe.a
 endif
 LIBS += drivers/sk98lin/libsk98lin.a
-LIBS += post/libpost.a post/cpu/libcpu.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/cpu/$(CPU) ]; then echo \
+       "post/cpu/$(CPU)/libpost$(CPU).a"; fi)
+LIBS += $(shell if [ -d post/board/$(BOARDDIR) ]; then echo \
+       "post/board/$(BOARDDIR)/libpost$(BOARD).a"; fi)
 LIBS += common/libcommon.a
 LIBS += $(BOARDLIBS)
 
@@ -216,9 +222,8 @@ PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -
 # The "tools" are needed early, so put this first
 # Don't include stuff already done in $(LIBS)
 SUBDIRS        = tools \
-         examples \
-         post \
-         post/cpu
+         examples
+
 .PHONY : $(SUBDIRS)
 
 ifeq ($(CONFIG_NAND_U_BOOT),y)
index 35b23152f3b57cd9d2997f9b5c8102ab06611e40..3ab050f9f735e872865a9efef985a8e0a7ae8a4c 100644 (file)
@@ -168,8 +168,8 @@ static void program_codt(unsigned long *dimm_populated,
 static void program_mode(unsigned long *dimm_populated,
                         unsigned char *iic0_dimm_addr,
                         unsigned long num_dimm_banks,
-                         ddr_cas_id_t *selected_cas,
-                         int *write_recovery);
+                        ddr_cas_id_t *selected_cas,
+                        int *write_recovery);
 static void program_tr(unsigned long *dimm_populated,
                       unsigned char *iic0_dimm_addr,
                       unsigned long num_dimm_banks);
@@ -185,7 +185,7 @@ static void program_copt1(unsigned long *dimm_populated,
 static void program_initplr(unsigned long *dimm_populated,
                            unsigned char *iic0_dimm_addr,
                            unsigned long num_dimm_banks,
-                            ddr_cas_id_t selected_cas,
+                           ddr_cas_id_t selected_cas,
                            int write_recovery);
 static unsigned long is_ecc_enabled(void);
 static void program_ecc(unsigned long *dimm_populated,
@@ -1149,7 +1149,7 @@ static void program_codt(unsigned long *dimm_populated,
 static void program_initplr(unsigned long *dimm_populated,
                            unsigned char *iic0_dimm_addr,
                            unsigned long num_dimm_banks,
-                            ddr_cas_id_t selected_cas,
+                           ddr_cas_id_t selected_cas,
                            int write_recovery)
 {
        u32 cas = 0;
index 24b30dfe71680b428b3dbf800699cda81f969b9a..6b2c170335910b159ad8eaec0d853f907ed202c6 100644 (file)
@@ -1916,43 +1916,43 @@ pll_wait:
 /*----------------------------------------------------------------------------+
 | dcbz_area.
 +----------------------------------------------------------------------------*/
-        function_prolog(dcbz_area)
-        rlwinm. r5,r4,0,27,31
-        rlwinm  r5,r4,27,5,31
-        beq     ..d_ra2
-        addi    r5,r5,0x0001
+       function_prolog(dcbz_area)
+       rlwinm. r5,r4,0,27,31
+       rlwinm  r5,r4,27,5,31
+       beq     ..d_ra2
+       addi    r5,r5,0x0001
 ..d_ra2:mtctr   r5
 ..d_ag2:dcbz    r0,r3
-        addi    r3,r3,32
-        bdnz    ..d_ag2
-        sync
-        blr
-        function_epilog(dcbz_area)
+       addi    r3,r3,32
+       bdnz    ..d_ag2
+       sync
+       blr
+       function_epilog(dcbz_area)
 
 /*----------------------------------------------------------------------------+
 | dflush.  Assume 32K at vector address is cachable.
 +----------------------------------------------------------------------------*/
-        function_prolog(dflush)
-        mfmsr   r9
-        rlwinm  r8,r9,0,15,13
-        rlwinm  r8,r8,0,17,15
-        mtmsr   r8
-        addi    r3,r0,0x0000
-        mtspr   dvlim,r3
-        mfspr   r3,ivpr
-        addi    r4,r0,1024
-        mtctr   r4
+       function_prolog(dflush)
+       mfmsr   r9
+       rlwinm  r8,r9,0,15,13
+       rlwinm  r8,r8,0,17,15
+       mtmsr   r8
+       addi    r3,r0,0x0000
+       mtspr   dvlim,r3
+       mfspr   r3,ivpr
+       addi    r4,r0,1024
+       mtctr   r4
 ..dflush_loop:
-        lwz     r6,0x0(r3)
-        addi    r3,r3,32
-        bdnz    ..dflush_loop
-        addi    r3,r3,-32
-        mtctr   r4
+       lwz     r6,0x0(r3)
+       addi    r3,r3,32
+       bdnz    ..dflush_loop
+       addi    r3,r3,-32
+       mtctr   r4
 ..ag:   dcbf    r0,r3
-        addi    r3,r3,-32
-        bdnz    ..ag
-        sync
-        mtmsr   r9
-        blr
-        function_epilog(dflush)
+       addi    r3,r3,-32
+       bdnz    ..ag
+       sync
+       mtmsr   r9
+       blr
+       function_epilog(dflush)
 #endif /* CONFIG_440 */
index 228bafc6a77e0c115ce91c8a60805378e55a9054..f32af951624ceb56ecbc9061771e12bc10ef7ddd 100644 (file)
 #
 
 
-SUBDIRS = cpu
+SUBDIRS = drivers cpu lib_$(ARCH) board/$(BOARDDIR)
 
 LIB    = libpost.a
 
-AOBJS  = cache_8xx.o
-COBJS  = cache.o codec.o cpu.o dsp.o ether.o
-COBJS  += i2c.o memory.o post.o rtc.o
-COBJS  += spr.o sysmon.o tests.o uart.o
-COBJS  += usb.o watchdog.o
+COBJS  = post.o tests.o
 
 include $(TOPDIR)/post/rules.mk
diff --git a/post/board/lwmon/Makefile b/post/board/lwmon/Makefile
new file mode 100644 (file)
index 0000000..899b0dc
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2002-2006
+# 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    = libpostlwmon.a
+
+COBJS  = sysmon.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/board/lwmon/sysmon.c b/post/board/lwmon/sysmon.c
new file mode 100644 (file)
index 0000000..f61d598
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * (C) Copyright 2003
+ * 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 <post.h>
+#include <common.h>
+
+#ifdef CONFIG_POST
+
+/*
+ * SYSMON test
+ *
+ * This test performs the system hardware monitoring.
+ * The test passes when all the following voltages and temperatures
+ * are within allowed ranges:
+ *
+ * Board temperature
+ * Front temperature
+ * +3.3V CPU logic
+ * +5V logic
+ * +12V PCMCIA
+ * +12V CCFL
+ * +5V standby
+ *
+ * CCFL is not enabled if temperature values are not within allowed ranges
+ *
+ * See the list off all parameters in the sysmon_table below
+ */
+
+#include <post.h>
+#include <watchdog.h>
+#include <i2c.h>
+
+#if CONFIG_POST & CFG_POST_SYSMON
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int sysmon_temp_invalid = 0;
+
+/* #define DEBUG */
+
+#define        RELOC(x) if (x != NULL) x = (void *) ((ulong) (x) + gd->reloc_off)
+
+typedef struct sysmon_s sysmon_t;
+typedef struct sysmon_table_s sysmon_table_t;
+
+static void sysmon_lm87_init (sysmon_t * this);
+static void sysmon_pic_init (sysmon_t * this);
+static uint sysmon_i2c_read (sysmon_t * this, uint addr);
+static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr);
+static void sysmon_ccfl_disable (sysmon_table_t * this);
+static void sysmon_ccfl_enable (sysmon_table_t * this);
+
+struct sysmon_s
+{
+       uchar   chip;
+       void    (*init)(sysmon_t *);
+       uint    (*read)(sysmon_t *, uint);
+};
+
+static sysmon_t sysmon_lm87 =
+       {CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read};
+static sysmon_t sysmon_lm87_sgn =
+       {CFG_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read_sgn};
+static sysmon_t sysmon_pic =
+       {CFG_I2C_PICIO_ADDR, sysmon_pic_init, sysmon_i2c_read};
+
+static sysmon_t * sysmon_list[] =
+{
+       &sysmon_lm87,
+       &sysmon_lm87_sgn,
+       &sysmon_pic,
+       NULL
+};
+
+struct sysmon_table_s
+{
+       char *          name;
+       char *          unit_name;
+       sysmon_t *      sysmon;
+       void            (*exec_before)(sysmon_table_t *);
+       void            (*exec_after)(sysmon_table_t *);
+
+       int             unit_precision;
+       int             unit_div;
+       int             unit_min;
+       int             unit_max;
+       uint            val_mask;
+       uint            val_min;
+       uint            val_max;
+       int             val_valid;
+       uint            val_min_alt;
+       uint            val_max_alt;
+       int             val_valid_alt;
+       uint            addr;
+};
+
+static sysmon_table_t sysmon_table[] =
+{
+    {"Board temperature", " C", &sysmon_lm87_sgn, NULL, sysmon_ccfl_disable,
+     1, 1, -128, 127, 0xFF, 0x58, 0xD5, 0, 0x6C, 0xC6, 0, 0x27},
+
+    {"Front temperature", " C", &sysmon_lm87, NULL, sysmon_ccfl_disable,
+     1, 100, -27316, 8984, 0xFF, 0xA4, 0xFC, 0, 0xB2, 0xF1, 0, 0x29},
+
+    {"+3.3V CPU logic", "V", &sysmon_lm87, NULL, NULL,
+     100, 1000, 0, 4386, 0xFF, 0xB6, 0xC9, 0, 0xB6, 0xC9, 0, 0x22},
+
+    {"+ 5 V logic", "V", &sysmon_lm87, NULL, NULL,
+     100, 1000, 0, 6630, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x23},
+
+    {"+12 V PCMCIA", "V", &sysmon_lm87, NULL, NULL,
+     100, 1000, 0, 15460, 0xFF, 0xBC, 0xD0, 0, 0xBC, 0xD0, 0, 0x21},
+
+    {"+12 V CCFL", "V", &sysmon_lm87, NULL, sysmon_ccfl_enable,
+     100, 1000, 0, 15900, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x24},
+
+    {"+ 5 V standby", "V", &sysmon_pic, NULL, NULL,
+     100, 1000, 0, 6040, 0xFF, 0xC8, 0xDE, 0, 0xC8, 0xDE, 0, 0x7C},
+};
+static int sysmon_table_size = sizeof(sysmon_table) / sizeof(sysmon_table[0]);
+
+static int conversion_done = 0;
+
+
+int sysmon_init_f (void)
+{
+       sysmon_t ** l;
+       ulong reg;
+
+       /* Power on CCFL, PCMCIA */
+       reg = pic_read  (0x60);
+       reg |= 0x09;
+       pic_write (0x60, reg);
+
+       for (l = sysmon_list; *l; l++) {
+               (*l)->init(*l);
+       }
+
+       return 0;
+}
+
+void sysmon_reloc (void)
+{
+       sysmon_t ** l;
+       sysmon_table_t * t;
+
+       for (l = sysmon_list; *l; l++) {
+               RELOC(*l);
+               RELOC((*l)->init);
+               RELOC((*l)->read);
+       }
+
+       for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
+               RELOC(t->exec_before);
+               RELOC(t->exec_after);
+               RELOC(t->sysmon);
+       }
+}
+
+static char *sysmon_unit_value (sysmon_table_t *s, uint val)
+{
+       static char buf[32];
+       int unit_val =
+           s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask;
+       char *p, sign;
+       int dec, frac;
+
+       if (val == -1) {
+               return "I/O ERROR";
+       }
+
+       if (unit_val < 0) {
+               sign = '-';
+               unit_val = -unit_val;
+       } else {
+               sign = '+';
+       }
+
+       p = buf + sprintf(buf, "%c%2d", sign, unit_val / s->unit_div);
+
+
+       frac = unit_val % s->unit_div;
+
+       frac /= (s->unit_div / s->unit_precision);
+
+       dec = s->unit_precision;
+
+       if (dec != 1) {
+               *p++ = '.';
+       }
+       for (dec /= 10; dec != 0; dec /= 10) {
+               *p++ = '0' + (frac / dec) % 10;
+       }
+       strcpy(p, s->unit_name);
+
+       return buf;
+}
+
+static void sysmon_lm87_init (sysmon_t * this)
+{
+       uchar val;
+
+       /* Detect LM87 chip */
+       if (i2c_read(this->chip, 0x40, 1, &val, 1) || (val & 0x80) != 0 ||
+           i2c_read(this->chip, 0x3E, 1, &val, 1) || val != 0x02) {
+               printf("Error: LM87 not found at 0x%02X\n", this->chip);
+               return;
+       }
+
+       /* Configure pins 5,6 as AIN */
+       val = 0x03;
+       if (i2c_write(this->chip, 0x16, 1, &val, 1)) {
+               printf("Error: can't write LM87 config register\n");
+               return;
+       }
+
+       /* Start monitoring */
+       val = 0x01;
+       if (i2c_write(this->chip, 0x40, 1, &val, 1)) {
+               printf("Error: can't write LM87 config register\n");
+               return;
+       }
+}
+
+static void sysmon_pic_init (sysmon_t * this)
+{
+}
+
+static uint sysmon_i2c_read (sysmon_t * this, uint addr)
+{
+       uchar val;
+       uint res = i2c_read(this->chip, addr, 1, &val, 1);
+
+       return res == 0 ? val : -1;
+}
+
+static uint sysmon_i2c_read_sgn (sysmon_t * this, uint addr)
+{
+       uchar val;
+       return i2c_read(this->chip, addr, 1, &val, 1) == 0 ?
+               128 + (signed char)val : -1;
+}
+
+static void sysmon_ccfl_disable (sysmon_table_t * this)
+{
+       if (!this->val_valid_alt) {
+               sysmon_temp_invalid = 1;
+       }
+}
+
+static void sysmon_ccfl_enable (sysmon_table_t * this)
+{
+       ulong reg;
+
+       if (!sysmon_temp_invalid) {
+               reg = pic_read  (0x60);
+               reg |= 0x06;
+               pic_write (0x60, reg);
+       }
+}
+
+int sysmon_post_test (int flags)
+{
+       int res = 0;
+       sysmon_table_t * t;
+       uint val;
+
+       /*
+        * The A/D conversion on the LM87 sensor takes 300 ms.
+        */
+       if (! conversion_done) {
+               while (post_time_ms(gd->post_init_f_time) < 300) WATCHDOG_RESET ();
+               conversion_done = 1;
+       }
+
+       for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
+               if (t->exec_before) {
+                       t->exec_before(t);
+               }
+
+               val = t->sysmon->read(t->sysmon, t->addr);
+               if (val != -1) {
+                       t->val_valid = val >= t->val_min && val <= t->val_max;
+                       t->val_valid_alt = val >= t->val_min_alt && val <= t->val_max_alt;
+               } else {
+                       t->val_valid = 0;
+                       t->val_valid_alt = 0;
+               }
+
+               if (t->exec_after) {
+                       t->exec_after(t);
+               }
+
+               if ((!t->val_valid) || (flags & POST_MANUAL)) {
+                       printf("%-17s = %-10s ", t->name, sysmon_unit_value(t, val));
+                       printf("allowed range");
+                       printf(" %-8s ..", sysmon_unit_value(t, t->val_min));
+                       printf(" %-8s", sysmon_unit_value(t, t->val_max));
+                       printf("     %s\n", t->val_valid ? "OK" : "FAIL");
+               }
+
+               if (!t->val_valid) {
+                       res = -1;
+               }
+       }
+
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_SYSMON */
+#endif /* CONFIG_POST */
diff --git a/post/board/netta/Makefile b/post/board/netta/Makefile
new file mode 100644 (file)
index 0000000..60c7790
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2002-2006
+# 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    = libpostnetta.a
+
+COBJS  = codec.o dsp.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/board/netta/codec.c b/post/board/netta/codec.c
new file mode 100644 (file)
index 0000000..e881752
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2004
+ * Pantelis Antoniou, Intracom S.A. , panto@intracom.gr
+ *
+ * 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>
+
+/*
+ * CODEC test
+ *
+ * This test verifies the connection and performs a memory test
+ * on any connected codec(s). The meat of the work is done
+ * in the board specific function.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_CODEC
+
+extern int board_post_codec(int flags);
+
+int codec_post_test (int flags)
+{
+       return board_post_codec(flags);
+}
+
+#endif /* CONFIG_POST & CFG_POST_CODEC */
+#endif /* CONFIG_POST */
diff --git a/post/board/netta/dsp.c b/post/board/netta/dsp.c
new file mode 100644 (file)
index 0000000..63531a2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2004
+ * Pantelis Antoniou, Intracom S.A. , panto@intracom.gr
+ *
+ * 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>
+
+/*
+ * DSP test
+ *
+ * This test verifies the connection and performs a memory test
+ * on any connected DSP(s). The meat of the work is done
+ * in the board specific function.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_DSP
+
+extern int board_post_dsp(int flags);
+
+int dsp_post_test (int flags)
+{
+       return board_post_dsp(flags);
+}
+
+#endif /* CONFIG_POST & CFG_POST_DSP */
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/Makefile b/post/cpu/mpc8xx/Makefile
new file mode 100644 (file)
index 0000000..9dd3f0f
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2002-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+LIB    = libpostmpc8xx.a
+
+AOBJS  = cache_8xx.o
+COBJS  = ether.o spr.o uart.o usb.o watchdog.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/cpu/mpc8xx/cache_8xx.S b/post/cpu/mpc8xx/cache_8xx.S
new file mode 100644 (file)
index 0000000..2d41b55
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ *  Copyright (C) 2002 Wolfgang Denk <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 <config.h>
+
+#ifdef CONFIG_POST
+#if defined(CONFIG_MPC823) || \
+    defined(CONFIG_MPC850) || \
+    defined(CONFIG_MPC855) || \
+    defined(CONFIG_MPC860) || \
+    defined(CONFIG_MPC862)
+
+#include <post.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+
+#if CONFIG_POST & CFG_POST_CACHE
+
+       .text
+
+cache_post_dinvalidate:
+       lis     r10, IDC_INVALL@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_iinvalidate:
+       lis     r10, IDC_INVALL@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ddisable:
+       lis     r10, IDC_DISABLE@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_dwb:
+       lis     r10, IDC_ENABLE@h
+       mtspr   DC_CST, r10
+       lis     r10, DC_CFWT@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_dwt:
+       lis     r10, IDC_ENABLE@h
+       mtspr   DC_CST, r10
+       lis     r10, DC_SFWT@h
+       mtspr   DC_CST, r10
+       blr
+
+cache_post_idisable:
+       lis     r10, IDC_DISABLE@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ienable:
+       lis     r10, IDC_ENABLE@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_iunlock:
+       lis     r10, IDC_UNALL@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+cache_post_ilock:
+       mtspr   IC_ADR, r3
+       lis     r10, IDC_LDLCK@h
+       mtspr   IC_CST, r10
+       isync
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back or write-through mode
+ * invalidate the data cache
+ * write the negative pattern to a cached area
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test1
+cache_post_test1:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back or write-through mode
+ * invalidate the data cache
+ * write the zero pattern to a cached area
+ * turn off the data cache
+ * write the negative pattern to the area
+ * turn on the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test2
+cache_post_test2:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwb
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-through mode
+ * invalidate the data cache
+ * write the zero pattern to a cached area
+ * flush the data cache
+ * write the negative pattern to the area
+ * turn off the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test3
+cache_post_test3:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwt
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+/*
+ * turn on the data cache
+ * switch the data cache to write-back mode
+ * invalidate the data cache
+ * write the negative pattern to a cached area
+ * flush the data cache
+ * write the zero pattern to the area
+ * invalidate the data cache
+ * read the area
+ *
+ * The negative pattern must be read at the last step
+ */
+       .global cache_post_test4
+cache_post_test4:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       stwu    r3, -4(r1)
+       stwu    r4, -4(r1)
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Write the negative pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0xff
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_dwb
+       bl      cache_post_dinvalidate
+
+       /* Write the zero pattern to the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       li      r0, 0
+       lwz     r3, 4(r1)
+       subi    r3, r3, 1
+1:
+       stbu    r0, 1(r3)
+       bdnz    1b
+
+       bl      cache_post_ddisable
+       bl      cache_post_dinvalidate
+
+       /* Read the test area */
+       lwz     r0, 0(r1)
+       mtctr   r0
+       lwz     r4, 4(r1)
+       subi    r4, r4, 1
+       li      r3, 0
+1:
+       lbzu    r0, 1(r4)
+       cmpli   cr0, r0, 0xff
+       beq     2f
+       li      r3, -1
+       b       3f
+2:
+       bdnz    1b
+3:
+
+       addi    r1, r1, 8
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+cache_post_test5_1:
+       li      r3, 0
+cache_post_test5_2:
+       li      r3, -1
+
+/*
+ * turn on the instruction cache
+ * unlock the entire instruction cache
+ * invalidate the instruction cache
+ * lock a branch instruction in the instruction cache
+ * replace the branch instruction with "nop"
+ * jump to the branch instruction
+ * check that the branch instruction was executed
+*/
+       .global cache_post_test5
+cache_post_test5:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       bl      cache_post_ienable
+       bl      cache_post_iunlock
+       bl      cache_post_iinvalidate
+
+       /* Compute r9 = cache_post_test5_reloc */
+       bl      cache_post_test5_reloc
+cache_post_test5_reloc:
+       mflr    r9
+
+       /* Copy the test instruction to cache_post_test5_data */
+       lis     r3, (cache_post_test5_1 - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_1 - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Lock the branch instruction */
+       lis     r3, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       bl      cache_post_ilock
+
+       /* Replace the test instruction */
+       lis     r3, (cache_post_test5_2 - cache_post_test5_reloc)@h
+       ori     r3, r3, (cache_post_test5_2 - cache_post_test5_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test5_data - cache_post_test5_reloc)@h
+       ori     r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Execute to the test instruction */
+cache_post_test5_data:
+       nop
+
+       bl      cache_post_iunlock
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+cache_post_test6_1:
+       li      r3, -1
+cache_post_test6_2:
+       li      r3, 0
+
+/*
+ * turn on the instruction cache
+ * unlock the entire instruction cache
+ * invalidate the instruction cache
+ * lock a branch instruction in the instruction cache
+ * replace the branch instruction with "nop"
+ * jump to the branch instruction
+ * check that the branch instruction was executed
+ */
+       .global cache_post_test6
+cache_post_test6:
+       mflr    r0
+       stw     r0, 4(r1)
+
+       bl      cache_post_ienable
+       bl      cache_post_iunlock
+       bl      cache_post_iinvalidate
+
+       /* Compute r9 = cache_post_test6_reloc */
+       bl      cache_post_test6_reloc
+cache_post_test6_reloc:
+       mflr    r9
+
+       /* Copy the test instruction to cache_post_test6_data */
+       lis     r3, (cache_post_test6_1 - cache_post_test6_reloc)@h
+       ori     r3, r3, (cache_post_test6_1 - cache_post_test6_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test6_data - cache_post_test6_reloc)@h
+       ori     r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Replace the test instruction */
+       lis     r3, (cache_post_test6_2 - cache_post_test6_reloc)@h
+       ori     r3, r3, (cache_post_test6_2 - cache_post_test6_reloc)@l
+       add     r3, r3, r9
+       lis     r4, (cache_post_test6_data - cache_post_test6_reloc)@h
+       ori     r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l
+       add     r4, r4, r9
+       lwz     r0, 0(r3)
+       stw     r0, 0(r4)
+
+       bl      cache_post_iinvalidate
+
+       /* Execute to the test instruction */
+cache_post_test6_data:
+       nop
+
+       lwz     r0, 4(r1)
+       mtlr    r0
+       blr
+
+#endif /* CONFIG_MPC823 || MPC850 || MPC855 || MPC860 */
+#endif /* CONFIG_POST & CFG_POST_CACHE */
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/ether.c b/post/cpu/mpc8xx/ether.c
new file mode 100644 (file)
index 0000000..8c87b59
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+ * (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>
+
+/*
+ * Ethernet test
+ *
+ * The Serial Communication Controllers (SCC) listed in ctlr_list array below
+ * are tested in the loopback ethernet 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
+#if defined(CONFIG_8xx)
+#include <commproc.h>
+#elif defined(CONFIG_MPC8260)
+#include <asm/cpm_8260.h>
+#else
+#error "Apparently a bad configuration, please fix."
+#endif
+
+#include <command.h>
+#include <net.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MIN_PACKET_LENGTH      64
+#define MAX_PACKET_LENGTH      256
+#define TEST_NUM               1
+
+#define CTLR_SCC 0
+
+extern void spi_init_f (void);
+extern void spi_init_r (void);
+
+/* The list of controllers to test */
+#if defined(CONFIG_MPC823)
+static int ctlr_list[][2] = { {CTLR_SCC, 1} };
+#else
+static int ctlr_list[][2] = { };
+#endif
+
+#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0]))
+
+static struct {
+       void (*init) (int index);
+       void (*halt) (int index);
+       int (*send) (int index, volatile void *packet, int length);
+       int (*recv) (int index, void *packet, int length);
+} ctlr_proc[1];
+
+static char *ctlr_name[1] = { "SCC" };
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH  1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 100
+
+static char txbuf[DBUF_LENGTH];
+
+static uint rxIdx;             /* index of the current RX buffer */
+static uint txIdx;             /* index of the current TX buffer */
+
+/*
+  * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+
+typedef volatile struct CommonBufferDescriptor {
+       cbd_t rxbd[PKTBUFSRX];          /* Rx BD */
+       cbd_t txbd[TX_BUF_CNT];         /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+  /*
+   * SCC callbacks
+   */
+
+static void scc_init (int scc_index)
+{
+       bd_t *bd = gd->bd;
+
+       static int proff[] =
+                       { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
+       static unsigned int cpm_cr[] =
+                       { CPM_CR_CH_SCC1, CPM_CR_CH_SCC2, CPM_CR_CH_SCC3,
+CPM_CR_CH_SCC4 };
+
+       int i;
+       scc_enet_t *pram_ptr;
+
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl &=
+                       ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+#if defined(CONFIG_FADS)
+#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC86xADS)
+       /* The FADS860T and MPC86xADS don't use the MODEM_EN or DATA_VOICE signals. */
+       *((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
+       *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL;
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#else
+       *((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN);
+       *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE;
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif
+#endif
+
+       pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[proff[scc_index]]);
+
+       rxIdx = 0;
+       txIdx = 0;
+
+#ifdef CFG_ALLOC_DPRAM
+       rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+                                        dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+       rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE);
+#endif
+
+#if 0
+
+#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
+       /* Configure port A pins for Txd and Rxd.
+        */
+       immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+       immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+       immr->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
+       /* Configure port B pins for Txd and Rxd.
+        */
+       immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
+       immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
+       immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
+#else
+#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
+#endif
+
+#if defined(PC_ENET_LBK)
+       /* Configure port C pins to disable External Loopback
+        */
+       immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
+       immr->im_ioport.iop_pcdir |= PC_ENET_LBK;
+       immr->im_ioport.iop_pcso &= ~PC_ENET_LBK;
+       immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK;      /* Disable Loopback */
+#endif /* PC_ENET_LBK */
+
+       /* Configure port C pins to enable CLSN and RENA.
+        */
+       immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+       immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+       immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+
+       /* Configure port A for TCLK and RCLK.
+        */
+       immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+       immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
+
+       /*
+        * Configure Serial Interface clock routing -- see section 16.7.5.3
+        * First, clear all SCC bits to zero, then set the ones we want.
+        */
+
+       immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
+       immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
+#else
+       /*
+        * SCC2 receive clock is BRG2
+        * SCC2 transmit clock is BRG3
+        */
+       immr->im_cpm.cp_brgc2 = 0x0001000C;
+       immr->im_cpm.cp_brgc3 = 0x0001000C;
+
+       immr->im_cpm.cp_sicr &= ~0x00003F00;
+       immr->im_cpm.cp_sicr |=  0x00000a00;
+#endif /* 0 */
+
+
+       /*
+        * Initialize SDCR -- see section 16.9.23.7
+        * SDMA configuration register
+        */
+       immr->im_siu_conf.sc_sdcr = 0x01;
+
+
+       /*
+        * Setup SCC Ethernet Parameter RAM
+        */
+
+       pram_ptr->sen_genscc.scc_rfcr = 0x18;   /* Normal Operation and Mot byte ordering */
+       pram_ptr->sen_genscc.scc_tfcr = 0x18;   /* Mot byte ordering, Normal access */
+
+       pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;   /* max. ET package len 1520 */
+
+       pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]);        /* Set RXBD tbl start at Dual Port */
+       pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]);        /* Set TXBD tbl start at Dual Port */
+
+       /*
+        * Setup Receiver Buffer Descriptors (13.14.24.18)
+        * Settings:
+        *     Empty, Wrap
+        */
+
+       for (i = 0; i < PKTBUFSRX; i++) {
+               rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+               rtx->rxbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+       }
+
+       rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+       /*
+        * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+        * Settings:
+        *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
+        */
+
+       for (i = 0; i < TX_BUF_CNT; i++) {
+               rtx->txbd[i].cbd_sc =
+                               (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+               rtx->txbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+       }
+
+       rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+       /*
+        * Enter Command:  Initialize Rx Params for SCC
+        */
+
+       do {                            /* Spin until ready to issue command    */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+       /* Issue command */
+       immr->im_cpm.cp_cpcr =
+                       ((CPM_CR_INIT_RX << 8) | (cpm_cr[scc_index] << 4) |
+                        CPM_CR_FLG);
+       do {                            /* Spin until command processed     */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /*
+        * Ethernet Specific Parameter RAM
+        *     see table 13-16, pg. 660,
+        *     pg. 681 (example with suggested settings)
+        */
+
+       pram_ptr->sen_cpres = ~(0x0);   /* Preset CRC */
+       pram_ptr->sen_cmask = 0xdebb20e3;       /* Constant Mask for CRC */
+       pram_ptr->sen_crcec = 0x0;      /* Error Counter CRC (unused) */
+       pram_ptr->sen_alec = 0x0;       /* Alignment Error Counter (unused) */
+       pram_ptr->sen_disfc = 0x0;      /* Discard Frame Counter (unused) */
+       pram_ptr->sen_pads = 0x8888;    /* Short Frame PAD Characters */
+
+       pram_ptr->sen_retlim = 15;      /* Retry Limit Threshold */
+       pram_ptr->sen_maxflr = 1518;    /* MAX Frame Length Register */
+       pram_ptr->sen_minflr = 64;      /* MIN Frame Length Register */
+
+       pram_ptr->sen_maxd1 = DBUF_LENGTH;      /* MAX DMA1 Length Register */
+       pram_ptr->sen_maxd2 = DBUF_LENGTH;      /* MAX DMA2 Length Register */
+
+       pram_ptr->sen_gaddr1 = 0x0;     /* Group Address Filter 1 (unused) */
+       pram_ptr->sen_gaddr2 = 0x0;     /* Group Address Filter 2 (unused) */
+       pram_ptr->sen_gaddr3 = 0x0;     /* Group Address Filter 3 (unused) */
+       pram_ptr->sen_gaddr4 = 0x0;     /* Group Address Filter 4 (unused) */
+
+#define ea bd->bi_enetaddr
+       pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+       pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+       pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+       pram_ptr->sen_pper = 0x0;       /* Persistence (unused) */
+       pram_ptr->sen_iaddr1 = 0x0;     /* Individual Address Filter 1 (unused) */
+       pram_ptr->sen_iaddr2 = 0x0;     /* Individual Address Filter 2 (unused) */
+       pram_ptr->sen_iaddr3 = 0x0;     /* Individual Address Filter 3 (unused) */
+       pram_ptr->sen_iaddr4 = 0x0;     /* Individual Address Filter 4 (unused) */
+       pram_ptr->sen_taddrh = 0x0;     /* Tmp Address (MSB) (unused) */
+       pram_ptr->sen_taddrm = 0x0;     /* Tmp Address (unused) */
+       pram_ptr->sen_taddrl = 0x0;     /* Tmp Address (LSB) (unused) */
+
+       /*
+        * Enter Command:  Initialize Tx Params for SCC
+        */
+
+       do {                            /* Spin until ready to issue command    */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+       /* Issue command */
+       immr->im_cpm.cp_cpcr =
+                       ((CPM_CR_INIT_TX << 8) | (cpm_cr[scc_index] << 4) |
+                        CPM_CR_FLG);
+       do {                            /* Spin until command processed     */
+               __asm__ ("eieio");
+       } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /*
+        * Mask all Events in SCCM - we use polling mode
+        */
+       immr->im_cpm.cp_scc[scc_index].scc_sccm = 0;
+
+       /*
+        * Clear Events in SCCE -- Clear bits by writing 1's
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_scce = ~(0x0);
+
+
+       /*
+        * Initialize GSMR High 32-Bits
+        * Settings:  Normal Mode
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrh = 0;
+
+       /*
+        * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
+        * Settings:
+        *     TCI = Invert
+        *     TPL =  48 bits
+        *     TPP = Repeating 10's
+        *     LOOP = Loopback
+        *     MODE = Ethernet
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl = (SCC_GSMRL_TCI |
+                                                   SCC_GSMRL_TPL_48 |
+                                                   SCC_GSMRL_TPP_10 |
+                                                   SCC_GSMRL_DIAG_LOOP |
+                                                   SCC_GSMRL_MODE_ENET);
+
+       /*
+        * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_dsr = 0xd555;
+
+       /*
+        * Initialize the PSMR
+        * Settings:
+        *  CRC = 32-Bit CCITT
+        *  NIB = Begin searching for SFD 22 bits after RENA
+        *  LPB = Loopback Enable (Needed when FDE is set)
+        */
+       immr->im_cpm.cp_scc[scc_index].scc_psmr = SCC_PSMR_ENCRC |
+                       SCC_PSMR_NIB22 | SCC_PSMR_LPB;
+
+#if 0
+       /*
+        * Configure Ethernet TENA Signal
+        */
+
+#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA))
+       immr->im_ioport.iop_pcpar |= PC_ENET_TENA;
+       immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA))
+       immr->im_cpm.cp_pbpar |= PB_ENET_TENA;
+       immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
+#else
+#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined
+#endif
+
+#if defined(CONFIG_ADS) && defined(CONFIG_MPC860)
+       /*
+        * Port C is used to control the PHY,MC68160.
+        */
+       immr->im_ioport.iop_pcdir |=
+                       (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL);
+
+       immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL;
+       immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL);
+       *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif /* MPC860ADS */
+
+#if defined(CONFIG_AMX860)
+       /*
+        * Port B is used to control the PHY,MC68160.
+        */
+       immr->im_cpm.cp_pbdir |=
+                       (PB_ENET_ETHLOOP | PB_ENET_TPFLDL | PB_ENET_TPSQEL);
+
+       immr->im_cpm.cp_pbdat |= PB_ENET_TPFLDL;
+       immr->im_cpm.cp_pbdat &= ~(PB_ENET_ETHLOOP | PB_ENET_TPSQEL);
+
+       immr->im_ioport.iop_pddir |= PD_ENET_ETH_EN;
+       immr->im_ioport.iop_pddat &= ~PD_ENET_ETH_EN;
+#endif /* AMX860 */
+
+#endif /* 0 */
+
+#ifdef CONFIG_RPXCLASSIC
+       *((uchar *) BCSR0) &= ~BCSR0_ETHLPBK;
+       *((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX);
+#endif
+
+#ifdef CONFIG_RPXLITE
+       *((uchar *) BCSR0) |= BCSR0_ETHEN;
+#endif
+
+#ifdef CONFIG_MBX
+       board_ether_init ();
+#endif
+
+       /*
+        * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
+        */
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl |=
+                       (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+       /*
+        * Work around transmit problem with first eth packet
+        */
+#if defined (CONFIG_FADS)
+       udelay (10000);                         /* wait 10 ms */
+#elif defined (CONFIG_AMX860) || defined(CONFIG_RPXCLASSIC)
+       udelay (100000);                        /* wait 100 ms */
+#endif
+}
+
+static void scc_halt (int scc_index)
+{
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+
+       immr->im_cpm.cp_scc[scc_index].scc_gsmrl &=
+                       ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       immr->im_ioport.iop_pcso  &=  ~(PC_ENET_CLSN | PC_ENET_RENA);
+}
+
+static int scc_send (int index, volatile void *packet, int length)
+{
+       int i, j = 0;
+
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
+               udelay (1);             /* will also trigger Wd if needed */
+               j++;
+       }
+       if (j >= TOUT_LOOP)
+               printf ("TX not ready\n");
+       rtx->txbd[txIdx].cbd_bufaddr = (uint) packet;
+       rtx->txbd[txIdx].cbd_datlen = length;
+       rtx->txbd[txIdx].cbd_sc |=
+                       (BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_WRAP);
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
+               udelay (1);             /* will also trigger Wd if needed */
+               j++;
+       }
+       if (j >= TOUT_LOOP)
+               printf ("TX timeout\n");
+       i = (rtx->txbd[txIdx].
+                cbd_sc & BD_ENET_TX_STATS) /* return only status bits */ ;
+       return i;
+}
+
+static int scc_recv (int index, void *packet, int max_length)
+{
+       int length = -1;
+
+       if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+               goto Done;              /* nothing received */
+       }
+
+       if (!(rtx->rxbd[rxIdx].cbd_sc & 0x003f)) {
+               length = rtx->rxbd[rxIdx].cbd_datlen - 4;
+               memcpy (packet,
+                               (void *) (NetRxPackets[rxIdx]),
+                               length < max_length ? length : max_length);
+       }
+
+       /* Give the buffer back to the SCC. */
+       rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+       /* wrap around buffer index when necessary */
+       if ((rxIdx + 1) >= PKTBUFSRX) {
+               rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+                               (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+               rxIdx = 0;
+       } else {
+               rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+               rxIdx++;
+       }
+
+Done:
+       return length;
+}
+
+  /*
+   * Test routines
+   */
+
+static void packet_fill (char *packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       packet[0] = 0xFF;
+       packet[1] = 0xFF;
+       packet[2] = 0xFF;
+       packet[3] = 0xFF;
+       packet[4] = 0xFF;
+       packet[5] = 0xFF;
+
+       for (i = 6; i < length; i++) {
+               packet[i] = c++;
+       }
+}
+
+static int packet_check (char *packet, int length)
+{
+       char c = (char) length;
+       int i;
+
+       for (i = 6; i < length; i++) {
+               if (packet[i] != c++)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int test_ctlr (int ctlr, int index)
+{
+       int res = -1;
+       char packet_send[MAX_PACKET_LENGTH];
+       char packet_recv[MAX_PACKET_LENGTH];
+       int length;
+       int i;
+       int l;
+
+       ctlr_proc[ctlr].init (index);
+
+       for (i = 0; i < TEST_NUM; i++) {
+               for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) {
+                       packet_fill (packet_send, l);
+
+                       ctlr_proc[ctlr].send (index, packet_send, l);
+
+                       length = ctlr_proc[ctlr].recv (index, packet_recv,
+                                                       MAX_PACKET_LENGTH);
+
+                       if (length != l || packet_check (packet_recv, length) < 0) {
+                               goto Done;
+                       }
+               }
+       }
+
+       res = 0;
+
+Done:
+
+       ctlr_proc[ctlr].halt (index);
+
+       /*
+        * SCC2 Ethernet parameter RAM space overlaps
+        * the SPI parameter RAM space. So we need to restore
+        * the SPI configuration after SCC2 ethernet test.
+        */
+#if defined(CONFIG_SPI)
+       if (ctlr == CTLR_SCC && index == 1) {
+               spi_init_f ();
+               spi_init_r ();
+       }
+#endif
+
+       if (res != 0) {
+               post_log ("ethernet %s%d test failed\n", ctlr_name[ctlr],
+                                 index + 1);
+       }
+
+       return res;
+}
+
+int ether_post_test (int flags)
+{
+       int res = 0;
+       int i;
+
+       ctlr_proc[CTLR_SCC].init = scc_init;
+       ctlr_proc[CTLR_SCC].halt = scc_halt;
+       ctlr_proc[CTLR_SCC].send = scc_send;
+       ctlr_proc[CTLR_SCC].recv = scc_recv;
+
+       for (i = 0; i < CTRL_LIST_SIZE; i++) {
+               if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
+                       res = -1;
+               }
+       }
+
+#if !defined(CONFIG_8xx_CONS_NONE)
+       serial_reinit_all ();
+#endif
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_ETHER */
+
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/spr.c b/post/cpu/mpc8xx/spr.c
new file mode 100644 (file)
index 0000000..330b977
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * (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>
+
+/*
+ * SPR test
+ *
+ * The test checks the contents of Special Purpose Registers (SPR) listed
+ * in the spr_test_list array below.
+ * Each SPR value is read using mfspr instruction, some bits are masked
+ * according to the table and the resulting value is compared to the
+ * corresponding table value.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_SPR
+
+static struct
+{
+    int number;
+    char * name;
+    unsigned long mask;
+    unsigned long value;
+} spr_test_list [] = {
+       /* Standard Special-Purpose Registers */
+
+       {1,     "XER",          0x00000000,     0x00000000},
+       {8,     "LR",           0x00000000,     0x00000000},
+       {9,     "CTR",          0x00000000,     0x00000000},
+       {18,    "DSISR",        0x00000000,     0x00000000},
+       {19,    "DAR",          0x00000000,     0x00000000},
+       {22,    "DEC",          0x00000000,     0x00000000},
+       {26,    "SRR0",         0x00000000,     0x00000000},
+       {27,    "SRR1",         0x00000000,     0x00000000},
+       {272,   "SPRG0",        0x00000000,     0x00000000},
+       {273,   "SPRG1",        0x00000000,     0x00000000},
+       {274,   "SPRG2",        0x00000000,     0x00000000},
+       {275,   "SPRG3",        0x00000000,     0x00000000},
+       {287,   "PVR",          0xFFFF0000,     0x00500000},
+
+       /* Additional Special-Purpose Registers */
+
+       {144,   "CMPA",         0x00000000,     0x00000000},
+       {145,   "CMPB",         0x00000000,     0x00000000},
+       {146,   "CMPC",         0x00000000,     0x00000000},
+       {147,   "CMPD",         0x00000000,     0x00000000},
+       {148,   "ICR",          0xFFFFFFFF,     0x00000000},
+       {149,   "DER",          0x00000000,     0x00000000},
+       {150,   "COUNTA",       0xFFFFFFFF,     0x00000000},
+       {151,   "COUNTB",       0xFFFFFFFF,     0x00000000},
+       {152,   "CMPE",         0x00000000,     0x00000000},
+       {153,   "CMPF",         0x00000000,     0x00000000},
+       {154,   "CMPG",         0x00000000,     0x00000000},
+       {155,   "CMPH",         0x00000000,     0x00000000},
+       {156,   "LCTRL1",       0xFFFFFFFF,     0x00000000},
+       {157,   "LCTRL2",       0xFFFFFFFF,     0x00000000},
+       {158,   "ICTRL",        0xFFFFFFFF,     0x00000007},
+       {159,   "BAR",          0x00000000,     0x00000000},
+       {630,   "DPDR",         0x00000000,     0x00000000},
+       {631,   "DPIR",         0x00000000,     0x00000000},
+       {638,   "IMMR",         0xFFFF0000,     CFG_IMMR  },
+       {560,   "IC_CST",       0x8E380000,     0x00000000},
+       {561,   "IC_ADR",       0x00000000,     0x00000000},
+       {562,   "IC_DAT",       0x00000000,     0x00000000},
+       {568,   "DC_CST",       0xEF380000,     0x00000000},
+       {569,   "DC_ADR",       0x00000000,     0x00000000},
+       {570,   "DC_DAT",       0x00000000,     0x00000000},
+       {784,   "MI_CTR",       0xFFFFFFFF,     0x00000000},
+       {786,   "MI_AP",        0x00000000,     0x00000000},
+       {787,   "MI_EPN",       0x00000000,     0x00000000},
+       {789,   "MI_TWC",       0xFFFFFE02,     0x00000000},
+       {790,   "MI_RPN",       0x00000000,     0x00000000},
+       {816,   "MI_DBCAM",     0x00000000,     0x00000000},
+       {817,   "MI_DBRAM0",    0x00000000,     0x00000000},
+       {818,   "MI_DBRAM1",    0x00000000,     0x00000000},
+       {792,   "MD_CTR",       0xFFFFFFFF,     0x04000000},
+       {793,   "M_CASID",      0xFFFFFFF0,     0x00000000},
+       {794,   "MD_AP",        0x00000000,     0x00000000},
+       {795,   "MD_EPN",       0x00000000,     0x00000000},
+       {796,   "M_TWB",        0x00000003,     0x00000000},
+       {797,   "MD_TWC",       0x00000003,     0x00000000},
+       {798,   "MD_RPN",       0x00000000,     0x00000000},
+       {799,   "M_TW",         0x00000000,     0x00000000},
+       {824,   "MD_DBCAM",     0x00000000,     0x00000000},
+       {825,   "MD_DBRAM0",    0x00000000,     0x00000000},
+       {826,   "MD_DBRAM1",    0x00000000,     0x00000000},
+};
+
+static int spr_test_list_size =
+               sizeof (spr_test_list) / sizeof (spr_test_list[0]);
+
+int spr_post_test (int flags)
+{
+       int ret = 0;
+       int ic = icache_status ();
+       int i;
+
+       unsigned long code[] = {
+               0x7c6002a6,                             /* mfspr r3,SPR */
+               0x4e800020                              /* blr          */
+       };
+       unsigned long (*get_spr) (void) = (void *) code;
+
+       if (ic)
+               icache_disable ();
+
+       for (i = 0; i < spr_test_list_size; i++) {
+               int num = spr_test_list[i].number;
+
+               /* mfspr r3,num */
+               code[0] = 0x7c6002a6 | ((num & 0x1F) << 16) | ((num & 0x3E0) << 6);
+
+               if ((get_spr () & spr_test_list[i].mask) !=
+                       (spr_test_list[i].value & spr_test_list[i].mask)) {
+                       post_log ("The value of %s special register "
+                                 "is incorrect: 0x%08X\n",
+                                       spr_test_list[i].name, get_spr ());
+                       ret = -1;
+               }
+       }
+
+       if (ic)
+               icache_enable ();
+
+       return ret;
+}
+#endif /* CONFIG_POST & CFG_POST_SPR */
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/uart.c b/post/cpu/mpc8xx/uart.c
new file mode 100644 (file)
index 0000000..fd97e38
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * (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>
+
+/*
+ * UART test
+ *
+ * The Serial Management Controllers (SMC) and the Serial Communication
+ * Controllers (SCC) listed in ctlr_list array below are tested in
+ * the loopback UART mode.
+ * The controllers are configured accordingly and several characters
+ * 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_UART
+#if defined(CONFIG_8xx)
+#include <commproc.h>
+#elif defined(CONFIG_MPC8260)
+#include <asm/cpm_8260.h>
+#else
+#error "Apparently a bad configuration, please fix."
+#endif
+#include <command.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CTLR_SMC 0
+#define CTLR_SCC 1
+
+/* The list of controllers to test */
+#if defined(CONFIG_MPC823)
+static int ctlr_list[][2] =
+               { {CTLR_SMC, 0}, {CTLR_SMC, 1}, {CTLR_SCC, 1} };
+#else
+static int ctlr_list[][2] = { };
+#endif
+
+#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0]))
+
+static struct {
+       void (*init) (int index);
+       void (*halt) (int index);
+       void (*putc) (int index, const char c);
+       int (*getc) (int index);
+} ctlr_proc[2];
+
+static char *ctlr_name[2] = { "SMC", "SCC" };
+
+static int proff_smc[] = { PROFF_SMC1, PROFF_SMC2 };
+static int proff_scc[] =
+               { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
+
+/*
+ * SMC callbacks
+ */
+
+static void smc_init (int smc_index)
+{
+       static int cpm_cr_ch[] = { CPM_CR_CH_SMC1, CPM_CR_CH_SMC2 };
+
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile smc_t *sp;
+       volatile smc_uart_t *up;
+       volatile cbd_t *tbdf, *rbdf;
+       volatile cpm8xx_t *cp = &(im->im_cpm);
+       uint dpaddr;
+
+       /* initialize pointers to SMC */
+
+       sp = (smc_t *) & (cp->cp_smc[smc_index]);
+       up = (smc_uart_t *) & cp->cp_dparam[proff_smc[smc_index]];
+
+       /* Disable transmitter/receiver.
+        */
+       sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+       /* Enable SDMA.
+        */
+       im->im_siu_conf.sc_sdcr = 1;
+
+       /* clear error conditions */
+#ifdef CFG_SDSR
+       im->im_sdma.sdma_sdsr = CFG_SDSR;
+#else
+       im->im_sdma.sdma_sdsr = 0x83;
+#endif
+
+       /* clear SDMA interrupt mask */
+#ifdef CFG_SDMR
+       im->im_sdma.sdma_sdmr = CFG_SDMR;
+#else
+       im->im_sdma.sdma_sdmr = 0x00;
+#endif
+
+#if defined(CONFIG_FADS)
+       /* Enable RS232 */
+       *((uint *) BCSR1) &=
+                       ~(smc_index == 1 ? BCSR1_RS232EN_1 : BCSR1_RS232EN_2);
+#endif
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+       /* Enable Monitor Port Transceiver */
+       *((uchar *) BCSR0) |= BCSR0_ENMONXCVR;
+#endif
+
+       /* Set the physical address of the host memory buffers in
+        * the buffer descriptors.
+        */
+
+#ifdef CFG_ALLOC_DPRAM
+       dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
+#else
+       dpaddr = CPM_POST_BASE;
+#endif
+
+       /* Allocate space for two buffer descriptors in the DP ram.
+        * For now, this address seems OK, but it may have to
+        * change with newer versions of the firmware.
+        * damm: allocating space after the two buffers for rx/tx data
+        */
+
+       rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
+       rbdf->cbd_bufaddr = (uint) (rbdf + 2);
+       rbdf->cbd_sc = 0;
+       tbdf = rbdf + 1;
+       tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
+       tbdf->cbd_sc = 0;
+
+       /* Set up the uart parameters in the parameter ram.
+        */
+       up->smc_rbase = dpaddr;
+       up->smc_tbase = dpaddr + sizeof (cbd_t);
+       up->smc_rfcr = SMC_EB;
+       up->smc_tfcr = SMC_EB;
+
+#if defined(CONFIG_MBX)
+       board_serial_init ();
+#endif
+
+       /* Set UART mode, 8 bit, no parity, one stop.
+        * Enable receive and transmit.
+        * Set local loopback mode.
+        */
+       sp->smc_smcmr = smcr_mk_clen (9) | SMCMR_SM_UART | (ushort) 0x0004;
+
+       /* Mask all interrupts and remove anything pending.
+        */
+       sp->smc_smcm = 0;
+       sp->smc_smce = 0xff;
+
+       /* Set up the baud rate generator.
+        */
+       cp->cp_simode = 0x00000000;
+
+       cp->cp_brgc1 =
+                       (((gd->cpu_clk / 16 / gd->baudrate) -
+                         1) << 1) | CPM_BRG_EN;
+
+       /* Make the first buffer the only buffer.
+        */
+       tbdf->cbd_sc |= BD_SC_WRAP;
+       rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+       /* Single character receive.
+        */
+       up->smc_mrblr = 1;
+       up->smc_maxidl = 0;
+
+       /* Initialize Tx/Rx parameters.
+        */
+
+       while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
+               ;
+
+       cp->cp_cpcr =
+                       mk_cr_cmd (cpm_cr_ch[smc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+       while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
+               ;
+
+       /* Enable transmitter/receiver.
+        */
+       sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+static void smc_halt(int smc_index)
+{
+}
+
+static void smc_putc (int smc_index, const char c)
+{
+       volatile cbd_t *tbdf;
+       volatile char *buf;
+       volatile smc_uart_t *up;
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+       up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
+
+       tbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_tbase];
+
+       /* Wait for last character to go.
+        */
+
+       buf = (char *) tbdf->cbd_bufaddr;
+#if 0
+       __asm__ ("eieio");
+       while (tbdf->cbd_sc & BD_SC_READY)
+               __asm__ ("eieio");
+#endif
+
+       *buf = c;
+       tbdf->cbd_datlen = 1;
+       tbdf->cbd_sc |= BD_SC_READY;
+       __asm__ ("eieio");
+#if 1
+       while (tbdf->cbd_sc & BD_SC_READY)
+               __asm__ ("eieio");
+#endif
+}
+
+static int smc_getc (int smc_index)
+{
+       volatile cbd_t *rbdf;
+       volatile unsigned char *buf;
+       volatile smc_uart_t *up;
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cpmp = &(im->im_cpm);
+       unsigned char c;
+       int i;
+
+       up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
+
+       rbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_rbase];
+
+       /* Wait for character to show up.
+        */
+       buf = (unsigned char *) rbdf->cbd_bufaddr;
+#if 0
+       while (rbdf->cbd_sc & BD_SC_EMPTY);
+#else
+       for (i = 100; i > 0; i--) {
+               if (!(rbdf->cbd_sc & BD_SC_EMPTY))
+                       break;
+               udelay (1000);
+       }
+
+       if (i == 0)
+               return -1;
+#endif
+       c = *buf;
+       rbdf->cbd_sc |= BD_SC_EMPTY;
+
+       return (c);
+}
+
+  /*
+   * SCC callbacks
+   */
+
+static void scc_init (int scc_index)
+{
+       static int cpm_cr_ch[] = {
+               CPM_CR_CH_SCC1,
+               CPM_CR_CH_SCC2,
+               CPM_CR_CH_SCC3,
+               CPM_CR_CH_SCC4,
+       };
+
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile scc_t *sp;
+       volatile scc_uart_t *up;
+       volatile cbd_t *tbdf, *rbdf;
+       volatile cpm8xx_t *cp = &(im->im_cpm);
+       uint dpaddr;
+
+       /* initialize pointers to SCC */
+
+       sp = (scc_t *) & (cp->cp_scc[scc_index]);
+       up = (scc_uart_t *) & cp->cp_dparam[proff_scc[scc_index]];
+
+       /* Disable transmitter/receiver.
+        */
+       sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+
+       /* Allocate space for two buffer descriptors in the DP ram.
+        */
+
+#ifdef CFG_ALLOC_DPRAM
+       dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
+#else
+       dpaddr = CPM_POST_BASE;
+#endif
+
+       /* Enable SDMA.
+        */
+       im->im_siu_conf.sc_sdcr = 0x0001;
+
+       /* Set the physical address of the host memory buffers in
+        * the buffer descriptors.
+        */
+
+       rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
+       rbdf->cbd_bufaddr = (uint) (rbdf + 2);
+       rbdf->cbd_sc = 0;
+       tbdf = rbdf + 1;
+       tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
+       tbdf->cbd_sc = 0;
+
+       /* Set up the baud rate generator.
+        */
+       cp->cp_sicr &= ~(0x000000FF << (8 * scc_index));
+       /* no |= needed, since BRG1 is 000 */
+
+       cp->cp_brgc1 =
+                       (((gd->cpu_clk / 16 / gd->baudrate) -
+                         1) << 1) | CPM_BRG_EN;
+
+       /* Set up the uart parameters in the parameter ram.
+        */
+       up->scc_genscc.scc_rbase = dpaddr;
+       up->scc_genscc.scc_tbase = dpaddr + sizeof (cbd_t);
+
+       /* Initialize Tx/Rx parameters.
+        */
+       while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
+               ;
+       cp->cp_cpcr =
+                       mk_cr_cmd (cpm_cr_ch[scc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+       while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
+               ;
+
+       up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
+       up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
+
+       up->scc_genscc.scc_mrblr = 1;   /* Single character receive */
+       up->scc_maxidl = 0;             /* disable max idle */
+       up->scc_brkcr = 1;              /* send one break character on stop TX */
+       up->scc_parec = 0;
+       up->scc_frmec = 0;
+       up->scc_nosec = 0;
+       up->scc_brkec = 0;
+       up->scc_uaddr1 = 0;
+       up->scc_uaddr2 = 0;
+       up->scc_toseq = 0;
+       up->scc_char1 = 0x8000;
+       up->scc_char2 = 0x8000;
+       up->scc_char3 = 0x8000;
+       up->scc_char4 = 0x8000;
+       up->scc_char5 = 0x8000;
+       up->scc_char6 = 0x8000;
+       up->scc_char7 = 0x8000;
+       up->scc_char8 = 0x8000;
+       up->scc_rccm = 0xc0ff;
+
+       /* Set low latency / small fifo.
+        */
+       sp->scc_gsmrh = SCC_GSMRH_RFW;
+
+       /* Set UART mode
+        */
+       sp->scc_gsmrl &= ~0xF;
+       sp->scc_gsmrl |= SCC_GSMRL_MODE_UART;
+
+       /* Set local loopback mode.
+        */
+       sp->scc_gsmrl &= ~SCC_GSMRL_DIAG_LE;
+       sp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
+
+       /* Set clock divider 16 on Tx and Rx
+        */
+       sp->scc_gsmrl |= (SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+       sp->scc_psmr |= SCU_PSMR_CL;
+
+       /* Mask all interrupts and remove anything pending.
+        */
+       sp->scc_sccm = 0;
+       sp->scc_scce = 0xffff;
+       sp->scc_dsr = 0x7e7e;
+       sp->scc_psmr = 0x3000;
+
+       /* Make the first buffer the only buffer.
+        */
+       tbdf->cbd_sc |= BD_SC_WRAP;
+       rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+       /* Enable transmitter/receiver.
+        */
+       sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+
+static void scc_halt(int scc_index)
+{
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cp = &(im->im_cpm);
+       volatile scc_t *sp = (scc_t *) & (cp->cp_scc[scc_index]);
+
+       sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT | SCC_GSMRL_DIAG_LE);
+}
+
+static void scc_putc (int scc_index, const char c)
+{
+       volatile cbd_t *tbdf;
+       volatile char *buf;
+       volatile scc_uart_t *up;
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+       up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
+
+       tbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
+
+       /* Wait for last character to go.
+        */
+
+       buf = (char *) tbdf->cbd_bufaddr;
+#if 0
+       __asm__ ("eieio");
+       while (tbdf->cbd_sc & BD_SC_READY)
+               __asm__ ("eieio");
+#endif
+
+       *buf = c;
+       tbdf->cbd_datlen = 1;
+       tbdf->cbd_sc |= BD_SC_READY;
+       __asm__ ("eieio");
+#if 1
+       while (tbdf->cbd_sc & BD_SC_READY)
+               __asm__ ("eieio");
+#endif
+}
+
+static int scc_getc (int scc_index)
+{
+       volatile cbd_t *rbdf;
+       volatile unsigned char *buf;
+       volatile scc_uart_t *up;
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cpmp = &(im->im_cpm);
+       unsigned char c;
+       int i;
+
+       up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
+
+       rbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+       /* Wait for character to show up.
+        */
+       buf = (unsigned char *) rbdf->cbd_bufaddr;
+#if 0
+       while (rbdf->cbd_sc & BD_SC_EMPTY);
+#else
+       for (i = 100; i > 0; i--) {
+               if (!(rbdf->cbd_sc & BD_SC_EMPTY))
+                       break;
+               udelay (1000);
+       }
+
+       if (i == 0)
+               return -1;
+#endif
+       c = *buf;
+       rbdf->cbd_sc |= BD_SC_EMPTY;
+
+       return (c);
+}
+
+  /*
+   * Test routines
+   */
+
+static int test_ctlr (int ctlr, int index)
+{
+       int res = -1;
+       char test_str[] = "*** UART Test String ***\r\n";
+       int i;
+
+       ctlr_proc[ctlr].init (index);
+
+       for (i = 0; i < sizeof (test_str) - 1; i++) {
+               ctlr_proc[ctlr].putc (index, test_str[i]);
+               if (ctlr_proc[ctlr].getc (index) != test_str[i])
+                       goto Done;
+       }
+
+       res = 0;
+
+Done:
+       ctlr_proc[ctlr].halt (index);
+
+       if (res != 0) {
+               post_log ("uart %s%d test failed\n",
+                               ctlr_name[ctlr], index + 1);
+       }
+
+       return res;
+}
+
+int uart_post_test (int flags)
+{
+       int res = 0;
+       int i;
+
+       ctlr_proc[CTLR_SMC].init = smc_init;
+       ctlr_proc[CTLR_SMC].halt = smc_halt;
+       ctlr_proc[CTLR_SMC].putc = smc_putc;
+       ctlr_proc[CTLR_SMC].getc = smc_getc;
+
+       ctlr_proc[CTLR_SCC].init = scc_init;
+       ctlr_proc[CTLR_SCC].halt = scc_halt;
+       ctlr_proc[CTLR_SCC].putc = scc_putc;
+       ctlr_proc[CTLR_SCC].getc = scc_getc;
+
+       for (i = 0; i < CTRL_LIST_SIZE; i++) {
+               if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
+                       res = -1;
+               }
+       }
+
+#if !defined(CONFIG_8xx_CONS_NONE)
+       serial_reinit_all ();
+#endif
+
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_UART */
+
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/usb.c b/post/cpu/mpc8xx/usb.c
new file mode 100644 (file)
index 0000000..0c74cfa
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * (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>
+
+/*
+ * USB test
+ *
+ * The USB controller is tested in the local loopback mode.
+ * It is configured so that endpoint 0 operates as host and endpoint 1
+ * operates as function endpoint. After that an IN token transaction
+ * is performed.
+ * Refer to MPC850 User Manual, Section 32.11.1 USB Host Controller
+ * Initialization Example.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_USB
+
+#include <commproc.h>
+#include <command.h>
+
+#define TOUT_LOOP 100
+
+#define        PROFF_USB               ((uint)0x0000)
+
+#define CPM_USB_EP0_BASE       0x0a00
+#define CPM_USB_EP1_BASE       0x0a20
+
+#define CPM_USB_DT0_BASE       0x0a80
+#define CPM_USB_DT1_BASE       0x0a90
+#define CPM_USB_DR0_BASE       0x0aa0
+#define CPM_USB_DR1_BASE       0x0ab0
+
+#define CPM_USB_RX0_BASE       0x0b00
+#define CPM_USB_RX1_BASE       0x0b08
+#define CPM_USB_TX0_BASE       0x0b20
+#define CPM_USB_TX1_BASE       0x0b28
+
+#define USB_EXPECT(x)          if (!(x)) goto Done;
+
+typedef struct usb_param {
+       ushort ep0ptr;
+       ushort ep1ptr;
+       ushort ep2ptr;
+       ushort ep3ptr;
+       uint rstate;
+       uint rptr;
+       ushort frame_n;
+       ushort rbcnt;
+       ushort rtemp;
+} usb_param_t;
+
+typedef struct usb_param_block {
+       ushort rbase;
+       ushort tbase;
+       uchar rfcr;
+       uchar tfcr;
+       ushort mrblr;
+       ushort rbptr;
+       ushort tbptr;
+       uint tstate;
+       uint tptr;
+       ushort tcrc;
+       ushort tbcnt;
+       uint res[2];
+} usb_param_block_t;
+
+typedef struct usb {
+       uchar usmod;
+       uchar usadr;
+       uchar uscom;
+       uchar res1;
+       ushort usep[4];
+       uchar res2[4];
+       ushort usber;
+       uchar res3[2];
+       ushort usbmr;
+       uchar res4;
+       uchar usbs;
+       uchar res5[8];
+} usb_t;
+
+int usb_post_test (int flags)
+{
+       int res = -1;
+       volatile immap_t *im = (immap_t *) CFG_IMMR;
+       volatile cpm8xx_t *cp = &(im->im_cpm);
+       volatile usb_param_t *pram_ptr;
+       uint dpram;
+       ushort DPRAM;
+       volatile cbd_t *tx;
+       volatile cbd_t *rx;
+       volatile usb_t *usbr;
+       volatile usb_param_block_t *ep0;
+       volatile usb_param_block_t *ep1;
+       int j;
+
+       pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]);
+       dpram = (uint) im->im_cpm.cp_dpmem;
+       DPRAM = dpram;
+       tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE);
+       rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE);
+       ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE);
+       ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE);
+       usbr = (usb_t *) & (im->im_cpm.cp_scc[0]);
+
+       /* 01 */
+       im->im_ioport.iop_padir &= ~(ushort) 0x0200;
+       im->im_ioport.iop_papar |= (ushort) 0x0200;
+
+       cp->cp_sicr &= ~0x000000FF;
+       cp->cp_sicr |= 0x00000018;
+
+       cp->cp_brgc4 = 0x00010001;
+
+       /* 02 */
+       im->im_ioport.iop_padir &= ~(ushort) 0x0002;
+       im->im_ioport.iop_padir &= ~(ushort) 0x0001;
+
+       im->im_ioport.iop_papar |= (ushort) 0x0002;
+       im->im_ioport.iop_papar |= (ushort) 0x0001;
+
+       /* 03 */
+       im->im_ioport.iop_pcdir &= ~(ushort) 0x0020;
+       im->im_ioport.iop_pcdir &= ~(ushort) 0x0010;
+
+       im->im_ioport.iop_pcpar &= ~(ushort) 0x0020;
+       im->im_ioport.iop_pcpar &= ~(ushort) 0x0010;
+
+       im->im_ioport.iop_pcso |= (ushort) 0x0020;
+       im->im_ioport.iop_pcso |= (ushort) 0x0010;
+
+       /* 04 */
+       im->im_ioport.iop_pcdir |= (ushort) 0x0200;
+       im->im_ioport.iop_pcdir |= (ushort) 0x0100;
+
+       im->im_ioport.iop_pcpar |= (ushort) 0x0200;
+       im->im_ioport.iop_pcpar |= (ushort) 0x0100;
+
+       /* 05 */
+       pram_ptr->frame_n = 0;
+
+       /* 06 */
+       pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE;
+       pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE;
+
+       /* 07-10 */
+       tx[0].cbd_sc = 0xB800;
+       tx[0].cbd_datlen = 3;
+       tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE;
+
+       tx[1].cbd_sc = 0xBC80;
+       tx[1].cbd_datlen = 3;
+       tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE;
+
+       rx[0].cbd_sc = 0xA000;
+       rx[0].cbd_datlen = 0;
+       rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE;
+
+       rx[1].cbd_sc = 0xA000;
+       rx[1].cbd_datlen = 0;
+       rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE;
+
+       /* 11-12 */
+       *(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000;
+       *(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234;
+
+       *(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0;
+       *(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0;
+
+       /* 13-16 */
+       ep0->rbase = DPRAM + CPM_USB_RX0_BASE;
+       ep0->tbase = DPRAM + CPM_USB_TX0_BASE;
+       ep0->rfcr = 0x18;
+       ep0->tfcr = 0x18;
+       ep0->mrblr = 0x100;
+       ep0->rbptr = DPRAM + CPM_USB_RX0_BASE;
+       ep0->tbptr = DPRAM + CPM_USB_TX0_BASE;
+       ep0->tstate = 0;
+
+       /* 17-20 */
+       ep1->rbase = DPRAM + CPM_USB_RX1_BASE;
+       ep1->tbase = DPRAM + CPM_USB_TX1_BASE;
+       ep1->rfcr = 0x18;
+       ep1->tfcr = 0x18;
+       ep1->mrblr = 0x100;
+       ep1->rbptr = DPRAM + CPM_USB_RX1_BASE;
+       ep1->tbptr = DPRAM + CPM_USB_TX1_BASE;
+       ep1->tstate = 0;
+
+       /* 21-24 */
+       usbr->usep[0] = 0x0000;
+       usbr->usep[1] = 0x1100;
+       usbr->usep[2] = 0x2200;
+       usbr->usep[3] = 0x3300;
+
+       /* 25 */
+       usbr->usmod = 0x06;
+
+       /* 26 */
+       usbr->usadr = 0x05;
+
+       /* 27 */
+       usbr->uscom = 0;
+
+       /* 28 */
+       usbr->usmod |= 0x01;
+       udelay (1);
+
+       /* 29-30 */
+       usbr->uscom = 0x80;
+       usbr->uscom = 0x81;
+
+       /* Wait for the data packet to be transmitted */
+       for (j = 0; j < TOUT_LOOP; j++) {
+               if (tx[1].cbd_sc & (ushort) 0x8000)
+                       udelay (1);
+               else
+                       break;
+       }
+
+       USB_EXPECT (j < TOUT_LOOP);
+
+       USB_EXPECT (tx[0].cbd_sc == 0x3800);
+       USB_EXPECT (tx[0].cbd_datlen == 3);
+
+       USB_EXPECT (tx[1].cbd_sc == 0x3C80);
+       USB_EXPECT (tx[1].cbd_datlen == 3);
+
+       USB_EXPECT (rx[0].cbd_sc == 0x2C00);
+       USB_EXPECT (rx[0].cbd_datlen == 5);
+
+       USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) ==
+                               0xABCD122B);
+       USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42);
+
+       res = 0;
+  Done:
+
+       return res;
+}
+
+#endif /* CONFIG_POST & CFG_POST_USB */
+
+#endif /* CONFIG_POST */
diff --git a/post/cpu/mpc8xx/watchdog.c b/post/cpu/mpc8xx/watchdog.c
new file mode 100644 (file)
index 0000000..48c4282
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * (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>
+
+/*
+ * Watchdog test
+ *
+ * The test verifies the watchdog timer operation.
+ * On the first iteration, the test routine disables interrupts and
+ * makes a 10-second delay. If the system does not reboot during this delay,
+ * the watchdog timer is not operational and the test fails. If the system
+ * reboots, on the second iteration the test routine reports a success.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <watchdog.h>
+
+#if CONFIG_POST & CFG_POST_WATCHDOG
+
+static ulong gettbl (void)
+{
+       ulong r;
+
+  asm ("mftbl %0":"=r" (r));
+
+       return r;
+}
+
+int watchdog_post_test (int flags)
+{
+       if (flags & POST_REBOOT) {
+               /* Test passed */
+
+               return 0;
+       } else {
+               /* 10-second delay */
+               int ints = disable_interrupts ();
+               ulong base = gettbl ();
+               ulong clk = get_tbclk ();
+
+               while ((gettbl () - base) / 10 < clk);
+
+               if (ints)
+                       enable_interrupts ();
+
+               /*
+                * If we have reached this point, the watchdog timer
+                * does not work
+                */
+               return -1;
+       }
+}
+
+#endif /* CONFIG_POST & CFG_POST_WATCHDOG */
+#endif /* CONFIG_POST */
diff --git a/post/drivers/Makefile b/post/drivers/Makefile
new file mode 100644 (file)
index 0000000..068fa98
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2002-2006
+# 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
+#
+
+
+SUBDIRS =
+
+LIB    = libpostdrivers.a
+
+COBJS  = cache.o i2c.o memory.o rtc.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/drivers/cache.c b/post/drivers/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 */
diff --git a/post/drivers/i2c.c b/post/drivers/i2c.c
new file mode 100644 (file)
index 0000000..1b2e644
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * (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>
+
+#ifdef CONFIG_POST
+
+/*
+ * I2C test
+ *
+ * For verifying the I2C bus, a full I2C bus scanning is performed.
+ *
+ * #ifdef I2C_ADDR_LIST
+ *   The test is considered as passed if all the devices and
+ *   only the devices in the list are found.
+ * #else [ ! I2C_ADDR_LIST ]
+ *   The test is considered as passed if any I2C device is found.
+ * #endif
+ */
+
+#include <post.h>
+#include <i2c.h>
+
+#if CONFIG_POST & CFG_POST_I2C
+
+int i2c_post_test (int flags)
+{
+       unsigned int i;
+       unsigned int good = 0;
+#ifdef I2C_ADDR_LIST
+       unsigned int bad  = 0;
+       int j;
+       unsigned char i2c_addr_list[] = I2C_ADDR_LIST;
+       unsigned char i2c_miss_list[] = I2C_ADDR_LIST;
+#endif
+
+       for (i = 0; i < 128; i++) {
+               if (i2c_probe (i) == 0) {
+#ifndef        I2C_ADDR_LIST
+                       good++;
+#else  /* I2C_ADDR_LIST */
+                       for (j=0; j<sizeof(i2c_addr_list); ++j) {
+                               if (i == i2c_addr_list[j]) {
+                                       good++;
+                                       i2c_miss_list[j] = 0xFF;
+                                       break;
+                               }
+                       }
+                       if (j == sizeof(i2c_addr_list)) {
+                               bad++;
+                               post_log ("I2C: addr %02X not expected\n",
+                                               i);
+                       }
+#endif /* I2C_ADDR_LIST */
+               }
+       }
+
+#ifndef        I2C_ADDR_LIST
+       return good > 0 ? 0 : -1;
+#else  /* I2C_ADDR_LIST */
+       if (good != sizeof(i2c_addr_list)) {
+               for (j=0; j<sizeof(i2c_miss_list); ++j) {
+                       if (i2c_miss_list[j] != 0xFF) {
+                               post_log ("I2C: addr %02X did not respond\n",
+                                               i2c_miss_list[j]);
+                       }
+               }
+       }
+       return ((good == sizeof(i2c_addr_list)) && (bad == 0)) ? 0 : -1;
+#endif
+}
+
+#endif /* CONFIG_POST & CFG_POST_I2C */
+#endif /* CONFIG_POST */
diff --git a/post/drivers/memory.c b/post/drivers/memory.c
new file mode 100644 (file)
index 0000000..a2c088b
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * (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>
+
+/* Memory test
+ *
+ * General observations:
+ * o The recommended test sequence is to test the data lines: if they are
+ *   broken, nothing else will work properly.  Then test the address
+ *   lines.  Finally, test the cells in the memory now that the test
+ *   program knows that the address and data lines work properly.
+ *   This sequence also helps isolate and identify what is faulty.
+ *
+ * o For the address line test, it is a good idea to use the base
+ *   address of the lowest memory location, which causes a '1' bit to
+ *   walk through a field of zeros on the address lines and the highest
+ *   memory location, which causes a '0' bit to walk through a field of
+ *   '1's on the address line.
+ *
+ * o Floating buses can fool memory tests if the test routine writes
+ *   a value and then reads it back immediately.  The problem is, the
+ *   write will charge the residual capacitance on the data bus so the
+ *   bus retains its state briefely.  When the test program reads the
+ *   value back immediately, the capacitance of the bus can allow it
+ *   to read back what was written, even though the memory circuitry
+ *   is broken.  To avoid this, the test program should write a test
+ *   pattern to the target location, write a different pattern elsewhere
+ *   to charge the residual capacitance in a differnt manner, then read
+ *   the target location back.
+ *
+ * o Always read the target location EXACTLY ONCE and save it in a local
+ *   variable.  The problem with reading the target location more than
+ *   once is that the second and subsequent reads may work properly,
+ *   resulting in a failed test that tells the poor technician that
+ *   "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
+ *   doesn't help him one bit and causes puzzled phone calls.  Been there,
+ *   done that.
+ *
+ * Data line test:
+ * ---------------
+ * This tests data lines for shorts and opens by forcing adjacent data
+ * to opposite states. Because the data lines could be routed in an
+ * arbitrary manner the must ensure test patterns ensure that every case
+ * is tested. By using the following series of binary patterns every
+ * combination of adjacent bits is test regardless of routing.
+ *
+ *     ...101010101010101010101010
+ *     ...110011001100110011001100
+ *     ...111100001111000011110000
+ *     ...111111110000000011111111
+ *
+ * Carrying this out, gives us six hex patterns as follows:
+ *
+ *     0xaaaaaaaaaaaaaaaa
+ *     0xcccccccccccccccc
+ *     0xf0f0f0f0f0f0f0f0
+ *     0xff00ff00ff00ff00
+ *     0xffff0000ffff0000
+ *     0xffffffff00000000
+ *
+ * To test for short and opens to other signals on our boards, we
+ * simply test with the 1's complemnt of the paterns as well, resulting
+ * in twelve patterns total.
+ *
+ * After writing a test pattern. a special pattern 0x0123456789ABCDEF is
+ * written to a different address in case the data lines are floating.
+ * Thus, if a byte lane fails, you will see part of the special
+ * pattern in that byte lane when the test runs.  For example, if the
+ * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
+ * (for the 'a' test pattern).
+ *
+ * Address line test:
+ * ------------------
+ *  This function performs a test to verify that all the address lines
+ *  hooked up to the RAM work properly.  If there is an address line
+ *  fault, it usually shows up as two different locations in the address
+ *  map (related by the faulty address line) mapping to one physical
+ *  memory storage location.  The artifact that shows up is writing to
+ *  the first location "changes" the second location.
+ *
+ * To test all address lines, we start with the given base address and
+ * xor the address with a '1' bit to flip one address line.  For each
+ * test, we shift the '1' bit left to test the next address line.
+ *
+ * In the actual code, we start with address sizeof(ulong) since our
+ * test pattern we use is a ulong and thus, if we tried to test lower
+ * order address bits, it wouldn't work because our pattern would
+ * overwrite itself.
+ *
+ * Example for a 4 bit address space with the base at 0000:
+ *   0000 <- base
+ *   0001 <- test 1
+ *   0010 <- test 2
+ *   0100 <- test 3
+ *   1000 <- test 4
+ * Example for a 4 bit address space with the base at 0010:
+ *   0010 <- base
+ *   0011 <- test 1
+ *   0000 <- (below the base address, skipped)
+ *   0110 <- test 2
+ *   1010 <- test 3
+ *
+ * The test locations are successively tested to make sure that they are
+ * not "mirrored" onto the base address due to a faulty address line.
+ * Note that the base and each test location are related by one address
+ * line flipped.  Note that the base address need not be all zeros.
+ *
+ * Memory tests 1-4:
+ * -----------------
+ * These tests verify RAM using sequential writes and reads
+ * to/from RAM. There are several test cases that use different patterns to
+ * verify RAM. Each test case fills a region of RAM with one pattern and
+ * then reads the region back and compares its contents with the pattern.
+ * The following patterns are used:
+ *
+ *  1a) zero pattern (0x00000000)
+ *  1b) negative pattern (0xffffffff)
+ *  1c) checkerboard pattern (0x55555555)
+ *  1d) checkerboard pattern (0xaaaaaaaa)
+ *  2)  bit-flip pattern ((1 << (offset % 32))
+ *  3)  address pattern (offset)
+ *  4)  address pattern (~offset)
+ *
+ * Being run in normal mode, the test verifies only small 4Kb
+ * regions of RAM around each 1Mb boundary. For example, for 64Mb
+ * RAM the following areas are verified: 0x00000000-0x00000800,
+ * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
+ * 0x04000000. If the test is run in slow-test mode, it verifies
+ * the whole RAM.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <watchdog.h>
+
+#if CONFIG_POST & CFG_POST_MEMORY
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Define INJECT_*_ERRORS for testing error detection in the presence of
+ * _good_ hardware.
+ */
+#undef  INJECT_DATA_ERRORS
+#undef  INJECT_ADDRESS_ERRORS
+
+#ifdef INJECT_DATA_ERRORS
+#warning "Injecting data line errors for testing purposes"
+#endif
+
+#ifdef INJECT_ADDRESS_ERRORS
+#warning "Injecting address line errors for testing purposes"
+#endif
+
+
+/*
+ * This function performs a double word move from the data at
+ * the source pointer to the location at the destination pointer.
+ * This is helpful for testing memory on processors which have a 64 bit
+ * wide data bus.
+ *
+ * On those PowerPC with FPU, use assembly and a floating point move:
+ * this does a 64 bit move.
+ *
+ * For other processors, let the compiler generate the best code it can.
+ */
+static void move64(unsigned long long *src, unsigned long long *dest)
+{
+#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X)
+       asm ("lfd  0, 0(3)\n\t" /* fpr0   =  *scr       */
+        "stfd 0, 0(4)"         /* *dest  =  fpr0       */
+        : : : "fr0" );         /* Clobbers fr0         */
+    return;
+#else
+       *dest = *src;
+#endif
+}
+
+/*
+ * This is 64 bit wide test patterns.  Note that they reside in ROM
+ * (which presumably works) and the tests write them to RAM which may
+ * not work.
+ *
+ * The "otherpattern" is written to drive the data bus to values other
+ * than the test pattern.  This is for detecting floating bus lines.
+ *
+ */
+const static unsigned long long pattern[] = {
+       0xaaaaaaaaaaaaaaaaULL,
+       0xccccccccccccccccULL,
+       0xf0f0f0f0f0f0f0f0ULL,
+       0xff00ff00ff00ff00ULL,
+       0xffff0000ffff0000ULL,
+       0xffffffff00000000ULL,
+       0x00000000ffffffffULL,
+       0x0000ffff0000ffffULL,
+       0x00ff00ff00ff00ffULL,
+       0x0f0f0f0f0f0f0f0fULL,
+       0x3333333333333333ULL,
+       0x5555555555555555ULL
+};
+const unsigned long long otherpattern = 0x0123456789abcdefULL;
+
+
+static int memory_post_dataline(unsigned long long * pmem)
+{
+       unsigned long long temp64 = 0;
+       int num_patterns = sizeof(pattern)/ sizeof(pattern[0]);
+       int i;
+       unsigned int hi, lo, pathi, patlo;
+       int ret = 0;
+
+       for ( i = 0; i < num_patterns; i++) {
+               move64((unsigned long long *)&(pattern[i]), pmem++);
+               /*
+                * Put a different pattern on the data lines: otherwise they
+                * may float long enough to read back what we wrote.
+                */
+               move64((unsigned long long *)&otherpattern, pmem--);
+               move64(pmem, &temp64);
+
+#ifdef INJECT_DATA_ERRORS
+               temp64 ^= 0x00008000;
+#endif
+
+               if (temp64 != pattern[i]){
+                       pathi = (pattern[i]>>32) & 0xffffffff;
+                       patlo = pattern[i] & 0xffffffff;
+
+                       hi = (temp64>>32) & 0xffffffff;
+                       lo = temp64 & 0xffffffff;
+
+                       post_log ("Memory (date line) error at %08x, "
+                                 "wrote %08x%08x, read %08x%08x !\n",
+                                         pmem, pathi, patlo, hi, lo);
+                       ret = -1;
+               }
+       }
+       return ret;
+}
+
+static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
+{
+       ulong *target;
+       ulong *end;
+       ulong readback;
+       ulong xor;
+       int   ret = 0;
+
+       end = (ulong *)((ulong)base + size);    /* pointer arith! */
+       xor = 0;
+       for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
+               target = (ulong *)((ulong)testaddr ^ xor);
+               if((target >= base) && (target < end)) {
+                       *testaddr = ~*target;
+                       readback  = *target;
+
+#ifdef INJECT_ADDRESS_ERRORS
+                       if(xor == 0x00008000) {
+                               readback = *testaddr;
+                       }
+#endif
+                       if(readback == *testaddr) {
+                               post_log ("Memory (address line) error at %08x<->%08x, "
+                                       "XOR value %08x !\n",
+                                       testaddr, target, xor);
+                               ret = -1;
+                       }
+               }
+       }
+       return ret;
+}
+
+static int memory_post_test1 (unsigned long start,
+                             unsigned long size,
+                             unsigned long val)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = val;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != val) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, val, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test2 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = 1 << (i % 32);
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != (1 << (i % 32))) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, 1 << (i % 32), readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test3 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = i;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != i) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, i, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_test4 (unsigned long start, unsigned long size)
+{
+       unsigned long i;
+       ulong *mem = (ulong *) start;
+       ulong readback;
+       int ret = 0;
+
+       for (i = 0; i < size / sizeof (ulong); i++) {
+               mem[i] = ~i;
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) {
+               readback = mem[i];
+               if (readback != ~i) {
+                       post_log ("Memory error at %08x, "
+                                 "wrote %08x, read %08x !\n",
+                                         mem + i, ~i, readback);
+
+                       ret = -1;
+                       break;
+               }
+               if (i % 1024 == 0)
+                       WATCHDOG_RESET ();
+       }
+
+       return ret;
+}
+
+static int memory_post_tests (unsigned long start, unsigned long size)
+{
+       int ret = 0;
+
+       if (ret == 0)
+               ret = memory_post_dataline ((unsigned long long *)start);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_addrline ((ulong *)start, (ulong *)start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_addrline ((ulong *)(start + size - 8),
+                                           (ulong *)start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0x00000000);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0xffffffff);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0x55555555);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test1 (start, size, 0xaaaaaaaa);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test2 (start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test3 (start, size);
+       WATCHDOG_RESET ();
+       if (ret == 0)
+               ret = memory_post_test4 (start, size);
+       WATCHDOG_RESET ();
+
+       return ret;
+}
+
+int memory_post_test (int flags)
+{
+       int ret = 0;
+       bd_t *bd = gd->bd;
+       unsigned long memsize = (bd->bi_memsize >= 256 << 20 ?
+                                256 << 20 : bd->bi_memsize) - (1 << 20);
+
+
+       if (flags & POST_SLOWTEST) {
+               ret = memory_post_tests (CFG_SDRAM_BASE, memsize);
+       } else {                        /* POST_NORMAL */
+
+               unsigned long i;
+
+               for (i = 0; i < (memsize >> 20) && ret == 0; i++) {
+                       if (ret == 0)
+                               ret = memory_post_tests (i << 20, 0x800);
+                       if (ret == 0)
+                               ret = memory_post_tests ((i << 20) + 0xff800, 0x800);
+               }
+       }
+
+       return ret;
+}
+
+#endif /* CONFIG_POST & CFG_POST_MEMORY */
+#endif /* CONFIG_POST */
diff --git a/post/drivers/rtc.c b/post/drivers/rtc.c
new file mode 100644 (file)
index 0000000..7d4f9b8
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * (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>
+
+/*
+ * RTC test
+ *
+ * The Real Time Clock (RTC) operation is verified by this test.
+ * The following features are verified:
+ *   o) Time uniformity
+ *      This is verified by reading RTC in polling within
+ *      a short period of time.
+ *   o) Passing month boundaries
+ *      This is checked by setting RTC to a second before
+ *      a month boundary and reading it after its passing the
+ *      boundary. The test is performed for both leap- and
+ *      nonleap-years.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <rtc.h>
+
+#if CONFIG_POST & CFG_POST_RTC
+
+static int rtc_post_skip (ulong * diff)
+{
+       struct rtc_time tm1;
+       struct rtc_time tm2;
+       ulong start1;
+       ulong start2;
+
+       rtc_get (&tm1);
+       start1 = get_timer (0);
+
+       while (1) {
+               rtc_get (&tm2);
+               start2 = get_timer (0);
+               if (tm1.tm_sec != tm2.tm_sec)
+                       break;
+               if (start2 - start1 > 1500)
+                       break;
+       }
+
+       if (tm1.tm_sec != tm2.tm_sec) {
+               *diff = start2 - start1;
+
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
+static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
+{
+       time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+                                          tm->tm_min, tm->tm_sec) + sec;
+       struct rtc_time ntm;
+
+       to_tm (t, &ntm);
+
+       rtc_set (&ntm);
+}
+
+int rtc_post_test (int flags)
+{
+       ulong diff;
+       unsigned int i;
+       struct rtc_time svtm;
+       static unsigned int daysnl[] =
+                       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+       static unsigned int daysl[] =
+                       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+       unsigned int ynl = 1999;
+       unsigned int yl = 2000;
+       unsigned int skipped = 0;
+
+       /* Time uniformity */
+       if (rtc_post_skip (&diff) != 0) {
+               post_log ("Timeout while waiting for a new second !\n");
+
+               return -1;
+       }
+
+       for (i = 0; i < 5; i++) {
+               if (rtc_post_skip (&diff) != 0) {
+                       post_log ("Timeout while waiting for a new second !\n");
+
+                       return -1;
+               }
+
+               if (diff < 950 || diff > 1050) {
+                       post_log ("Invalid second duration !\n");
+
+                       return -1;
+               }
+       }
+
+       /* Passing month boundaries */
+
+       if (rtc_post_skip (&diff) != 0) {
+               post_log ("Timeout while waiting for a new second !\n");
+
+               return -1;
+       }
+       rtc_get (&svtm);
+
+       for (i = 0; i < 12; i++) {
+               time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
+               struct rtc_time tm;
+
+               to_tm (t, &tm);
+               rtc_set (&tm);
+
+               skipped++;
+               if (rtc_post_skip (&diff) != 0) {
+                       rtc_post_restore (&svtm, skipped);
+                       post_log ("Timeout while waiting for a new second !\n");
+
+                       return -1;
+               }
+
+               rtc_get (&tm);
+               if (tm.tm_mon == i + 1) {
+                       rtc_post_restore (&svtm, skipped);
+                       post_log ("Month %d boundary is not passed !\n", i + 1);
+
+                       return -1;
+               }
+       }
+
+       for (i = 0; i < 12; i++) {
+               time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
+               struct rtc_time tm;
+
+               to_tm (t, &tm);
+               rtc_set (&tm);
+
+               skipped++;
+               if (rtc_post_skip (&diff) != 0) {
+                       rtc_post_restore (&svtm, skipped);
+                       post_log ("Timeout while waiting for a new second !\n");
+
+                       return -1;
+               }
+
+               rtc_get (&tm);
+               if (tm.tm_mon == i + 1) {
+                       rtc_post_restore (&svtm, skipped);
+                       post_log ("Month %d boundary is not passed !\n", i + 1);
+
+                       return -1;
+               }
+       }
+       rtc_post_restore (&svtm, skipped);
+
+       return 0;
+}
+
+#endif /* CONFIG_POST & CFG_POST_RTC */
+#endif /* CONFIG_POST */
diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile
new file mode 100644 (file)
index 0000000..14354a0
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# (C) Copyright 2002-2006
+# 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    = libpostppc.a
+
+AOBJS  = asm.o
+COBJS  = cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o
+COBJS   += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o
+COBJS  += store.o load.o cr.o b.o multi.o string.o complex.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/lib_ppc/andi.c b/post/lib_ppc/andi.c
new file mode 100644 (file)
index 0000000..7ddf2ab
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Logic instructions:         andi., andis.
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_andi_s
+{
+    ulong cmd;
+    ulong op1;
+    ushort op2;
+    ulong res;
+} cpu_post_andi_table[] =
+{
+    {
+       OP_ANDI_,
+       0x80008000,
+       0xffff,
+       0x00008000
+    },
+    {
+       OP_ANDIS_,
+       0x80008000,
+       0xffff,
+       0x80000000
+    },
+};
+static unsigned int cpu_post_andi_size =
+    sizeof (cpu_post_andi_table) / sizeof (struct cpu_post_andi_s);
+
+int cpu_post_test_andi (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_andi_size && ret == 0; i++)
+    {
+       struct cpu_post_andi_s *test = cpu_post_andi_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11IX(test->cmd, reg1, reg0, test->op2),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           cpu_post_exec_21 (codecr, & cr, & res, test->op1);
+
+           ret = res == test->res &&
+                 (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+           if (ret != 0)
+           {
+               post_log ("Error at andi test %d !\n", i);
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/asm.S b/post/lib_ppc/asm.S
new file mode 100644 (file)
index 0000000..a0815a4
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ *  Copyright (C) 2002 Wolfgang Denk <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 <config.h>
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+
+#if CONFIG_POST & CFG_POST_CPU
+
+/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */
+       .global cpu_post_exec_02
+cpu_post_exec_02:
+       mflr    r0
+       stwu    r0, -4(r1)
+
+       subi    r1, r1, 104
+       stmw    r6, 0(r1)
+
+       mtlr    r3
+       mr      r3, r4
+       mr      r4, r5
+       blrl
+
+       lmw     r6, 0(r1)
+       addi    r1, r1, 104
+
+       lwz     r0, 0(r1)
+       addi    r1, r1, 4
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, ulong op4); */
+       .global cpu_post_exec_04
+cpu_post_exec_04:
+       mflr    r0
+       stwu    r0, -4(r1)
+
+       subi    r1, r1, 96
+       stmw    r8, 0(r1)
+
+       mtlr    r3
+       mr      r3, r4
+       mr      r4, r5
+       mr      r5, r6
+       mtxer   r7
+       blrl
+
+       lmw     r8, 0(r1)
+       addi    r1, r1, 96
+
+       lwz     r0, 0(r1)
+       addi    r1, r1, 4
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); */
+       .global cpu_post_exec_12
+cpu_post_exec_12:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+
+       mtlr    r3
+       mr      r3, r5
+       mr      r4, r6
+       blrl
+
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 4(r1)
+       addi    r1, r1, 8
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); */
+       .global cpu_post_exec_11
+cpu_post_exec_11:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+
+       mtlr    r3
+       mr      r3, r5
+       blrl
+
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 4(r1)
+       addi    r1, r1, 8
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); */
+       .global cpu_post_exec_21
+cpu_post_exec_21:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r5, -4(r1)
+
+       li      r0, 0
+       mtxer   r0
+       lwz     r0, 0(r4)
+       mtcr    r0
+
+       mtlr    r3
+       mr      r3, r6
+       blrl
+
+       mfcr    r0
+       lwz     r4, 4(r1)
+       stw     r0, 0(r4)
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 8(r1)
+       addi    r1, r1, 12
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2); */
+       .global cpu_post_exec_22
+cpu_post_exec_22:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r5, -4(r1)
+
+       li      r0, 0
+       mtxer   r0
+       lwz     r0, 0(r4)
+       mtcr    r0
+
+       mtlr    r3
+       mr      r3, r6
+       mr      r4, r7
+       blrl
+
+       mfcr    r0
+       lwz     r4, 4(r1)
+       stw     r0, 0(r4)
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 8(r1)
+       addi    r1, r1, 12
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); */
+       .global cpu_post_exec_12w
+cpu_post_exec_12w:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+
+       mtlr    r3
+       lwz     r3, 0(r4)
+       mr      r4, r5
+       mr      r5, r6
+       blrl
+
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 4(r1)
+       addi    r1, r1, 8
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); */
+       .global cpu_post_exec_11w
+cpu_post_exec_11w:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+
+       mtlr    r3
+       lwz     r3, 0(r4)
+       mr      r4, r5
+       blrl
+
+       lwz     r4, 0(r1)
+       stw     r3, 0(r4)
+
+       lwz     r0, 4(r1)
+       addi    r1, r1, 8
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); */
+       .global cpu_post_exec_22w
+cpu_post_exec_22w:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r6, -4(r1)
+
+       mtlr    r3
+       lwz     r3, 0(r4)
+       mr      r4, r5
+       blrl
+
+       lwz     r4, 4(r1)
+       stw     r3, 0(r4)
+       lwz     r4, 0(r1)
+       stw     r5, 0(r4)
+
+       lwz     r0, 8(r1)
+       addi    r1, r1, 12
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); */
+       .global cpu_post_exec_21w
+cpu_post_exec_21w:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r5, -4(r1)
+
+       mtlr    r3
+       lwz     r3, 0(r4)
+       blrl
+
+       lwz     r5, 4(r1)
+       stw     r3, 0(r5)
+       lwz     r5, 0(r1)
+       stw     r4, 0(r5)
+
+       lwz     r0, 8(r1)
+       addi    r1, r1, 12
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); */
+       .global cpu_post_exec_21x
+cpu_post_exec_21x:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r5, -4(r1)
+
+       mtlr    r3
+       mr      r3, r6
+       blrl
+
+       lwz     r5, 4(r1)
+       stw     r3, 0(r5)
+       lwz     r5, 0(r1)
+       stw     r4, 0(r5)
+
+       lwz     r0, 8(r1)
+       addi    r1, r1, 12
+       mtlr    r0
+       blr
+
+/* void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump,
+    ulong cr); */
+       .global cpu_post_exec_31
+cpu_post_exec_31:
+       mflr    r0
+       stwu    r0, -4(r1)
+       stwu    r4, -4(r1)
+       stwu    r5, -4(r1)
+       stwu    r6, -4(r1)
+
+       mtlr    r3
+       lwz     r3, 0(r4)
+       lwz     r4, 0(r5)
+       mr      r6, r7
+       blrl
+
+       lwz     r7, 8(r1)
+       stw     r3, 0(r7)
+       lwz     r7, 4(r1)
+       stw     r4, 0(r7)
+       lwz     r7, 0(r1)
+       stw     r5, 0(r7)
+
+       lwz     r0, 12(r1)
+       addi    r1, r1, 16
+       mtlr    r0
+       blr
+
+/* int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); */
+       .global cpu_post_complex_1_asm
+cpu_post_complex_1_asm:
+       li      r9,0
+       cmpw    r9,r7
+       bge     cpu_post_complex_1_done
+       mtctr   r7
+cpu_post_complex_1_loop:
+       mullw   r0,r3,r4
+       subf    r0,r5,r0
+       divw    r0,r0,r6
+       add     r9,r9,r0
+       bdnz    cpu_post_complex_1_loop
+cpu_post_complex_1_done:
+       mr      r3,r9
+       blr
+
+/* int cpu_post_complex_2_asm (int x, int n); */
+       .global cpu_post_complex_2_asm
+cpu_post_complex_2_asm:
+       mr.     r0,r4
+       mtctr   r0
+       mr      r0,r3
+       li      r3,1
+       li      r4,1
+       blelr
+cpu_post_complex_2_loop:
+       mullw   r3,r3,r0
+       add     r3,r3,r4
+       bdnz    cpu_post_complex_2_loop
+blr
+
+#endif
+#endif
diff --git a/post/lib_ppc/b.c b/post/lib_ppc/b.c
new file mode 100644 (file)
index 0000000..b4b17c8
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Branch instructions:                b, bl, bc
+ *
+ * The first 2 instructions (b, bl) are verified by jumping
+ * to a fixed address and checking whether control was transfered
+ * to that very point. For the bl instruction the value of the
+ * link register is checked as well (using mfspr).
+ * To verify the bc instruction various combinations of the BI/BO
+ * fields, the CTR and the condition register values are
+ * checked. The list of such combinations is pre-built and
+ * linked in U-Boot at build time.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump,
+    ulong cr);
+
+static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi,
+    int pjump, int dec, int link, ulong pctr, ulong cr)
+{
+    int ret = 0;
+    ulong lr = 0;
+    ulong ctr = pctr;
+    ulong jump;
+
+    unsigned long code[] =
+    {
+       ASM_MTCR(6),
+       ASM_MFLR(6),
+       ASM_MTCTR(3),
+       ASM_MTLR(4),
+       ASM_LI(5, 1),
+       ASM_3O(cmd, bo, bi, 8),
+       ASM_LI(5, 0),
+       ASM_MFCTR(3),
+       ASM_MFLR(4),
+       ASM_MTLR(6),
+       ASM_BLR,
+    };
+
+    cpu_post_exec_31 (code, &ctr, &lr, &jump, cr);
+
+    if (ret == 0)
+       ret = pjump == jump ? 0 : -1;
+    if (ret == 0)
+    {
+       if (dec)
+           ret = pctr == ctr + 1 ? 0 : -1;
+       else
+           ret = pctr == ctr ? 0 : -1;
+    }
+    if (ret == 0)
+    {
+       if (link)
+           ret = lr == (ulong) code + 24 ? 0 : -1;
+       else
+           ret = lr == 0 ? 0 : -1;
+    }
+
+    return ret;
+}
+
+int cpu_post_test_b (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    if (ret == 0)
+    {
+       ulong code[] =
+       {
+          ASM_MFLR(4),
+          ASM_MTLR(3),
+          ASM_B(4),
+          ASM_MFLR(3),
+          ASM_MTLR(4),
+          ASM_BLR,
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, &res, 0);
+
+       ret = res == 0 ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at b1 test !\n");
+       }
+    }
+
+    if (ret == 0)
+    {
+       ulong code[] =
+       {
+          ASM_MFLR(4),
+          ASM_MTLR(3),
+          ASM_BL(4),
+          ASM_MFLR(3),
+          ASM_MTLR(4),
+          ASM_BLR,
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, &res, 0);
+
+       ret = res == (ulong)code + 12 ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at b2 test !\n");
+       }
+    }
+
+    if (ret == 0)
+    {
+       ulong cc, cd;
+       int cond;
+       ulong ctr;
+       int link;
+
+       i = 0;
+
+       for (cc = 0; cc < 4 && ret == 0; cc++)
+       {
+           for (cd = 0; cd < 4 && ret == 0; cd++)
+           {
+               for (link = 0; link <= 1 && ret == 0; link++)
+               {
+                   for (cond = 0; cond <= 1 && ret == 0; cond++)
+                   {
+                       for (ctr = 1; ctr <= 2 && ret == 0; ctr++)
+                       {
+                           int dec = cd < 2;
+                           int cr = cond ? 0x80000000 : 0x00000000;
+                           int jumpc = cc >= 2 ||
+                                       (cc == 0 && !cond) ||
+                                       (cc == 1 && cond);
+                           int jumpd = cd >= 2 ||
+                                       (cd == 0 && ctr != 1) ||
+                                       (cd == 1 && ctr == 1);
+                           int jump = jumpc && jumpd;
+
+                           ret = cpu_post_test_bc (link ? OP_BCL : OP_BC,
+                               (cc << 3) + (cd << 1), 0, jump, dec, link,
+                               ctr, cr);
+
+                           if (ret != 0)
+                           {
+                               post_log ("Error at b3 test %d !\n", i);
+                           }
+
+                           i++;
+                       }
+                   }
+               }
+           }
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/cmp.c b/post/lib_ppc/cmp.c
new file mode 100644 (file)
index 0000000..789a24c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Integer compare instructions:       cmpw, cmplw
+ *
+ * To verify these instructions the test runs them with
+ * different combinations of operands, reads the condition
+ * register value and compares it with the expected one.
+ * The test contains a pre-built table
+ * containing the description of each test case: the instruction,
+ * the values of the operands, the condition field to save
+ * the result in and the expected result.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2);
+
+static struct cpu_post_cmp_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong cr;
+    ulong res;
+} cpu_post_cmp_table[] =
+{
+    {
+       OP_CMPW,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPW,
+       123,
+       133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPW,
+       123,
+       -133,
+       4,
+       0x04
+    },
+    {
+       OP_CMPLW,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPLW,
+       123,
+       -133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPLW,
+       123,
+       113,
+       4,
+       0x04
+    },
+};
+static unsigned int cpu_post_cmp_size =
+    sizeof (cpu_post_cmp_table) / sizeof (struct cpu_post_cmp_s);
+
+int cpu_post_test_cmp (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_cmp_size && ret == 0; i++)
+    {
+       struct cpu_post_cmp_s *test = cpu_post_cmp_table + i;
+       unsigned long code[] =
+       {
+           ASM_2C(test->cmd, test->cr, 3, 4),
+           ASM_MFCR(3),
+           ASM_BLR
+       };
+       ulong res;
+
+       cpu_post_exec_12 (code, & res, test->op1, test->op2);
+
+       ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cmp test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/cmpi.c b/post/lib_ppc/cmpi.c
new file mode 100644 (file)
index 0000000..e0c2aaf
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Integer compare instructions:       cmpwi, cmplwi
+ *
+ * To verify these instructions the test runs them with
+ * different combinations of operands, reads the condition
+ * register value and compares it with the expected one.
+ * The test contains a pre-built table
+ * containing the description of each test case: the instruction,
+ * the values of the operands, the condition field to save
+ * the result in and the expected result.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+
+static struct cpu_post_cmpi_s
+{
+    ulong cmd;
+    ulong op1;
+    ushort op2;
+    ulong cr;
+    ulong res;
+} cpu_post_cmpi_table[] =
+{
+    {
+       OP_CMPWI,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPWI,
+       123,
+       133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPWI,
+       123,
+       -133,
+       4,
+       0x04
+    },
+    {
+       OP_CMPLWI,
+       123,
+       123,
+       2,
+       0x02
+    },
+    {
+       OP_CMPLWI,
+       123,
+       -133,
+       3,
+       0x08
+    },
+    {
+       OP_CMPLWI,
+       123,
+       113,
+       4,
+       0x04
+    },
+};
+static unsigned int cpu_post_cmpi_size =
+    sizeof (cpu_post_cmpi_table) / sizeof (struct cpu_post_cmpi_s);
+
+int cpu_post_test_cmpi (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_cmpi_size && ret == 0; i++)
+    {
+       struct cpu_post_cmpi_s *test = cpu_post_cmpi_table + i;
+       unsigned long code[] =
+       {
+           ASM_1IC(test->cmd, test->cr, 3, test->op2),
+           ASM_MFCR(3),
+           ASM_BLR
+       };
+       ulong res;
+
+       cpu_post_exec_11 (code, & res, test->op1);
+
+       ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cmpi test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/complex.c b/post/lib_ppc/complex.c
new file mode 100644 (file)
index 0000000..033584b
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Complex calculations
+ *
+ * The calculations in this test are just a combination of simpler
+ * calculations, but probably under different timing conditions, etc.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n);
+extern int cpu_post_complex_2_asm (int x, int n);
+
+  /*
+   *     n
+   *   SUM (a1 * a2 - a3) / a4 = n * result
+   *    i=1
+   */
+static int cpu_post_test_complex_1 (void)
+{
+    int a1 = 666;
+    int a2 = 667;
+    int a3 = 668;
+    int a4 = 66;
+    int n = 100;
+    int result = 6720; /* (a1 * a2 - a3) / a4 */
+
+    if (cpu_post_complex_1_asm(a1, a2, a3, a4, n) != n * result)
+    {
+       return -1;
+    }
+
+    return 0;
+}
+
+  /*   (1 + x + x^2 + ... + x^n) * (1 - x) = 1 - x^(n+1)
+   */
+static int cpu_post_test_complex_2 (void)
+{
+    int ret = -1;
+    int x;
+    int n;
+    int k;
+    int left;
+    int right;
+
+    for (x = -8; x <= 8; x ++)
+    {
+       n = 9;
+
+       left = cpu_post_complex_2_asm(x, n);
+       left *= 1 - x;
+
+       right = 1;
+       for (k = 0; k <= n; k ++)
+       {
+           right *= x;
+       }
+       right = 1 - right;
+
+       if (left != right)
+       {
+           goto Done;
+       }
+    }
+
+    ret = 0;
+    Done:
+
+    return ret;
+}
+
+int cpu_post_test_complex (void)
+{
+    int ret = 0;
+
+    if (ret == 0)
+    {
+       ret = cpu_post_test_complex_1();
+    }
+
+    if (ret == 0)
+    {
+       ret = cpu_post_test_complex_2();
+    }
+
+    if (ret != 0)
+    {
+       post_log ("Error at complex test !\n");
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/cpu.c b/post/lib_ppc/cpu.c
new file mode 100644 (file)
index 0000000..1f2ded2
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * (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>
+
+/*
+ * CPU 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 <watchdog.h>
+#include <post.h>
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern int cpu_post_test_cmp (void);
+extern int cpu_post_test_cmpi (void);
+extern int cpu_post_test_two (void);
+extern int cpu_post_test_twox (void);
+extern int cpu_post_test_three (void);
+extern int cpu_post_test_threex (void);
+extern int cpu_post_test_threei (void);
+extern int cpu_post_test_andi (void);
+extern int cpu_post_test_srawi (void);
+extern int cpu_post_test_rlwnm (void);
+extern int cpu_post_test_rlwinm (void);
+extern int cpu_post_test_rlwimi (void);
+extern int cpu_post_test_store (void);
+extern int cpu_post_test_load (void);
+extern int cpu_post_test_cr (void);
+extern int cpu_post_test_b (void);
+extern int cpu_post_test_multi (void);
+extern int cpu_post_test_string (void);
+extern int cpu_post_test_complex (void);
+
+ulong cpu_post_makecr (long v)
+{
+       ulong cr = 0;
+
+       if (v < 0)
+               cr |= 0x80000000;
+       if (v > 0)
+               cr |= 0x40000000;
+       if (v == 0)
+               cr |= 0x20000000;
+
+       return cr;
+}
+
+int cpu_post_test (int flags)
+{
+       int ic = icache_status ();
+       int ret = 0;
+
+       WATCHDOG_RESET();
+       if (ic)
+               icache_disable ();
+
+       if (ret == 0)
+               ret = cpu_post_test_cmp ();
+       if (ret == 0)
+               ret = cpu_post_test_cmpi ();
+       if (ret == 0)
+               ret = cpu_post_test_two ();
+       if (ret == 0)
+               ret = cpu_post_test_twox ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_three ();
+       if (ret == 0)
+               ret = cpu_post_test_threex ();
+       if (ret == 0)
+               ret = cpu_post_test_threei ();
+       if (ret == 0)
+               ret = cpu_post_test_andi ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_srawi ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwnm ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwinm ();
+       if (ret == 0)
+               ret = cpu_post_test_rlwimi ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_store ();
+       if (ret == 0)
+               ret = cpu_post_test_load ();
+       if (ret == 0)
+               ret = cpu_post_test_cr ();
+       if (ret == 0)
+               ret = cpu_post_test_b ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_multi ();
+       WATCHDOG_RESET();
+       if (ret == 0)
+               ret = cpu_post_test_string ();
+       if (ret == 0)
+               ret = cpu_post_test_complex ();
+       WATCHDOG_RESET();
+
+       if (ic)
+               icache_enable ();
+
+       WATCHDOG_RESET();
+
+       return ret;
+}
+
+#endif /* CONFIG_POST & CFG_POST_CPU */
+#endif /* CONFIG_POST */
diff --git a/post/lib_ppc/cpu_asm.h b/post/lib_ppc/cpu_asm.h
new file mode 100644 (file)
index 0000000..1cbaf41
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * (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
+ */
+#ifndef _CPU_ASM_H
+#define _CPU_ASM_H
+
+#define BIT_C                          0x00000001
+
+#define OP_BLR                         0x4e800020
+#define OP_EXTSB                       0x7c000774
+#define OP_EXTSH                       0x7c000734
+#define OP_NEG                         0x7c0000d0
+#define OP_CNTLZW                      0x7c000034
+#define OP_ADD                         0x7c000214
+#define OP_ADDC                                0x7c000014
+#define OP_ADDME                       0x7c0001d4
+#define OP_ADDZE                       0x7c000194
+#define OP_ADDE                                0x7c000114
+#define OP_ADDI                                0x38000000
+#define OP_SUBF                                0x7c000050
+#define OP_SUBFC                       0x7c000010
+#define OP_SUBFE                       0x7c000110
+#define OP_SUBFME                      0x7c0001d0
+#define OP_SUBFZE                      0x7c000190
+#define OP_MFCR                                0x7c000026
+#define OP_MTCR                                0x7c0ff120
+#define OP_MFXER                       0x7c0102a6
+#define OP_MTXER                       0x7c0103a6
+#define OP_MCRXR                       0x7c000400
+#define OP_MCRF                                0x4c000000
+#define OP_CRAND                       0x4c000202
+#define OP_CRANDC                      0x4c000102
+#define OP_CROR                                0x4c000382
+#define OP_CRORC                       0x4c000342
+#define OP_CRXOR                       0x4c000182
+#define OP_CRNAND                      0x4c0001c2
+#define OP_CRNOR                       0x4c000042
+#define OP_CREQV                       0x4c000242
+#define OP_CMPW                                0x7c000000
+#define OP_CMPLW                       0x7c000040
+#define OP_CMPWI                       0x2c000000
+#define OP_CMPLWI                      0x28000000
+#define OP_MULLW                       0x7c0001d6
+#define OP_MULHW                       0x7c000096
+#define OP_MULHWU                      0x7c000016
+#define OP_DIVW                                0x7c0003d6
+#define OP_DIVWU                       0x7c000396
+#define OP_OR                          0x7c000378
+#define OP_ORC                         0x7c000338
+#define OP_XOR                         0x7c000278
+#define OP_NAND                                0x7c0003b8
+#define OP_NOR                         0x7c0000f8
+#define OP_EQV                         0x7c000238
+#define OP_SLW                         0x7c000030
+#define OP_SRW                         0x7c000430
+#define OP_SRAW                                0x7c000630
+#define OP_ORI                         0x60000000
+#define OP_ORIS                                0x64000000
+#define OP_XORI                                0x68000000
+#define OP_XORIS                       0x6c000000
+#define OP_ANDI_                       0x70000000
+#define OP_ANDIS_                      0x74000000
+#define OP_SRAWI                       0x7c000670
+#define OP_RLWINM                      0x54000000
+#define OP_RLWNM                       0x5c000000
+#define OP_RLWIMI                      0x50000000
+#define OP_LWZ                         0x80000000
+#define OP_LHZ                         0xa0000000
+#define OP_LHA                         0xa8000000
+#define OP_LBZ                         0x88000000
+#define OP_LWZU                                0x84000000
+#define OP_LHZU                                0xa4000000
+#define OP_LHAU                                0xac000000
+#define OP_LBZU                                0x8c000000
+#define OP_LWZX                                0x7c00002e
+#define OP_LHZX                                0x7c00022e
+#define OP_LHAX                                0x7c0002ae
+#define OP_LBZX                                0x7c0000ae
+#define OP_LWZUX                       0x7c00006e
+#define OP_LHZUX                       0x7c00026e
+#define OP_LHAUX                       0x7c0002ee
+#define OP_LBZUX                       0x7c0000ee
+#define OP_STW                         0x90000000
+#define OP_STH                         0xb0000000
+#define OP_STB                         0x98000000
+#define OP_STWU                                0x94000000
+#define OP_STHU                                0xb4000000
+#define OP_STBU                                0x9c000000
+#define OP_STWX                                0x7c00012e
+#define OP_STHX                                0x7c00032e
+#define OP_STBX                                0x7c0001ae
+#define OP_STWUX                       0x7c00016e
+#define OP_STHUX                       0x7c00036e
+#define OP_STBUX                       0x7c0001ee
+#define OP_B                           0x48000000
+#define OP_BL                          0x48000001
+#define OP_BC                          0x40000000
+#define OP_BCL                         0x40000001
+#define OP_MTLR                                0x7c0803a6
+#define OP_MFLR                                0x7c0802a6
+#define OP_MTCTR                       0x7c0903a6
+#define OP_MFCTR                       0x7c0902a6
+#define OP_LMW                         0xb8000000
+#define OP_STMW                                0xbc000000
+#define OP_LSWI                                0x7c0004aa
+#define OP_LSWX                                0x7c00042a
+#define OP_STSWI                       0x7c0005aa
+#define OP_STSWX                       0x7c00052a
+
+#define ASM_0(opcode)                  (opcode)
+#define ASM_1(opcode, rd)              ((opcode) +             \
+                                        ((rd) << 21))
+#define ASM_1C(opcode, cr)             ((opcode) +             \
+                                        ((cr) << 23))
+#define ASM_11(opcode, rd, rs)         ((opcode) +             \
+                                        ((rd) << 21) +         \
+                                        ((rs) << 16))
+#define ASM_11C(opcode, cd, cs)                ((opcode) +             \
+                                        ((cd) << 23) +         \
+                                        ((cs) << 18))
+#define ASM_11X(opcode, rd, rs)                ((opcode) +             \
+                                        ((rs) << 21) +         \
+                                        ((rd) << 16))
+#define ASM_11I(opcode, rd, rs, simm)  ((opcode) +             \
+                                        ((rd) << 21) +         \
+                                        ((rs) << 16) +         \
+                                        ((simm) & 0xffff))
+#define ASM_11IF(opcode, rd, rs, simm) ((opcode) +             \
+                                        ((rd) << 21) +         \
+                                        ((rs) << 16) +         \
+                                        ((simm) << 11))
+#define ASM_11S(opcode, rd, rs, sh)    ((opcode) +             \
+                                        ((rs) << 21) +         \
+                                        ((rd) << 16) +         \
+                                        ((sh) << 11))
+#define ASM_11IX(opcode, rd, rs, imm)  ((opcode) +             \
+                                        ((rs) << 21) +         \
+                                        ((rd) << 16) +         \
+                                        ((imm) & 0xffff))
+#define ASM_12(opcode, rd, rs1, rs2)   ((opcode) +             \
+                                        ((rd) << 21) +         \
+                                        ((rs1) << 16) +        \
+                                        ((rs2) << 11))
+#define ASM_12F(opcode, fd, fs1, fs2)  ((opcode) +             \
+                                        ((fd) << 21) +         \
+                                        ((fs1) << 16) +        \
+                                        ((fs2) << 11))
+#define ASM_12X(opcode, rd, rs1, rs2)  ((opcode) +             \
+                                        ((rs1) << 21) +        \
+                                        ((rd) << 16) +         \
+                                        ((rs2) << 11))
+#define ASM_2C(opcode, cr, rs1, rs2)   ((opcode) +             \
+                                        ((cr) << 23) +         \
+                                        ((rs1) << 16) +        \
+                                        ((rs2) << 11))
+#define ASM_1IC(opcode, cr, rs, imm)   ((opcode) +             \
+                                        ((cr) << 23) +         \
+                                        ((rs) << 16) +         \
+                                        ((imm) & 0xffff))
+#define ASM_122(opcode, rd, rs1, rs2, imm1, imm2)              \
+                                       ((opcode) +             \
+                                        ((rs1) << 21) +        \
+                                        ((rd) << 16) +         \
+                                        ((rs2) << 11) +        \
+                                        ((imm1) << 6) +        \
+                                        ((imm2) << 1))
+#define ASM_113(opcode, rd, rs, imm1, imm2, imm3)              \
+                                       ((opcode) +             \
+                                        ((rs) << 21) +         \
+                                        ((rd) << 16) +         \
+                                        ((imm1) << 11) +       \
+                                        ((imm2) << 6) +        \
+                                        ((imm3) << 1))
+#define ASM_1O(opcode, off)            ((opcode) + (off))
+#define ASM_3O(opcode, bo, bi, off)    ((opcode) +             \
+                                        ((bo) << 21) +         \
+                                        ((bi) << 16) +         \
+                                        (off))
+
+#define ASM_ADDI(rd, rs, simm)         ASM_11I(OP_ADDI, rd, rs, simm)
+#define ASM_BLR                                ASM_0(OP_BLR)
+#define ASM_STW(rd, rs, simm)          ASM_11I(OP_STW, rd, rs, simm)
+#define ASM_LWZ(rd, rs, simm)          ASM_11I(OP_LWZ, rd, rs, simm)
+#define ASM_MFCR(rd)                   ASM_1(OP_MFCR, rd)
+#define ASM_MTCR(rd)                   ASM_1(OP_MTCR, rd)
+#define ASM_MFXER(rd)                  ASM_1(OP_MFXER, rd)
+#define ASM_MTXER(rd)                  ASM_1(OP_MTXER, rd)
+#define ASM_MFCTR(rd)                  ASM_1(OP_MFCTR, rd)
+#define ASM_MTCTR(rd)                  ASM_1(OP_MTCTR, rd)
+#define ASM_MCRXR(cr)                  ASM_1C(OP_MCRXR, cr)
+#define ASM_MCRF(cd, cs)               ASM_11C(OP_MCRF, cd, cs)
+#define ASM_B(off)                     ASM_1O(OP_B, off)
+#define ASM_BL(off)                    ASM_1O(OP_BL, off)
+#define ASM_MFLR(rd)                   ASM_1(OP_MFLR, rd)
+#define ASM_MTLR(rd)                   ASM_1(OP_MTLR, rd)
+#define ASM_LI(rd, imm)                        ASM_ADDI(rd, 0, imm)
+#define ASM_LMW(rd, rs, simm)          ASM_11I(OP_LMW, rd, rs, simm)
+#define ASM_STMW(rd, rs, simm)         ASM_11I(OP_STMW, rd, rs, simm)
+#define ASM_LSWI(rd, rs, simm)         ASM_11IF(OP_LSWI, rd, rs, simm)
+#define ASM_LSWX(rd, rs1, rs2)         ASM_12(OP_LSWX, rd, rs1, rs2)
+#define ASM_STSWI(rd, rs, simm)                ASM_11IF(OP_STSWI, rd, rs, simm)
+#define ASM_STSWX(rd, rs1, rs2)                ASM_12(OP_STSWX, rd, rs1, rs2)
+
+
+#endif /* _CPU_ASM_H */
diff --git a/post/lib_ppc/cr.c b/post/lib_ppc/cr.c
new file mode 100644 (file)
index 0000000..da6ef37
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Condition register istructions:     mtcr, mfcr, mcrxr,
+ *                                     crand, crandc, cror, crorc, crxor,
+ *                                     crnand, crnor, creqv, mcrf
+ *
+ * The mtcrf/mfcr instructions is tested by loading different
+ * values into the condition register (mtcrf), moving its value
+ * to a general-purpose register (mfcr) and comparing this value
+ * with the expected one.
+ * The mcrxr instruction is tested by loading a fixed value
+ * into the XER register (mtspr), moving XER value to the
+ * condition register (mcrxr), moving it to a general-purpose
+ * register (mfcr) and comparing the value of this register with
+ * the expected one.
+ * The rest of instructions is tested by loading a fixed
+ * value into the condition register (mtcrf), executing each
+ * instruction several times to modify all 4-bit condition
+ * fields, moving the value of the conditional register to a
+ * general-purpose register (mfcr) and comparing it with the
+ * expected one.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
+extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3);
+
+static ulong cpu_post_cr_table1[] =
+{
+    0xaaaaaaaa,
+    0x55555555,
+};
+static unsigned int cpu_post_cr_size1 =
+    sizeof (cpu_post_cr_table1) / sizeof (ulong);
+
+static struct cpu_post_cr_s2 {
+    ulong xer;
+    ulong cr;
+} cpu_post_cr_table2[] =
+{
+    {
+       0xa0000000,
+       1
+    },
+    {
+       0x40000000,
+       5
+    },
+};
+static unsigned int cpu_post_cr_size2 =
+    sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2);
+
+static struct cpu_post_cr_s3 {
+    ulong cr;
+    ulong cs;
+    ulong cd;
+    ulong res;
+} cpu_post_cr_table3[] =
+{
+    {
+       0x01234567,
+       0,
+       4,
+       0x01230567
+    },
+    {
+       0x01234567,
+       7,
+       0,
+       0x71234567
+    },
+};
+static unsigned int cpu_post_cr_size3 =
+    sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3);
+
+static struct cpu_post_cr_s4 {
+    ulong cmd;
+    ulong cr;
+    ulong op1;
+    ulong op2;
+    ulong op3;
+    ulong res;
+} cpu_post_cr_table4[] =
+{
+    {
+       OP_CRAND,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRAND,
+       0x0000ffff,
+       16,
+       17,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRANDC,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRANDC,
+       0x0000ffff,
+       16,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CROR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CROR,
+       0x0000ffff,
+       0,
+       1,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRORC,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRORC,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRXOR,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRXOR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRNAND,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CRNAND,
+       0x0000ffff,
+       16,
+       17,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRNOR,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+    {
+       OP_CRNOR,
+       0x0000ffff,
+       0,
+       1,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CREQV,
+       0x0000ffff,
+       0,
+       0,
+       0,
+       0x8000ffff
+    },
+    {
+       OP_CREQV,
+       0x0000ffff,
+       0,
+       16,
+       0,
+       0x0000ffff
+    },
+};
+static unsigned int cpu_post_cr_size4 =
+    sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4);
+
+int cpu_post_test_cr (void)
+{
+    int ret = 0;
+    unsigned int i;
+    unsigned long cr_sav;
+
+    asm ( "mfcr %0" : "=r" (cr_sav) : );
+
+    for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++)
+    {
+       ulong cr = cpu_post_cr_table1[i];
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, cr);
+
+       ret = res == cr ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cr1 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i;
+       ulong res;
+       ulong xer;
+
+       unsigned long code[] =
+       {
+           ASM_MTXER(3),
+           ASM_MCRXR(test->cr),
+           ASM_MFCR(3),
+           ASM_MFXER(4),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_21x (code, &res, &xer, test->xer);
+
+       ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ?
+             0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cr2 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i;
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_MCRF(test->cd, test->cs),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, test->cr);
+
+       ret = res == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cr3 test %d !\n", i);
+       }
+    }
+
+    for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++)
+    {
+       struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i;
+       ulong res;
+
+       unsigned long code[] =
+       {
+           ASM_MTCR(3),
+           ASM_12F(test->cmd, test->op3, test->op1, test->op2),
+           ASM_MFCR(3),
+           ASM_BLR,
+       };
+
+       cpu_post_exec_11 (code, &res, test->cr);
+
+       ret = res == test->res ? 0 : -1;
+
+       if (ret != 0)
+       {
+           post_log ("Error at cr4 test %d !\n", i);
+       }
+    }
+
+    asm ( "mtcr %0" : : "r" (cr_sav));
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/load.c b/post/lib_ppc/load.c
new file mode 100644 (file)
index 0000000..393c568
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Load instructions:          lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u)
+ *
+ * All operations are performed on a 16-byte array. The array
+ * is 4-byte aligned. The base register points to offset 8.
+ * The immediate offset (index register) ranges in [-8 ... +7].
+ * The test cases are composed so that they do not
+ * cause alignment exceptions.
+ * The test contains a pre-built table describing all test cases.
+ * The table entry contains:
+ * the instruction opcode, the array contents, the value of the index
+ * register and the expected value of the destination register.
+ * After executing the instruction, the test verifies the
+ * value of the destination register and the value of the base
+ * register (it must change for "load with update" instructions).
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
+extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
+
+static struct cpu_post_load_s
+{
+    ulong cmd;
+    uint width;
+    int update;
+    int index;
+    ulong offset;
+} cpu_post_load_table[] =
+{
+    {
+       OP_LWZ,
+       4,
+       0,
+       0,
+       4
+    },
+    {
+       OP_LHA,
+       3,
+       0,
+       0,
+       2
+    },
+    {
+       OP_LHZ,
+       2,
+       0,
+       0,
+       2
+    },
+    {
+       OP_LBZ,
+       1,
+       0,
+       0,
+       1
+    },
+    {
+       OP_LWZU,
+       4,
+       1,
+       0,
+       4
+    },
+    {
+       OP_LHAU,
+       3,
+       1,
+       0,
+       2
+    },
+    {
+       OP_LHZU,
+       2,
+       1,
+       0,
+       2
+    },
+    {
+       OP_LBZU,
+       1,
+       1,
+       0,
+       1
+    },
+    {
+       OP_LWZX,
+       4,
+       0,
+       1,
+       4
+    },
+    {
+       OP_LHAX,
+       3,
+       0,
+       1,
+       2
+    },
+    {
+       OP_LHZX,
+       2,
+       0,
+       1,
+       2
+    },
+    {
+       OP_LBZX,
+       1,
+       0,
+       1,
+       1
+    },
+    {
+       OP_LWZUX,
+       4,
+       1,
+       1,
+       4
+    },
+    {
+       OP_LHAUX,
+       3,
+       1,
+       1,
+       2
+    },
+    {
+       OP_LHZUX,
+       2,
+       1,
+       1,
+       2
+    },
+    {
+       OP_LBZUX,
+       1,
+       1,
+       1,
+       1
+    },
+};
+static unsigned int cpu_post_load_size =
+    sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s);
+
+int cpu_post_test_load (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_load_size && ret == 0; i++)
+    {
+       struct cpu_post_load_s *test = cpu_post_load_table + i;
+       uchar data[16] =
+       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+       ulong base0 = (ulong) (data + 8);
+       ulong base = base0;
+       ulong value;
+
+       if (test->index)
+       {
+           ulong code[] =
+           {
+               ASM_12(test->cmd, 5, 3, 4),
+               ASM_BLR,
+           };
+
+           cpu_post_exec_22w (code, &base, test->offset, &value);
+       }
+       else
+       {
+           ulong code[] =
+           {
+               ASM_11I(test->cmd, 4, 3, test->offset),
+               ASM_BLR,
+           };
+
+           cpu_post_exec_21w (code, &base, &value);
+       }
+
+       if (ret == 0)
+       {
+          if (test->update)
+              ret = base == base0 + test->offset ? 0 : -1;
+          else
+              ret = base == base0 ? 0 : -1;
+       }
+
+       if (ret == 0)
+       {
+           switch (test->width)
+           {
+           case 1:
+               ret = *(uchar *)(base0 + test->offset) == value ?
+                     0 : -1;
+               break;
+           case 2:
+               ret = *(ushort *)(base0 + test->offset) == value ?
+                     0 : -1;
+               break;
+           case 3:
+               ret = *(short *)(base0 + test->offset) == value ?
+                     0 : -1;
+               break;
+           case 4:
+               ret = *(ulong *)(base0 + test->offset) == value ?
+                     0 : -1;
+               break;
+           }
+       }
+
+       if (ret != 0)
+       {
+           post_log ("Error at load test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/multi.c b/post/lib_ppc/multi.c
new file mode 100644 (file)
index 0000000..8724384
--- /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>
+
+/*
+ * CPU test
+ * Load/store multiple word instructions:      lmw, stmw
+ *
+ * 26 consecutive words are loaded from a source memory buffer
+ * into GPRs r6 through r31. After that, 26 consecutive words are stored
+ * from the GPRs r6 through r31 into a target memory buffer. The contents
+ * of the source and target buffers are then compared.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2);
+
+int cpu_post_test_multi (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    if (ret == 0)
+    {
+       ulong src [26], dst [26];
+
+       ulong code[] =
+       {
+           ASM_LMW(5, 3, 0),
+           ASM_STMW(5, 4, 0),
+           ASM_BLR,
+       };
+
+       for (i = 0; i < sizeof(src) / sizeof(src[0]); i ++)
+       {
+           src[i] = i;
+           dst[i] = 0;
+       }
+
+       cpu_post_exec_02(code, (ulong)src, (ulong)dst);
+
+       ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
+    }
+
+    if (ret != 0)
+    {
+       post_log ("Error at multi test !\n");
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/rlwimi.c b/post/lib_ppc/rlwimi.c
new file mode 100644 (file)
index 0000000..f65f79a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Shift instructions:         rlwimi
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_rlwimi_s
+{
+    ulong cmd;
+    ulong op0;
+    ulong op1;
+    uchar op2;
+    uchar mb;
+    uchar me;
+    ulong res;
+} cpu_post_rlwimi_table[] =
+{
+    {
+       OP_RLWIMI,
+       0xff00ffff,
+       0x0000aa00,
+       8,
+       8,
+       15,
+       0xffaaffff
+    },
+};
+static unsigned int cpu_post_rlwimi_size =
+    sizeof (cpu_post_rlwimi_table) / sizeof (struct cpu_post_rlwimi_s);
+
+int cpu_post_test_rlwimi (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_rlwimi_size && ret == 0; i++)
+    {
+       struct cpu_post_rlwimi_s *test = cpu_post_rlwimi_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -20),
+               ASM_STW(3, stk, 8),
+               ASM_STW(4, stk, 12),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg1, stk, 8),
+               ASM_LWZ(reg0, stk, 12),
+               ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 20),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -20),
+               ASM_STW(3, stk, 8),
+               ASM_STW(4, stk, 12),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg1, stk, 8),
+               ASM_LWZ(reg0, stk, 12),
+               ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me) |
+                   BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 20),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op0, test->op1);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwimi test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op0, test->op1);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwimi test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/rlwinm.c b/post/lib_ppc/rlwinm.c
new file mode 100644 (file)
index 0000000..e240c41
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Shift instructions:         rlwinm
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_rlwinm_s
+{
+    ulong cmd;
+    ulong op1;
+    uchar op2;
+    uchar mb;
+    uchar me;
+    ulong res;
+} cpu_post_rlwinm_table[] =
+{
+   {
+       OP_RLWINM,
+       0xffff0000,
+       24,
+       16,
+       23,
+       0x0000ff00
+   },
+};
+static unsigned int cpu_post_rlwinm_size =
+    sizeof (cpu_post_rlwinm_table) / sizeof (struct cpu_post_rlwinm_s);
+
+int cpu_post_test_rlwinm (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_rlwinm_size && ret == 0; i++)
+    {
+       struct cpu_post_rlwinm_s *test = cpu_post_rlwinm_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_113(test->cmd, reg1, reg0, test->op2, test->mb,
+                   test->me) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op1);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwinm test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op1);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwinm test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/rlwnm.c b/post/lib_ppc/rlwnm.c
new file mode 100644 (file)
index 0000000..523cf4d
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Shift instructions:         rlwnm
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_rlwnm_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    uchar mb;
+    uchar me;
+    ulong res;
+} cpu_post_rlwnm_table[] =
+{
+   {
+       OP_RLWNM,
+       0xffff0000,
+       24,
+       16,
+       23,
+       0x0000ff00
+   },
+};
+static unsigned int cpu_post_rlwnm_size =
+    sizeof (cpu_post_rlwnm_table) / sizeof (struct cpu_post_rlwnm_s);
+
+int cpu_post_test_rlwnm (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_rlwnm_size && ret == 0; i++)
+    {
+       struct cpu_post_rlwnm_s *test = cpu_post_rlwnm_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int reg2 = (reg + 2) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me),
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me) |
+                   BIT_C,
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwnm test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at rlwnm test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/srawi.c b/post/lib_ppc/srawi.c
new file mode 100644 (file)
index 0000000..91c82c9
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Shift instructions:         srawi
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_srawi_s
+{
+    ulong cmd;
+    ulong op1;
+    uchar op2;
+    ulong res;
+} cpu_post_srawi_table[] =
+{
+    {
+       OP_SRAWI,
+       0x8000,
+       3,
+       0x1000
+    },
+    {
+       OP_SRAWI,
+       0x80000000,
+       3,
+       0xf0000000
+    },
+};
+static unsigned int cpu_post_srawi_size =
+    sizeof (cpu_post_srawi_table) / sizeof (struct cpu_post_srawi_s);
+
+int cpu_post_test_srawi (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_srawi_size && ret == 0; i++)
+    {
+       struct cpu_post_srawi_s *test = cpu_post_srawi_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11S(test->cmd, reg1, reg0, test->op2),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11S(test->cmd, reg1, reg0, test->op2) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op1);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at srawi test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op1);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at srawi test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/store.c b/post/lib_ppc/store.c
new file mode 100644 (file)
index 0000000..f495bf2
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Store instructions:         stb(x)(u), sth(x)(u), stw(x)(u)
+ *
+ * All operations are performed on a 16-byte array. The array
+ * is 4-byte aligned. The base register points to offset 8.
+ * The immediate offset (index register) ranges in [-8 ... +7].
+ * The test cases are composed so that they do not
+ * cause alignment exceptions.
+ * The test contains a pre-built table describing all test cases.
+ * The table entry contains:
+ * the instruction opcode, the value of the index register and
+ * the value of the source register. After executing the
+ * instruction, the test verifies the contents of the array
+ * and the value of the base register (it must change for "store
+ * with update" instructions).
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3);
+extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2);
+
+static struct cpu_post_store_s
+{
+    ulong cmd;
+    uint width;
+    int update;
+    int index;
+    ulong offset;
+    ulong value;
+} cpu_post_store_table[] =
+{
+    {
+       OP_STW,
+       4,
+       0,
+       0,
+       -4,
+       0xff00ff00
+    },
+    {
+       OP_STH,
+       2,
+       0,
+       0,
+       -2,
+       0xff00
+    },
+    {
+       OP_STB,
+       1,
+       0,
+       0,
+       -1,
+       0xff
+    },
+    {
+       OP_STWU,
+       4,
+       1,
+       0,
+       -4,
+       0xff00ff00
+    },
+    {
+       OP_STHU,
+       2,
+       1,
+       0,
+       -2,
+       0xff00
+    },
+    {
+       OP_STBU,
+       1,
+       1,
+       0,
+       -1,
+       0xff
+    },
+    {
+       OP_STWX,
+       4,
+       0,
+       1,
+       -4,
+       0xff00ff00
+    },
+    {
+       OP_STHX,
+       2,
+       0,
+       1,
+       -2,
+       0xff00
+    },
+    {
+       OP_STBX,
+       1,
+       0,
+       1,
+       -1,
+       0xff
+    },
+    {
+       OP_STWUX,
+       4,
+       1,
+       1,
+       -4,
+       0xff00ff00
+    },
+    {
+       OP_STHUX,
+       2,
+       1,
+       1,
+       -2,
+       0xff00
+    },
+    {
+       OP_STBUX,
+       1,
+       1,
+       1,
+       -1,
+       0xff
+    },
+};
+static unsigned int cpu_post_store_size =
+    sizeof (cpu_post_store_table) / sizeof (struct cpu_post_store_s);
+
+int cpu_post_test_store (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    for (i = 0; i < cpu_post_store_size && ret == 0; i++)
+    {
+       struct cpu_post_store_s *test = cpu_post_store_table + i;
+       uchar data[16] =
+       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+       ulong base0 = (ulong) (data + 8);
+       ulong base = base0;
+
+       if (test->index)
+       {
+           ulong code[] =
+           {
+               ASM_12(test->cmd, 5, 3, 4),
+               ASM_BLR,
+           };
+
+           cpu_post_exec_12w (code, &base, test->offset, test->value);
+       }
+       else
+       {
+           ulong code[] =
+           {
+               ASM_11I(test->cmd, 4, 3, test->offset),
+               ASM_BLR,
+           };
+
+           cpu_post_exec_11w (code, &base, test->value);
+       }
+
+       if (ret == 0)
+       {
+          if (test->update)
+              ret = base == base0 + test->offset ? 0 : -1;
+          else
+              ret = base == base0 ? 0 : -1;
+       }
+
+       if (ret == 0)
+       {
+           switch (test->width)
+           {
+           case 1:
+               ret = *(uchar *)(base0 + test->offset) == test->value ?
+                     0 : -1;
+               break;
+           case 2:
+               ret = *(ushort *)(base0 + test->offset) == test->value ?
+                     0 : -1;
+               break;
+           case 4:
+               ret = *(ulong *)(base0 + test->offset) == test->value ?
+                     0 : -1;
+               break;
+           }
+       }
+
+       if (ret != 0)
+       {
+           post_log ("Error at store test %d !\n", i);
+       }
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/string.c b/post/lib_ppc/string.c
new file mode 100644 (file)
index 0000000..bd83bd1
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Load/store string instructions:     lswi, stswi, lswx, stswx
+ *
+ * Several consecutive bytes from a source memory buffer are loaded
+ * left to right into GPRs. After that, the bytes are stored
+ * from the GPRs into a target memory buffer. The contents
+ * of the source and target buffers are then compared.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2);
+extern void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3,
+    ulong op4);
+
+#include <bedbug/regs.h>
+int cpu_post_test_string (void)
+{
+    int ret = 0;
+    unsigned int i;
+
+    if (ret == 0)
+    {
+       char src [31], dst [31];
+
+       ulong code[] =
+       {
+           ASM_LSWI(5, 3, 31),
+           ASM_STSWI(5, 4, 31),
+           ASM_BLR,
+       };
+
+       for (i = 0; i < sizeof(src); i ++)
+       {
+           src[i] = (char) i;
+           dst[i] = 0;
+       }
+
+       cpu_post_exec_02(code, (ulong)src, (ulong)dst);
+
+       ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
+    }
+
+    if (ret == 0)
+    {
+       char src [95], dst [95];
+
+       ulong code[] =
+       {
+           ASM_LSWX(8, 3, 5),
+           ASM_STSWX(8, 4, 5),
+           ASM_BLR,
+       };
+
+       for (i = 0; i < sizeof(src); i ++)
+       {
+           src[i] = (char) i;
+           dst[i] = 0;
+       }
+
+       cpu_post_exec_04(code, (ulong)src, (ulong)dst, 0, sizeof(src));
+
+       ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1;
+    }
+
+    if (ret != 0)
+    {
+       post_log ("Error at string test !\n");
+    }
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/three.c b/post/lib_ppc/three.c
new file mode 100644 (file)
index 0000000..c2d7476
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rD,rA,rB
+ *
+ * Arithmetic instructions:    add, addc, adde, subf, subfc, subfe,
+ *                             mullw, mulhw, mulhwu, divw, divwu
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_three_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong res;
+} cpu_post_three_table[] =
+{
+    {
+       OP_ADD,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADD,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_ADDC,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADDC,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_ADDE,
+       100,
+       200,
+       300
+    },
+    {
+       OP_ADDE,
+       100,
+       -200,
+       -100
+    },
+    {
+       OP_SUBF,
+       100,
+       200,
+       100
+    },
+    {
+       OP_SUBF,
+       300,
+       200,
+       -100
+    },
+    {
+       OP_SUBFC,
+       100,
+       200,
+       100
+    },
+    {
+       OP_SUBFC,
+       300,
+       200,
+       -100
+    },
+    {
+       OP_SUBFE,
+       100,
+       200,
+       200 + ~100
+    },
+    {
+       OP_SUBFE,
+       300,
+       200,
+       200 + ~300
+    },
+    {
+       OP_MULLW,
+       200,
+       300,
+       200 * 300
+    },
+    {
+       OP_MULHW,
+       0x10000000,
+       0x10000000,
+       0x1000000
+    },
+    {
+       OP_MULHWU,
+       0x80000000,
+       0x80000000,
+       0x40000000
+    },
+    {
+       OP_DIVW,
+       -20,
+       5,
+       -4
+    },
+    {
+       OP_DIVWU,
+       0x8000,
+       0x200,
+       0x40
+    },
+};
+static unsigned int cpu_post_three_size =
+    sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s);
+
+int cpu_post_test_three (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_three_size && ret == 0; i++)
+    {
+       struct cpu_post_three_s *test = cpu_post_three_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int reg2 = (reg + 2) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12(test->cmd, reg2, reg1, reg0),
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at three test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at three test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/threei.c b/post/lib_ppc/threei.c
new file mode 100644 (file)
index 0000000..79f0178
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rA,rS,UIMM
+ *
+ * Logic instructions:         ori, oris, xori, xoris
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_threei_s
+{
+    ulong cmd;
+    ulong op1;
+    ushort op2;
+    ulong res;
+} cpu_post_threei_table[] =
+{
+    {
+       OP_ORI,
+       0x80000000,
+       0xffff,
+       0x8000ffff
+    },
+    {
+       OP_ORIS,
+       0x00008000,
+       0xffff,
+       0xffff8000
+    },
+    {
+       OP_XORI,
+       0x8000ffff,
+       0xffff,
+       0x80000000
+    },
+    {
+       OP_XORIS,
+       0x00008000,
+       0xffff,
+       0xffff8000
+    },
+};
+static unsigned int cpu_post_threei_size =
+    sizeof (cpu_post_threei_table) / sizeof (struct cpu_post_threei_s);
+
+int cpu_post_test_threei (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_threei_size && ret == 0; i++)
+    {
+       struct cpu_post_threei_s *test = cpu_post_threei_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11IX(test->cmd, reg1, reg0, test->op2),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           cr = 0;
+           cpu_post_exec_21 (code, & cr, & res, test->op1);
+
+           ret = res == test->res && cr == 0 ? 0 : -1;
+
+           if (ret != 0)
+           {
+               post_log ("Error at threei test %d !\n", i);
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/threex.c b/post/lib_ppc/threex.c
new file mode 100644 (file)
index 0000000..2c72063
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Ternary instructions                instr rA,rS,rB
+ *
+ * Logic instructions:         or, orc, xor, nand, nor, eqv
+ * Shift instructions:         slw, srw, sraw
+ *
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
+    ulong op2);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_threex_s
+{
+    ulong cmd;
+    ulong op1;
+    ulong op2;
+    ulong res;
+} cpu_post_threex_table[] =
+{
+    {
+       OP_OR,
+       0x1234,
+       0x5678,
+       0x1234 | 0x5678
+    },
+    {
+       OP_ORC,
+       0x1234,
+       0x5678,
+       0x1234 | ~0x5678
+    },
+    {
+       OP_XOR,
+       0x1234,
+       0x5678,
+       0x1234 ^ 0x5678
+    },
+    {
+       OP_NAND,
+       0x1234,
+       0x5678,
+       ~(0x1234 & 0x5678)
+    },
+    {
+       OP_NOR,
+       0x1234,
+       0x5678,
+       ~(0x1234 | 0x5678)
+    },
+    {
+       OP_EQV,
+       0x1234,
+       0x5678,
+       ~(0x1234 ^ 0x5678)
+    },
+    {
+       OP_SLW,
+       0x80,
+       16,
+       0x800000
+    },
+    {
+       OP_SLW,
+       0x80,
+       32,
+       0
+    },
+    {
+       OP_SRW,
+       0x800000,
+       16,
+       0x80
+    },
+    {
+       OP_SRW,
+       0x800000,
+       32,
+       0
+    },
+    {
+       OP_SRAW,
+       0x80000000,
+       3,
+       0xf0000000
+    },
+    {
+       OP_SRAW,
+       0x8000,
+       3,
+       0x1000
+    },
+};
+static unsigned int cpu_post_threex_size =
+    sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s);
+
+int cpu_post_test_threex (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
+    {
+       struct cpu_post_threex_s *test = cpu_post_threex_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int reg2 = (reg + 2) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12X(test->cmd, reg2, reg1, reg0),
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -24),
+               ASM_STW(3, stk, 12),
+               ASM_STW(4, stk, 16),
+               ASM_STW(reg0, stk, 8),
+               ASM_STW(reg1, stk, 4),
+               ASM_STW(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 12),
+               ASM_LWZ(reg0, stk, 16),
+               ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
+               ASM_STW(reg2, stk, 12),
+               ASM_LWZ(reg2, stk, 0),
+               ASM_LWZ(reg1, stk, 4),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_LWZ(3, stk, 12),
+               ASM_ADDI(1, stk, 24),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at threex test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at threex test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/two.c b/post/lib_ppc/two.c
new file mode 100644 (file)
index 0000000..cfbac5e
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Binary instructions         instr rD,rA
+ *
+ * Logic instructions:         neg
+ * Arithmetic instructions:    addme, addze, subfme, subfze
+
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_two_s
+{
+    ulong cmd;
+    ulong op;
+    ulong res;
+} cpu_post_two_table[] =
+{
+    {
+       OP_NEG,
+       3,
+       -3
+    },
+    {
+       OP_NEG,
+       5,
+       -5
+    },
+    {
+       OP_ADDME,
+       6,
+       5
+    },
+    {
+       OP_ADDZE,
+       5,
+       5
+    },
+    {
+       OP_SUBFME,
+       6,
+       ~6 - 1
+    },
+    {
+       OP_SUBFZE,
+       5,
+       ~5
+    },
+};
+static unsigned int cpu_post_two_size =
+    sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s);
+
+int cpu_post_test_two (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_two_size && ret == 0; i++)
+    {
+       struct cpu_post_two_s *test = cpu_post_two_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11(test->cmd, reg1, reg0),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11(test->cmd, reg1, reg0) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at two test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at two test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
diff --git a/post/lib_ppc/twox.c b/post/lib_ppc/twox.c
new file mode 100644 (file)
index 0000000..48d9954
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (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>
+
+/*
+ * CPU test
+ * Binary instructions         instr rA,rS
+ *
+ * Logic instructions:         cntlzw
+ * Arithmetic instructions:    extsb, extsh
+
+ * The test contains a pre-built table of instructions, operands and
+ * expected results. For each table entry, the test will cyclically use
+ * different sets of operand registers and result registers.
+ */
+
+#ifdef CONFIG_POST
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CFG_POST_CPU
+
+extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
+extern ulong cpu_post_makecr (long v);
+
+static struct cpu_post_twox_s
+{
+    ulong cmd;
+    ulong op;
+    ulong res;
+} cpu_post_twox_table[] =
+{
+    {
+       OP_EXTSB,
+       3,
+       3
+    },
+    {
+       OP_EXTSB,
+       0xff,
+       -1
+    },
+    {
+       OP_EXTSH,
+       3,
+       3
+    },
+    {
+       OP_EXTSH,
+       0xff,
+       0xff
+    },
+    {
+       OP_EXTSH,
+       0xffff,
+       -1
+    },
+    {
+       OP_CNTLZW,
+       0x000fffff,
+       12
+    },
+};
+static unsigned int cpu_post_twox_size =
+    sizeof (cpu_post_twox_table) / sizeof (struct cpu_post_twox_s);
+
+int cpu_post_test_twox (void)
+{
+    int ret = 0;
+    unsigned int i, reg;
+    int flag = disable_interrupts();
+
+    for (i = 0; i < cpu_post_twox_size && ret == 0; i++)
+    {
+       struct cpu_post_twox_s *test = cpu_post_twox_table + i;
+
+       for (reg = 0; reg < 32 && ret == 0; reg++)
+       {
+           unsigned int reg0 = (reg + 0) % 32;
+           unsigned int reg1 = (reg + 1) % 32;
+           unsigned int stk = reg < 16 ? 31 : 15;
+           unsigned long code[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11X(test->cmd, reg1, reg0),
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           unsigned long codecr[] =
+           {
+               ASM_STW(stk, 1, -4),
+               ASM_ADDI(stk, 1, -16),
+               ASM_STW(3, stk, 8),
+               ASM_STW(reg0, stk, 4),
+               ASM_STW(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 8),
+               ASM_11X(test->cmd, reg1, reg0) | BIT_C,
+               ASM_STW(reg1, stk, 8),
+               ASM_LWZ(reg1, stk, 0),
+               ASM_LWZ(reg0, stk, 4),
+               ASM_LWZ(3, stk, 8),
+               ASM_ADDI(1, stk, 16),
+               ASM_LWZ(stk, 1, -4),
+               ASM_BLR,
+           };
+           ulong res;
+           ulong cr;
+
+           if (ret == 0)
+           {
+               cr = 0;
+               cpu_post_exec_21 (code, & cr, & res, test->op);
+
+               ret = res == test->res && cr == 0 ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at twox test %d !\n", i);
+               }
+           }
+
+           if (ret == 0)
+           {
+               cpu_post_exec_21 (codecr, & cr, & res, test->op);
+
+               ret = res == test->res &&
+                     (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
+
+               if (ret != 0)
+               {
+                   post_log ("Error at twox test %d !\n", i);
+               }
+           }
+       }
+    }
+
+    if (flag)
+       enable_interrupts();
+
+    return ret;
+}
+
+#endif
+#endif
index e1066da6bd1e9b5ec7237e7f3e2eeb2f7346e2d8..ac419908605578ce66322fe5ea26ba08303a9073 100644 (file)
@@ -430,6 +430,7 @@ unsigned long post_time_ms (unsigned long base)
 #ifdef CONFIG_PPC
        return (unsigned long)get_ticks () / (get_tbclk () / CFG_HZ) - base;
 #else
+#warning "Not implemented yet"
        return 0; /* Not implemented yet */
 #endif
 }