1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Use teltonika uboot for RUTX

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-08-11 21:25:23 +02:00
parent 21c8a33dbb
commit 839fcf1cab
7338 changed files with 1833685 additions and 0 deletions

View file

@ -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
#########################################################################

View file

@ -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

View file

@ -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 = ARRAY_SIZE(sysmon_table);
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 */

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -0,0 +1,379 @@
/*
* (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)
{
uint read_value;
/* write test pattern */
out_be32((void *)GDC_SCRATCH_REG, value);
/* read other location (protect against data lines capacity) */
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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -0,0 +1,631 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* Ethernet test
*
* The Serial Communication Controllers (SCC) listed in ctlr_list array below
* are tested in the loopback ethernet mode.
* The controllers are configured accordingly and several packets
* are transmitted. The configurable test parameters are:
* MIN_PACKET_LENGTH - minimum size of packet to transmit
* MAX_PACKET_LENGTH - maximum size of packet to transmit
* TEST_NUM - number of tests
*/
#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
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 < ARRAY_SIZE(ctlr_list); 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 */

View file

@ -0,0 +1,148 @@
/*
* (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 = ARRAY_SIZE(spr_test_list);
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 */

View file

@ -0,0 +1,554 @@
/*
* (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
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 < ARRAY_SIZE(ctlr_list); 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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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) */

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -0,0 +1,200 @@
/*
* (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 = ARRAY_SIZE(spr_test_list);
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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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) += flash.o i2c.o memory.o rtc.o
include $(TOPDIR)/post/rules.mk

View file

@ -0,0 +1,107 @@
/*
* Parallel NOR Flash tests
*
* Copyright (c) 2005-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <common.h>
#include <malloc.h>
#include <post.h>
#include <flash.h>
#if CONFIG_POST & CONFIG_SYS_POST_FLASH
/*
* This code will walk over the declared sectors erasing them,
* then programming them, then verifying the written contents.
* Possible future work:
* - verify sectors before/after are not erased/written
* - verify partial writes (e.g. programming only middle of sector)
* - verify the contents of the erased sector
* - better seed pattern than 0x00..0xff
*/
#ifndef CONFIG_SYS_POST_FLASH_NUM
# define CONFIG_SYS_POST_FLASH_NUM 0
#endif
#if CONFIG_SYS_POST_FLASH_START >= CONFIG_SYS_POST_FLASH_END
# error "invalid flash block start/end"
#endif
extern flash_info_t flash_info[];
static void *seed_src_data(void *ptr, ulong *old_len, ulong new_len)
{
unsigned char *p;
ulong i;
p = ptr = realloc(ptr, new_len);
if (!ptr)
return ptr;
for (i = *old_len; i < new_len; ++i)
p[i] = i;
*old_len = new_len;
return ptr;
}
int flash_post_test(int flags)
{
ulong len;
void *src;
int ret, n, n_start, n_end;
flash_info_t *info;
/* the output from the common flash layers needs help */
puts("\n");
len = 0;
src = NULL;
info = &flash_info[CONFIG_SYS_POST_FLASH_NUM];
n_start = CONFIG_SYS_POST_FLASH_START;
n_end = CONFIG_SYS_POST_FLASH_END;
for (n = n_start; n < n_end; ++n) {
ulong s_start, s_len, s_off;
s_start = info->start[n];
s_len = flash_sector_size(info, n);
s_off = s_start - info->start[0];
src = seed_src_data(src, &len, s_len);
if (!src) {
printf("malloc(%#lx) failed\n", s_len);
return 1;
}
printf("\tsector %i: %#lx +%#lx", n, s_start, s_len);
ret = flash_erase(info, n, n + 1);
if (ret) {
flash_perror(ret);
break;
}
ret = write_buff(info, src, s_start, s_len);
if (ret) {
flash_perror(ret);
break;
}
ret = memcmp(src, (void *)s_start, s_len);
if (ret) {
printf(" verify failed with %i\n", ret);
break;
}
}
free(src);
return ret;
}
#endif

View file

@ -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 */

View file

@ -0,0 +1,566 @@
/*
* (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 | CONFIG_SYS_POST_MEM_REGIONS)
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 = ARRAY_SIZE(pattern);
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; 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; 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; 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; 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_test_lines(unsigned long start, unsigned long size)
{
int ret = 0;
ret = memory_post_dataline((unsigned long long *)start);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_addrline((ulong *)start, (ulong *)start,
size);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_addrline((ulong *)(start+size-8),
(ulong *)start, size);
WATCHDOG_RESET();
return ret;
}
static int memory_post_test_patterns(unsigned long start, unsigned long size)
{
int ret = 0;
ret = memory_post_test1(start, size, 0x00000000);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test1(start, size, 0xffffffff);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test1(start, size, 0x55555555);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test1(start, size, 0xaaaaaaaa);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test2(start, size);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test3(start, size);
WATCHDOG_RESET();
if (!ret)
ret = memory_post_test4(start, size);
WATCHDOG_RESET();
return ret;
}
static int memory_post_test_regions(unsigned long start, unsigned long size)
{
unsigned long i;
int ret = 0;
for (i = 0; i < (size >> 20) && (!ret); i++) {
if (!ret)
ret = memory_post_test_patterns(start + (i << 20),
0x800);
if (!ret)
ret = memory_post_test_patterns(start + (i << 20) +
0xff800, 0x800);
}
return ret;
}
static int memory_post_tests(unsigned long start, unsigned long size)
{
int ret = 0;
ret = memory_post_test_lines(start, size);
if (!ret)
ret = memory_post_test_patterns(start, size);
return ret;
}
/*
* !! this is only valid, if you have contiguous memory banks !!
*/
__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 = (gd->ram_size >= 256 << 20 ?
256 << 20 : gd->ram_size) - (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_regions_post_test(int flags)
{
int ret = 0;
phys_addr_t phys_offset = 0;
u32 memsize, vstart;
arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
ret = memory_post_test_lines(vstart, memsize);
if (!ret)
ret = memory_post_test_regions(vstart, memsize);
return ret;
}
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 */
ret = memory_post_test_regions(vstart, memsize);
}
} 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|CONFIG_SYS_POST_MEM_REGIONS) */

View file

@ -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 */

View file

@ -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

View file

@ -0,0 +1,119 @@
/*
* (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 = ARRAY_SIZE(cpu_post_andi_table);
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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,133 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* Integer compare instructions: cmpw, cmplw
*
* To verify these instructions the test runs them with
* different combinations of operands, reads the condition
* register value and compares it with the expected one.
* The test contains a pre-built table
* containing the description of each test case: the instruction,
* the values of the operands, the condition field to save
* the result in and the expected result.
*/
#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 = ARRAY_SIZE(cpu_post_cmp_table);
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

View file

@ -0,0 +1,133 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* Integer compare instructions: cmpwi, cmplwi
*
* To verify these instructions the test runs them with
* different combinations of operands, reads the condition
* register value and compares it with the expected one.
* The test contains a pre-built table
* containing the description of each test case: the instruction,
* the values of the operands, the condition field to save
* the result in and the expected result.
*/
#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 = ARRAY_SIZE(cpu_post_cmpi_table);
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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -0,0 +1,353 @@
/*
* (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 = ARRAY_SIZE(cpu_post_cr_table1);
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 = ARRAY_SIZE(cpu_post_cr_table2);
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 = ARRAY_SIZE(cpu_post_cr_table3);
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 = ARRAY_SIZE(cpu_post_cr_table4);
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

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2007
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* This file is originally a part of the GCC testsuite.
*/
#include <common.h>
#include <post.h>
GNU_FPOST_ATTR
#if CONFIG_POST & CONFIG_SYS_POST_FPU
int fpu_post_test_math1 (void)
{
volatile double a;
double c, d;
volatile double b;
d = 1.0;
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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -0,0 +1,46 @@
#
# (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) += 20001122-1.o
COBJS-$(CONFIG_HAS_POST) += 20010114-2.o
COBJS-$(CONFIG_HAS_POST) += 20010226-1.o
COBJS-$(CONFIG_HAS_POST) += 980619-1.o
COBJS-$(CONFIG_HAS_POST) += acc1.o
COBJS-$(CONFIG_HAS_POST) += compare-fp-1.o
COBJS-$(CONFIG_HAS_POST) += fpu.o
COBJS-$(CONFIG_HAS_POST) += mul-subnormal-single-1.o
COBJS-$(CONFIG_HAS_POST) += darwin-ldouble.o
include $(TOPDIR)/post/rules.mk
CFLAGS := $(shell echo $(CFLAGS) | sed s/-msoft-float//)
CFLAGS += -mhard-float -fkeep-inline-functions
$(obj)%.o: %.c
$(CC) $(ALL_CFLAGS) -o $@.fp $< -c
$(OBJCOPY) -R .gnu.attributes $@.fp $@
rm -f $@.fp

View file

@ -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 */

View file

@ -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 */

View file

@ -0,0 +1,141 @@
/*
* Borrowed from GCC 4.2.2 (which still was GPL v2+)
*/
/* 128-bit long double support routines for Darwin.
Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
GCC 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, or (at your option) any later
version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GCC 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 GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
/*
* Implementations of floating-point long double basic arithmetic
* functions called by the IBM C compiler when generating code for
* PowerPC platforms. In particular, the following functions are
* implemented: __gcc_qadd, __gcc_qsub, __gcc_qmul, and __gcc_qdiv.
* Double-double algorithms are based on the paper "Doubled-Precision
* IEEE Standard 754 Floating-Point Arithmetic" by W. Kahan, February 26,
* 1987. An alternative published reference is "Software for
* Doubled-Precision Floating-Point Computations", by Seppo Linnainmaa,
* ACM TOMS vol 7 no 3, September 1981, pages 272-283.
*/
/*
* Each long double is made up of two IEEE doubles. The value of the
* long double is the sum of the values of the two parts. The most
* significant part is required to be the value of the long double
* rounded to the nearest double, as specified by IEEE. For Inf
* values, the least significant part is required to be one of +0.0 or
* -0.0. No other requirements are made; so, for example, 1.0 may be
* represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a
* NaN is don't-care.
*
* This code currently assumes big-endian.
*/
#define fabs(x) __builtin_fabs(x)
#define isless(x, y) __builtin_isless(x, y)
#define inf() __builtin_inf()
#define unlikely(x) __builtin_expect((x), 0)
#define nonfinite(a) unlikely(!isless(fabs(a), inf()))
typedef union {
long double ldval;
double dval[2];
} longDblUnion;
/* Add two 'long double' values and return the result. */
long double __gcc_qadd(double a, double aa, double c, double cc)
{
longDblUnion x;
double z, q, zz, xh;
z = a + c;
if (nonfinite(z)) {
z = cc + aa + c + a;
if (nonfinite(z))
return z;
x.dval[0] = z; /* Will always be DBL_MAX. */
zz = aa + cc;
if (fabs(a) > fabs(c))
x.dval[1] = a - z + c + zz;
else
x.dval[1] = c - z + a + zz;
} else {
q = a - z;
zz = q + c + (a - (q + z)) + aa + cc;
/* Keep -0 result. */
if (zz == 0.0)
return z;
xh = z + zz;
if (nonfinite(xh))
return xh;
x.dval[0] = xh;
x.dval[1] = z - xh + zz;
}
return x.ldval;
}
long double __gcc_qsub(double a, double b, double c, double d)
{
return __gcc_qadd(a, b, -c, -d);
}
long double __gcc_qmul(double a, double b, double c, double d)
{
longDblUnion z;
double t, tau, u, v, w;
t = a * c; /* Highest order double term. */
if (unlikely(t == 0) /* Preserve -0. */
|| nonfinite(t))
return t;
/* Sum terms of two highest orders. */
/* Use fused multiply-add to get low part of a * c. */
#ifndef __NO_FPRS__
asm("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t));
#else
tau = fmsub(a, c, t);
#endif
v = a * d;
w = b * c;
tau += v + w; /* Add in other second-order terms. */
u = t + tau;
/* Construct long double result. */
if (nonfinite(u))
return u;
z.dval[0] = u;
z.dval[1] = (t - u) + tau;
return z.ldval;
}

View file

@ -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 */

View file

@ -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 < ARRAY_SIZE(expected); 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 */

View file

@ -0,0 +1,255 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* Load instructions: lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u)
*
* All operations are performed on a 16-byte array. The array
* is 4-byte aligned. The base register points to offset 8.
* The immediate offset (index register) ranges in [-8 ... +7].
* The test cases are composed so that they do not
* cause alignment exceptions.
* The test contains a pre-built table describing all test cases.
* The table entry contains:
* the instruction opcode, the array contents, the value of the index
* register and the expected value of the destination register.
* After executing the instruction, the test verifies the
* value of the destination register and the value of the base
* register (it must change for "load with update" instructions).
*/
#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 = ARRAY_SIZE(cpu_post_load_table);
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

View file

@ -0,0 +1,74 @@
/*
* (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
*
* 27 consecutive words are loaded from a source memory buffer
* into GPRs r5 through r31. After that, 27 consecutive words are stored
* from the GPRs r5 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;
ulong src[27], dst[27];
int flag = disable_interrupts();
ulong code[] = {
ASM_LMW(5, 3, 0), /* lmw r5, 0(r3) */
ASM_STMW(5, 4, 0), /* stmr r5, 0(r4) */
ASM_BLR, /* blr */
};
for (i = 0; i < ARRAY_SIZE(src); ++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

View file

@ -0,0 +1,158 @@
/*
* (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 = ARRAY_SIZE(cpu_post_rlwimi_table);
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

View file

@ -0,0 +1,151 @@
/*
* (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 = ARRAY_SIZE(cpu_post_rlwinm_table);
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

View file

@ -0,0 +1,161 @@
/*
* (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 = ARRAY_SIZE(cpu_post_rlwnm_table);
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

View file

@ -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: 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 = ARRAY_SIZE(cpu_post_srawi_table);
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

View file

@ -0,0 +1,235 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* Store instructions: stb(x)(u), sth(x)(u), stw(x)(u)
*
* All operations are performed on a 16-byte array. The array
* is 4-byte aligned. The base register points to offset 8.
* The immediate offset (index register) ranges in [-8 ... +7].
* The test cases are composed so that they do not
* cause alignment exceptions.
* The test contains a pre-built table describing all test cases.
* The table entry contains:
* the instruction opcode, the value of the index register and
* the value of the source register. After executing the
* instruction, the test verifies the contents of the array
* and the value of the base register (it must change for "store
* with update" instructions).
*/
#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 = ARRAY_SIZE(cpu_post_store_table);
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

View file

@ -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

View file

@ -0,0 +1,255 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* 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 = ARRAY_SIZE(cpu_post_three_table);
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

View file

@ -0,0 +1,133 @@
/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
/*
* CPU test
* 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 = ARRAY_SIZE(cpu_post_threei_table);
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

View file

@ -0,0 +1,225 @@
/*
* (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 = ARRAY_SIZE(cpu_post_threex_table);
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

View file

@ -0,0 +1,172 @@
/*
* (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 = ARRAY_SIZE(cpu_post_two_table);
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

View file

@ -0,0 +1,172 @@
/*
* (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 = ARRAY_SIZE(cpu_post_twox_table);
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

View file

@ -0,0 +1,505 @@
/*
* (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 <div64.h>
#include <post.h>
#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
#include <asm/gpio.h>
#endif
#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("%s: post_time_ms not implemented\n", __FILE__);
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)
{
#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
int ret;
unsigned gpio = CONFIG_SYS_POST_HOTKEYS_GPIO;
ret = gpio_request(gpio, "hotkeys");
if (ret) {
printf("POST: gpio hotkey request failed\n");
return 0;
}
gpio_direction_input(gpio);
ret = gpio_get_value(gpio);
gpio_free(gpio);
return ret;
#endif
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;
gd->post_log_res = 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;
}
static void post_log_mark_succ(unsigned long testid)
{
gd->post_log_res |= 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)) {
post_log("POST %s ", post_list[j].cmd);
if (gd->post_log_res & post_list[j].testid)
post_log("PASSED\n");
else {
post_log("FAILED\n");
bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
}
}
}
}
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);
}
#ifndef CONFIG_POST_SKIP_ENV_FLAGS
static void post_get_env_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 = ARRAY_SIZE(var);
char list[128]; /* long enough for POST list */
char *name;
char *s;
int last;
int i, j;
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;
}
}
}
#endif
static void post_get_flags(int *test_flags)
{
int j;
for (j = 0; j < post_list_size; j++)
test_flags[j] = post_list[j].flags;
#ifndef CONFIG_POST_SKIP_ENV_FLAGS
post_get_env_flags(test_flags);
#endif
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");
bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
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;
char printbuffer[CONFIG_SYS_PBSIZE];
va_start(args, format);
/* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
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)
{
#if defined(CONFIG_PPC) || defined(CONFIG_BLACKFIN) || defined(CONFIG_ARM)
return (unsigned long)lldiv(get_ticks(), get_tbclk() / CONFIG_SYS_HZ)
- base;
#else
#warning "Not implemented yet"
return 0; /* Not implemented yet */
#endif
}

View file

@ -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
#########################################################################

View file

@ -0,0 +1,336 @@
/*
* (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 flash_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 led_post_test(int flags);
extern int button_post_test(int flags);
extern int memory_regions_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,
&ether_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
#if CONFIG_POST & CONFIG_SYS_POST_FLASH
{
"Parallel NOR flash test",
"flash",
"This test verifies parallel flash operations.",
POST_RAM | POST_SLOWTEST | POST_MANUAL,
&flash_post_test,
NULL,
NULL,
CONFIG_SYS_POST_FLASH
},
#endif
#if CONFIG_POST & CONFIG_SYS_POST_MEM_REGIONS
{
"Memory regions test",
"mem_regions",
"This test checks regularly placed regions of the RAM.",
POST_ROM | POST_SLOWTEST | POST_PREREL,
&memory_regions_post_test,
NULL,
NULL,
CONFIG_SYS_POST_MEM_REGIONS
},
#endif
};
unsigned int post_list_size = ARRAY_SIZE(post_list);