diff options
Diffstat (limited to 'u-boot/post')
74 files changed, 12947 insertions, 0 deletions
diff --git a/u-boot/post/Makefile b/u-boot/post/Makefile new file mode 100644 index 0000000..200e2f1 --- /dev/null +++ b/u-boot/post/Makefile @@ -0,0 +1,75 @@ +# +# (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 +# + +include $(TOPDIR)/config.mk +include $(OBJTREE)/include/autoconf.mk + +LIB = libpost.o +GPLIB-$(CONFIG_HAS_POST) += libgenpost.o +COBJS-$(CONFIG_HAS_POST) += post.o +COBJS-$(CONFIG_POST_STD_LIST) += tests.o + +SPLIB-$(CONFIG_HAS_POST) = drivers/libpostdrivers.o +SPLIB-$(CONFIG_HAS_POST) += $(shell if [ -d lib_$(ARCH) ]; then echo \ + "lib_$(ARCH)/libpost$(ARCH).o"; fi) +SPLIB-$(CONFIG_HAS_POST) += $(shell if [ -d lib_$(ARCH)/fpu ]; then echo \ + "lib_$(ARCH)/fpu/libpost$(ARCH)fpu.o"; fi) +SPLIB-$(CONFIG_HAS_POST) += $(shell if [ -d cpu/$(CPU) ]; then echo \ + "cpu/$(CPU)/libpost$(CPU).o"; fi) +SPLIB-$(CONFIG_HAS_POST) += $(shell if [ -d board/$(BOARD) ]; then echo \ + "board/$(BOARD)/libpost$(BOARD).o"; fi) + +GPLIB := $(addprefix $(obj),$(GPLIB-y)) +SPLIB := $(addprefix $(obj),$(SPLIB-y)) +COBJS := $(COBJS-y) +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +LIB := $(obj)$(LIB) + +all: $(LIB) + +postdeps: + @for lib in $(SPLIB-y) ; do \ + $(MAKE) -C `dirname $$lib` all ; \ + done + +# generic POST library +$(GPLIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +# specific POST libraries +$(SPLIB): $(obj).depend postdeps + $(MAKE) -C $(dir $(subst $(obj),,$@)) + +# the POST lib archive +$(LIB): $(GPLIB) $(SPLIB) + $(call cmd_link_o_target, $^) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/post/board/lwmon/Makefile b/u-boot/post/board/lwmon/Makefile new file mode 100644 index 0000000..83026c0 --- /dev/null +++ b/u-boot/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 +# +include $(OBJTREE)/include/autoconf.mk + +LIB = libpostlwmon.o + +COBJS-$(CONFIG_HAS_POST) += sysmon.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/board/lwmon/sysmon.c b/u-boot/post/board/lwmon/sysmon.c new file mode 100644 index 0000000..fc828b2 --- /dev/null +++ b/u-boot/post/board/lwmon/sysmon.c @@ -0,0 +1,313 @@ +/* + * (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> + +/* + * 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 & CONFIG_SYS_POST_SYSMON + +DECLARE_GLOBAL_DATA_PTR; + +static int sysmon_temp_invalid = 0; + +/* #define DEBUG */ + +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 = + {CONFIG_SYS_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read}; +static sysmon_t sysmon_lm87_sgn = + {CONFIG_SYS_I2C_SYSMON_ADDR, sysmon_lm87_init, sysmon_i2c_read_sgn}; +static sysmon_t sysmon_pic = + {CONFIG_SYS_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) +{ + /* Do nothing for now, sysmon_reloc() is required by the sysmon post */ +} + +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 & CONFIG_SYS_POST_SYSMON */ diff --git a/u-boot/post/board/lwmon5/Makefile b/u-boot/post/board/lwmon5/Makefile new file mode 100644 index 0000000..b199688 --- /dev/null +++ b/u-boot/post/board/lwmon5/Makefile @@ -0,0 +1,29 @@ +# +# (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com +# +# Developed for DENX Software Engineering GmbH +# +# 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 $(OBJTREE)/include/autoconf.mk + +LIB = libpostlwmon5.o + +COBJS-$(CONFIG_HAS_POST) += sysmon.o watchdog.o dspic.o fpga.o dsp.o gdc.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/board/lwmon5/dsp.c b/u-boot/post/board/lwmon5/dsp.c new file mode 100644 index 0000000..913cd97 --- /dev/null +++ b/u-boot/post/board/lwmon5/dsp.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_DSP +#include <asm/io.h> + +/* This test verifies DSP status bits in FPGA */ + +DECLARE_GLOBAL_DATA_PTR; + +#define DSP_STATUS_REG 0xC4000008 +#define FPGA_STATUS_REG 0xC400000C + +int dsp_post_test(int flags) +{ + uint old_value; + uint read_value; + int ret; + + /* momorize fpga status */ + old_value = in_be32((void *)FPGA_STATUS_REG); + /* enable outputs */ + out_be32((void *)FPGA_STATUS_REG, 0x30); + + /* generate sync signal */ + out_be32((void *)DSP_STATUS_REG, 0x300); + udelay(5); + out_be32((void *)DSP_STATUS_REG, 0); + udelay(500); + + /* read status */ + ret = 0; + read_value = in_be32((void *)DSP_STATUS_REG) & 0x3; + if (read_value != 0x03) { + post_log("\nDSP status read %08X\n", read_value); + ret = 1; + } + + /* restore fpga status */ + out_be32((void *)FPGA_STATUS_REG, old_value); + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_DSP */ diff --git a/u-boot/post/board/lwmon5/dspic.c b/u-boot/post/board/lwmon5/dspic.c new file mode 100644 index 0000000..8616739 --- /dev/null +++ b/u-boot/post/board/lwmon5/dspic.c @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* There are two tests for dsPIC currently implemented: + * 1. dsPIC ready test. Done in board_early_init_f(). Only result verified here. + * 2. dsPIC POST result test. This test gets dsPIC POST codes and version. + */ + +#include <post.h> + +#include <i2c.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define DSPIC_POST_ERROR_REG 0x800 +#define DSPIC_SYS_ERROR_REG 0x802 +#define DSPIC_SYS_VERSION_REG 0x804 +#define DSPIC_FW_VERSION_REG 0x808 + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1 + +/* Verify that dsPIC ready test done early at hw init passed ok */ +int dspic_init_post_test(int flags) +{ + if (in_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR) & + CONFIG_SYS_DSPIC_TEST_MASK) { + post_log("dsPIC init test failed\n"); + return 1; + } + + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC1 */ + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC2 +/* Read a register from the dsPIC. */ +int dspic_read(ushort reg, ushort *data) +{ + uchar buf[sizeof(*data)]; + int rval; + + if (i2c_read(CONFIG_SYS_I2C_DSPIC_IO_ADDR, reg, 2, buf, 2)) + return -1; + rval = i2c_read(CONFIG_SYS_I2C_DSPIC_IO_ADDR, reg, sizeof(reg), + buf, sizeof(*data)); + *data = (buf[0] << 8) | buf[1]; + + return rval; +} + +/* Verify error codes regs, display version */ +int dspic_post_test(int flags) +{ + ushort data; + int ret = 0; + + post_log("\n"); + + /* read dspic FW-Version */ + if (dspic_read(DSPIC_FW_VERSION_REG, &data)) { + post_log("dsPIC: failed read FW-Version\n"); + ret = 1; + } else { + post_log("dsPIC FW-Version: %u.%u\n", + (data >> 8) & 0xFF, data & 0xFF); + } + + /* read dspic SYS-Version */ + if (dspic_read(DSPIC_SYS_VERSION_REG, &data)) { + post_log("dsPIC: failed read version\n"); + ret = 1; + } else { + post_log("dsPIC SYS-Version: %u.%u\n", + (data >> 8) & 0xFF, data & 0xFF); + } + + /* read dspic POST error code */ + if (dspic_read(DSPIC_POST_ERROR_REG, &data)) { + post_log("dsPIC: failed read POST code\n"); + ret = 1; + } else { + post_log("dsPIC POST-ERROR code: 0x%04X\n", data); + } + + /* read dspic SYS error code */ + if ((data = dspic_read(DSPIC_SYS_ERROR_REG, &data))) { + post_log("dsPIC: failed read system error\n"); + ret = 1; + } else { + post_log("dsPIC SYS-ERROR code: 0x%04X\n", data); + } + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC2 */ diff --git a/u-boot/post/board/lwmon5/fpga.c b/u-boot/post/board/lwmon5/fpga.c new file mode 100644 index 0000000..501369b --- /dev/null +++ b/u-boot/post/board/lwmon5/fpga.c @@ -0,0 +1,360 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* This test performs testing of FPGA SCRATCH register, + * gets FPGA version and run get_ram_size() on FPGA memory + */ + +#include <post.h> +#include <watchdog.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define FPGA_SCRATCH_REG 0xC4000050 +#define FPGA_VERSION_REG 0xC4000040 +#define FPGA_RAM_START 0xC4200000 +#define FPGA_RAM_END 0xC4203FFF +#define FPGA_STAT 0xC400000C +#define FPGA_BUFFER 0x00800000 +#define FPGA_RAM_SIZE (FPGA_RAM_END - FPGA_RAM_START + 1) + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC3 + +const static unsigned long pattern[] = { + 0xffffffff, + 0xaaaaaaaa, + 0xcccccccc, + 0xf0f0f0f0, + 0xff00ff00, + 0xffff0000, + 0x0000ffff, + 0x00ff00ff, + 0x0f0f0f0f, + 0x33333333, + 0x55555555, + 0x00000000, +}; + +const static unsigned long otherpattern = 0x01234567; + +static int one_scratch_test(uint value) +{ + uint read_value; + int ret = 0; + + out_be32((void *)FPGA_SCRATCH_REG, value); + /* read other location (protect against data lines capacity) */ + ret = in_be16((void *)FPGA_VERSION_REG); + /* verify test pattern */ + read_value = in_be32((void *)FPGA_SCRATCH_REG); + if (read_value != value) { + post_log("FPGA SCRATCH test failed write %08X, read %08X\n", + value, read_value); + ret = -1; + } + + return ret; +} + +static int fpga_post_test1(ulong *start, ulong size, ulong val) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = val; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != val) { + post_log("FPGA 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 fpga_post_test2(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + 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); i++) { + readback = mem[i]; + if (readback != 1 << (i % 32)) { + post_log("FPGA 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 fpga_post_test3(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = i; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != i) { + post_log("FPGA 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 fpga_post_test4(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = ~i; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != ~i) { + post_log("FPGA Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, ~i, readback); + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + return ret; +} + +/* FPGA Memory-pattern-test */ +static int fpga_mem_test(void) +{ + int ret = 0; + ulong* start = (ulong *)FPGA_RAM_START; + ulong size = FPGA_RAM_SIZE; + + if (ret == 0) + ret = fpga_post_test1(start, size, 0x00000000); + + if (ret == 0) + ret = fpga_post_test1(start, size, 0xffffffff); + + if (ret == 0) + ret = fpga_post_test1(start, size, 0x55555555); + + if (ret == 0) + ret = fpga_post_test1(start, size, 0xaaaaaaaa); + + WATCHDOG_RESET(); + + if (ret == 0) + ret = fpga_post_test2(start, size); + + if (ret == 0) + ret = fpga_post_test3(start, size); + + if (ret == 0) + ret = fpga_post_test4(start, size); + + return ret; +} + +/* Verify FPGA addresslines */ +static int fpga_post_addrline(ulong *address, ulong *base, ulong size) +{ + unsigned long *target; + unsigned long *end; + unsigned long readback; + unsigned long xor; + int ret = 0; + + end = (ulong *)((ulong)base + size); + xor = 0; + + for (xor = sizeof(ulong); xor > 0; xor <<= 1) { + target = (ulong*)((ulong)address ^ xor); + if ((target >= base) && (target < end)) { + *address = ~*target; + readback = *target; + + if (readback == *address) { + post_log("Memory (address line) error at %08x" + "XOR value %08x !\n", + address, target, xor); + ret = -1; + break; + } + } + } + + return ret; +} + +/* Verify FPGA addresslines */ +static int fpga_post_dataline(ulong *address) +{ + unsigned long temp32 = 0; + int i = 0; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(pattern); i++) { + *address = pattern[i]; + /* + * Put a different pattern on the data lines: otherwise they + * may float long enough to read back what we wrote. + */ + *(address + 1) = otherpattern; + temp32 = *address; + + if (temp32 != pattern[i]){ + post_log("Memory (date line) error at %08x, " + "wrote %08x, read %08x !\n", + address, pattern[i], temp32); + ret = 1; + } + } + + return ret; +} + +/* Verify FPGA, get version & memory size */ +int fpga_post_test(int flags) +{ + uint old_value; + uint version; + uint read_value; + int ret = 0; + + post_log("\n"); + old_value = in_be32((void *)FPGA_SCRATCH_REG); + + if (one_scratch_test(0x55555555)) + ret = 1; + if (one_scratch_test(0xAAAAAAAA)) + ret = 1; + + out_be32((void *)FPGA_SCRATCH_REG, old_value); + + version = in_be32((void *)FPGA_VERSION_REG); + post_log("FPGA version %u.%u\n", + (version >> 8) & 0xFF, version & 0xFF); + + /* Enable write to FPGA RAM */ + out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) | 0x1000); + + /* get RAM size */ + read_value = get_ram_size((void *)CONFIG_SYS_FPGA_BASE_1, FPGA_RAM_SIZE); + post_log("FPGA RAM size %d bytes\n", read_value); + WATCHDOG_RESET(); + + /* copy fpga memory to DDR2 RAM*/ + memcpy((void *)FPGA_BUFFER,(void *)FPGA_RAM_START, FPGA_RAM_SIZE); + WATCHDOG_RESET(); + + /* Test datalines */ + if (fpga_post_dataline((ulong *)FPGA_RAM_START)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + + /* Test addresslines */ + if (fpga_post_addrline((ulong *)FPGA_RAM_START, + (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + if (fpga_post_addrline((ulong *)FPGA_RAM_END - sizeof(long), + (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + + /* Memory Pattern Test */ + if (fpga_mem_test()) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + + /* restore memory */ + memcpy((void *)FPGA_RAM_START,(void *)FPGA_BUFFER, FPGA_RAM_SIZE); + WATCHDOG_RESET(); + +out: + /* Disable write to RAM */ + out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) & 0xEFFF); + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC3 */ diff --git a/u-boot/post/board/lwmon5/gdc.c b/u-boot/post/board/lwmon5/gdc.c new file mode 100644 index 0000000..719194b --- /dev/null +++ b/u-boot/post/board/lwmon5/gdc.c @@ -0,0 +1,380 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* This test attempts to verify board GDC. A scratch register tested, then + * simple memory test (get_ram_size()) run over GDC memory. + */ + +#include <post.h> +#include <watchdog.h> +#include <asm/io.h> +#include <video.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define GDC_SCRATCH_REG 0xC1FF8044 +#define GDC_VERSION_REG 0xC1FF8084 +#define GDC_HOST_BASE 0xC1FC0000 +#define GDC_RAM_START 0xC0000000 +#define GDC_RAM_END (GDC_HOST_BASE - 1) +#define GDC_RAM_SIZE (GDC_RAM_END - GDC_RAM_START) + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC4 + +const static unsigned long pattern[] = { + 0xffffffff, + 0xaaaaaaaa, + 0xcccccccc, + 0xf0f0f0f0, + 0xff00ff00, + 0xffff0000, + 0x0000ffff, + 0x00ff00ff, + 0x0f0f0f0f, + 0x33333333, + 0x55555555, + 0x00000000 +}; + +const static unsigned long otherpattern = 0x01234567; + +/* test write/read og a given LIME Register */ +static int gdc_test_reg_one(uint value) +{ + int ret; + uint read_value; + + /* write test pattern */ + out_be32((void *)GDC_SCRATCH_REG, value); + /* read other location (protect against data lines capacity) */ + ret = in_be32((void *)GDC_RAM_START); + /* verify test pattern */ + read_value = in_be32((void *)GDC_SCRATCH_REG); + if (read_value != value) { + post_log("GDC SCRATCH test failed write %08X, read %08X\n", + value, read_value); + } + + return (read_value != value); +} + +/* test with a given static 32 bit pattern in a given memory addressrange */ +static int gdc_post_test1(ulong *start, ulong size, ulong val) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = val; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != val) { + post_log("GDC Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, val, readback); + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + return ret; +} + +/* test with dynamic 32 bit pattern in a given memory addressrange */ +static int gdc_post_test2(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + 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); i++) { + readback = mem[i]; + if (readback != 1 << (i % 32)) { + post_log("GDC 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; +} + +/* test with dynamic 32 bit pattern in a given memory addressrange */ +static int gdc_post_test3(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = i; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != i) { + post_log("GDC Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, i, readback); + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + return ret; +} + +/* test with dynamic 32 bit pattern in a given memory addressrange */ +static int gdc_post_test4(ulong *start, ulong size) +{ + int ret = 0; + ulong i = 0; + ulong *mem = start; + ulong readback; + + for (i = 0; i < size / sizeof(ulong); i++) { + mem[i] = ~i; + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + for (i = 0; i < size / sizeof(ulong); i++) { + readback = mem[i]; + if (readback != ~i) { + post_log("GDC Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, ~i, readback); + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET(); + } + + return ret; +} + +/* do some patterntests in a given addressrange */ +int gdc_mem_test(ulong *start, ulong size) +{ + int ret = 0; + + /* + * check addressrange and do different static and dynamic + * pattern tests with it. + */ + if (((void *)start) + size <= (void *)GDC_RAM_END) { + if (ret == 0) + ret = gdc_post_test1(start, size, 0x00000000); + + if (ret == 0) + ret = gdc_post_test1(start, size, 0xffffffff); + + if (ret == 0) + ret = gdc_post_test1(start, size, 0x55555555); + + if (ret == 0) + ret = gdc_post_test1(start, size, 0xaaaaaaaa); + + if (ret == 0) + ret = gdc_post_test2(start, size); + + if (ret == 0) + ret = gdc_post_test3(start, size); + + if (ret == 0) + ret = gdc_post_test4(start, size); + } + + return ret; +} + +/* test function of gdc memory addresslines*/ +static int gdc_post_addrline(ulong *address, ulong *base, ulong size) +{ + ulong *target; + ulong *end; + ulong readback = 0; + ulong xor = 0; + int ret = 0; + + end = (ulong *)((ulong)base + size); + + for (xor = sizeof(long); xor > 0; xor <<= 1) { + target = (ulong *)((ulong)address ^ xor); + if ((target >= base) && (target < end)) { + *address = ~*target; + readback = *target; + } + + if (readback == *address) { + post_log("GDC Memory (address line) error at %08x" + "XOR value %08x !\n", + address, target , xor); + ret = -1; + break; + } + } + + return ret; +} + +static int gdc_post_dataline(ulong *address) +{ + unsigned long temp32 = 0; + int i = 0; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(pattern); i++) { + *address = pattern[i]; + /* + * Put a different pattern on the data lines: otherwise they + * may float long enough to read back what we wrote. + */ + *(address + 1) = otherpattern; + temp32 = *address; + + if (temp32 != pattern[i]){ + post_log("GDC Memory (date line) error at %08x, " + "wrote %08x, read %08x !\n", + address, pattern[i], temp32); + ret = 1; + } + } + + return ret; +} + +/* Verify GDC, get memory size, verify GDC memory */ +int gdc_post_test(int flags) +{ + uint old_value; + int i = 0; + int ret = 0; + + post_log("\n"); + old_value = in_be32((void *)GDC_SCRATCH_REG); + + /* + * GPIOC2 register behaviour: the LIME graphics processor has a + * maximum of 5 GPIO ports that can be used in this hardware + * configuration. Thus only the bits for these 5 GPIOs can be + * activated in the GPIOC2 register. All other bits will always be + * read as zero. + */ + if (gdc_test_reg_one(0x00150015)) + ret = 1; + if (gdc_test_reg_one(0x000A000A)) + ret = 1; + + out_be32((void *)GDC_SCRATCH_REG, old_value); + + old_value = in_be32((void *)GDC_VERSION_REG); + post_log("GDC chip version %u.%u, year %04X\n", + (old_value >> 8) & 0xFF, old_value & 0xFF, + (old_value >> 16) & 0xFFFF); + + old_value = get_ram_size((void *)GDC_RAM_START, + 0x02000000); + + debug("GDC RAM size (ist): %d bytes\n", old_value); + debug("GDC RAM size (soll): %d bytes\n", GDC_RAM_SIZE); + post_log("GDC RAM size: %d bytes\n", old_value); + + /* Test SDRAM datalines */ + if (gdc_post_dataline((ulong *)GDC_RAM_START)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + + /* Test SDRAM adresslines */ + if (gdc_post_addrline((ulong *)GDC_RAM_START, + (ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + if (gdc_post_addrline((ulong *)GDC_RAM_END - sizeof(long), + (ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { + ret = 1; + goto out; + } + WATCHDOG_RESET(); + + /* memory pattern test */ + debug("GDC Memory test (flags %8x:%8x)\n", flags, + POST_SLOWTEST | POST_MANUAL); + + if (flags & POST_MANUAL) { + debug("Full memory test\n"); + if (gdc_mem_test((ulong *)GDC_RAM_START, GDC_RAM_SIZE)) { + ret = 1; + goto out; + } + /* load splashscreen again */ + } else { + debug("smart memory test\n"); + for (i = 0; i < (GDC_RAM_SIZE >> 20) && ret == 0; i++) { + if (ret == 0) + ret = gdc_mem_test((ulong *)(GDC_RAM_START + + (i << 20)), + 0x800); + if (ret == 0) + ret = gdc_mem_test((ulong *)(GDC_RAM_START + + (i << 20) + 0xff800), + 0x800); + } + } + WATCHDOG_RESET(); + +out: + return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC4 */ diff --git a/u-boot/post/board/lwmon5/sysmon.c b/u-boot/post/board/lwmon5/sysmon.c new file mode 100644 index 0000000..4a78240 --- /dev/null +++ b/u-boot/post/board/lwmon5/sysmon.c @@ -0,0 +1,293 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* + * SYSMON test + * + * This test performs the system hardware monitoring. + * The test passes when all the following voltages and temperatures + * are within allowed ranges: + * + * Temperature -40 .. +90 C + * +5V +4.50 .. +5.50 V + * +5V standby +3.50 .. +5.50 V + * + * LCD backlight is not enabled if temperature values are not within + * allowed ranges (-30 .. + 80). The brightness of backlite can be + * controlled by setting "brightness" enviroment variable. Default value is 50% + * + * See the list of all parameters in the sysmon_table below + */ + +#include <post.h> +#include <watchdog.h> +#include <i2c.h> + +#if defined(CONFIG_VIDEO) +#include <mb862xx.h> +#endif + +#if CONFIG_POST & CONFIG_SYS_POST_SYSMON + +DECLARE_GLOBAL_DATA_PTR; + +/* from dspic.c */ +extern int dspic_read(ushort reg, ushort *data); + +#define REG_TEMPERATURE 0x12BC +#define REG_VOLTAGE_5V 0x12CA +#define REG_VOLTAGE_5V_STANDBY 0x12C6 + +#define TEMPERATURE_MIN (-40) /* degr. C */ +#define TEMPERATURE_MAX (+90) /* degr. C */ +#define TEMPERATURE_DISPLAY_MIN (-35) /* degr. C */ +#define TEMPERATURE_DISPLAY_MAX (+85) /* degr. C */ + +#define VOLTAGE_5V_MIN (+4500) /* mV */ +#define VOLTAGE_5V_MAX (+5500) /* mV */ + +#define VOLTAGE_5V_STANDBY_MIN (+3500) /* mV */ +#define VOLTAGE_5V_STANDBY_MAX (+5500) /* mV */ + +typedef struct sysmon_s sysmon_t; +typedef struct sysmon_table_s sysmon_table_t; + +static void sysmon_dspic_init(sysmon_t *this); +static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val); +static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr, int *val); +static void sysmon_backlight_disable(sysmon_table_t *this); + +struct sysmon_s { + uchar chip; + void (*init)(sysmon_t *); + int (*read)(sysmon_t *, uint, int *); +}; + +static sysmon_t sysmon_dspic = { + CONFIG_SYS_I2C_DSPIC_IO_ADDR, + sysmon_dspic_init, + sysmon_dspic_read +}; + +static sysmon_t sysmon_dspic_sgn = { + CONFIG_SYS_I2C_DSPIC_IO_ADDR, + sysmon_dspic_init, + sysmon_dspic_read_sgn +}; + +static sysmon_t *sysmon_list[] = { + &sysmon_dspic, + 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[] = { + { + "Temperature", " C", &sysmon_dspic, NULL, sysmon_backlight_disable, + 1, 1, -32768, 32767, 0xFFFF, + 0x8000 + TEMPERATURE_MIN, 0x8000 + TEMPERATURE_MAX, 0, + 0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0, + REG_TEMPERATURE, + }, + + { + "+ 5 V", "V", &sysmon_dspic, NULL, NULL, + 100, 1000, -0x8000, 0x7FFF, 0xFFFF, + 0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0, + 0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0, + REG_VOLTAGE_5V, + }, + + { + "+ 5 V standby", "V", &sysmon_dspic, NULL, NULL, + 100, 1000, -0x8000, 0x7FFF, 0xFFFF, + 0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0, + 0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0, + REG_VOLTAGE_5V_STANDBY, + }, + + { + "Temperature", "°C", &sysmon_dspic_sgn, NULL, sysmon_backlight_disable, + 1, 1, -32768, 32767, 0xFFFF, + 0x8000 + TEMPERATURE_MIN, 0x8000 + TEMPERATURE_MAX, 0, + 0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0, + REG_TEMPERATURE, + }, +}; + +int sysmon_init_f(void) +{ + sysmon_t **l; + + for (l = sysmon_list; *l; l++) + (*l)->init(*l); + + return 0; +} + +void sysmon_reloc(void) +{ + /* Do nothing for now, sysmon_reloc() is required by the sysmon post */ +} + +static char *sysmon_unit_value(sysmon_table_t *s, uint val) +{ + static char buf[32]; + char *p, sign; + int decimal, frac; + int unit_val; + + unit_val = s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask; + + 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); + + decimal = s->unit_precision; + + if (decimal != 1) + *p++ = '.'; + for (decimal /= 10; decimal != 0; decimal /= 10) + *p++ = '0' + (frac / decimal) % 10; + strcpy(p, s->unit_name); + + return buf; +} + +static void sysmon_dspic_init(sysmon_t *this) +{ +} + +static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val) +{ + ushort data; + + if (dspic_read(addr, &data) == 0){ + /* To fit into the table range we should add 0x8000 */ + *val = data + 0x8000; + return 0; + } + + return -1; +} + +static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr, int *val) +{ + ushort data; + + if (dspic_read(addr, &data) == 0){ + /* To fit into the table range we should add 0x8000 */ + *val = (signed short)data + 0x8000; + return 0; + } + + return -1; +} + +static void sysmon_backlight_disable(sysmon_table_t *this) +{ +#if defined(CONFIG_VIDEO) + board_backlight_switch(this->val_valid_alt); +#endif +} + +int sysmon_post_test(int flags) +{ + int res = 0; + sysmon_table_t * t; + int val; + + for (t = sysmon_table; t < sysmon_table + ARRAY_SIZE(sysmon_table); t++) { + t->val_valid = 1; + if (t->exec_before) + t->exec_before(t); + + if (t->sysmon->read(t->sysmon, t->addr, &val) != 0) { + t->val_valid = 0; + t->val_valid_alt = 0; + post_log(": read failed\n"); + res = 1; + break; + } + + if (t->val_valid != 0) { + 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; + } + + if (t->exec_after) + t->exec_after(t); + + if ((!t->val_valid) || (flags)) { + post_log("\n\t%-17s = %-10s ", t->name, sysmon_unit_value(t, val)); + post_log("allowed range"); + post_log(" %-8s ..", sysmon_unit_value(t, t->val_min)); + post_log(" %-8s", sysmon_unit_value(t, t->val_max)); + post_log(" %s", t->val_valid ? "OK" : "FAIL"); + } + + if (!t->val_valid) { + res = 1; + break; + } + } + post_log("\n"); + + return res; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_SYSMON */ diff --git a/u-boot/post/board/lwmon5/watchdog.c b/u-boot/post/board/lwmon5/watchdog.c new file mode 100644 index 0000000..4e5ed0d --- /dev/null +++ b/u-boot/post/board/lwmon5/watchdog.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* This test verifies if the reason of last reset was an abnormal voltage + * condition, than it performs watchdog test, measuing time required to + * trigger watchdog reset. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +#include <watchdog.h> +#include <asm/ppc4xx-gpio.h> +#include <asm/io.h> + +static uint watchdog_magic_read(void) +{ + return in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & + CONFIG_SYS_WATCHDOG_MAGIC_MASK; +} + +static void watchdog_magic_write(uint value) +{ + out_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR, value | + (in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & + ~CONFIG_SYS_WATCHDOG_MAGIC_MASK)); +} + +int sysmon1_post_test(int flags) +{ + if (gpio_read_in_bit(CONFIG_SYS_GPIO_SYSMON_STATUS) == 0) { + /* + * 3.1. GPIO62 is low + * Assuming system voltage failure. + */ + post_log("sysmon1 Abnormal voltage detected (GPIO62)\n"); + post_log("POST sysmon1 FAILED\n"); + return 1; + } else { + post_log("sysmon1 PASSED\n"); + } + + return 0; +} + +int lwmon5_watchdog_post_test(int flags) +{ + /* On each reset scratch register 1 should be tested, + * but first test GPIO62: + */ + if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) { + /* 3.1. GPIO62 is low + * Assuming system voltage failure. + */ + /* 3.1.1. Set scratch register 1 to 0x0000xxxx */ + watchdog_magic_write(0); + /* 3.1.2. Mark test as failed due to voltage?! */ + return 1; + } + + if (watchdog_magic_read() != CONFIG_SYS_WATCHDOG_MAGIC) { + /* 3.2. Scratch register 1 differs from magic value 0x1248xxxx + * Assuming PowerOn + */ + int ints; + ulong base; + ulong time; + + /* 3.2.1. Set magic value to scratch register */ + watchdog_magic_write(CONFIG_SYS_WATCHDOG_MAGIC); + + ints = disable_interrupts (); + /* 3.2.2. strobe watchdog once */ + WATCHDOG_RESET(); + out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, 0); + /* 3.2.3. save time of strobe in scratch register 2 */ + base = post_time_ms (0); + + /* 3.2.4. Wait for 150 ms (enough for reset to happen) */ + while ((time = post_time_ms (base)) < 150) + out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, time); + if (ints) + enable_interrupts (); + + /* 3.2.5. Reset didn't happen. - Set 0x0000xxxx + * into scratch register 1 + */ + watchdog_magic_write(0); + /* 3.2.6. Mark test as failed. */ + post_log("hw watchdog time : %u ms, failed ", time); + return 2; + } else { + /* 3.3. Scratch register matches magic value 0x1248xxxx + * Assume this is watchdog-initiated reset + */ + ulong time; + /* 3.3.1. So, the test succeed, save measured time to syslog. */ + time = in_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR); + if (time > 90 ) { /* ms*/ + post_log("hw watchdog time : %u ms, passed ", time); + /* 3.3.2. Set scratch register 1 to 0x0000xxxx */ + watchdog_magic_write(0); + return 0; + } else { + /*test minimum watchdogtime */ + post_log("hw watchdog time : %u ms, failed ", time); + return 2; + } + } + return -1; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ diff --git a/u-boot/post/board/netta/Makefile b/u-boot/post/board/netta/Makefile new file mode 100644 index 0000000..2d34dd8 --- /dev/null +++ b/u-boot/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 +# +include $(OBJTREE)/include/autoconf.mk + +LIB = libpostnetta.o + +COBJS-$(CONFIG_HAS_POST) += codec.o dsp.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/board/netta/codec.c b/u-boot/post/board/netta/codec.c new file mode 100644 index 0000000..a095a91 --- /dev/null +++ b/u-boot/post/board/netta/codec.c @@ -0,0 +1,45 @@ +/* + * (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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CODEC + +extern int board_post_codec(int flags); + +int codec_post_test (int flags) +{ + return board_post_codec(flags); +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CODEC */ diff --git a/u-boot/post/board/netta/dsp.c b/u-boot/post/board/netta/dsp.c new file mode 100644 index 0000000..438ced5 --- /dev/null +++ b/u-boot/post/board/netta/dsp.c @@ -0,0 +1,45 @@ +/* + * (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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_DSP + +extern int board_post_dsp(int flags); + +int dsp_post_test (int flags) +{ + return board_post_dsp(flags); +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_DSP */ diff --git a/u-boot/post/board/pdm360ng/Makefile b/u-boot/post/board/pdm360ng/Makefile new file mode 100644 index 0000000..d25b0d1 --- /dev/null +++ b/u-boot/post/board/pdm360ng/Makefile @@ -0,0 +1,29 @@ +# +# (C) Copyright 2010 DENX Software Engineering +# Anatolij Gustschin, agust@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 $(OBJTREE)/include/autoconf.mk + +LIB = libpostpdm360ng.o + +COBJS-$(CONFIG_HAS_POST) += coproc_com.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/board/pdm360ng/coproc_com.c b/u-boot/post/board/pdm360ng/coproc_com.c new file mode 100644 index 0000000..0755352 --- /dev/null +++ b/u-boot/post/board/pdm360ng/coproc_com.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2010 DENX Software Engineering, + * Anatolij Gustschin, agust@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 + */ + +/* + * Co-Processor communication POST + */ +#include <common.h> +#include <post.h> +#include <serial.h> + +#if defined(CONFIG_SERIAL_MULTI) + +/* + * Actually the termination sequence of the coprocessor + * commands is "\r\n" (CR LF), but here we use a side effect of + * the putc() routine of the serial driver which checks for LF + * and sends CR before sending LF. Therefore the termination + * sequence in the command below is only "\n". + * "alive" string is the coprocessor response for ping command + * and not a command, therefore it is terminated with "\r\n". + */ +char alive[] = "$AL;38\r\n"; +char ping[] = "$PI;2C\n"; + +int coprocessor_post_test(int flags) +{ + struct stdio_dev *cop_port; + int ret; + char buf[10]; + + /* Test IO Coprocessor communication */ + cop_port = open_port(4, CONFIG_SYS_PDM360NG_COPROC_BAUDRATE); + if (!cop_port) + return -1; + + write_port(cop_port, ping); + udelay(CONFIG_SYS_PDM360NG_COPROC_READ_DELAY); + + memset(buf, 0, sizeof(buf)); + ret = read_port(cop_port, buf, sizeof(buf)); + close_port(4); + if (ret <= 0) { + post_log("Error: Can't read IO Coprocessor port.\n"); + return -1; + } + + if (strcmp(buf, alive)) { + post_log("Error: IO-Cop. resp.: %s\n", buf); + return -1; + } + + /* Test WD Coprocessor communication */ + cop_port = open_port(1, CONFIG_SYS_PDM360NG_COPROC_BAUDRATE); + if (!cop_port) { + post_log("Error: Can't open WD Coprocessor port.\n"); + return -1; + } + + write_port(cop_port, ping); + udelay(CONFIG_SYS_PDM360NG_COPROC_READ_DELAY); + + memset(buf, 0, sizeof(buf)); + ret = read_port(cop_port, buf, sizeof(buf)); + close_port(1); + if (ret <= 0) { + post_log("Error: Can't read WD Coprocessor port.\n"); + return -1; + } + + if (strcmp(buf, alive)) { + post_log("Error: WD-Cop. resp.: %s\n", buf); + return -1; + } + + return 0; +} +#endif /* CONFIG_SERIAL_MULTI */ diff --git a/u-boot/post/cpu/mpc83xx/Makefile b/u-boot/post/cpu/mpc83xx/Makefile new file mode 100644 index 0000000..a8b7005 --- /dev/null +++ b/u-boot/post/cpu/mpc83xx/Makefile @@ -0,0 +1,30 @@ +# +# (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 +# +include $(OBJTREE)/include/autoconf.mk + +LIB = libpostmpc83xx.o + +AOBJS-$(CONFIG_HAS_POST) += +COBJS-$(CONFIG_HAS_POST) += ecc.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/cpu/mpc83xx/ecc.c b/u-boot/post/cpu/mpc83xx/ecc.c new file mode 100644 index 0000000..de87339 --- /dev/null +++ b/u-boot/post/cpu/mpc83xx/ecc.c @@ -0,0 +1,166 @@ +/* + * (C) Copyright 2010 + * Eastman Kodak Company, <www.kodak.com> + * Michael Zaidman, <michael.zaidman@kodak.com> + * + * The code is based on the cpu/mpc83xx/ecc.c written by + * Dave Liu <daveliu@freescale.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc83xx.h> +#include <watchdog.h> +#include <asm/io.h> +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC +/* + * We use the RAW I/O accessors where possible in order to + * achieve performance goal, since the test's execution time + * affects the board start up time. + */ +static inline void ecc_clear(ddr83xx_t *ddr) +{ + /* Clear capture registers */ + __raw_writel(0, &ddr->capture_address); + __raw_writel(0, &ddr->capture_data_hi); + __raw_writel(0, &ddr->capture_data_lo); + __raw_writel(0, &ddr->capture_ecc); + __raw_writel(0, &ddr->capture_attributes); + + /* Clear SBEC and set SBET to 1 */ + out_be32(&ddr->err_sbe, 1 << ECC_ERROR_MAN_SBET_SHIFT); + + /* Clear Error Detect register */ + out_be32(&ddr->err_detect, ECC_ERROR_DETECT_MME |\ + ECC_ERROR_DETECT_MBE |\ + ECC_ERROR_DETECT_SBE |\ + ECC_ERROR_DETECT_MSE); + + isync(); +} + +int ecc_post_test(int flags) +{ + int ret = 0; + int int_state; + int errbit; + u32 pattern[2], writeback[2], retval[2]; + ddr83xx_t *ddr = &((immap_t *)CONFIG_SYS_IMMR)->ddr; + volatile u64 *addr = (u64 *)CONFIG_SYS_POST_ECC_START_ADDR; + + /* The pattern is written into memory to generate error */ + pattern[0] = 0xfedcba98UL; + pattern[1] = 0x76543210UL; + + /* After injecting error, re-initialize the memory with the value */ + writeback[0] = ~pattern[0]; + writeback[1] = ~pattern[1]; + + /* Check if ECC is enabled */ + if (__raw_readl(&ddr->err_disable) & ECC_ERROR_ENABLE) { + debug("DDR's ECC is not enabled, skipping the ECC POST.\n"); + return 0; + } + + int_state = disable_interrupts(); + icache_enable(); + +#ifdef CONFIG_DDR_32BIT + /* It seems like no one really uses the CONFIG_DDR_32BIT mode */ +#error "Add ECC POST support for CONFIG_DDR_32BIT here!" +#else + for (addr = (u64*)CONFIG_SYS_POST_ECC_START_ADDR, errbit=0; + addr < (u64*)CONFIG_SYS_POST_ECC_STOP_ADDR; addr++, errbit++ ) { + + WATCHDOG_RESET(); + + ecc_clear(ddr); + + /* Enable error injection */ + setbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); + sync(); + isync(); + + /* Set bit to be injected */ + if (errbit < 32) { + __raw_writel(1 << errbit, &ddr->data_err_inject_lo); + __raw_writel(0, &ddr->data_err_inject_hi); + } else { + __raw_writel(0, &ddr->data_err_inject_lo); + __raw_writel(1<<(errbit-32), &ddr->data_err_inject_hi); + } + sync(); + isync(); + + /* Write memory location injecting SBE */ + ppcDWstore((u32*)addr, pattern); + sync(); + + /* Disable error injection */ + clrbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); + sync(); + isync(); + + /* Data read should generate SBE */ + ppcDWload((u32*)addr, retval); + sync(); + + if (!(__raw_readl(&ddr->err_detect) & ECC_ERROR_DETECT_SBE) || + (__raw_readl(&ddr->data_err_inject_hi) != + (__raw_readl(&ddr->capture_data_hi) ^ pattern[0])) || + (__raw_readl(&ddr->data_err_inject_lo) != + (__raw_readl(&ddr->capture_data_lo) ^ pattern[1]))) { + + post_log("ECC failed to detect SBE error at %08x, " + "SBE injection mask %08x-%08x, wrote " + "%08x-%08x, read %08x-%08x\n", addr, + ddr->data_err_inject_hi, + ddr->data_err_inject_lo, + pattern[0], pattern[1], + retval[0], retval[1]); + + printf("ERR_DETECT Reg: %08x\n", ddr->err_detect); + printf("ECC CAPTURE_DATA Reg: %08x-%08x\n", + ddr->capture_data_hi, ddr->capture_data_lo); + ret = 1; + break; + } + + /* Re-initialize the ECC memory */ + ppcDWstore((u32*)addr, writeback); + sync(); + isync(); + + errbit %= 63; + } +#endif /* !CONFIG_DDR_32BIT */ + + ecc_clear(ddr); + + icache_disable(); + + if (int_state) + enable_interrupts(); + + return ret; +} +#endif diff --git a/u-boot/post/cpu/mpc8xx/Makefile b/u-boot/post/cpu/mpc8xx/Makefile new file mode 100644 index 0000000..3e1792f --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/Makefile @@ -0,0 +1,30 @@ +# +# (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 +# +include $(OBJTREE)/include/autoconf.mk + +LIB = libpostmpc8xx.o + +AOBJS-$(CONFIG_HAS_POST) += cache_8xx.o +COBJS-$(CONFIG_HAS_POST) += cache.o ether.o spr.o uart.o usb.o watchdog.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/cpu/mpc8xx/cache.c b/u-boot/post/cpu/mpc8xx/cache.c new file mode 100644 index 0000000..06cb501 --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/cache.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> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_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 & CONFIG_SYS_POST_CACHE */ diff --git a/u-boot/post/cpu/mpc8xx/cache_8xx.S b/u-boot/post/cpu/mpc8xx/cache_8xx.S new file mode 100644 index 0000000..097eedb --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/cache_8xx.S @@ -0,0 +1,493 @@ +/* + * 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> + +#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 & CONFIG_SYS_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 & CONFIG_SYS_POST_CACHE */ diff --git a/u-boot/post/cpu/mpc8xx/ether.c b/u-boot/post/cpu/mpc8xx/ether.c new file mode 100644 index 0000000..43ea817 --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/ether.c @@ -0,0 +1,633 @@ +/* + * (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 + */ + +#include <post.h> +#if CONFIG_POST & CONFIG_SYS_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) +{ + uchar ea[6]; + + 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 *) CONFIG_SYS_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 CONFIG_SYS_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) */ + + eth_getenv_enetaddr("ethaddr", ea); + 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]; + + 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 *) CONFIG_SYS_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 & CONFIG_SYS_POST_ETHER */ diff --git a/u-boot/post/cpu/mpc8xx/spr.c b/u-boot/post/cpu/mpc8xx/spr.c new file mode 100644 index 0000000..db84dbe --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/spr.c @@ -0,0 +1,149 @@ +/* + * (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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_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, CONFIG_SYS_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 & CONFIG_SYS_POST_SPR */ diff --git a/u-boot/post/cpu/mpc8xx/uart.c b/u-boot/post/cpu/mpc8xx/uart.c new file mode 100644 index 0000000..f351ac0 --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/uart.c @@ -0,0 +1,556 @@ +/* + * (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 + */ + +#include <post.h> +#if CONFIG_POST & CONFIG_SYS_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 *) CONFIG_SYS_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 CONFIG_SYS_SDSR + im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR; +#else + im->im_sdma.sdma_sdsr = 0x83; +#endif + + /* clear SDMA interrupt mask */ +#ifdef CONFIG_SYS_SDMR + im->im_sdma.sdma_sdmr = CONFIG_SYS_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 CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 *) CONFIG_SYS_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 & CONFIG_SYS_POST_UART */ diff --git a/u-boot/post/cpu/mpc8xx/usb.c b/u-boot/post/cpu/mpc8xx/usb.c new file mode 100644 index 0000000..e3fe075 --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/usb.c @@ -0,0 +1,265 @@ +/* + * (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. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_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 *) CONFIG_SYS_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 & CONFIG_SYS_POST_USB */ diff --git a/u-boot/post/cpu/mpc8xx/watchdog.c b/u-boot/post/cpu/mpc8xx/watchdog.c new file mode 100644 index 0000000..da191c2 --- /dev/null +++ b/u-boot/post/cpu/mpc8xx/watchdog.c @@ -0,0 +1,75 @@ +/* + * (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. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_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 & CONFIG_SYS_POST_WATCHDOG */ diff --git a/u-boot/post/cpu/ppc4xx/Makefile b/u-boot/post/cpu/ppc4xx/Makefile new file mode 100644 index 0000000..9220131 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/Makefile @@ -0,0 +1,37 @@ +# +# (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 +# +include $(OBJTREE)/include/autoconf.mk + +LIB = libpostppc4xx.o + +AOBJS-$(CONFIG_HAS_POST) += cache_4xx.o +COBJS-$(CONFIG_HAS_POST) += cache.o +COBJS-$(CONFIG_HAS_POST) += denali_ecc.o +COBJS-$(CONFIG_HAS_POST) += ether.o +COBJS-$(CONFIG_HAS_POST) += fpu.o +COBJS-$(CONFIG_HAS_POST) += ocm.o +COBJS-$(CONFIG_HAS_POST) += spr.o +COBJS-$(CONFIG_HAS_POST) += uart.o +COBJS-$(CONFIG_HAS_POST) += watchdog.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/cpu/ppc4xx/cache.c b/u-boot/post/cpu/ppc4xx/cache.c new file mode 100644 index 0000000..482f819 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/cache.c @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +#include <asm/mmu.h> +#include <watchdog.h> + +#define CACHE_POST_SIZE 1024 + +int cache_post_test1 (int tlb, void *p, int size); +int cache_post_test2 (int tlb, void *p, int size); +int cache_post_test3 (int tlb, void *p, int size); +int cache_post_test4 (int tlb, void *p, int size); +int cache_post_test5 (int tlb, void *p, int size); +int cache_post_test6 (int tlb, void *p, int size); + +#ifdef CONFIG_440 +static unsigned char testarea[CACHE_POST_SIZE] +__attribute__((__aligned__(CACHE_POST_SIZE))); +#endif + +int cache_post_test (int flags) +{ + void *virt = (void *)CONFIG_SYS_POST_CACHE_ADDR; + int ints; + int res = 0; + int tlb = -1; /* index to the victim TLB entry */ + + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 + int word0, i; + + /* + * Allocate a new TLB entry, since we are going to modify + * the write-through and caching inhibited storage attributes. + */ + program_tlb((u32)testarea, (u32)virt, CACHE_POST_SIZE, + TLB_WORD2_I_ENABLE); + + /* Find the TLB entry */ + for (i = 0;; i++) { + if (i >= PPC4XX_TLB_SIZE) { + printf ("Failed to program tlb entry\n"); + return -1; + } + word0 = mftlb1(i); + if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) { + tlb = i; + break; + } + } +#endif + ints = disable_interrupts (); + + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE); + WATCHDOG_RESET (); + if (res == 0) + res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE); + + if (ints) + enable_interrupts (); + +#ifdef CONFIG_440 + remove_tlb((u32)virt, CACHE_POST_SIZE); +#endif + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/u-boot/post/cpu/ppc4xx/cache_4xx.S b/u-boot/post/cpu/ppc4xx/cache_4xx.S new file mode 100644 index 0000000..3f3e585 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,489 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + + .text + + /* + * All 44x variants deal with cache management differently + * because they have the address translation always enabled. + * The 40x ppc's don't use address translation in U-Boot at all, + * so we have to distinguish here between 40x and 44x. + */ +#ifdef CONFIG_440 +/* void cache_post_disable (int tlb) + */ +cache_post_disable: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + tlbre r0, r3, 0x0002 + ori r0, r0, TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + tlbre r0, r3, 0x0002 + andi. r0, r0, ~TLB_WORD2_W_ENABLE@l + andi. r0, r0, ~TLB_WORD2_I_ENABLE@l + tlbwe r0, r3, 0x0002 + sync + isync + blr +#else +/* void cache_post_disable (int tlb) + */ +cache_post_disable: + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdccr r0 + sync + isync + blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: + lis r0, 0x8000 + ori r0, r0, 0x0000 + mtdccr r0 + lis r0, 0x0000 + ori r0, r0, 0x0000 + mtdcwr r0 + sync + isync + blr +#endif + +/* void cache_post_dinvalidate (void *p, int size) + */ +cache_post_dinvalidate: + dcbi r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dinvalidate + sync + blr + +/* void cache_post_dstore (void *p, int size) + */ +cache_post_dstore: + dcbst r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dstore + sync + blr + +/* void cache_post_dtouch (void *p, int size) + */ +cache_post_dtouch: + dcbt r0, r3 + addi r3, r3, CONFIG_SYS_CACHELINE_SIZE + subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE + bgt cache_post_dtouch + sync + blr + +/* void cache_post_iinvalidate (void) + */ +cache_post_iinvalidate: + iccci r0, r0 + sync + blr + +/* void cache_post_memset (void *p, int val, int size) + */ +cache_post_memset: + mtctr r5 +1: + stb r4, 0(r3) + addi r3, r3, 1 + bdnz 1b + blr + +/* int cache_post_check (void *p, int size) + */ +cache_post_check: + mtctr r4 +1: + lbz r0, 0(r3) + addi r3, r3, 1 + cmpwi r0, 0xff + bne 2f + bdnz 1b + li r3, 0 + blr +2: + li r3, -1 + blr + +#define CACHE_POST_DISABLE() \ + mr r3, r10; \ + bl cache_post_disable + +#define CACHE_POST_WT() \ + mr r3, r10; \ + bl cache_post_wt + +#define CACHE_POST_WB() \ + mr r3, r10; \ + bl cache_post_wb + +#define CACHE_POST_DINVALIDATE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dinvalidate + +#define CACHE_POST_DFLUSH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dflush + +#define CACHE_POST_DSTORE() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dstore + +#define CACHE_POST_DTOUCH() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_dtouch + +#define CACHE_POST_IINVALIDATE() \ + bl cache_post_iinvalidate + +#define CACHE_POST_MEMSET(val) \ + mr r3, r11; \ + li r4, val; \ + mr r5, r12; \ + bl cache_post_memset + +#define CACHE_POST_CHECK() \ + mr r3, r11; \ + mr r4, r12; \ + bl cache_post_check; \ + mr r13, r3 + +/* + * Write and read 0xff pattern with caching enabled. + */ + .global cache_post_test1 +cache_post_test1: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write zeroes with caching enabled. + * Write 0xff pattern with caching disabled. + * Read 0xff pattern with caching enabled. + */ + .global cache_post_test2 +cache_post_test2: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_WB() + + /* Read the test area */ + CACHE_POST_CHECK() + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-through mode test. + * Write zeroes, store the cache, write 0xff pattern. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test3 +cache_post_test3: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DSTORE() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Write-back mode test. + * Write 0xff pattern, store the cache, write zeroes. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ + .global cache_post_test4 +cache_post_test4: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WB() + CACHE_POST_DINVALIDATE() + + /* Cache the test area */ + CACHE_POST_DTOUCH() + + /* Write the negative pattern to the test area */ + CACHE_POST_MEMSET(0xff) + + CACHE_POST_DSTORE() + + /* Write the zero pattern to the test area */ + CACHE_POST_MEMSET(0) + + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + /* Read the test area */ + CACHE_POST_CHECK() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions. + * Check that the original instructions are executed. + */ + .global cache_post_test5 +cache_post_test5: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test5_reloc +cache_post_test5_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test5_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 0(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 4(r13) + stw r0, 0(r11) + sync + + /* Do not invalidate the cache line */ + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions and invalidate the cache. + * Check that the replaced instructions are executed. + */ + .global cache_post_test6 +cache_post_test6: + mflr r9 + mr r10, r3 /* tlb */ + mr r11, r4 /* p */ + mr r12, r5 /* size */ + + CACHE_POST_WT() + CACHE_POST_IINVALIDATE() + + /* Compute r13 = cache_post_test_inst */ + bl cache_post_test6_reloc +cache_post_test6_reloc: + mflr r13 + lis r0, (cache_post_test_inst - cache_post_test6_reloc)@h + ori r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l + add r13, r13, r0 + + /* Copy the test instructions to the test area */ + lwz r0, 4(r13) + stw r0, 0(r11) + lwz r0, 8(r13) + stw r0, 4(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + + /* Replace the test instruction */ + lwz r0, 0(r13) + stw r0, 0(r11) + sync + + /* Invalidate the cache line */ + icbi r0, r11 + sync + isync + + /* Execute the test instructions */ + mtlr r11 + blrl + mr r13, r3 + + CACHE_POST_IINVALIDATE() + CACHE_POST_DINVALIDATE() + CACHE_POST_DISABLE() + + mr r3, r13 + mtlr r9 + blr + +/* Test instructions. + */ +cache_post_test_inst: + li r3, 0 + li r3, -1 + blr + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/u-boot/post/cpu/ppc4xx/denali_ecc.c b/u-boot/post/cpu/ppc4xx/denali_ecc.c new file mode 100644 index 0000000..6d14635 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/denali_ecc.c @@ -0,0 +1,275 @@ +/* + * (C) Copyright 2007 + * Developed for DENX Software Engineering GmbH. + * + * Author: Pavel Kolesnikov <concord@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <watchdog.h> + +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC + +/* + * MEMORY ECC test + * + * This test performs the checks ECC facility of memory. + */ +#include <asm/processor.h> +#include <asm/mmu.h> +#include <asm/io.h> +#include <asm/ppc440.h> + +DECLARE_GLOBAL_DATA_PTR; + +const static uint8_t syndrome_codes[] = { + 0xF4, 0XF1, 0XEC, 0XEA, 0XE9, 0XE6, 0XE5, 0XE3, + 0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB, + 0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2, + 0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A, + 0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62, + 0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A, + 0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23, + 0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +#define ECC_START_ADDR 0x10 +#define ECC_STOP_ADDR 0x2000 +#define ECC_PATTERN 0x01010101 +#define ECC_PATTERN_CORR 0x11010101 +#define ECC_PATTERN_UNCORR 0x61010101 + +inline static void disable_ecc(void) +{ + uint32_t value; + + sync(); /* Wait for any pending memory accesses to complete. */ + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_DISABLE); +} + +inline static void clear_and_enable_ecc(void) +{ + uint32_t value; + + sync(); /* Wait for any pending memory accesses to complete. */ + mfsdram(DDR0_00, value); + mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); + mfsdram(DDR0_22, value); + mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) + | DDR0_22_CTRL_RAW_ECC_ENABLE); +} + +static uint32_t get_ecc_status(void) +{ + uint32_t int_status; +#if defined(DEBUG) + uint8_t syndrome; + uint32_t hdata, ldata, haddr, laddr; + uint32_t value; +#endif + + mfsdram(DDR0_00, int_status); + int_status &= DDR0_00_INT_STATUS_MASK; + +#if defined(DEBUG) + if (int_status & (DDR0_00_INT_STATUS_BIT0 | DDR0_00_INT_STATUS_BIT1)) { + mfsdram(DDR0_32, laddr); + mfsdram(DDR0_33, haddr); + haddr &= 0x00000001; + if (int_status & DDR0_00_INT_STATUS_BIT1) + debug("Multiple accesses"); + else + debug("A single access"); + + debug(" outside the defined physical memory space detected\n" + " addr = 0x%01x%08x\n", haddr, laddr); + } + if (int_status & (DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT3)) { + unsigned int bit; + + mfsdram(DDR0_23, value); + syndrome = (value >> 16) & 0xff; + for (bit = 0; bit < sizeof(syndrome_codes); bit++) + if (syndrome_codes[bit] == syndrome) + break; + + mfsdram(DDR0_38, laddr); + mfsdram(DDR0_39, haddr); + haddr &= 0x00000001; + mfsdram(DDR0_40, ldata); + mfsdram(DDR0_41, hdata); + if (int_status & DDR0_00_INT_STATUS_BIT3) + debug("Multiple correctable ECC events"); + else + debug("Single correctable ECC event"); + + debug(" detected\n 0x%01x%08x - 0x%08x%08x, bit - %d\n", + haddr, laddr, hdata, ldata, bit); + } + if (int_status & (DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT5)) { + mfsdram(DDR0_23, value); + syndrome = (value >> 8) & 0xff; + mfsdram(DDR0_34, laddr); + mfsdram(DDR0_35, haddr); + haddr &= 0x00000001; + mfsdram(DDR0_36, ldata); + mfsdram(DDR0_37, hdata); + if (int_status & DDR0_00_INT_STATUS_BIT5) + debug("Multiple uncorrectable ECC events"); + else + debug("Single uncorrectable ECC event"); + + debug(" detected\n 0x%01x%08x - 0x%08x%08x, " + "syndrome - 0x%02x\n", + haddr, laddr, hdata, ldata, syndrome); + } + if (int_status & DDR0_00_INT_STATUS_BIT6) + debug("DRAM initialization complete\n"); +#endif /* defined(DEBUG) */ + + return int_status; +} + +static int test_ecc(uint32_t ecc_addr) +{ + uint32_t value; + volatile uint32_t *const ecc_mem = (volatile uint32_t *)ecc_addr; + int ret = 0; + + WATCHDOG_RESET(); + + debug("Entering test_ecc(0x%08x)\n", ecc_addr); + /* Set up correct ECC in memory */ + disable_ecc(); + clear_and_enable_ecc(); + out_be32(ecc_mem, ECC_PATTERN); + out_be32(ecc_mem + 1, ECC_PATTERN); + ppcDcbf((u32)ecc_mem); + + /* Verify no ECC error reading back */ + value = in_be32(ecc_mem); + disable_ecc(); + if (ECC_PATTERN != value) { + debug("Data read error (no-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); + ret = 1; + } + value = get_ecc_status(); + if (0x00000000 != value) { + /* Expected no ECC status reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + 0x00000000, value); + ret = 1; + } + + /* Test for correctable error by creating a one-bit error */ + out_be32(ecc_mem, ECC_PATTERN_CORR); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + value = in_be32(ecc_mem); + disable_ecc(); + /* Test that the corrected data was read */ + if (ECC_PATTERN != value) { + debug("Data read error (correctable-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); + ret = 1; + } + value = get_ecc_status(); + if ((DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT7) != value) { + /* Expected a single correctable error reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + DDR0_00_INT_STATUS_BIT2, value); + ret = 1; + } + + /* Test for uncorrectable error by creating a two-bit error */ + out_be32(ecc_mem, ECC_PATTERN_UNCORR); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + value = in_be32(ecc_mem); + disable_ecc(); + /* Test that the corrected data was read */ + if (ECC_PATTERN_UNCORR != value) { + debug("Data read error (uncorrectable-error case): " + "expected 0x%08x, read 0x%08x\n", ECC_PATTERN_UNCORR, + value); + ret = 1; + } + value = get_ecc_status(); + if ((DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT7) != value) { + /* Expected a single uncorrectable error reported */ + debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", + DDR0_00_INT_STATUS_BIT4, value); + ret = 1; + } + + /* Remove error from SDRAM and enable ECC. */ + out_be32(ecc_mem, ECC_PATTERN); + ppcDcbf((u32)ecc_mem); + clear_and_enable_ecc(); + + return ret; +} + +int ecc_post_test(int flags) +{ + int ret = 0; + uint32_t value; + uint32_t iaddr; + + mfsdram(DDR0_22, value); + if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) { + debug("SDRAM ECC not enabled, skipping ECC POST.\n"); + return 0; + } + + /* Mask all interrupts. */ + mfsdram(DDR0_01, value); + mtsdram(DDR0_01, (value & ~DDR0_01_INT_MASK_MASK) + | DDR0_01_INT_MASK_ALL_OFF); + + for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) { + ret = test_ecc(iaddr); + if (ret) + break; + } + /* + * Clear possible errors resulting from ECC testing. (If not done, we + * we could get an interrupt later on when exceptions are enabled.) + */ + set_mcsr(get_mcsr()); + debug("ecc_post_test() returning %d\n", ret); + return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_ECC */ +#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */ diff --git a/u-boot/post/cpu/ppc4xx/ether.c b/u-boot/post/cpu/ppc4xx/ether.c new file mode 100644 index 0000000..c508670 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/ether.c @@ -0,0 +1,435 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * Ethernet test + * + * The Ethernet Media Access Controllers (EMAC) are tested in the + * internal loopback mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + * MIN_PACKET_LENGTH - minimum size of packet to transmit + * MAX_PACKET_LENGTH - maximum size of packet to transmit + * CONFIG_SYS_POST_ETH_LOOPS - Number of test loops. Each loop + * is tested with a different frame length. Starting with + * MAX_PACKET_LENGTH and going down to MIN_PACKET_LENGTH. + * Defaults to 10 and can be overriden in the board config header. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ETHER + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/ppc4xx-mal.h> +#include <asm/ppc4xx-emac.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Get count of EMAC devices (doesn't have to be the max. possible number + * supported by the cpu) + * + * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the + * EMAC count is possible. As it is needed for the Kilauea/Haleakala + * 405EX/405EXr eval board, using the same binary. + */ +#if defined(CONFIG_BOARD_EMAC_COUNT) +#define LAST_EMAC_NUM board_emac_count() +#else /* CONFIG_BOARD_EMAC_COUNT */ +#if defined(CONFIG_HAS_ETH3) +#define LAST_EMAC_NUM 4 +#elif defined(CONFIG_HAS_ETH2) +#define LAST_EMAC_NUM 3 +#elif defined(CONFIG_HAS_ETH1) +#define LAST_EMAC_NUM 2 +#else +#define LAST_EMAC_NUM 1 +#endif +#endif /* CONFIG_BOARD_EMAC_COUNT */ + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) +#endif + +#define MIN_PACKET_LENGTH 64 +#define MAX_PACKET_LENGTH 1514 +#ifndef CONFIG_SYS_POST_ETH_LOOPS +#define CONFIG_SYS_POST_ETH_LOOPS 10 +#endif +#define PACKET_INCR ((MAX_PACKET_LENGTH - MIN_PACKET_LENGTH) / \ + CONFIG_SYS_POST_ETH_LOOPS) + +static volatile mal_desc_t tx __cacheline_aligned; +static volatile mal_desc_t rx __cacheline_aligned; +static char *tx_buf; +static char *rx_buf; + +int board_emac_count(void); + +static void ether_post_init (int devnum, int hw_addr) +{ + int i; +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + unsigned mode_reg; + sys_info_t sysinfo; +#endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) + unsigned long mfr; +#endif + +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Need to get the OPB frequency so we can access the PHY */ + get_sys_info (&sysinfo); +#endif + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* provide clocks for EMAC internal loopback */ + mfsdr (SDR0_MFR, mfr); + mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (SDR0_MFR, mfr); + sync (); +#endif + /* reset emac */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); + sync (); + + for (i = 0;; i++) { + if (!(in_be32 ((void*)(EMAC0_MR0 + hw_addr)) & EMAC_MR0_SRST)) + break; + if (i >= 1000) { + printf ("Timeout resetting EMAC\n"); + break; + } + udelay (1000); + } +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + /* Whack the M1 register */ + mode_reg = 0x0; + if (sysinfo.freqOPB <= 50000000); + else if (sysinfo.freqOPB <= 66666667) + mode_reg |= EMAC_MR1_OBCI_66; + else if (sysinfo.freqOPB <= 83333333) + mode_reg |= EMAC_MR1_OBCI_83; + else if (sysinfo.freqOPB <= 100000000) + mode_reg |= EMAC_MR1_OBCI_100; + else + mode_reg |= EMAC_MR1_OBCI_GT100; + + out_be32 ((void*)(EMAC0_MR1 + hw_addr), mode_reg); + +#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ + + /* set the Mal configuration reg */ +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | + MAL_CR_PLBLT_DEFAULT | 0x00330000); +#else + mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); + /* Errata 1.12: MAL_1 -- Disable MAL bursting */ + if (get_pvr() == PVR_440GP_RB) { + mtdcr (MAL0_CFG, mfdcr(MAL0_CFG) & ~MAL_CR_PLBB); + } +#endif + /* setup buffer descriptors */ + tx.ctrl = MAL_TX_CTRL_WRAP; + tx.data_len = 0; + tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf); + + rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY; + rx.data_len = 0; + rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf); + flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + + switch (devnum) { + case 1: + /* setup MAL tx & rx channel pointers */ +#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) + mtdcr (MAL0_TXCTP2R, &tx); +#else + mtdcr (MAL0_TXCTP1R, &tx); +#endif +#if defined(CONFIG_440) + mtdcr (MAL0_TXBADDR, 0x0); + mtdcr (MAL0_RXBADDR, 0x0); +#endif + mtdcr (MAL0_RXCTP1R, &rx); + /* set RX buffer size */ + mtdcr (MAL0_RCBS1, PKTSIZE_ALIGN / 16); + break; + case 0: + default: + /* setup MAL tx & rx channel pointers */ +#if defined(CONFIG_440) + mtdcr (MAL0_TXBADDR, 0x0); + mtdcr (MAL0_RXBADDR, 0x0); +#endif + mtdcr (MAL0_TXCTP0R, &tx); + mtdcr (MAL0_RXCTP0R, &rx); + /* set RX buffer size */ + mtdcr (MAL0_RCBS0, PKTSIZE_ALIGN / 16); + break; + } + + /* Enable MAL transmit and receive channels */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> (devnum*2))); +#else + mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> devnum)); +#endif + mtdcr (MAL0_RXCASR, (MAL_TXRX_CASR >> devnum)); + + /* set internal loopback mode */ +#ifdef CONFIG_SYS_POST_ETHER_EXT_LOOPBACK + out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | 0 | + EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | + EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | + in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#else + out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | EMAC_MR1_ILE | + EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | + EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | + in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#endif + + /* set transmit enable & receive enable */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_TXE | EMAC_MR0_RXE); + + /* enable broadcast address */ + out_be32 ((void*)(EMAC0_RXM + hw_addr), EMAC_RMR_BAE); + + /* set transmit request threshold register */ + out_be32 ((void*)(EMAC0_TRTR + hw_addr), 0x18000000); /* 256 byte threshold */ + + /* set receive low/high water mark register */ +#if defined(CONFIG_440) + /* 440s has a 64 byte burst length */ + out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x80009000); +#else + /* 405s have a 16 byte burst length */ + out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x0f002000); +#endif /* defined(CONFIG_440) */ + out_be32 ((void*)(EMAC0_TMR1 + hw_addr), 0xf8640000); + + /* Set fifo limit entry in tx mode 0 */ + out_be32 ((void*)(EMAC0_TMR0 + hw_addr), 0x00000003); + /* Frame gap set */ + out_be32 ((void*)(EMAC0_I_FRAME_GAP_REG + hw_addr), 0x00000008); + sync (); +} + +static void ether_post_halt (int devnum, int hw_addr) +{ + int i = 0; +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + unsigned long mfr; +#endif + + /* 1st reset MAL channel */ + /* Note: writing a 0 to a channel has no effect */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) + mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> (devnum * 2)); +#else + mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> devnum); +#endif + mtdcr (MAL0_RXCARR, MAL_TXRX_CASR >> devnum); + + /* wait for reset */ + while (mfdcr (MAL0_RXCASR) & (MAL_TXRX_CASR >> devnum)) { + if (i++ >= 1000) + break; + udelay (1000); + } + /* emac reset */ + out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + /* remove clocks for EMAC internal loopback */ + mfsdr (SDR0_MFR, mfr); + mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); + mtsdr (SDR0_MFR, mfr); +#endif +} + +static void ether_post_send (int devnum, int hw_addr, void *packet, int length) +{ + int i = 0; + + while (tx.ctrl & MAL_TX_CTRL_READY) { + if (i++ > 100) { + printf ("TX timeout\n"); + return; + } + udelay (1000); + invalidate_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + } + tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST | + EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP; + tx.data_len = length; + memcpy (tx.data_ptr, packet, length); + flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + flush_dcache_range((u32)tx.data_ptr, (u32)tx.data_ptr + length); + sync (); + + out_be32 ((void*)(EMAC0_TMR0 + hw_addr), in_be32 ((void*)(EMAC0_TMR0 + hw_addr)) | EMAC_TMR0_GNP0); + sync (); +} + +static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length) +{ + int length; + int i = 0; + + while (rx.ctrl & MAL_RX_CTRL_EMPTY) { + if (i++ > 100) { + printf ("RX timeout\n"); + return 0; + } + udelay (1000); + invalidate_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + } + length = rx.data_len - 4; + if (length <= max_length) { + invalidate_dcache_range((u32)rx.data_ptr, (u32)rx.data_ptr + length); + memcpy(packet, rx.data_ptr, length); + } + sync (); + + rx.ctrl |= MAL_RX_CTRL_EMPTY; + flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); + sync (); + + return length; +} + + /* + * Test routines + */ + +static void packet_fill (char *packet, int length) +{ + char c = (char) length; + int i; + + /* set up ethernet header */ + memset (packet, 0xff, 14); + + for (i = 14; i < length; i++) { + packet[i] = c++; + } +} + +static int packet_check (char *packet, int length) +{ + char c = (char) length; + int i; + + for (i = 14; i < length; i++) { + if (packet[i] != c++) + return -1; + } + + return 0; +} + + char packet_send[MAX_PACKET_LENGTH]; + char packet_recv[MAX_PACKET_LENGTH]; +static int test_ctlr (int devnum, int hw_addr) +{ + int res = -1; + int length; + int l; + + ether_post_init (devnum, hw_addr); + + for (l = MAX_PACKET_LENGTH; l >= MIN_PACKET_LENGTH; + l -= PACKET_INCR) { + packet_fill (packet_send, l); + + ether_post_send (devnum, hw_addr, packet_send, l); + + length = ether_post_recv (devnum, hw_addr, packet_recv, + sizeof (packet_recv)); + + if (length != l || packet_check (packet_recv, length) < 0) { + goto Done; + } + } + + res = 0; + +Done: + + ether_post_halt (devnum, hw_addr); + + if (res != 0) { + post_log ("EMAC%d test failed\n", devnum); + } + + return res; +} + +int ether_post_test (int flags) +{ + int res = 0; + int i; + + /* Allocate tx & rx packet buffers */ + tx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); + rx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); + + if (!tx_buf || !rx_buf) { + printf ("Failed to allocate packet buffers\n"); + res = -1; + goto out_free; + } + + for (i = 0; i < LAST_EMAC_NUM; i++) { + if (test_ctlr (i, i*0x100)) + res = -1; + } + +out_free: + free (tx_buf); + free (rx_buf); + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */ diff --git a/u-boot/post/cpu/ppc4xx/fpu.c b/u-boot/post/cpu/ppc4xx/fpu.c new file mode 100644 index 0000000..9f49690 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/fpu.c @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> + +#if defined(CONFIG_440EP) || \ + defined(CONFIG_440EPX) + +#include <asm/processor.h> +#include <asm/ppc4xx.h> + + +int fpu_status(void) +{ + if (mfspr(SPRN_CCR0) & CCR0_DAPUIB) + return 0; /* Disabled */ + else + return 1; /* Enabled */ +} + + +void fpu_disable(void) +{ + mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) | CCR0_DAPUIB); + mtmsr(mfmsr() & ~MSR_FP); +} + + +void fpu_enable(void) +{ + mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) & ~CCR0_DAPUIB); + mtmsr(mfmsr() | MSR_FP); +} + +#endif diff --git a/u-boot/post/cpu/ppc4xx/ocm.c b/u-boot/post/cpu/ppc4xx/ocm.c new file mode 100644 index 0000000..584e30c --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/ocm.c @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2008 Ilya Yanok, EmCraft Systems, yanok@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * 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> + +/* + * This test attempts to verify on-chip memory (OCM). Result is written + * to the scratch register and if test succeed it won't be run till next + * power on. + */ + +#include <post.h> + +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define OCM_TEST_PATTERN1 0x55555555 +#define OCM_TEST_PATTERN2 0xAAAAAAAA + +#if CONFIG_POST & CONFIG_SYS_POST_OCM + +static uint ocm_status_read(void) +{ + return in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & + CONFIG_SYS_OCM_STATUS_MASK; +} + +static void ocm_status_write(uint value) +{ + out_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR, value | + (in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & + ~CONFIG_SYS_OCM_STATUS_MASK)); +} + +static inline int ocm_test_word(uint value, uint *address) +{ + uint read_value; + + *address = value; + sync(); + read_value = *address; + + return (read_value != value); +} + +int ocm_post_test(int flags) +{ + uint old_value; + int ret = 0; + uint *address = (uint*)CONFIG_SYS_OCM_BASE; + + if (ocm_status_read() == CONFIG_SYS_OCM_STATUS_OK) + return 0; + for (; address < (uint*)(CONFIG_SYS_OCM_BASE + CONFIG_SYS_OCM_SIZE); address++) { + old_value = *address; + if (ocm_test_word(OCM_TEST_PATTERN1, address) || + ocm_test_word(OCM_TEST_PATTERN2, address)) { + ret = 1; + *address = old_value; + printf("OCM POST failed at %p!\n", address); + break; + } + *address = old_value; + } + ocm_status_write(ret ? CONFIG_SYS_OCM_STATUS_FAIL : CONFIG_SYS_OCM_STATUS_OK); + return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_OCM */ diff --git a/u-boot/post/cpu/ppc4xx/spr.c b/u-boot/post/cpu/ppc4xx/spr.c new file mode 100644 index 0000000..cb18b64 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/spr.c @@ -0,0 +1,201 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * SPR test + * + * The test checks the contents of Special Purpose Registers (SPR) listed + * in the spr_test_list array below. + * Each SPR value is read using mfspr instruction, some bits are masked + * according to the table and the resulting value is compared to the + * corresponding table value. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_SPR + +#include <asm/processor.h> + +#ifdef CONFIG_4xx_DCACHE +#include <asm/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; +#endif + +static struct { + int number; + char * name; + unsigned long mask; + unsigned long value; +} spr_test_list [] = { + /* Standard Special-Purpose Registers */ + + {0x001, "XER", 0x00000000, 0x00000000}, + {0x008, "LR", 0x00000000, 0x00000000}, + {0x009, "CTR", 0x00000000, 0x00000000}, + {0x016, "DEC", 0x00000000, 0x00000000}, + {0x01a, "SRR0", 0x00000000, 0x00000000}, + {0x01b, "SRR1", 0x00000000, 0x00000000}, + {0x110, "SPRG0", 0x00000000, 0x00000000}, + {0x111, "SPRG1", 0x00000000, 0x00000000}, + {0x112, "SPRG2", 0x00000000, 0x00000000}, + {0x113, "SPRG3", 0x00000000, 0x00000000}, + {0x11f, "PVR", 0x00000000, 0x00000000}, + + /* Additional Special-Purpose Registers. + * The values must match the initialization + * values from arch/powerpc/cpu/ppc4xx/start.S + */ + {0x30, "PID", 0x00000000, 0x00000000}, + {0x3a, "CSRR0", 0x00000000, 0x00000000}, + {0x3b, "CSRR1", 0x00000000, 0x00000000}, + {0x3d, "DEAR", 0x00000000, 0x00000000}, + {0x3e, "ESR", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x3f, "IVPR", 0xffff0000, 0x00000000}, +#endif + {0x100, "USPRG0", 0x00000000, 0x00000000}, + {0x104, "SPRG4", 0x00000000, 0x00000000}, + {0x105, "SPRG5", 0x00000000, 0x00000000}, + {0x106, "SPRG6", 0x00000000, 0x00000000}, + {0x107, "SPRG7", 0x00000000, 0x00000000}, + {0x10c, "TBL", 0x00000000, 0x00000000}, + {0x10d, "TBU", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x11e, "PIR", 0x0000000f, 0x00000000}, +#endif + {0x130, "DBSR", 0x00000000, 0x00000000}, + {0x134, "DBCR0", 0x00000000, 0x00000000}, + {0x135, "DBCR1", 0x00000000, 0x00000000}, + {0x136, "DBCR2", 0x00000000, 0x00000000}, + {0x138, "IAC1", 0x00000000, 0x00000000}, + {0x139, "IAC2", 0x00000000, 0x00000000}, + {0x13a, "IAC3", 0x00000000, 0x00000000}, + {0x13b, "IAC4", 0x00000000, 0x00000000}, + {0x13c, "DAC1", 0x00000000, 0x00000000}, + {0x13d, "DAC2", 0x00000000, 0x00000000}, + {0x13e, "DVC1", 0x00000000, 0x00000000}, + {0x13f, "DVC2", 0x00000000, 0x00000000}, + {0x150, "TSR", 0x00000000, 0x00000000}, + {0x154, "TCR", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x190, "IVOR0", 0x0000fff0, 0x00000100}, + {0x191, "IVOR1", 0x0000fff0, 0x00000200}, + {0x192, "IVOR2", 0x0000fff0, 0x00000300}, + {0x193, "IVOR3", 0x0000fff0, 0x00000400}, + {0x194, "IVOR4", 0x0000fff0, 0x00000500}, + {0x195, "IVOR5", 0x0000fff0, 0x00000600}, + {0x196, "IVOR6", 0x0000fff0, 0x00000700}, + {0x197, "IVOR7", 0x0000fff0, 0x00000800}, + {0x198, "IVOR8", 0x0000fff0, 0x00000c00}, + {0x199, "IVOR9", 0x00000000, 0x00000000}, + {0x19a, "IVOR10", 0x0000fff0, 0x00000900}, + {0x19b, "IVOR11", 0x00000000, 0x00000000}, + {0x19c, "IVOR12", 0x00000000, 0x00000000}, + {0x19d, "IVOR13", 0x0000fff0, 0x00001300}, + {0x19e, "IVOR14", 0x0000fff0, 0x00001400}, + {0x19f, "IVOR15", 0x0000fff0, 0x00002000}, +#endif + {0x23a, "MCSRR0", 0x00000000, 0x00000000}, + {0x23b, "MCSRR1", 0x00000000, 0x00000000}, + {0x23c, "MCSR", 0x00000000, 0x00000000}, + {0x370, "INV0", 0x00000000, 0x00000000}, + {0x371, "INV1", 0x00000000, 0x00000000}, + {0x372, "INV2", 0x00000000, 0x00000000}, + {0x373, "INV3", 0x00000000, 0x00000000}, + {0x374, "ITV0", 0x00000000, 0x00000000}, + {0x375, "ITV1", 0x00000000, 0x00000000}, + {0x376, "ITV2", 0x00000000, 0x00000000}, + {0x377, "ITV3", 0x00000000, 0x00000000}, + {0x378, "CCR1", 0x00000000, 0x00000000}, + {0x390, "DNV0", 0x00000000, 0x00000000}, + {0x391, "DNV1", 0x00000000, 0x00000000}, + {0x392, "DNV2", 0x00000000, 0x00000000}, + {0x393, "DNV3", 0x00000000, 0x00000000}, + {0x394, "DTV0", 0x00000000, 0x00000000}, + {0x395, "DTV1", 0x00000000, 0x00000000}, + {0x396, "DTV2", 0x00000000, 0x00000000}, + {0x397, "DTV3", 0x00000000, 0x00000000}, +#ifdef CONFIG_440 + {0x398, "DVLIM", 0x0fc1f83f, 0x0001f800}, + {0x399, "IVLIM", 0x0fc1f83f, 0x0001f800}, +#endif + {0x39b, "RSTCFG", 0x00000000, 0x00000000}, + {0x39c, "DCDBTRL", 0x00000000, 0x00000000}, + {0x39d, "DCDBTRH", 0x00000000, 0x00000000}, + {0x39e, "ICDBTRL", 0x00000000, 0x00000000}, + {0x39f, "ICDBTRH", 0x00000000, 0x00000000}, + {0x3b2, "MMUCR", 0x00000000, 0x00000000}, + {0x3b3, "CCR0", 0x00000000, 0x00000000}, + {0x3d3, "ICDBDR", 0x00000000, 0x00000000}, + {0x3f3, "DBDR", 0x00000000, 0x00000000}, +}; + +static int spr_test_list_size = + sizeof (spr_test_list) / sizeof (spr_test_list[0]); + +int spr_post_test (int flags) +{ + int ret = 0; + int i; + + unsigned long code[] = { + 0x7c6002a6, /* mfspr r3,SPR */ + 0x4e800020 /* blr */ + }; + unsigned long (*get_spr) (void) = (void *) code; + +#ifdef CONFIG_4xx_DCACHE + /* disable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); +#endif + for (i = 0; i < spr_test_list_size; i++) { + int num = spr_test_list[i].number; + + /* mfspr r3,num */ + code[0] = 0x7c6002a6 | ((num & 0x1F) << 16) | ((num & 0x3E0) << 6); + + asm volatile ("isync"); + + if ((get_spr () & spr_test_list[i].mask) != + (spr_test_list[i].value & spr_test_list[i].mask)) { + post_log ("The value of %s special register " + "is incorrect: 0x%08X\n", + spr_test_list[i].name, get_spr ()); + ret = -1; + } + } +#ifdef CONFIG_4xx_DCACHE + /* enable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_SPR */ diff --git a/u-boot/post/cpu/ppc4xx/uart.c b/u-boot/post/cpu/ppc4xx/uart.c new file mode 100644 index 0000000..d768956 --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/uart.c @@ -0,0 +1,108 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * Copyright 2010, Stefan Roese, DENX Software Engineering, sr@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> +#include <asm/ppc4xx.h> +#include <ns16550.h> +#include <asm/io.h> +#include <serial.h> + +/* + * UART test + * + * The controllers are configured to loopback mode and several + * characters are transmitted. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_UART + +/* + * This table defines the UART's that should be tested and can + * be overridden in the board config file + */ +#ifndef CONFIG_SYS_POST_UART_TABLE +#define CONFIG_SYS_POST_UART_TABLE { CONFIG_SYS_NS16550_COM1, \ + CONFIG_SYS_NS16550_COM2, CONFIG_SYS_NS16550_COM3, \ + CONFIG_SYS_NS16550_COM4 } +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static int test_ctlr (struct NS16550 *com_port, int index) +{ + int res = -1; + char test_str[] = "*** UART Test String ***\r\n"; + int i; + int divisor; + + divisor = (get_serial_clock() + (gd->baudrate * (16 / 2))) / + (16 * gd->baudrate); + NS16550_init(com_port, divisor); + + /* + * Set internal loopback mode in UART + */ + out_8(&com_port->mcr, in_8(&com_port->mcr) | UART_MCR_LOOP); + + /* Reset FIFOs */ + out_8(&com_port->fcr, UART_FCR_RXSR | UART_FCR_TXSR); + udelay(100); + + /* Flush RX-FIFO */ + while (NS16550_tstc(com_port)) + NS16550_getc(com_port); + + for (i = 0; i < sizeof (test_str) - 1; i++) { + NS16550_putc(com_port, test_str[i]); + if (NS16550_getc(com_port) != test_str[i]) + goto done; + } + res = 0; +done: + if (res) + post_log ("uart%d test failed\n", index); + + return res; +} + +int uart_post_test (int flags) +{ + int i, res = 0; + static unsigned long base[] = CONFIG_SYS_POST_UART_TABLE; + + for (i = 0; i < ARRAY_SIZE(base); i++) { + if (test_ctlr((struct NS16550 *)base[i], i)) + res = -1; + } + serial_reinit_all (); + + return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_UART */ diff --git a/u-boot/post/cpu/ppc4xx/watchdog.c b/u-boot/post/cpu/ppc4xx/watchdog.c new file mode 100644 index 0000000..221adfc --- /dev/null +++ b/u-boot/post/cpu/ppc4xx/watchdog.c @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * Watchdog test + * + * The test verifies the watchdog timer operation. + * On the first iteration, the test routine disables interrupts and + * makes a 10-second delay. If the system does not reboot during this delay, + * the watchdog timer is not operational and the test fails. If the system + * reboots, on the second iteration the test routine reports a success. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +#include <watchdog.h> + +int watchdog_post_test (int flags) +{ + if (flags & POST_REBOOT) { + /* Test passed */ + return 0; + } + else { + /* 10-second delay */ + int ints = disable_interrupts (); + ulong base = post_time_ms (0); + + while (post_time_ms (base) < 10000) + ; + if (ints) + enable_interrupts (); + + /* + * If we have reached this point, the watchdog timer + * does not work + */ + return -1; + } +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ diff --git a/u-boot/post/drivers/Makefile b/u-boot/post/drivers/Makefile new file mode 100644 index 0000000..0d87ae0 --- /dev/null +++ b/u-boot/post/drivers/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 +# +include $(TOPDIR)/config.mk + +LIB = libpostdrivers.o + +COBJS-$(CONFIG_HAS_POST) += i2c.o memory.o rtc.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/drivers/i2c.c b/u-boot/post/drivers/i2c.c new file mode 100644 index 0000000..4cbd9f3 --- /dev/null +++ b/u-boot/post/drivers/i2c.c @@ -0,0 +1,111 @@ +/* + * (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 + */ + +/* + * I2C test + * + * For verifying the I2C bus, a full I2C bus scanning is performed. + * + * #ifdef CONFIG_SYS_POST_I2C_ADDRS + * The test is considered as passed if all the devices and only the devices + * in the list are found. + * #ifdef CONFIG_SYS_POST_I2C_IGNORES + * Ignore devices listed in CONFIG_SYS_POST_I2C_IGNORES. These devices + * are optional or not vital to board functionality. + * #endif + * #else [ ! CONFIG_SYS_POST_I2C_ADDRS ] + * The test is considered as passed if any I2C device is found. + * #endif + */ + +#include <common.h> +#include <post.h> +#include <i2c.h> + +#if CONFIG_POST & CONFIG_SYS_POST_I2C + +static int i2c_ignore_device(unsigned int chip) +{ +#ifdef CONFIG_SYS_POST_I2C_IGNORES + const unsigned char i2c_ignore_list[] = CONFIG_SYS_POST_I2C_IGNORES; + int i; + + for (i = 0; i < sizeof(i2c_ignore_list); i++) + if (i2c_ignore_list[i] == chip) + return 1; +#endif + + return 0; +} + +int i2c_post_test (int flags) +{ + unsigned int i; +#ifndef CONFIG_SYS_POST_I2C_ADDRS + /* Start at address 1, address 0 is the general call address */ + for (i = 1; i < 128; i++) { + if (i2c_ignore_device(i)) + continue; + if (i2c_probe (i) == 0) + return 0; + } + + /* No devices found */ + return -1; +#else + unsigned int ret = 0; + int j; + unsigned char i2c_addr_list[] = CONFIG_SYS_POST_I2C_ADDRS; + + /* Start at address 1, address 0 is the general call address */ + for (i = 1; i < 128; i++) { + if (i2c_ignore_device(i)) + continue; + if (i2c_probe(i) != 0) + continue; + + for (j = 0; j < sizeof(i2c_addr_list); ++j) { + if (i == i2c_addr_list[j]) { + i2c_addr_list[j] = 0xff; + break; + } + } + + if (j == sizeof(i2c_addr_list)) { + ret = -1; + post_log("I2C: addr %02x not expected\n", i); + } + } + + for (i = 0; i < sizeof(i2c_addr_list); ++i) { + if (i2c_addr_list[i] == 0xff) + continue; + post_log("I2C: addr %02x did not respond\n", i2c_addr_list[i]); + ret = -1; + } + + return ret; +#endif +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_I2C */ diff --git a/u-boot/post/drivers/memory.c b/u-boot/post/drivers/memory.c new file mode 100644 index 0000000..3f47449 --- /dev/null +++ b/u-boot/post/drivers/memory.c @@ -0,0 +1,519 @@ +/* + * (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. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_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(const 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(&(pattern[i]), pmem++); + /* + * Put a different pattern on the data lines: otherwise they + * may float long enough to read back what we wrote. + */ + move64(&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; +} + +__attribute__((weak)) +int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ + bd_t *bd = gd->bd; + *vstart = CONFIG_SYS_SDRAM_BASE; + *size = (bd->bi_memsize >= 256 << 20 ? + 256 << 20 : bd->bi_memsize) - (1 << 20); + + /* Limit area to be tested with the board info struct */ + if ((*vstart) + (*size) > (ulong)bd) + *size = (ulong)bd - *vstart; + + return 0; +} + +__attribute__((weak)) +int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ + return 1; +} + +__attribute__((weak)) +int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset) +{ + return 0; +} + +__attribute__((weak)) +void arch_memory_failure_handle(void) +{ + return; +} + +int memory_post_test(int flags) +{ + int ret = 0; + phys_addr_t phys_offset = 0; + u32 memsize, vstart; + + arch_memory_test_prepare(&vstart, &memsize, &phys_offset); + + do { + if (flags & POST_SLOWTEST) { + ret = memory_post_tests(vstart, 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); + } + } + } while (!ret && + !arch_memory_test_advance(&vstart, &memsize, &phys_offset)); + + arch_memory_test_cleanup(&vstart, &memsize, &phys_offset); + if (ret) + arch_memory_failure_handle(); + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_MEMORY */ diff --git a/u-boot/post/drivers/rtc.c b/u-boot/post/drivers/rtc.c new file mode 100644 index 0000000..8b0f463 --- /dev/null +++ b/u-boot/post/drivers/rtc.c @@ -0,0 +1,195 @@ +/* + * (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) RTC Power Fault + * This is verified by analyzing the rtc_get() return status. + * 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. + */ + +#include <post.h> +#include <rtc.h> + +#if CONFIG_POST & CONFIG_SYS_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; + int reliable; + + /* Time reliability */ + reliable = rtc_get (&svtm); + + /* 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); + + /* If come here, then RTC operates correcty, check the correctness + * of the time it reports. + */ + if (reliable < 0) { + post_log ("RTC Time is not reliable! Power fault? \n"); + + return -1; + } + + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */ diff --git a/u-boot/post/lib_powerpc/Makefile b/u-boot/post/lib_powerpc/Makefile new file mode 100644 index 0000000..bc9b82e --- /dev/null +++ b/u-boot/post/lib_powerpc/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 +# +include $(TOPDIR)/config.mk + +LIB = libpost$(ARCH).o + +AOBJS-$(CONFIG_HAS_POST) += asm.o +COBJS-$(CONFIG_HAS_POST) += cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o +COBJS-$(CONFIG_HAS_POST) += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o +COBJS-$(CONFIG_HAS_POST) += store.o load.o cr.o b.o multi.o string.o complex.o + +include $(TOPDIR)/post/rules.mk diff --git a/u-boot/post/lib_powerpc/andi.c b/u-boot/post/lib_powerpc/andi.c new file mode 100644 index 0000000..52ec7c4 --- /dev/null +++ b/u-boot/post/lib_powerpc/andi.c @@ -0,0 +1,120 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/asm.S b/u-boot/post/lib_powerpc/asm.S new file mode 100644 index 0000000..f6b329a --- /dev/null +++ b/u-boot/post/lib_powerpc/asm.S @@ -0,0 +1,358 @@ +/* + * 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> + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */ + .global cpu_post_exec_02 +cpu_post_exec_02: + isync + mflr r0 + stwu r0, -4(r1) + + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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: + isync + 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 + + mfcr r7 + blrl + mtcr r7 + + 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 diff --git a/u-boot/post/lib_powerpc/b.c b/u-boot/post/lib_powerpc/b.c new file mode 100644 index 0000000..492fba4 --- /dev/null +++ b/u-boot/post/lib_powerpc/b.c @@ -0,0 +1,198 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 decr, 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 (decr) + 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; + int flag = disable_interrupts(); + + 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 decr = 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, decr, link, + ctr, cr); + + if (ret != 0) + { + post_log ("Error at b3 test %d !\n", i); + } + + i++; + } + } + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/cmp.c b/u-boot/post/lib_powerpc/cmp.c new file mode 100644 index 0000000..5f6a3b9 --- /dev/null +++ b/u-boot/post/lib_powerpc/cmp.c @@ -0,0 +1,134 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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); + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/cmpi.c b/u-boot/post/lib_powerpc/cmpi.c new file mode 100644 index 0000000..1a2fc3d --- /dev/null +++ b/u-boot/post/lib_powerpc/cmpi.c @@ -0,0 +1,134 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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); + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/complex.c b/u-boot/post/lib_powerpc/complex.c new file mode 100644 index 0000000..4a3bc00 --- /dev/null +++ b/u-boot/post/lib_powerpc/complex.c @@ -0,0 +1,127 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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"); + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/cpu.c b/u-boot/post/lib_powerpc/cpu.c new file mode 100644 index 0000000..3793a60 --- /dev/null +++ b/u-boot/post/lib_powerpc/cpu.c @@ -0,0 +1,147 @@ +/* + * (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. + */ + +#include <watchdog.h> +#include <post.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CONFIG_SYS_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); + +DECLARE_GLOBAL_DATA_PTR; + +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 (); +#ifdef CONFIG_4xx_DCACHE + /* disable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); +#endif + + 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 (); +#ifdef CONFIG_4xx_DCACHE + /* enable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif + + WATCHDOG_RESET(); + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CPU */ diff --git a/u-boot/post/lib_powerpc/cpu_asm.h b/u-boot/post/lib_powerpc/cpu_asm.h new file mode 100644 index 0000000..ef6fe61 --- /dev/null +++ b/u-boot/post/lib_powerpc/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/u-boot/post/lib_powerpc/cr.c b/u-boot/post/lib_powerpc/cr.c new file mode 100644 index 0000000..fbee6d5 --- /dev/null +++ b/u-boot/post/lib_powerpc/cr.c @@ -0,0 +1,357 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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)); + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/fpu/20001122-1.c b/u-boot/post/lib_powerpc/fpu/20001122-1.c new file mode 100644 index 0000000..4af300d --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/20001122-1.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math1 (void) +{ + volatile double a, *p; + double c, d; + volatile double b; + + d = 1.0; + p = &b; + + do + { + c = d; + d = c * 0.5; + b = 1 + d; + } while (b != 1.0); + + a = 1.0 + c; + + if (a == 1.0) { + post_log ("Error in FPU math1 test\n"); + return -1; + } + + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/20010114-2.c b/u-boot/post/lib_powerpc/fpu/20010114-2.c new file mode 100644 index 0000000..dab4d7e --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/20010114-2.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static float rintf (float x) +{ + volatile float TWO23 = 8388608.0; + + if (__builtin_fabs (x) < TWO23) + { + if (x > 0.0) + { + x += TWO23; + x -= TWO23; + } + else if (x < 0.0) + { + x = TWO23 - x; + x = -(x - TWO23); + } + } + + return x; +} + +int fpu_post_test_math2 (void) +{ + if (rintf (-1.5) != -2.0) { + post_log ("Error in FPU math2 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/20010226-1.c b/u-boot/post/lib_powerpc/fpu/20010226-1.c new file mode 100644 index 0000000..c644bc9 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/20010226-1.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math3 (void) +{ + volatile long double dfrom = 1.1; + volatile long double m1; + volatile long double m2; + volatile unsigned long mant_long; + + m1 = dfrom / 2.0; + m2 = m1 * 4294967296.0; + mant_long = ((unsigned long) m2) & 0xffffffff; + + if (mant_long != 0x8ccccccc) { + post_log ("Error in FPU math3 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/980619-1.c b/u-boot/post/lib_powerpc/fpu/980619-1.c new file mode 100644 index 0000000..0c195c1 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/980619-1.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math4 (void) +{ + volatile float reale = 1.0f; + volatile float oneplus; + int i; + + if (sizeof (float) != 4) + return 0; + + for (i = 0; ; i++) + { + oneplus = 1.0f + reale; + if (oneplus == 1.0f) + break; + reale = reale / 2.0f; + } + /* Assumes ieee754 accurate arithmetic above. */ + if (i != 24) { + post_log ("Error in FPU math4 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/Makefile b/u-boot/post/lib_powerpc/fpu/Makefile new file mode 100644 index 0000000..b97ad6f --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/Makefile @@ -0,0 +1,33 @@ +# +# (C) Copyright 2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +include $(TOPDIR)/config.mk + +LIB = libpost$(ARCH)fpu.o + +COBJS-$(CONFIG_HAS_POST) += fpu.o 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o +COBJS-$(CONFIG_HAS_POST) += acc1.o compare-fp-1.o mul-subnormal-single-1.o + +include $(TOPDIR)/post/rules.mk + +CFLAGS := $(shell echo $(CFLAGS) | sed s/-msoft-float//) +CFLAGS += -mhard-float -fkeep-inline-functions diff --git a/u-boot/post/lib_powerpc/fpu/acc1.c b/u-boot/post/lib_powerpc/fpu/acc1.c new file mode 100644 index 0000000..4dc1362 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/acc1.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static double func (const double *array) +{ + double d = *array; + + if (d == 0.0) + return d; + else + return d + func (array + 1); +} + +int fpu_post_test_math5 (void) +{ + double values[] = { 0.1e-100, 1.0, -1.0, 0.0 }; + + if (func (values) != 0.1e-100) { + post_log ("Error in FPU math5 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/compare-fp-1.c b/u-boot/post/lib_powerpc/fpu/compare-fp-1.c new file mode 100644 index 0000000..a0859f8 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/compare-fp-1.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * Test for correctness of composite floating-point comparisons. + * Written by Paolo Bonzini, 26th May 2004. + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static int failed; + +#define TEST(c) if ((c) != ok) failed++ +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b))) +#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b))) +#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b))) +#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b))) +#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b))) +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) + +static float pinf; +static float ninf; +static float NaN; + +static void iuneq (float x, float y, int ok) +{ + TEST (UNEQ (x, y)); + TEST (!LTGT (x, y)); + TEST (UNLE (x, y) && UNGE (x,y)); +} + +static void ieq (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNEQ (x, y)); +} + +static void iltgt (float x, float y, int ok) +{ + TEST (!UNEQ (x, y)); /* Not optimizable. */ + TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */ + TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y))); +} + +static void ine (float x, float y, int ok) +{ + TEST (UNLT (x, y) || UNGT (x, y)); +} + +static void iunlt (float x, float y, int ok) +{ + TEST (UNLT (x, y)); + TEST (UNORD (x, y) || (x < y)); +} + +static void ilt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */ + TEST ((x <= y) && (x != y)); + TEST ((x <= y) && (y != x)); + TEST ((x != y) && (x <= y)); /* Not optimized */ + TEST ((y != x) && (x <= y)); /* Not optimized */ +} + +static void iunle (float x, float y, int ok) +{ + TEST (UNLE (x, y)); + TEST (UNORD (x, y) || (x <= y)); +} + +static void ile (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */ + TEST ((x < y) || (x == y)); + TEST ((y > x) || (x == y)); + TEST ((x == y) || (x < y)); /* Not optimized */ + TEST ((y == x) || (x < y)); /* Not optimized */ +} + +static void iungt (float x, float y, int ok) +{ + TEST (UNGT (x, y)); + TEST (UNORD (x, y) || (x > y)); +} + +static void igt (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */ + TEST ((x >= y) && (x != y)); + TEST ((x >= y) && (y != x)); + TEST ((x != y) && (x >= y)); /* Not optimized */ + TEST ((y != x) && (x >= y)); /* Not optimized */ +} + +static void iunge (float x, float y, int ok) +{ + TEST (UNGE (x, y)); + TEST (UNORD (x, y) || (x >= y)); +} + +static void ige (float x, float y, int ok) +{ + TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */ + TEST ((x > y) || (x == y)); + TEST ((y < x) || (x == y)); + TEST ((x == y) || (x > y)); /* Not optimized */ + TEST ((y == x) || (x > y)); /* Not optimized */ +} + +int fpu_post_test_math6 (void) +{ + pinf = __builtin_inf (); + ninf = -__builtin_inf (); + NaN = __builtin_nan (""); + + iuneq (ninf, pinf, 0); + iuneq (NaN, NaN, 1); + iuneq (pinf, ninf, 0); + iuneq (1, 4, 0); + iuneq (3, 3, 1); + iuneq (5, 2, 0); + + ieq (1, 4, 0); + ieq (3, 3, 1); + ieq (5, 2, 0); + + iltgt (ninf, pinf, 1); + iltgt (NaN, NaN, 0); + iltgt (pinf, ninf, 1); + iltgt (1, 4, 1); + iltgt (3, 3, 0); + iltgt (5, 2, 1); + + ine (1, 4, 1); + ine (3, 3, 0); + ine (5, 2, 1); + + iunlt (NaN, ninf, 1); + iunlt (pinf, NaN, 1); + iunlt (pinf, ninf, 0); + iunlt (pinf, pinf, 0); + iunlt (ninf, ninf, 0); + iunlt (1, 4, 1); + iunlt (3, 3, 0); + iunlt (5, 2, 0); + + ilt (1, 4, 1); + ilt (3, 3, 0); + ilt (5, 2, 0); + + iunle (NaN, ninf, 1); + iunle (pinf, NaN, 1); + iunle (pinf, ninf, 0); + iunle (pinf, pinf, 1); + iunle (ninf, ninf, 1); + iunle (1, 4, 1); + iunle (3, 3, 1); + iunle (5, 2, 0); + + ile (1, 4, 1); + ile (3, 3, 1); + ile (5, 2, 0); + + iungt (NaN, ninf, 1); + iungt (pinf, NaN, 1); + iungt (pinf, ninf, 1); + iungt (pinf, pinf, 0); + iungt (ninf, ninf, 0); + iungt (1, 4, 0); + iungt (3, 3, 0); + iungt (5, 2, 1); + + igt (1, 4, 0); + igt (3, 3, 0); + igt (5, 2, 1); + + iunge (NaN, ninf, 1); + iunge (pinf, NaN, 1); + iunge (ninf, pinf, 0); + iunge (pinf, pinf, 1); + iunge (ninf, ninf, 1); + iunge (1, 4, 0); + iunge (3, 3, 1); + iunge (5, 2, 1); + + ige (1, 4, 0); + ige (3, 3, 1); + ige (5, 2, 1); + + if (failed) { + post_log ("Error in FPU math6 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/fpu.c b/u-boot/post/lib_powerpc/fpu/fpu.c new file mode 100644 index 0000000..a4369f1 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/fpu.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * FPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +#include <watchdog.h> + +extern int fpu_status (void); +extern void fpu_enable (void); +extern void fpu_disable (void); + +extern int fpu_post_test_math1 (void); +extern int fpu_post_test_math2 (void); +extern int fpu_post_test_math3 (void); +extern int fpu_post_test_math4 (void); +extern int fpu_post_test_math5 (void); +extern int fpu_post_test_math6 (void); +extern int fpu_post_test_math7 (void); + +int fpu_post_test (int flags) +{ + int fpu = fpu_status (); + + int ret = 0; + + WATCHDOG_RESET (); + + if (!fpu) + fpu_enable (); + + if (ret == 0) + ret = fpu_post_test_math1 (); + if (ret == 0) + ret = fpu_post_test_math2 (); + if (ret == 0) + ret = fpu_post_test_math3 (); + if (ret == 0) + ret = fpu_post_test_math4 (); + if (ret == 0) + ret = fpu_post_test_math5 (); + if (ret == 0) + ret = fpu_post_test_math6 (); + if (ret == 0) + ret = fpu_post_test_math7 (); + + if (!fpu) + fpu_disable (); + + WATCHDOG_RESET (); + + return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c b/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c new file mode 100644 index 0000000..23a3f30 --- /dev/null +++ b/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * This file is originally a part of the GCC testsuite. + * Check that certain subnormal numbers (formerly known as denormalized + * numbers) are rounded to within 0.5 ulp. PR other/14354. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +union uf +{ + unsigned int u; + float f; +}; + +static float +u2f (unsigned int v) +{ + union uf u; + u.u = v; + return u.f; +} + +static unsigned int +f2u (float v) +{ + union uf u; + u.f = v; + return u.u; +} + +static int ok = 1; + +static void +tstmul (unsigned int ux, unsigned int uy, unsigned int ur) +{ + float x = u2f (ux); + float y = u2f (uy); + + if (f2u (x * y) != ur) + /* Set a variable rather than aborting here, to simplify tracing when + several computations are wrong. */ + ok = 0; +} + +/* We don't want to make this const and static, or else we risk inlining + causing the test to fold as constants at compile-time. */ +struct +{ + unsigned int p1, p2, res; +} static volatile expected[] = +{ + {0xfff, 0x3f800400, 0xfff}, + {0xf, 0x3fc88888, 0x17}, + {0xf, 0x3f844444, 0xf} +}; + +int fpu_post_test_math7 (void) +{ + unsigned int i; + + for (i = 0; i < sizeof (expected) / sizeof (expected[0]); i++) + { + tstmul (expected[i].p1, expected[i].p2, expected[i].res); + tstmul (expected[i].p2, expected[i].p1, expected[i].res); + } + + if (!ok) { + post_log ("Error in FPU math7 test\n"); + return -1; + } + return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/u-boot/post/lib_powerpc/load.c b/u-boot/post/lib_powerpc/load.c new file mode 100644 index 0000000..98d4373 --- /dev/null +++ b/u-boot/post/lib_powerpc/load.c @@ -0,0 +1,256 @@ +/* + * (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). + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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); + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/multi.c b/u-boot/post/lib_powerpc/multi.c new file mode 100644 index 0000000..e42a7c0 --- /dev/null +++ b/u-boot/post/lib_powerpc/multi.c @@ -0,0 +1,82 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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"); + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/rlwimi.c b/u-boot/post/lib_powerpc/rlwimi.c new file mode 100644 index 0000000..fd628b3 --- /dev/null +++ b/u-boot/post/lib_powerpc/rlwimi.c @@ -0,0 +1,159 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/rlwinm.c b/u-boot/post/lib_powerpc/rlwinm.c new file mode 100644 index 0000000..88a28c6 --- /dev/null +++ b/u-boot/post/lib_powerpc/rlwinm.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> + +/* + * 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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/rlwnm.c b/u-boot/post/lib_powerpc/rlwnm.c new file mode 100644 index 0000000..60bcb6d --- /dev/null +++ b/u-boot/post/lib_powerpc/rlwnm.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: 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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/srawi.c b/u-boot/post/lib_powerpc/srawi.c new file mode 100644 index 0000000..be153ad --- /dev/null +++ b/u-boot/post/lib_powerpc/srawi.c @@ -0,0 +1,153 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/store.c b/u-boot/post/lib_powerpc/store.c new file mode 100644 index 0000000..1956f6b --- /dev/null +++ b/u-boot/post/lib_powerpc/store.c @@ -0,0 +1,236 @@ +/* + * (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). + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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); + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/string.c b/u-boot/post/lib_powerpc/string.c new file mode 100644 index 0000000..c0ddeaf --- /dev/null +++ b/u-boot/post/lib_powerpc/string.c @@ -0,0 +1,107 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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; + int flag = disable_interrupts(); + + 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"); + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif diff --git a/u-boot/post/lib_powerpc/three.c b/u-boot/post/lib_powerpc/three.c new file mode 100644 index 0000000..7f8c1e2 --- /dev/null +++ b/u-boot/post/lib_powerpc/three.c @@ -0,0 +1,256 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/threei.c b/u-boot/post/lib_powerpc/threei.c new file mode 100644 index 0000000..31953f9 --- /dev/null +++ b/u-boot/post/lib_powerpc/threei.c @@ -0,0 +1,134 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/threex.c b/u-boot/post/lib_powerpc/threex.c new file mode 100644 index 0000000..350a12a --- /dev/null +++ b/u-boot/post/lib_powerpc/threex.c @@ -0,0 +1,226 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/two.c b/u-boot/post/lib_powerpc/two.c new file mode 100644 index 0000000..2b11147 --- /dev/null +++ b/u-boot/post/lib_powerpc/two.c @@ -0,0 +1,173 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/lib_powerpc/twox.c b/u-boot/post/lib_powerpc/twox.c new file mode 100644 index 0000000..d6714f9 --- /dev/null +++ b/u-boot/post/lib_powerpc/twox.c @@ -0,0 +1,173 @@ +/* + * (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. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_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 diff --git a/u-boot/post/post.c b/u-boot/post/post.c new file mode 100644 index 0000000..1b7f2aa --- /dev/null +++ b/u-boot/post/post.c @@ -0,0 +1,487 @@ +/* + * (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> +#include <stdio_dev.h> +#include <watchdog.h> +#include <post.h> + +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define POST_MAX_NUMBER 32 + +#define BOOTMODE_MAGIC 0xDEAD0000 + +int post_init_f (void) +{ + int res = 0; + unsigned int i; + + for (i = 0; i < post_list_size; i++) { + struct post_test *test = post_list + i; + + if (test->init_f && test->init_f()) { + res = -1; + } + } + + gd->post_init_f_time = post_time_ms(0); + if (!gd->post_init_f_time) + { + printf("post/post.c: post_time_ms seems not to be implemented\n"); + } + + return res; +} + +/* + * Supply a default implementation for post_hotkeys_pressed() for boards + * without hotkey support. We always return 0 here, so that the + * long-running tests won't be started. + * + * Boards with hotkey support can override this weak default function + * by defining one in their board specific code. + */ +int __post_hotkeys_pressed(void) +{ + return 0; /* No hotkeys supported */ +} +int post_hotkeys_pressed(void) + __attribute__((weak, alias("__post_hotkeys_pressed"))); + + +void post_bootmode_init (void) +{ + int bootmode = post_bootmode_get (0); + int newword; + + if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST)) { + newword = BOOTMODE_MAGIC | POST_SLOWTEST; + } else if (bootmode == 0) { + newword = BOOTMODE_MAGIC | POST_POWERON; + } else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST) { + newword = BOOTMODE_MAGIC | POST_NORMAL; + } else { + /* Use old value */ + newword = post_word_load () & ~POST_COLDBOOT; + } + + if (bootmode == 0) + { + /* We are booting after power-on */ + newword |= POST_COLDBOOT; + } + + post_word_store (newword); + + /* Reset activity record */ + gd->post_log_word = 0; +} + +int post_bootmode_get (unsigned int *last_test) +{ + unsigned long word = post_word_load (); + int bootmode; + + if ((word & 0xFFFF0000) != BOOTMODE_MAGIC) { + return 0; + } + + bootmode = word & 0x7F; + + if (last_test && (bootmode & POST_POWERTEST)) { + *last_test = (word >> 8) & 0xFF; + } + + return bootmode; +} + +/* POST tests run before relocation only mark status bits .... */ +static void post_log_mark_start ( unsigned long testid ) +{ + gd->post_log_word |= (testid)<<16; +} + +static void post_log_mark_succ ( unsigned long testid ) +{ + gd->post_log_word |= testid; +} + +/* ... and the messages are output once we are relocated */ +void post_output_backlog ( void ) +{ + int j; + + for (j = 0; j < post_list_size; j++) { + if (gd->post_log_word & (post_list[j].testid<<16)) { + post_log ("POST %s ", post_list[j].cmd); + if (gd->post_log_word & post_list[j].testid) + post_log ("PASSED\n"); + else { + post_log ("FAILED\n"); + show_boot_progress (-31); + } + } + } +} + +static void post_bootmode_test_on (unsigned int last_test) +{ + unsigned long word = post_word_load (); + + word |= POST_POWERTEST; + + word |= (last_test & 0xFF) << 8; + + post_word_store (word); +} + +static void post_bootmode_test_off (void) +{ + unsigned long word = post_word_load (); + + word &= ~POST_POWERTEST; + + post_word_store (word); +} + +static void post_get_flags (int *test_flags) +{ + int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST, + POST_CRITICAL }; + char *var[] = { "post_poweron", "post_normal", "post_slowtest", + "post_critical" }; + int varnum = sizeof (var) / sizeof (var[0]); + char list[128]; /* long enough for POST list */ + char *name; + char *s; + int last; + int i, j; + + for (j = 0; j < post_list_size; j++) { + test_flags[j] = post_list[j].flags; + } + + for (i = 0; i < varnum; i++) { + if (getenv_f(var[i], list, sizeof (list)) <= 0) + continue; + + for (j = 0; j < post_list_size; j++) { + test_flags[j] &= ~flag[i]; + } + + last = 0; + name = list; + while (!last) { + while (*name && *name == ' ') + name++; + if (*name == 0) + break; + s = name + 1; + while (*s && *s != ' ') + s++; + if (*s == 0) + last = 1; + else + *s = 0; + + for (j = 0; j < post_list_size; j++) { + if (strcmp (post_list[j].cmd, name) == 0) { + test_flags[j] |= flag[i]; + break; + } + } + + if (j == post_list_size) { + printf ("No such test: %s\n", name); + } + + name = s + 1; + } + } + + for (j = 0; j < post_list_size; j++) { + if (test_flags[j] & POST_POWERON) { + test_flags[j] |= POST_SLOWTEST; + } + } +} + +void __show_post_progress (unsigned int test_num, int before, int result) +{ +} +void show_post_progress (unsigned int, int, int) + __attribute__((weak, alias("__show_post_progress"))); + +static int post_run_single (struct post_test *test, + int test_flags, int flags, unsigned int i) +{ + if ((flags & test_flags & POST_ALWAYS) && + (flags & test_flags & POST_MEM)) { + WATCHDOG_RESET (); + + if (!(flags & POST_REBOOT)) { + if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL)) { + post_bootmode_test_on ( + (gd->flags & GD_FLG_POSTFAIL) ? + POST_FAIL_SAVE | i : i); + } + + if (test_flags & POST_PREREL) + post_log_mark_start ( test->testid ); + else + post_log ("POST %s ", test->cmd); + } + + show_post_progress(i, POST_BEFORE, POST_FAILED); + + if (test_flags & POST_PREREL) { + if ((*test->test) (flags) == 0) { + post_log_mark_succ ( test->testid ); + show_post_progress(i, POST_AFTER, POST_PASSED); + } + else { + show_post_progress(i, POST_AFTER, POST_FAILED); + if (test_flags & POST_CRITICAL) + gd->flags |= GD_FLG_POSTFAIL; + if (test_flags & POST_STOP) + gd->flags |= GD_FLG_POSTSTOP; + } + } else { + if ((*test->test) (flags) != 0) { + post_log ("FAILED\n"); + show_boot_progress (-32); + show_post_progress(i, POST_AFTER, POST_FAILED); + if (test_flags & POST_CRITICAL) + gd->flags |= GD_FLG_POSTFAIL; + if (test_flags & POST_STOP) + gd->flags |= GD_FLG_POSTSTOP; + } + else + post_log ("PASSED\n"); + show_post_progress(i, POST_AFTER, POST_PASSED); + } + + if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL)) { + post_bootmode_test_off (); + } + + return 0; + } else { + return -1; + } +} + +int post_run (char *name, int flags) +{ + unsigned int i; + int test_flags[POST_MAX_NUMBER]; + + post_get_flags (test_flags); + + if (name == NULL) { + unsigned int last; + + if (gd->flags & GD_FLG_POSTSTOP) + return 0; + + if (post_bootmode_get (&last) & POST_POWERTEST) { + if (last & POST_FAIL_SAVE) { + last &= ~POST_FAIL_SAVE; + gd->flags |= GD_FLG_POSTFAIL; + } + if (last < post_list_size && + (flags & test_flags[last] & POST_ALWAYS) && + (flags & test_flags[last] & POST_MEM)) { + + post_run_single (post_list + last, + test_flags[last], + flags | POST_REBOOT, last); + + for (i = last + 1; i < post_list_size; i++) { + if (gd->flags & GD_FLG_POSTSTOP) + break; + post_run_single (post_list + i, + test_flags[i], + flags, i); + } + } + } else { + for (i = 0; i < post_list_size; i++) { + if (gd->flags & GD_FLG_POSTSTOP) + break; + post_run_single (post_list + i, + test_flags[i], + flags, i); + } + } + + return 0; + } else { + for (i = 0; i < post_list_size; i++) { + if (strcmp (post_list[i].cmd, name) == 0) + break; + } + + if (i < post_list_size) { + WATCHDOG_RESET(); + return post_run_single (post_list + i, + test_flags[i], + flags, i); + } else { + return -1; + } + } +} + +static int post_info_single (struct post_test *test, int full) +{ + if (test->flags & POST_MANUAL) { + if (full) + printf ("%s - %s\n" + " %s\n", test->cmd, test->name, test->desc); + else + printf (" %-15s - %s\n", test->cmd, test->name); + + return 0; + } else { + return -1; + } +} + +int post_info (char *name) +{ + unsigned int i; + + if (name == NULL) { + for (i = 0; i < post_list_size; i++) { + post_info_single (post_list + i, 0); + } + + return 0; + } else { + for (i = 0; i < post_list_size; i++) { + if (strcmp (post_list[i].cmd, name) == 0) + break; + } + + if (i < post_list_size) { + return post_info_single (post_list + i, 1); + } else { + return -1; + } + } +} + +int post_log (char *format, ...) +{ + va_list args; + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + va_start (args, format); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf (printbuffer, format, args); + va_end (args); + +#ifdef CONFIG_LOGBUFFER + /* Send to the logbuffer */ + logbuff_log (printbuffer); +#else + /* Send to the stdout file */ + puts (printbuffer); +#endif + + return 0; +} + +#ifdef CONFIG_NEEDS_MANUAL_RELOC +void post_reloc (void) +{ + unsigned int i; + + /* + * We have to relocate the test table manually + */ + for (i = 0; i < post_list_size; i++) { + ulong addr; + struct post_test *test = post_list + i; + + if (test->name) { + addr = (ulong) (test->name) + gd->reloc_off; + test->name = (char *) addr; + } + + if (test->cmd) { + addr = (ulong) (test->cmd) + gd->reloc_off; + test->cmd = (char *) addr; + } + + if (test->desc) { + addr = (ulong) (test->desc) + gd->reloc_off; + test->desc = (char *) addr; + } + + if (test->test) { + addr = (ulong) (test->test) + gd->reloc_off; + test->test = (int (*)(int flags)) addr; + } + + if (test->init_f) { + addr = (ulong) (test->init_f) + gd->reloc_off; + test->init_f = (int (*)(void)) addr; + } + + if (test->reloc) { + addr = (ulong) (test->reloc) + gd->reloc_off; + test->reloc = (void (*)(void)) addr; + + test->reloc(); + } + } +} +#endif + + +/* + * Some tests (e.g. SYSMON) need the time when post_init_f started, + * but we cannot use get_timer() at this point. + * + * On PowerPC we implement it using the timebase register. + */ +unsigned long post_time_ms (unsigned long base) +{ +#ifdef CONFIG_PPC + return (unsigned long)(get_ticks () / (get_tbclk () / CONFIG_SYS_HZ)) - base; +#else +#warning "Not implemented yet" + return 0; /* Not implemented yet */ +#endif +} diff --git a/u-boot/post/rules.mk b/u-boot/post/rules.mk new file mode 100644 index 0000000..17f8ef7 --- /dev/null +++ b/u-boot/post/rules.mk @@ -0,0 +1,46 @@ +# +# (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 +# + +include $(TOPDIR)/config.mk + +COBJS := $(COBJS-y) +AOBJS := $(AOBJS-y) +SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS)) +LIB := $(obj)$(LIB) + +CPPFLAGS += -I$(TOPDIR) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/post/tests.c b/u-boot/post/tests.c new file mode 100644 index 0000000..5f59fbb --- /dev/null +++ b/u-boot/post/tests.c @@ -0,0 +1,308 @@ +/* + * (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 + * + * Be sure to mark tests to be run before relocation as such with the + * CONFIG_SYS_POST_PREREL flag so that logging is done correctly if the + * logbuffer support is enabled. + */ + +#include <common.h> + +#include <post.h> + +extern int ocm_post_test (int flags); +extern int cache_post_test (int flags); +extern int watchdog_post_test (int flags); +extern int i2c_post_test (int flags); +extern int rtc_post_test (int flags); +extern int memory_post_test (int flags); +extern int cpu_post_test (int flags); +extern int fpu_post_test (int flags); +extern int uart_post_test (int flags); +extern int ether_post_test (int flags); +extern int spi_post_test (int flags); +extern int usb_post_test (int flags); +extern int spr_post_test (int flags); +extern int sysmon_post_test (int flags); +extern int dsp_post_test (int flags); +extern int codec_post_test (int flags); +extern int ecc_post_test (int flags); + +extern int dspic_init_post_test (int flags); +extern int dspic_post_test (int flags); +extern int gdc_post_test (int flags); +extern int fpga_post_test (int flags); +extern int lwmon5_watchdog_post_test(int flags); +extern int sysmon1_post_test(int flags); +extern int coprocessor_post_test(int flags); + +extern int sysmon_init_f (void); + +extern void sysmon_reloc (void); + + +struct post_test post_list[] = +{ +#if CONFIG_POST & CONFIG_SYS_POST_OCM + { + "OCM test", + "ocm", + "This test checks on chip memory (OCM).", + POST_ROM | POST_ALWAYS | POST_PREREL | POST_CRITICAL | POST_STOP, + &ocm_post_test, + NULL, + NULL, + CONFIG_SYS_POST_OCM + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + { + "Cache test", + "cache", + "This test verifies the CPU cache operation.", + POST_RAM | POST_ALWAYS, + &cache_post_test, + NULL, + NULL, + CONFIG_SYS_POST_CACHE + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG +#if defined(CONFIG_POST_WATCHDOG) + CONFIG_POST_WATCHDOG, +#else + { + "Watchdog timer test", + "watchdog", + "This test checks the watchdog timer.", + POST_RAM | POST_POWERON | POST_SLOWTEST | POST_MANUAL | POST_REBOOT, + &watchdog_post_test, + NULL, + NULL, + CONFIG_SYS_POST_WATCHDOG + }, +#endif +#endif +#if CONFIG_POST & CONFIG_SYS_POST_I2C + { + "I2C test", + "i2c", + "This test verifies the I2C operation.", + POST_RAM | POST_ALWAYS, + &i2c_post_test, + NULL, + NULL, + CONFIG_SYS_POST_I2C + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_RTC + { + "RTC test", + "rtc", + "This test verifies the RTC operation.", + POST_RAM | POST_SLOWTEST | POST_MANUAL, + &rtc_post_test, + NULL, + NULL, + CONFIG_SYS_POST_RTC + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_MEMORY + { + "Memory test", + "memory", + "This test checks RAM.", + POST_ROM | POST_POWERON | POST_SLOWTEST | POST_PREREL, + &memory_post_test, + NULL, + NULL, + CONFIG_SYS_POST_MEMORY + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_CPU + { + "CPU test", + "cpu", + "This test verifies the arithmetic logic unit of" + " CPU.", + POST_RAM | POST_ALWAYS, + &cpu_post_test, + NULL, + NULL, + CONFIG_SYS_POST_CPU + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_FPU + { + "FPU test", + "fpu", + "This test verifies the arithmetic logic unit of" + " FPU.", + POST_RAM | POST_ALWAYS, + &fpu_post_test, + NULL, + NULL, + CONFIG_SYS_POST_FPU + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_UART +#if defined(CONFIG_POST_UART) + CONFIG_POST_UART, +#else + { + "UART test", + "uart", + "This test verifies the UART operation.", + POST_RAM | POST_SLOWTEST | POST_MANUAL, + &uart_post_test, + NULL, + NULL, + CONFIG_SYS_POST_UART + }, +#endif /* CONFIG_POST_UART */ +#endif +#if CONFIG_POST & CONFIG_SYS_POST_ETHER + { + "ETHERNET test", + "ethernet", + "This test verifies the ETHERNET operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + ðer_post_test, + NULL, + NULL, + CONFIG_SYS_POST_ETHER + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SPI + { + "SPI test", + "spi", + "This test verifies the SPI operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &spi_post_test, + NULL, + NULL, + CONFIG_SYS_POST_SPI + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_USB + { + "USB test", + "usb", + "This test verifies the USB operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &usb_post_test, + NULL, + NULL, + CONFIG_SYS_POST_USB + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SPR + { + "SPR test", + "spr", + "This test checks SPR contents.", + POST_RAM | POST_ALWAYS, + &spr_post_test, + NULL, + NULL, + CONFIG_SYS_POST_SPR + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SYSMON + { + "SYSMON test", + "sysmon", + "This test monitors system hardware.", + POST_RAM | POST_ALWAYS, + &sysmon_post_test, + &sysmon_init_f, + &sysmon_reloc, + CONFIG_SYS_POST_SYSMON + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_DSP + { + "DSP test", + "dsp", + "This test checks any connected DSP(s).", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &dsp_post_test, + NULL, + NULL, + CONFIG_SYS_POST_DSP + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_CODEC + { + "CODEC test", + "codec", + "This test checks any connected codec(s).", + POST_RAM | POST_MANUAL, + &codec_post_test, + NULL, + NULL, + CONFIG_SYS_POST_CODEC + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_ECC + { + "ECC test", + "ecc", + "This test checks the ECC facility of memory.", + POST_ROM | POST_ALWAYS | POST_PREREL, + &ecc_post_test, + NULL, + NULL, + CONFIG_SYS_POST_ECC + }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1 + CONFIG_POST_BSPEC1, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC2 + CONFIG_POST_BSPEC2, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC3 + CONFIG_POST_BSPEC3, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC4 + CONFIG_POST_BSPEC4, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC5 + CONFIG_POST_BSPEC5, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_COPROC + { + "Coprocessors communication test", + "coproc_com", + "This test checks communication with coprocessors.", + POST_RAM | POST_ALWAYS | POST_CRITICAL, + &coprocessor_post_test, + NULL, + NULL, + CONFIG_SYS_POST_COPROC + } +#endif +}; + +unsigned int post_list_size = sizeof (post_list) / sizeof (struct post_test); |