summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Denk <wd@pollux.denx.de>2007-03-06 18:08:43 +0100
committerWolfgang Denk <wd@denx.de>2007-03-06 18:08:43 +0100
commitad5bb451ade552c44bef9119d907929ebc2c126f (patch)
treedf979d3c6385a161cd6df6b6f903ed7eaad31948
parenta5284efd125967675b2e9c6ef7b95832268ad360 (diff)
downloadu-boot-ad5bb451ade552c44bef9119d907929ebc2c126f.tar.gz
u-boot-ad5bb451ade552c44bef9119d907929ebc2c126f.tar.bz2
u-boot-ad5bb451ade552c44bef9119d907929ebc2c126f.zip
Restructure POST directory to support of other CPUs, boards, etc.
-rw-r--r--Makefile13
-rw-r--r--cpu/ppc4xx/44x_spd_ddr2.c8
-rw-r--r--cpu/ppc4xx/start.S62
-rw-r--r--post/Makefile8
-rw-r--r--post/board/lwmon/Makefile29
-rw-r--r--post/board/lwmon/sysmon.c331
-rw-r--r--post/board/netta/Makefile29
-rw-r--r--post/board/netta/codec.c48
-rw-r--r--post/board/netta/dsp.c48
-rw-r--r--post/cpu/mpc8xx/Makefile29
-rw-r--r--post/cpu/mpc8xx/cache_8xx.S495
-rw-r--r--post/cpu/mpc8xx/ether.c631
-rw-r--r--post/cpu/mpc8xx/spr.c152
-rw-r--r--post/cpu/mpc8xx/uart.c560
-rw-r--r--post/cpu/mpc8xx/usb.c269
-rw-r--r--post/cpu/mpc8xx/watchdog.c78
-rw-r--r--post/drivers/Makefile31
-rw-r--r--post/drivers/cache.c81
-rw-r--r--post/drivers/i2c.c94
-rw-r--r--post/drivers/memory.c483
-rw-r--r--post/drivers/rtc.c183
-rw-r--r--post/lib_ppc/Makefile32
-rw-r--r--post/lib_ppc/andi.c123
-rw-r--r--post/lib_ppc/asm.S346
-rw-r--r--post/lib_ppc/b.c197
-rw-r--r--post/lib_ppc/cmp.c133
-rw-r--r--post/lib_ppc/cmpi.c133
-rw-r--r--post/lib_ppc/complex.c126
-rw-r--r--post/lib_ppc/cpu.c139
-rw-r--r--post/lib_ppc/cpu_asm.h224
-rw-r--r--post/lib_ppc/cr.c356
-rw-r--r--post/lib_ppc/load.c255
-rw-r--r--post/lib_ppc/multi.c81
-rw-r--r--post/lib_ppc/rlwimi.c162
-rw-r--r--post/lib_ppc/rlwinm.c155
-rw-r--r--post/lib_ppc/rlwnm.c165
-rw-r--r--post/lib_ppc/srawi.c156
-rw-r--r--post/lib_ppc/store.c235
-rw-r--r--post/lib_ppc/string.c106
-rw-r--r--post/lib_ppc/three.c259
-rw-r--r--post/lib_ppc/threei.c137
-rw-r--r--post/lib_ppc/threex.c229
-rw-r--r--post/lib_ppc/two.c176
-rw-r--r--post/lib_ppc/twox.c176
-rw-r--r--post/post.c1
45 files changed, 7719 insertions, 45 deletions
diff --git a/Makefile b/Makefile
index 3809de0a41..fec114ff6b 100644
--- 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)
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 35b23152f3..3ab050f9f7 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -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;
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 24b30dfe71..6b2c170335 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -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 */
diff --git a/post/Makefile b/post/Makefile
index 228bafc6a7..f32af95162 100644
--- a/post/Makefile
+++ b/post/Makefile
@@ -22,14 +22,10 @@
#
-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
index 0000000000..899b0dc1f3
--- /dev/null
+++ b/post/board/lwmon/Makefile
@@ -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
index 0000000000..f61d598244
--- /dev/null
+++ b/post/board/lwmon/sysmon.c
@@ -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
index 0000000000..60c7790ace
--- /dev/null
+++ b/post/board/netta/Makefile
@@ -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
index 0000000000..e8817520fc
--- /dev/null
+++ b/post/board/netta/codec.c
@@ -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
index 0000000000..63531a2a4c
--- /dev/null
+++ b/post/board/netta/dsp.c
@@ -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
index 0000000000..9dd3f0fce9
--- /dev/null
+++ b/post/cpu/mpc8xx/Makefile
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2002-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+LIB = 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
index 0000000000..2d41b5566a
--- /dev/null
+++ b/post/cpu/mpc8xx/cache_8xx.S
@@ -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
index 0000000000..8c87b5927e
--- /dev/null
+++ b/post/cpu/mpc8xx/ether.c
@@ -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
index 0000000000..330b977f1a
--- /dev/null
+++ b/post/cpu/mpc8xx/spr.c
@@ -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
index 0000000000..fd97e3899e
--- /dev/null
+++ b/post/cpu/mpc8xx/uart.c
@@ -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
index 0000000000..0c74cfa5da
--- /dev/null
+++ b/post/cpu/mpc8xx/usb.c
@@ -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
index 0000000000..48c4282e1d
--- /dev/null
+++ b/post/cpu/mpc8xx/watchdog.c
@@ -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
index 0000000000..068fa98b14
--- /dev/null
+++ b/post/drivers/Makefile
@@ -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
index 0000000000..501465c06a
--- /dev/null
+++ b/post/drivers/cache.c
@@ -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
index 0000000000..1b2e64471b
--- /dev/null
+++ b/post/drivers/i2c.c
@@ -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
index 0000000000..a2c088bad8
--- /dev/null
+++ b/post/drivers/memory.c
@@ -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
index 0000000000..7d4f9b88ee
--- /dev/null
+++ b/post/drivers/rtc.c
@@ -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
index 0000000000..14354a0323
--- /dev/null
+++ b/post/lib_ppc/Makefile
@@ -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
index 0000000000..7ddf2ab2f3
--- /dev/null
+++ b/post/lib_ppc/andi.c
@@ -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
index 0000000000..a0815a43a7
--- /dev/null
+++ b/post/lib_ppc/asm.S
@@ -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
index 0000000000..b4b17c8ff0
--- /dev/null
+++ b/post/lib_ppc/b.c
@@ -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
index 0000000000..789a24cb7f
--- /dev/null
+++ b/post/lib_ppc/cmp.c
@@ -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
index 0000000000..e0c2aaff82
--- /dev/null
+++ b/post/lib_ppc/cmpi.c
@@ -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
index 0000000000..033584bec0
--- /dev/null
+++ b/post/lib_ppc/complex.c
@@ -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
index 0000000000..1f2ded2bf2
--- /dev/null
+++ b/post/lib_ppc/cpu.c
@@ -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
index 0000000000..1cbaf4121f
--- /dev/null
+++ b/post/lib_ppc/cpu_asm.h
@@ -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
index 0000000000..da6ef3745d
--- /dev/null
+++ b/post/lib_ppc/cr.c
@@ -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
index 0000000000..393c56830d
--- /dev/null
+++ b/post/lib_ppc/load.c
@@ -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
index 0000000000..872438478f
--- /dev/null
+++ b/post/lib_ppc/multi.c
@@ -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
index 0000000000..f65f79a8e8
--- /dev/null
+++ b/post/lib_ppc/rlwimi.c
@@ -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
index 0000000000..e240c41b1a
--- /dev/null
+++ b/post/lib_ppc/rlwinm.c
@@ -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
index 0000000000..523cf4da59
--- /dev/null
+++ b/post/lib_ppc/rlwnm.c
@@ -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
index 0000000000..91c82c915f
--- /dev/null
+++ b/post/lib_ppc/srawi.c
@@ -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
index 0000000000..f495bf2aab
--- /dev/null
+++ b/post/lib_ppc/store.c
@@ -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
index 0000000000..bd83bd1362
--- /dev/null
+++ b/post/lib_ppc/string.c
@@ -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
index 0000000000..c2d7476047
--- /dev/null
+++ b/post/lib_ppc/three.c
@@ -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
index 0000000000..79f01789c0
--- /dev/null
+++ b/post/lib_ppc/threei.c
@@ -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
index 0000000000..2c72063848
--- /dev/null
+++ b/post/lib_ppc/threex.c
@@ -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
index 0000000000..cfbac5e620
--- /dev/null
+++ b/post/lib_ppc/two.c
@@ -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
index 0000000000..48d9954ca4
--- /dev/null
+++ b/post/lib_ppc/twox.c
@@ -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
diff --git a/post/post.c b/post/post.c
index e1066da6bd..ac41990860 100644
--- a/post/post.c
+++ b/post/post.c
@@ -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
}