diff options
Diffstat (limited to 'roms/u-boot/post')
75 files changed, 11881 insertions, 0 deletions
diff --git a/roms/u-boot/post/Makefile b/roms/u-boot/post/Makefile new file mode 100644 index 00000000..2fa6f8a2 --- /dev/null +++ b/roms/u-boot/post/Makefile @@ -0,0 +1,18 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y	+= post.o +obj-$(CONFIG_POST_STD_LIST)	+= tests.o + +obj-y += drivers/ +obj-$(CONFIG_PPC) += lib_powerpc/ +obj-$(CONFIG_MPC83xx) += cpu/mpc83xx/ +obj-$(CONFIG_8xx) += cpu/mpc8xx/ +obj-$(CONFIG_4xx) += cpu/ppc4xx/ +ifneq ($(filter lwmon lwmon5 netta pdm360ng,$(BOARD)),) +obj-y += board/$(BOARD)/ +endif diff --git a/roms/u-boot/post/board/lwmon/Makefile b/roms/u-boot/post/board/lwmon/Makefile new file mode 100644 index 00000000..7f6d5a08 --- /dev/null +++ b/roms/u-boot/post/board/lwmon/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += sysmon.o diff --git a/roms/u-boot/post/board/lwmon/sysmon.c b/roms/u-boot/post/board/lwmon/sysmon.c new file mode 100644 index 00000000..f521b27d --- /dev/null +++ b/roms/u-boot/post/board/lwmon/sysmon.c @@ -0,0 +1,297 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 */ diff --git a/roms/u-boot/post/board/lwmon5/Makefile b/roms/u-boot/post/board/lwmon5/Makefile new file mode 100644 index 00000000..76262c76 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com +# +# Developed for DENX Software Engineering GmbH +# +# SPDX-License-Identifier:	GPL-2.0+ + +obj-y += sysmon.o watchdog.o dspic.o fpga.o dsp.o gdc.o diff --git a/roms/u-boot/post/board/lwmon5/dsp.c b/roms/u-boot/post/board/lwmon5/dsp.c new file mode 100644 index 00000000..2f55f01c --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/dsp.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_DSP +#include <asm/io.h> + +/* This test verifies DSP status bits in FPGA */ + +DECLARE_GLOBAL_DATA_PTR; + +#define DSP_STATUS_REG		0xC4000008 +#define FPGA_STATUS_REG		0xC400000C + +int dsp_post_test(int flags) +{ +	uint   old_value; +	uint   read_value; +	int    ret; + +	/* momorize fpga status */ +	old_value = in_be32((void *)FPGA_STATUS_REG); +	/* enable outputs */ +	out_be32((void *)FPGA_STATUS_REG, 0x30); + +	/* generate sync signal */ +	out_be32((void *)DSP_STATUS_REG, 0x300); +	udelay(5); +	out_be32((void *)DSP_STATUS_REG, 0); +	udelay(500); + +	/* read status */ +	ret = 0; +	read_value = in_be32((void *)DSP_STATUS_REG) & 0x3; +	if (read_value != 0x03) { +		post_log("\nDSP status read %08X\n", read_value); +		ret = 1; +	} + +	/* restore fpga status */ +	out_be32((void *)FPGA_STATUS_REG, old_value); + +	return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_DSP */ diff --git a/roms/u-boot/post/board/lwmon5/dspic.c b/roms/u-boot/post/board/lwmon5/dspic.c new file mode 100644 index 00000000..c5ed1902 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/dspic.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* There are two tests for dsPIC currently implemented: + * 1. dsPIC ready test. Done in board_early_init_f(). Only result verified here. + * 2. dsPIC POST result test.  This test gets dsPIC POST codes and version. + */ + +#include <post.h> + +#include <i2c.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define DSPIC_POST_ERROR_REG	0x800 +#define DSPIC_SYS_ERROR_REG	0x802 +#define DSPIC_SYS_VERSION_REG	0x804 +#define DSPIC_FW_VERSION_REG	0x808 + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1 + +/* Verify that dsPIC ready test done early at hw init passed ok */ +int dspic_init_post_test(int flags) +{ +	if (in_be32((void *)CONFIG_SYS_DSPIC_TEST_ADDR) & +	    CONFIG_SYS_DSPIC_TEST_MASK) { +		post_log("dsPIC init test failed\n"); +		return 1; +	} + +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC1 */ + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC2 +/* Read a register from the dsPIC. */ +int dspic_read(ushort reg, ushort *data) +{ +	uchar buf[sizeof(*data)]; +	int rval; + +	if (i2c_read(CONFIG_SYS_I2C_DSPIC_IO_ADDR, reg, 2, buf, 2)) +		return -1; +	rval = i2c_read(CONFIG_SYS_I2C_DSPIC_IO_ADDR, reg, sizeof(reg), +			buf, sizeof(*data)); +	*data = (buf[0] << 8) | buf[1]; + +	return rval; +} + +/* Verify error codes regs, display version */ +int dspic_post_test(int flags) +{ +	ushort data; +	int ret = 0; + +	post_log("\n"); + +	/* read dspic FW-Version */ +	if (dspic_read(DSPIC_FW_VERSION_REG, &data)) { +		post_log("dsPIC: failed read FW-Version\n"); +		ret = 1; +	} else { +		post_log("dsPIC FW-Version:  %u.%u\n", +			 (data >> 8) & 0xFF, data & 0xFF); +	} + +	/* read dspic SYS-Version */ +	if (dspic_read(DSPIC_SYS_VERSION_REG, &data)) { +		post_log("dsPIC: failed read version\n"); +		ret = 1; +	} else { +		post_log("dsPIC SYS-Version: %u.%u\n", +			 (data >> 8) & 0xFF, data & 0xFF); +	} + +	/* read dspic POST error code */ +	if (dspic_read(DSPIC_POST_ERROR_REG, &data)) { +		post_log("dsPIC: failed read POST code\n"); +		ret = 1; +	} else { +		post_log("dsPIC POST-ERROR   code:  0x%04X\n", data); +	} + +	/* read dspic SYS error code */ +	if ((data = dspic_read(DSPIC_SYS_ERROR_REG, &data))) { +		post_log("dsPIC: failed read system error\n"); +		ret = 1; +	} else { +		post_log("dsPIC SYS-ERROR    code:  0x%04X\n", data); +	} + +	return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC2 */ diff --git a/roms/u-boot/post/board/lwmon5/fpga.c b/roms/u-boot/post/board/lwmon5/fpga.c new file mode 100644 index 00000000..1a728239 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/fpga.c @@ -0,0 +1,344 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#include <common.h> + +/* This test performs testing of FPGA SCRATCH register, + * gets FPGA version and run get_ram_size() on FPGA memory + */ + +#include <post.h> +#include <watchdog.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define FPGA_SCRATCH_REG	0xC4000050 +#define FPGA_VERSION_REG	0xC4000040 +#define FPGA_RAM_START		0xC4200000 +#define FPGA_RAM_END		0xC4203FFF +#define FPGA_STAT		0xC400000C +#define FPGA_BUFFER		0x00800000 +#define FPGA_RAM_SIZE		(FPGA_RAM_END - FPGA_RAM_START + 1) + +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC3 + +const static unsigned long pattern[] = { +	0xffffffff, +	0xaaaaaaaa, +	0xcccccccc, +	0xf0f0f0f0, +	0xff00ff00, +	0xffff0000, +	0x0000ffff, +	0x00ff00ff, +	0x0f0f0f0f, +	0x33333333, +	0x55555555, +	0x00000000, +}; + +const static unsigned long otherpattern = 0x01234567; + +static int one_scratch_test(uint value) +{ +	uint read_value; +	int ret = 0; + +	out_be32((void *)FPGA_SCRATCH_REG, value); +	/* read other location (protect against data lines capacity) */ +	ret = in_be16((void *)FPGA_VERSION_REG); +	/* verify test pattern */ +	read_value = in_be32((void *)FPGA_SCRATCH_REG); +	if (read_value != value) { +		post_log("FPGA SCRATCH test failed write %08X, read %08X\n", +			 value, read_value); +		ret = -1; +	} + +	return ret; +} + +static int fpga_post_test1(ulong *start, ulong size, ulong val) +{ +	int ret = 0; +	ulong i = 0; +	ulong *mem = start; +	ulong readback; + +	for (i = 0; i < size / sizeof(ulong); i++) { +		mem[i] = val; +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	for (i = 0; i < size / sizeof(ulong); i++) { +		readback = mem[i]; +		if (readback != val) { +			post_log("FPGA Memory error at %08x, " +				 "wrote %08x, read %08x !\n", +				 mem + i, val, readback); +			ret = -1; +			break; +		} +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} +	return ret; +} + +static int fpga_post_test2(ulong *start, ulong size) +{ +	int ret = 0; +	ulong i = 0; +	ulong *mem = start; +	ulong readback; + +	for (i = 0; i < size / sizeof(ulong); i++) { +		mem[i] = 1 << (i % 32); +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	for (i = 0; i < size / sizeof(ulong); i++) { +		readback = mem[i]; +		if (readback != 1 << (i % 32)) { +			post_log("FPGA Memory error at %08x, " +				 "wrote %08x, read %08x !\n", +				 mem + i, 1 << (i % 32), readback); +			ret = -1; +			break; +		} +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	return ret; +} + +static int fpga_post_test3(ulong *start, ulong size) +{ +	int ret = 0; +	ulong i = 0; +	ulong *mem = start; +	ulong readback; + +	for (i = 0; i < size / sizeof(ulong); i++) { +		mem[i] = i; +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	for (i = 0; i < size / sizeof(ulong); i++) { +		readback = mem[i]; +		if (readback != i) { +			post_log("FPGA Memory error at %08x, " +				 "wrote %08x, read %08x !\n", +				 mem + i, i, readback); +			ret = -1; +			break; +		} +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	return ret; +} + +static int fpga_post_test4(ulong *start, ulong size) +{ +	int ret = 0; +	ulong i = 0; +	ulong *mem = start; +	ulong readback; + +	for (i = 0; i < size / sizeof(ulong); i++) { +		mem[i] = ~i; +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	for (i = 0; i < size / sizeof(ulong); i++) { +		readback = mem[i]; +		if (readback != ~i) { +			post_log("FPGA Memory error at %08x, " +				 "wrote %08x, read %08x !\n", +				 mem + i, ~i, readback); +			ret = -1; +			break; +		} +		if (i % 1024 == 0) +			WATCHDOG_RESET(); +	} + +	return ret; +} + +/* FPGA Memory-pattern-test */ +static int fpga_mem_test(void) +{ +	int ret = 0; +	ulong* start = (ulong *)FPGA_RAM_START; +	ulong  size  = FPGA_RAM_SIZE; + +	if (ret == 0) +		ret = fpga_post_test1(start, size, 0x00000000); + +	if (ret == 0) +		ret = fpga_post_test1(start, size, 0xffffffff); + +	if (ret == 0) +		ret = fpga_post_test1(start, size, 0x55555555); + +	if (ret == 0) +		ret = fpga_post_test1(start, size, 0xaaaaaaaa); + +	WATCHDOG_RESET(); + +	if (ret == 0) +		ret = fpga_post_test2(start, size); + +	if (ret == 0) +		ret = fpga_post_test3(start, size); + +	if (ret == 0) +		ret = fpga_post_test4(start, size); + +	return ret; +} + +/* Verify FPGA addresslines */ +static int fpga_post_addrline(ulong *address, ulong *base, ulong size) +{ +	unsigned long *target; +	unsigned long *end; +	unsigned long readback; +	unsigned long xor; +	int ret = 0; + +	end = (ulong *)((ulong)base + size); +	xor = 0; + +	for (xor = sizeof(ulong); xor > 0; xor <<= 1) { +		target = (ulong*)((ulong)address ^ xor); +		if ((target >= base) && (target < end)) { +			*address = ~*target; +			readback = *target; + +			if (readback == *address) { +				post_log("Memory (address line) error at %08x" +					 "XOR value %08x !\n", +					 address, target, xor); +				ret = -1; +				break; +			} +		} +	} + +	return ret; +} + +/* Verify FPGA addresslines */ +static int fpga_post_dataline(ulong *address) +{ +	unsigned long temp32 = 0; +	int i = 0; +	int ret = 0; + +	for (i = 0; i < ARRAY_SIZE(pattern); i++) { +		*address = pattern[i]; +		/* +		 * Put a different pattern on the data lines: otherwise they +		 * may float long enough to read back what we wrote. +		 */ +		*(address + 1) = otherpattern; +		temp32 = *address; + +		if (temp32 != pattern[i]){ +			post_log("Memory (date line) error at %08x, " +				 "wrote %08x, read %08x !\n", +				 address, pattern[i], temp32); +			ret = 1; +		} +	} + +	return ret; +} + +/* Verify FPGA, get version & memory size */ +int fpga_post_test(int flags) +{ +	uint   old_value; +	uint   version; +	uint   read_value; +	int    ret = 0; + +	post_log("\n"); +	old_value = in_be32((void *)FPGA_SCRATCH_REG); + +	if (one_scratch_test(0x55555555)) +		ret = 1; +	if (one_scratch_test(0xAAAAAAAA)) +		ret = 1; + +	out_be32((void *)FPGA_SCRATCH_REG, old_value); + +	version = in_be32((void *)FPGA_VERSION_REG); +	post_log("FPGA version %u.%u\n", +		 (version >> 8) & 0xFF, version & 0xFF); + +	/* Enable write to FPGA RAM */ +	out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) | 0x1000); + +	/* get RAM size */ +	read_value = get_ram_size((void *)CONFIG_SYS_FPGA_BASE_1, FPGA_RAM_SIZE); +	post_log("FPGA RAM size %d bytes\n", read_value); +	WATCHDOG_RESET(); + +	/* copy fpga memory to DDR2 RAM*/ +	memcpy((void *)FPGA_BUFFER,(void *)FPGA_RAM_START, FPGA_RAM_SIZE); +	WATCHDOG_RESET(); + +	/* Test datalines */ +	if (fpga_post_dataline((ulong *)FPGA_RAM_START)) { +		ret = 1; +		goto out; +	} +	WATCHDOG_RESET(); + +	/* Test addresslines */ +	if (fpga_post_addrline((ulong *)FPGA_RAM_START, +			       (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) { +		ret = 1; +		goto out; +	} +	WATCHDOG_RESET(); +	if (fpga_post_addrline((ulong *)FPGA_RAM_END - sizeof(long), +			       (ulong *)FPGA_RAM_START, FPGA_RAM_SIZE)) { +		ret = 1; +		goto out; +	} +	WATCHDOG_RESET(); + +	/* Memory Pattern Test */ +	if (fpga_mem_test()) { +		ret = 1; +		goto out; +	} +	WATCHDOG_RESET(); + +	/* restore memory */ +	memcpy((void *)FPGA_RAM_START,(void *)FPGA_BUFFER, FPGA_RAM_SIZE); +	WATCHDOG_RESET(); + +out: +	/* Disable write to RAM */ +	out_be32((void *)FPGA_STAT, in_be32((void *)FPGA_STAT) & 0xEFFF); +	return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_BSPEC3 */ diff --git a/roms/u-boot/post/board/lwmon5/gdc.c b/roms/u-boot/post/board/lwmon5/gdc.c new file mode 100644 index 00000000..9405e7d9 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/gdc.c @@ -0,0 +1,363 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#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 */ diff --git a/roms/u-boot/post/board/lwmon5/sysmon.c b/roms/u-boot/post/board/lwmon5/sysmon.c new file mode 100644 index 00000000..cca1a262 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/sysmon.c @@ -0,0 +1,277 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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" environment variable. Default value is 50% + * + * See the list of all parameters in the sysmon_table below + */ + +#include <post.h> +#include <watchdog.h> +#include <i2c.h> + +#if defined(CONFIG_VIDEO) +#include <mb862xx.h> +#endif + +#if CONFIG_POST & CONFIG_SYS_POST_SYSMON + +DECLARE_GLOBAL_DATA_PTR; + +/* from dspic.c */ +extern int dspic_read(ushort reg, ushort *data); + +#define REG_TEMPERATURE			0x12BC +#define REG_VOLTAGE_5V			0x12CA +#define REG_VOLTAGE_5V_STANDBY		0x12C6 + +#define TEMPERATURE_MIN			(-40)	/* degr. C */ +#define TEMPERATURE_MAX			(+90)	/* degr. C */ +#define TEMPERATURE_DISPLAY_MIN		(-35)	/* degr. C */ +#define TEMPERATURE_DISPLAY_MAX		(+85)	/* degr. C */ + +#define VOLTAGE_5V_MIN			(+4500)	/* mV */ +#define VOLTAGE_5V_MAX			(+5500)	/* mV */ + +#define VOLTAGE_5V_STANDBY_MIN		(+3500)	/* mV */ +#define VOLTAGE_5V_STANDBY_MAX		(+5500)	/* mV */ + +typedef struct sysmon_s sysmon_t; +typedef struct sysmon_table_s sysmon_table_t; + +static void sysmon_dspic_init(sysmon_t *this); +static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val); +static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr,  int *val); +static void sysmon_backlight_disable(sysmon_table_t *this); + +struct sysmon_s { +	uchar	chip; +	void	(*init)(sysmon_t *); +	int	(*read)(sysmon_t *, uint, int *); +}; + +static sysmon_t sysmon_dspic = { +	CONFIG_SYS_I2C_DSPIC_IO_ADDR, +	sysmon_dspic_init, +	sysmon_dspic_read +}; + +static sysmon_t sysmon_dspic_sgn = { +	CONFIG_SYS_I2C_DSPIC_IO_ADDR, +	sysmon_dspic_init, +	sysmon_dspic_read_sgn +}; + +static sysmon_t *sysmon_list[] = { +	&sysmon_dspic, +	NULL +}; + +struct sysmon_table_s { +	char		*name; +	char		*unit_name; +	sysmon_t	*sysmon; +	void		(*exec_before)(sysmon_table_t *); +	void		(*exec_after)(sysmon_table_t *); + +	int		unit_precision; +	int		unit_div; +	int		unit_min; +	int		unit_max; +	uint		val_mask; +	uint		val_min; +	uint		val_max; +	int		val_valid; +	uint		val_min_alt; +	uint		val_max_alt; +	int		val_valid_alt; +	uint		addr; +}; + +static sysmon_table_t sysmon_table[] = { +	{ +		"Temperature", " C", &sysmon_dspic, NULL, sysmon_backlight_disable, +		1, 1, -32768, 32767, 0xFFFF, +		0x8000 + TEMPERATURE_MIN,	  0x8000 + TEMPERATURE_MAX,	    0, +		0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0, +		REG_TEMPERATURE, +	}, + +	{ +		"+ 5 V", "V", &sysmon_dspic, NULL, NULL, +		100, 1000, -0x8000, 0x7FFF, 0xFFFF, +		0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0, +		0x8000 + VOLTAGE_5V_MIN, 0x8000 + VOLTAGE_5V_MAX, 0, +		REG_VOLTAGE_5V, +	}, + +	{ +		"+ 5 V standby", "V", &sysmon_dspic, NULL, NULL, +		100, 1000, -0x8000, 0x7FFF, 0xFFFF, +		0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0, +		0x8000 + VOLTAGE_5V_STANDBY_MIN, 0x8000 + VOLTAGE_5V_STANDBY_MAX, 0, +		REG_VOLTAGE_5V_STANDBY, +	}, + +	{ +		"Temperature", "°C", &sysmon_dspic_sgn, NULL, sysmon_backlight_disable, +		1, 1, -32768, 32767, 0xFFFF, +		0x8000 + TEMPERATURE_MIN,	  0x8000 + TEMPERATURE_MAX,	    0, +		0x8000 + TEMPERATURE_DISPLAY_MIN, 0x8000 + TEMPERATURE_DISPLAY_MAX, 0, +		REG_TEMPERATURE, +	}, +}; + +int sysmon_init_f(void) +{ +	sysmon_t **l; + +	for (l = sysmon_list; *l; l++) +		(*l)->init(*l); + +	return 0; +} + +void sysmon_reloc(void) +{ +	/* Do nothing for now, sysmon_reloc() is required by the sysmon post */ +} + +static char *sysmon_unit_value(sysmon_table_t *s, uint val) +{ +	static char buf[32]; +	char *p, sign; +	int decimal, frac; +	int unit_val; + +	unit_val = s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask; + +	if (val == -1) +		return "I/O ERROR"; + +	if (unit_val < 0) { +		sign = '-'; +		unit_val = -unit_val; +	} else { +		sign = '+'; +	} + +	p = buf + sprintf(buf, "%c%2d", sign, unit_val / s->unit_div); + +	frac = unit_val % s->unit_div; +	frac /= (s->unit_div / s->unit_precision); + +	decimal = s->unit_precision; + +	if (decimal != 1) +		*p++ = '.'; +	for (decimal /= 10; decimal != 0; decimal /= 10) +		*p++ = '0' + (frac / decimal) % 10; +	strcpy(p, s->unit_name); + +	return buf; +} + +static void sysmon_dspic_init(sysmon_t *this) +{ +} + +static int sysmon_dspic_read(sysmon_t *this, uint addr, int *val) +{ +	ushort data; + +	if (dspic_read(addr, &data) == 0){ +		/* To fit into the table range we should add 0x8000 */ +		*val = data + 0x8000; +		return 0; +	} + +	return -1; +} + +static int sysmon_dspic_read_sgn(sysmon_t *this, uint addr, int *val) +{ +	ushort data; + +	if (dspic_read(addr, &data) == 0){ +		/* To fit into the table range we should add 0x8000 */ +		*val = (signed short)data + 0x8000; +		return 0; +	} + +	return -1; +} + +static void sysmon_backlight_disable(sysmon_table_t *this) +{ +#if defined(CONFIG_VIDEO) +	board_backlight_switch(this->val_valid_alt); +#endif +} + +int sysmon_post_test(int flags) +{ +	int res = 0; +	sysmon_table_t * t; +	int val; + +	for (t = sysmon_table; t < sysmon_table + ARRAY_SIZE(sysmon_table); t++) { +		t->val_valid = 1; +		if (t->exec_before) +			t->exec_before(t); + +		if (t->sysmon->read(t->sysmon, t->addr, &val) != 0) { +			t->val_valid = 0; +			t->val_valid_alt = 0; +			post_log(": read failed\n"); +			res = 1; +			break; +		} + +		if (t->val_valid != 0) { +			t->val_valid = val >= t->val_min && val <= t->val_max; +			t->val_valid_alt = val >= t->val_min_alt && val <= t->val_max_alt; +		} + +		if (t->exec_after) +			t->exec_after(t); + +		if ((!t->val_valid) || (flags)) { +			post_log("\n\t%-17s = %-10s ", t->name, sysmon_unit_value(t, val)); +			post_log("allowed range"); +			post_log(" %-8s ..", sysmon_unit_value(t, t->val_min)); +			post_log(" %-8s", sysmon_unit_value(t, t->val_max)); +			post_log("     %s", t->val_valid ? "OK" : "FAIL"); +		} + +		if (!t->val_valid) { +			res = 1; +			break; +		} +	} +	post_log("\n"); + +	return res; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_SYSMON */ diff --git a/roms/u-boot/post/board/lwmon5/watchdog.c b/roms/u-boot/post/board/lwmon5/watchdog.c new file mode 100644 index 00000000..1332da21 --- /dev/null +++ b/roms/u-boot/post/board/lwmon5/watchdog.c @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* This test verifies if the reason of last reset was an abnormal voltage + * condition, than it performs watchdog test, measuing time required to + * trigger watchdog reset. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +#include <watchdog.h> +#include <asm/ppc4xx-gpio.h> +#include <asm/io.h> + +static uint watchdog_magic_read(void) +{ +	return in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & +		CONFIG_SYS_WATCHDOG_MAGIC_MASK; +} + +static void watchdog_magic_write(uint value) +{ +	out_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR, value | +		(in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & +			~CONFIG_SYS_WATCHDOG_MAGIC_MASK)); +} + +int sysmon1_post_test(int flags) +{ +	if (gpio_read_in_bit(CONFIG_SYS_GPIO_SYSMON_STATUS) == 0) { +		/* +		 * 3.1. GPIO62 is low +		 * Assuming system voltage failure. +		 */ +		post_log("sysmon1 Abnormal voltage detected (GPIO62)\n"); +		post_log("POST sysmon1 FAILED\n"); +		return 1; +	} else { +		post_log("sysmon1 PASSED\n"); +	} + +	return 0; +} + +int lwmon5_watchdog_post_test(int flags) +{ +	/* On each reset scratch register 1 should be tested, +	 * but first test GPIO62: +	 */ +	if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) { +		/* 3.1. GPIO62 is low +		 * Assuming system voltage failure. +		 */ +		/* 3.1.1. Set scratch register 1 to 0x0000xxxx */ +		watchdog_magic_write(0); +		/* 3.1.2. Mark test as failed due to voltage?! */ +		return 1; +	} + +	if (watchdog_magic_read() != CONFIG_SYS_WATCHDOG_MAGIC) { +		/* 3.2. Scratch register 1 differs from magic value 0x1248xxxx +		 * Assuming PowerOn +		 */ +		int ints; +		ulong base; +		ulong time; + +		/* 3.2.1. Set magic value to scratch register */ +		watchdog_magic_write(CONFIG_SYS_WATCHDOG_MAGIC); + +		ints = disable_interrupts (); +		/* 3.2.2. strobe watchdog once */ +		WATCHDOG_RESET(); +		out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, 0); +		/* 3.2.3. save time of strobe in scratch register 2 */ +		base = post_time_ms (0); + +		/* 3.2.4. Wait for 150 ms (enough for reset to happen) */ +		while ((time = post_time_ms (base)) < 150) +			out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, time); +		if (ints) +			enable_interrupts (); + +		/* 3.2.5. Reset didn't happen. - Set 0x0000xxxx +		 * into scratch register 1 +		 */ +		watchdog_magic_write(0); +		/* 3.2.6. Mark test as failed. */ +		post_log("hw watchdog time : %u ms, failed ", time); +		return 2; +	} else { +		/* 3.3. Scratch register matches magic value 0x1248xxxx +		 * Assume this is watchdog-initiated reset +		 */ +		ulong time; +		/* 3.3.1. So, the test succeed, save measured time to syslog. */ +		time = in_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR); +		if (time > 90 ) { /* ms*/ +			post_log("hw watchdog time : %u ms, passed ", time); +			/* 3.3.2. Set scratch register 1 to 0x0000xxxx */ +			watchdog_magic_write(0); +			return 0; +		} else { +			/*test minimum watchdogtime */ +			post_log("hw watchdog time : %u ms, failed ", time); +			return 2; +		} +	} +	return -1; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ diff --git a/roms/u-boot/post/board/netta/Makefile b/roms/u-boot/post/board/netta/Makefile new file mode 100644 index 00000000..8fc1945b --- /dev/null +++ b/roms/u-boot/post/board/netta/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += codec.o dsp.o diff --git a/roms/u-boot/post/board/netta/codec.c b/roms/u-boot/post/board/netta/codec.c new file mode 100644 index 00000000..7ff890a9 --- /dev/null +++ b/roms/u-boot/post/board/netta/codec.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2004 + * Pantelis Antoniou, Intracom S.A. , panto@intracom.gr + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * CODEC test + * + * This test verifies the connection and performs a memory test + * on any connected codec(s). The meat of the work is done + * in the board specific function. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CODEC + +extern int board_post_codec(int flags); + +int codec_post_test (int flags) +{ +	return board_post_codec(flags); +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CODEC */ diff --git a/roms/u-boot/post/board/netta/dsp.c b/roms/u-boot/post/board/netta/dsp.c new file mode 100644 index 00000000..f88c379a --- /dev/null +++ b/roms/u-boot/post/board/netta/dsp.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2004 + * Pantelis Antoniou, Intracom S.A. , panto@intracom.gr + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * DSP test + * + * This test verifies the connection and performs a memory test + * on any connected DSP(s). The meat of the work is done + * in the board specific function. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_DSP + +extern int board_post_dsp(int flags); + +int dsp_post_test (int flags) +{ +	return board_post_dsp(flags); +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_DSP */ diff --git a/roms/u-boot/post/board/pdm360ng/Makefile b/roms/u-boot/post/board/pdm360ng/Makefile new file mode 100644 index 00000000..9aa96a1f --- /dev/null +++ b/roms/u-boot/post/board/pdm360ng/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2010 DENX Software Engineering +# Anatolij Gustschin, agust@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += coproc_com.o diff --git a/roms/u-boot/post/board/pdm360ng/coproc_com.c b/roms/u-boot/post/board/pdm360ng/coproc_com.c new file mode 100644 index 00000000..e11b69bd --- /dev/null +++ b/roms/u-boot/post/board/pdm360ng/coproc_com.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2010 DENX Software Engineering, + * Anatolij Gustschin, agust@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * Co-Processor communication POST + */ +#include <common.h> +#include <post.h> +#include <serial.h> + +/* + * 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; +} diff --git a/roms/u-boot/post/cpu/mpc83xx/Makefile b/roms/u-boot/post/cpu/mpc83xx/Makefile new file mode 100644 index 00000000..d57b6675 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc83xx/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += ecc.o diff --git a/roms/u-boot/post/cpu/mpc83xx/ecc.c b/roms/u-boot/post/cpu/mpc83xx/ecc.c new file mode 100644 index 00000000..76a3693a --- /dev/null +++ b/roms/u-boot/post/cpu/mpc83xx/ecc.c @@ -0,0 +1,150 @@ +/* + * (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> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <mpc83xx.h> +#include <watchdog.h> +#include <asm/io.h> +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC +/* + * We use the RAW I/O accessors where possible in order to + * achieve performance goal, since the test's execution time + * affects the board start up time. + */ +static inline void ecc_clear(ddr83xx_t *ddr) +{ +	/* Clear capture registers */ +	__raw_writel(0, &ddr->capture_address); +	__raw_writel(0, &ddr->capture_data_hi); +	__raw_writel(0, &ddr->capture_data_lo); +	__raw_writel(0, &ddr->capture_ecc); +	__raw_writel(0, &ddr->capture_attributes); + +	/* Clear SBEC and set SBET to 1 */ +	out_be32(&ddr->err_sbe, 1 << ECC_ERROR_MAN_SBET_SHIFT); + +	/* Clear Error Detect register */ +	out_be32(&ddr->err_detect, ECC_ERROR_DETECT_MME |\ +			ECC_ERROR_DETECT_MBE |\ +			ECC_ERROR_DETECT_SBE |\ +			ECC_ERROR_DETECT_MSE); + +	isync(); +} + +int ecc_post_test(int flags) +{ +	int ret = 0; +	int int_state; +	int errbit; +	u32 pattern[2], writeback[2], retval[2]; +	ddr83xx_t *ddr = &((immap_t *)CONFIG_SYS_IMMR)->ddr; +	volatile u64 *addr = (u64 *)CONFIG_SYS_POST_ECC_START_ADDR; + +	/* The pattern is written into memory to generate error */ +	pattern[0] = 0xfedcba98UL; +	pattern[1] = 0x76543210UL; + +	/* After injecting error, re-initialize the memory with the value */ +	writeback[0] = ~pattern[0]; +	writeback[1] = ~pattern[1]; + +	/* Check if ECC is enabled */ +	if (__raw_readl(&ddr->err_disable) & ECC_ERROR_ENABLE) { +		debug("DDR's ECC is not enabled, skipping the ECC POST.\n"); +		return 0; +	} + +	int_state = disable_interrupts(); +	icache_enable(); + +#ifdef CONFIG_DDR_32BIT +	/* It seems like no one really uses the CONFIG_DDR_32BIT mode */ +#error "Add ECC POST support for CONFIG_DDR_32BIT here!" +#else +	for (addr = (u64*)CONFIG_SYS_POST_ECC_START_ADDR, errbit=0; +	     addr < (u64*)CONFIG_SYS_POST_ECC_STOP_ADDR; addr++, errbit++ ) { + +		WATCHDOG_RESET(); + +		ecc_clear(ddr); + +		/* Enable error injection */ +		setbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); +		sync(); +		isync(); + +		/* Set bit to be injected */ +		if (errbit < 32) { +			__raw_writel(1 << errbit, &ddr->data_err_inject_lo); +			__raw_writel(0, &ddr->data_err_inject_hi); +		} else { +			__raw_writel(0, &ddr->data_err_inject_lo); +			__raw_writel(1<<(errbit-32), &ddr->data_err_inject_hi); +		} +		sync(); +		isync(); + +		/* Write memory location injecting SBE */ +		ppcDWstore((u32*)addr, pattern); +		sync(); + +		/* Disable error injection */ +		clrbits_be32(&ddr->ecc_err_inject, ECC_ERR_INJECT_EIEN); +		sync(); +		isync(); + +		/* Data read should generate SBE */ +		ppcDWload((u32*)addr, retval); +		sync(); + +		if (!(__raw_readl(&ddr->err_detect) & ECC_ERROR_DETECT_SBE) || +			(__raw_readl(&ddr->data_err_inject_hi) != +			(__raw_readl(&ddr->capture_data_hi) ^ pattern[0])) || +			(__raw_readl(&ddr->data_err_inject_lo) != +			(__raw_readl(&ddr->capture_data_lo) ^ pattern[1]))) { + +			post_log("ECC failed to detect SBE error at %08x, " +				"SBE injection mask %08x-%08x, wrote " +				"%08x-%08x, read %08x-%08x\n", addr, +				ddr->data_err_inject_hi, +				ddr->data_err_inject_lo, +				pattern[0], pattern[1], +				retval[0], retval[1]); + +			printf("ERR_DETECT Reg: %08x\n", ddr->err_detect); +			printf("ECC CAPTURE_DATA Reg: %08x-%08x\n", +				ddr->capture_data_hi, ddr->capture_data_lo); +			ret = 1; +			break; +		} + +		/* Re-initialize the ECC memory */ +		ppcDWstore((u32*)addr, writeback); +		sync(); +		isync(); + +		errbit %= 63; +	} +#endif /* !CONFIG_DDR_32BIT */ + +	ecc_clear(ddr); + +	icache_disable(); + +	if (int_state) +		enable_interrupts(); + +	return ret; +} +#endif diff --git a/roms/u-boot/post/cpu/mpc8xx/Makefile b/roms/u-boot/post/cpu/mpc8xx/Makefile new file mode 100644 index 00000000..f8bb6c93 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-$(CONFIG_HAS_POST)	+= cache_8xx.o +obj-$(CONFIG_HAS_POST)	+= cache.o ether.o spr.o uart.o usb.o watchdog.o diff --git a/roms/u-boot/post/cpu/mpc8xx/cache.c b/roms/u-boot/post/cpu/mpc8xx/cache.c new file mode 100644 index 00000000..af1281b7 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/cache.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +#define CACHE_POST_SIZE	1024 + +extern int cache_post_test1 (char *, unsigned int); +extern int cache_post_test2 (char *, unsigned int); +extern int cache_post_test3 (char *, unsigned int); +extern int cache_post_test4 (char *, unsigned int); +extern int cache_post_test5 (void); +extern int cache_post_test6 (void); + +int cache_post_test (int flags) +{ +	int ints = disable_interrupts (); +	int res = 0; +	static char ta[CACHE_POST_SIZE + 0xf]; +	char *testarea = (char *) (((unsigned long) ta + 0xf) & ~0xf); + +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test1 (testarea, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test2 (testarea, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test3 (testarea, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test4 (testarea, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test5 (); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test6 (); + +	WATCHDOG_RESET (); +	if (ints) +		enable_interrupts (); +	return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S b/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S new file mode 100644 index 00000000..43649c89 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/cache_8xx.S @@ -0,0 +1,477 @@ +/* + *  Copyright (C) 2002 Wolfgang Denk <wd@denx.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> + +#if defined(CONFIG_MPC823) || \ +    defined(CONFIG_MPC850) || \ +    defined(CONFIG_MPC855) || \ +    defined(CONFIG_MPC860) || \ +    defined(CONFIG_MPC862) + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +	.text + +cache_post_dinvalidate: +	lis	r10, IDC_INVALL@h +	mtspr	DC_CST, r10 +	blr + +cache_post_iinvalidate: +	lis	r10, IDC_INVALL@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ddisable: +	lis	r10, IDC_DISABLE@h +	mtspr	DC_CST, r10 +	blr + +cache_post_dwb: +	lis	r10, IDC_ENABLE@h +	mtspr	DC_CST, r10 +	lis	r10, DC_CFWT@h +	mtspr	DC_CST, r10 +	blr + +cache_post_dwt: +	lis	r10, IDC_ENABLE@h +	mtspr	DC_CST, r10 +	lis	r10, DC_SFWT@h +	mtspr	DC_CST, r10 +	blr + +cache_post_idisable: +	lis	r10, IDC_DISABLE@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ienable: +	lis	r10, IDC_ENABLE@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_iunlock: +	lis	r10, IDC_UNALL@h +	mtspr	IC_CST, r10 +	isync +	blr + +cache_post_ilock: +	mtspr	IC_ADR, r3 +	lis	r10, IDC_LDLCK@h +	mtspr	IC_CST, r10 +	isync +	blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the negative pattern to a cached area + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test1 +cache_post_test1: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * turn off the data cache + * write the negative pattern to the area + * turn on the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test2 +cache_post_test2: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwb + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * flush the data cache + * write the negative pattern to the area + * turn off the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test3 +cache_post_test3: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwt +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +/* + * turn on the data cache + * switch the data cache to write-back mode + * invalidate the data cache + * write the negative pattern to a cached area + * flush the data cache + * write the zero pattern to the area + * invalidate the data cache + * read the area + * + * The negative pattern must be read at the last step + */ +	.global cache_post_test4 +cache_post_test4: +	mflr	r0 +	stw	r0, 4(r1) + +	stwu	r3, -4(r1) +	stwu	r4, -4(r1) + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Write the negative pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0xff +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_dwb +	bl	cache_post_dinvalidate + +	/* Write the zero pattern to the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	li	r0, 0 +	lwz	r3, 4(r1) +	subi	r3, r3, 1 +1: +	stbu	r0, 1(r3) +	bdnz	1b + +	bl	cache_post_ddisable +	bl	cache_post_dinvalidate + +	/* Read the test area */ +	lwz	r0, 0(r1) +	mtctr	r0 +	lwz	r4, 4(r1) +	subi	r4, r4, 1 +	li	r3, 0 +1: +	lbzu	r0, 1(r4) +	cmpli	cr0, r0, 0xff +	beq	2f +	li	r3, -1 +	b	3f +2: +	bdnz	1b +3: + +	addi	r1, r1, 8 + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +cache_post_test5_1: +	li	r3, 0 +cache_post_test5_2: +	li	r3, -1 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed +*/ +	.global cache_post_test5 +cache_post_test5: +	mflr	r0 +	stw	r0, 4(r1) + +	bl	cache_post_ienable +	bl	cache_post_iunlock +	bl	cache_post_iinvalidate + +	/* Compute r9 = cache_post_test5_reloc */ +	bl	cache_post_test5_reloc +cache_post_test5_reloc: +	mflr	r9 + +	/* Copy the test instruction to cache_post_test5_data */ +	lis	r3, (cache_post_test5_1 - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_1 - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Lock the branch instruction */ +	lis	r3, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	bl	cache_post_ilock + +	/* Replace the test instruction */ +	lis	r3, (cache_post_test5_2 - cache_post_test5_reloc)@h +	ori	r3, r3, (cache_post_test5_2 - cache_post_test5_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test5_data - cache_post_test5_reloc)@h +	ori	r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Execute to the test instruction */ +cache_post_test5_data: +	nop + +	bl	cache_post_iunlock + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +cache_post_test6_1: +	li	r3, -1 +cache_post_test6_2: +	li	r3, 0 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed + */ +	.global cache_post_test6 +cache_post_test6: +	mflr	r0 +	stw	r0, 4(r1) + +	bl	cache_post_ienable +	bl	cache_post_iunlock +	bl	cache_post_iinvalidate + +	/* Compute r9 = cache_post_test6_reloc */ +	bl	cache_post_test6_reloc +cache_post_test6_reloc: +	mflr	r9 + +	/* Copy the test instruction to cache_post_test6_data */ +	lis	r3, (cache_post_test6_1 - cache_post_test6_reloc)@h +	ori	r3, r3, (cache_post_test6_1 - cache_post_test6_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test6_data - cache_post_test6_reloc)@h +	ori	r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Replace the test instruction */ +	lis	r3, (cache_post_test6_2 - cache_post_test6_reloc)@h +	ori	r3, r3, (cache_post_test6_2 - cache_post_test6_reloc)@l +	add	r3, r3, r9 +	lis	r4, (cache_post_test6_data - cache_post_test6_reloc)@h +	ori	r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l +	add	r4, r4, r9 +	lwz	r0, 0(r3) +	stw	r0, 0(r4) + +	bl	cache_post_iinvalidate + +	/* Execute to the test instruction */ +cache_post_test6_data: +	nop + +	lwz	r0, 4(r1) +	mtlr	r0 +	blr + +#endif /* CONFIG_MPC823 || MPC850 || MPC855 || MPC860 */ +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/roms/u-boot/post/cpu/mpc8xx/ether.c b/roms/u-boot/post/cpu/mpc8xx/ether.c new file mode 100644 index 00000000..d1225001 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/ether.c @@ -0,0 +1,561 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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; + +#ifdef CONFIG_RPXLITE +	*((uchar *) BCSR0) |= BCSR0_ETHEN; +#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 */ +#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 */ diff --git a/roms/u-boot/post/cpu/mpc8xx/spr.c b/roms/u-boot/post/cpu/mpc8xx/spr.c new file mode 100644 index 00000000..d20da8d1 --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/spr.c @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 */ diff --git a/roms/u-boot/post/cpu/mpc8xx/uart.c b/roms/u-boot/post/cpu/mpc8xx/uart.c new file mode 100644 index 00000000..5214c71b --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/uart.c @@ -0,0 +1,534 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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) +	/* 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; + +	/* 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 */ diff --git a/roms/u-boot/post/cpu/mpc8xx/usb.c b/roms/u-boot/post/cpu/mpc8xx/usb.c new file mode 100644 index 00000000..6334088e --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/usb.c @@ -0,0 +1,249 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * USB test + * + * The USB controller is tested in the local loopback mode. + * It is configured so that endpoint 0 operates as host and endpoint 1 + * operates as function endpoint. After that an IN token transaction + * is performed. + * Refer to MPC850 User Manual, Section 32.11.1 USB Host Controller + * Initialization Example. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_USB + +#include <commproc.h> +#include <command.h> + +#define TOUT_LOOP 100 + +#define	PROFF_USB		((uint)0x0000) + +#define CPM_USB_EP0_BASE	0x0a00 +#define CPM_USB_EP1_BASE	0x0a20 + +#define CPM_USB_DT0_BASE	0x0a80 +#define CPM_USB_DT1_BASE	0x0a90 +#define CPM_USB_DR0_BASE	0x0aa0 +#define CPM_USB_DR1_BASE	0x0ab0 + +#define CPM_USB_RX0_BASE	0x0b00 +#define CPM_USB_RX1_BASE	0x0b08 +#define CPM_USB_TX0_BASE	0x0b20 +#define CPM_USB_TX1_BASE	0x0b28 + +#define USB_EXPECT(x)		if (!(x)) goto Done; + +typedef struct usb_param { +	ushort ep0ptr; +	ushort ep1ptr; +	ushort ep2ptr; +	ushort ep3ptr; +	uint rstate; +	uint rptr; +	ushort frame_n; +	ushort rbcnt; +	ushort rtemp; +} usb_param_t; + +typedef struct usb_param_block { +	ushort rbase; +	ushort tbase; +	uchar rfcr; +	uchar tfcr; +	ushort mrblr; +	ushort rbptr; +	ushort tbptr; +	uint tstate; +	uint tptr; +	ushort tcrc; +	ushort tbcnt; +	uint res[2]; +} usb_param_block_t; + +typedef struct usb { +	uchar usmod; +	uchar usadr; +	uchar uscom; +	uchar res1; +	ushort usep[4]; +	uchar res2[4]; +	ushort usber; +	uchar res3[2]; +	ushort usbmr; +	uchar res4; +	uchar usbs; +	uchar res5[8]; +} usb_t; + +int usb_post_test (int flags) +{ +	int res = -1; +	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; +	volatile cpm8xx_t *cp = &(im->im_cpm); +	volatile usb_param_t *pram_ptr; +	uint dpram; +	ushort DPRAM; +	volatile cbd_t *tx; +	volatile cbd_t *rx; +	volatile usb_t *usbr; +	volatile usb_param_block_t *ep0; +	volatile usb_param_block_t *ep1; +	int j; + +	pram_ptr = (usb_param_t *) & (im->im_cpm.cp_dparam[PROFF_USB]); +	dpram = (uint) im->im_cpm.cp_dpmem; +	DPRAM = dpram; +	tx = (cbd_t *) (dpram + CPM_USB_TX0_BASE); +	rx = (cbd_t *) (dpram + CPM_USB_RX0_BASE); +	ep0 = (usb_param_block_t *) (dpram + CPM_USB_EP0_BASE); +	ep1 = (usb_param_block_t *) (dpram + CPM_USB_EP1_BASE); +	usbr = (usb_t *) & (im->im_cpm.cp_scc[0]); + +	/* 01 */ +	im->im_ioport.iop_padir &= ~(ushort) 0x0200; +	im->im_ioport.iop_papar |= (ushort) 0x0200; + +	cp->cp_sicr &= ~0x000000FF; +	cp->cp_sicr |= 0x00000018; + +	cp->cp_brgc4 = 0x00010001; + +	/* 02 */ +	im->im_ioport.iop_padir &= ~(ushort) 0x0002; +	im->im_ioport.iop_padir &= ~(ushort) 0x0001; + +	im->im_ioport.iop_papar |= (ushort) 0x0002; +	im->im_ioport.iop_papar |= (ushort) 0x0001; + +	/* 03 */ +	im->im_ioport.iop_pcdir &= ~(ushort) 0x0020; +	im->im_ioport.iop_pcdir &= ~(ushort) 0x0010; + +	im->im_ioport.iop_pcpar &= ~(ushort) 0x0020; +	im->im_ioport.iop_pcpar &= ~(ushort) 0x0010; + +	im->im_ioport.iop_pcso |= (ushort) 0x0020; +	im->im_ioport.iop_pcso |= (ushort) 0x0010; + +	/* 04 */ +	im->im_ioport.iop_pcdir |= (ushort) 0x0200; +	im->im_ioport.iop_pcdir |= (ushort) 0x0100; + +	im->im_ioport.iop_pcpar |= (ushort) 0x0200; +	im->im_ioport.iop_pcpar |= (ushort) 0x0100; + +	/* 05 */ +	pram_ptr->frame_n = 0; + +	/* 06 */ +	pram_ptr->ep0ptr = DPRAM + CPM_USB_EP0_BASE; +	pram_ptr->ep1ptr = DPRAM + CPM_USB_EP1_BASE; + +	/* 07-10 */ +	tx[0].cbd_sc = 0xB800; +	tx[0].cbd_datlen = 3; +	tx[0].cbd_bufaddr = dpram + CPM_USB_DT0_BASE; + +	tx[1].cbd_sc = 0xBC80; +	tx[1].cbd_datlen = 3; +	tx[1].cbd_bufaddr = dpram + CPM_USB_DT1_BASE; + +	rx[0].cbd_sc = 0xA000; +	rx[0].cbd_datlen = 0; +	rx[0].cbd_bufaddr = dpram + CPM_USB_DR0_BASE; + +	rx[1].cbd_sc = 0xA000; +	rx[1].cbd_datlen = 0; +	rx[1].cbd_bufaddr = dpram + CPM_USB_DR1_BASE; + +	/* 11-12 */ +	*(volatile int *) (dpram + CPM_USB_DT0_BASE) = 0x69856000; +	*(volatile int *) (dpram + CPM_USB_DT1_BASE) = 0xABCD1234; + +	*(volatile int *) (dpram + CPM_USB_DR0_BASE) = 0; +	*(volatile int *) (dpram + CPM_USB_DR1_BASE) = 0; + +	/* 13-16 */ +	ep0->rbase = DPRAM + CPM_USB_RX0_BASE; +	ep0->tbase = DPRAM + CPM_USB_TX0_BASE; +	ep0->rfcr = 0x18; +	ep0->tfcr = 0x18; +	ep0->mrblr = 0x100; +	ep0->rbptr = DPRAM + CPM_USB_RX0_BASE; +	ep0->tbptr = DPRAM + CPM_USB_TX0_BASE; +	ep0->tstate = 0; + +	/* 17-20 */ +	ep1->rbase = DPRAM + CPM_USB_RX1_BASE; +	ep1->tbase = DPRAM + CPM_USB_TX1_BASE; +	ep1->rfcr = 0x18; +	ep1->tfcr = 0x18; +	ep1->mrblr = 0x100; +	ep1->rbptr = DPRAM + CPM_USB_RX1_BASE; +	ep1->tbptr = DPRAM + CPM_USB_TX1_BASE; +	ep1->tstate = 0; + +	/* 21-24 */ +	usbr->usep[0] = 0x0000; +	usbr->usep[1] = 0x1100; +	usbr->usep[2] = 0x2200; +	usbr->usep[3] = 0x3300; + +	/* 25 */ +	usbr->usmod = 0x06; + +	/* 26 */ +	usbr->usadr = 0x05; + +	/* 27 */ +	usbr->uscom = 0; + +	/* 28 */ +	usbr->usmod |= 0x01; +	udelay (1); + +	/* 29-30 */ +	usbr->uscom = 0x80; +	usbr->uscom = 0x81; + +	/* Wait for the data packet to be transmitted */ +	for (j = 0; j < TOUT_LOOP; j++) { +		if (tx[1].cbd_sc & (ushort) 0x8000) +			udelay (1); +		else +			break; +	} + +	USB_EXPECT (j < TOUT_LOOP); + +	USB_EXPECT (tx[0].cbd_sc == 0x3800); +	USB_EXPECT (tx[0].cbd_datlen == 3); + +	USB_EXPECT (tx[1].cbd_sc == 0x3C80); +	USB_EXPECT (tx[1].cbd_datlen == 3); + +	USB_EXPECT (rx[0].cbd_sc == 0x2C00); +	USB_EXPECT (rx[0].cbd_datlen == 5); + +	USB_EXPECT (*(volatile int *) (dpram + CPM_USB_DR0_BASE) == +				0xABCD122B); +	USB_EXPECT (*(volatile char *) (dpram + CPM_USB_DR0_BASE + 4) == 0x42); + +	res = 0; +  Done: + +	return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_USB */ diff --git a/roms/u-boot/post/cpu/mpc8xx/watchdog.c b/roms/u-boot/post/cpu/mpc8xx/watchdog.c new file mode 100644 index 00000000..a070539b --- /dev/null +++ b/roms/u-boot/post/cpu/mpc8xx/watchdog.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * Watchdog test + * + * The test verifies the watchdog timer operation. + * On the first iteration, the test routine disables interrupts and + * makes a 10-second delay. If the system does not reboot during this delay, + * the watchdog timer is not operational and the test fails. If the system + * reboots, on the second iteration the test routine reports a success. + */ + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +static ulong gettbl (void) +{ +	ulong r; + +  asm ("mftbl %0":"=r" (r)); + +	return r; +} + +int watchdog_post_test (int flags) +{ +	if (flags & POST_REBOOT) { +		/* Test passed */ + +		return 0; +	} else { +		/* 10-second delay */ +		int ints = disable_interrupts (); +		ulong base = gettbl (); +		ulong clk = get_tbclk (); + +		while ((gettbl () - base) / 10 < clk); + +		if (ints) +			enable_interrupts (); + +		/* +		 * If we have reached this point, the watchdog timer +		 * does not work +		 */ +		return -1; +	} +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ diff --git a/roms/u-boot/post/cpu/ppc4xx/Makefile b/roms/u-boot/post/cpu/ppc4xx/Makefile new file mode 100644 index 00000000..e9ec286c --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/Makefile @@ -0,0 +1,16 @@ +# +# (C) Copyright 2002-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += cache_4xx.o +obj-y += cache.o +obj-y += denali_ecc.o +obj-y += ether.o +obj-y += fpu.o +obj-y += ocm.o +obj-y += spr.o +obj-y += uart.o +obj-y += watchdog.o diff --git a/roms/u-boot/post/cpu/ppc4xx/cache.c b/roms/u-boot/post/cpu/ppc4xx/cache.c new file mode 100644 index 00000000..e5ea5335 --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/cache.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +#include <asm/mmu.h> +#include <watchdog.h> + +#define CACHE_POST_SIZE	1024 + +int cache_post_test1 (int tlb, void *p, int size); +int cache_post_test2 (int tlb, void *p, int size); +int cache_post_test3 (int tlb, void *p, int size); +int cache_post_test4 (int tlb, void *p, int size); +int cache_post_test5 (int tlb, void *p, int size); +int cache_post_test6 (int tlb, void *p, int size); + +#ifdef CONFIG_440 +static unsigned char testarea[CACHE_POST_SIZE] +__attribute__((__aligned__(CACHE_POST_SIZE))); +#endif + +int cache_post_test (int flags) +{ +	void *virt = (void *)CONFIG_SYS_POST_CACHE_ADDR; +	int ints; +	int res = 0; +	int tlb = -1;		/* index to the victim TLB entry */ + +	/* +	 * All 44x variants deal with cache management differently +	 * because they have the address translation always enabled. +	 * The 40x ppc's don't use address translation in U-Boot at all, +	 * so we have to distinguish here between 40x and 44x. +	 */ +#ifdef CONFIG_440 +	int word0, i; + +	/* +	 * Allocate a new TLB entry, since we are going to modify +	 * the write-through and caching inhibited storage attributes. +	 */ +	program_tlb((u32)testarea, (u32)virt, CACHE_POST_SIZE, +		    TLB_WORD2_I_ENABLE); + +	/* Find the TLB entry */ +	for (i = 0;; i++) { +		if (i >= PPC4XX_TLB_SIZE) { +			printf ("Failed to program tlb entry\n"); +			return -1; +		} +		word0 = mftlb1(i); +		if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) { +			tlb = i; +			break; +		} +	} +#endif +	ints = disable_interrupts (); + +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE); + +	if (ints) +		enable_interrupts (); + +#ifdef CONFIG_440 +	remove_tlb((u32)virt, CACHE_POST_SIZE); +#endif + +	return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S b/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S new file mode 100644 index 00000000..15a133cf --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,473 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CACHE + +	.text + +	/* +	 * All 44x variants deal with cache management differently +	 * because they have the address translation always enabled. +	 * The 40x ppc's don't use address translation in U-Boot at all, +	 * so we have to distinguish here between 40x and 44x. +	 */ +#ifdef CONFIG_440 +/* void cache_post_disable (int tlb) + */ +cache_post_disable: +	tlbre	r0, r3, 0x0002 +	ori	r0, r0, TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: +	tlbre	r0, r3, 0x0002 +	ori	r0, r0, TLB_WORD2_W_ENABLE@l +	andi.	r0, r0, ~TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: +	tlbre	r0, r3, 0x0002 +	andi.	r0, r0, ~TLB_WORD2_W_ENABLE@l +	andi.	r0, r0, ~TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr +#else +/* void cache_post_disable (int tlb) + */ +cache_post_disable: +	lis	r0, 0x0000 +	ori	r0, r0, 0x0000 +	mtdccr	r0 +	sync +	isync +	blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: +	lis	r0, 0x8000 +	ori	r0, r0, 0x0000 +	mtdccr	r0 +	lis	r0, 0x8000 +	ori	r0, r0, 0x0000 +	mtdcwr	r0 +	sync +	isync +	blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: +	lis	r0, 0x8000 +	ori	r0, r0, 0x0000 +	mtdccr	r0 +	lis	r0, 0x0000 +	ori	r0, r0, 0x0000 +	mtdcwr	r0 +	sync +	isync +	blr +#endif + +/* void cache_post_dinvalidate (void *p, int size) + */ +cache_post_dinvalidate: +	dcbi	r0, r3 +	addi	r3, r3, CONFIG_SYS_CACHELINE_SIZE +	subic.	r4, r4, CONFIG_SYS_CACHELINE_SIZE +	bgt	cache_post_dinvalidate +	sync +	blr + +/* void cache_post_dstore (void *p, int size) + */ +cache_post_dstore: +	dcbst	r0, r3 +	addi	r3, r3, CONFIG_SYS_CACHELINE_SIZE +	subic.	r4, r4, CONFIG_SYS_CACHELINE_SIZE +	bgt	cache_post_dstore +	sync +	blr + +/* void cache_post_dtouch (void *p, int size) + */ +cache_post_dtouch: +	dcbt	r0, r3 +	addi	r3, r3, CONFIG_SYS_CACHELINE_SIZE +	subic.	r4, r4, CONFIG_SYS_CACHELINE_SIZE +	bgt	cache_post_dtouch +	sync +	blr + +/* void cache_post_iinvalidate (void) + */ +cache_post_iinvalidate: +	iccci	r0, r0 +	sync +	blr + +/* void cache_post_memset (void *p, int val, int size) + */ +cache_post_memset: +	mtctr	r5 +1: +	stb	r4, 0(r3) +	addi	r3, r3, 1 +	bdnz	1b +	blr + +/* int cache_post_check (void *p, int size) + */ +cache_post_check: +	mtctr	r4 +1: +	lbz	r0, 0(r3) +	addi	r3, r3, 1 +	cmpwi	r0, 0xff +	bne	2f +	bdnz	1b +	li	r3, 0 +	blr +2: +	li	r3, -1 +	blr + +#define CACHE_POST_DISABLE()		\ +	mr	r3, r10;		\ +	bl	cache_post_disable + +#define CACHE_POST_WT()			\ +	mr	r3, r10;		\ +	bl	cache_post_wt + +#define CACHE_POST_WB()			\ +	mr	r3, r10;		\ +	bl	cache_post_wb + +#define CACHE_POST_DINVALIDATE()	\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dinvalidate + +#define CACHE_POST_DFLUSH()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dflush + +#define CACHE_POST_DSTORE()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dstore + +#define CACHE_POST_DTOUCH()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dtouch + +#define CACHE_POST_IINVALIDATE()	\ +	bl	cache_post_iinvalidate + +#define CACHE_POST_MEMSET(val)		\ +	mr	r3, r11;		\ +	li	r4, val;		\ +	mr	r5, r12;		\ +	bl	cache_post_memset + +#define CACHE_POST_CHECK()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_check;	\ +	mr	r13, r3 + +/* + * Write and read 0xff pattern with caching enabled. + */ +	.global cache_post_test1 +cache_post_test1: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write zeroes with caching enabled. + * Write 0xff pattern with caching disabled. + * Read 0xff pattern with caching enabled. + */ +	.global cache_post_test2 +cache_post_test2: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_WB() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write-through mode test. + * Write zeroes, store the cache, write 0xff pattern. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ +	.global cache_post_test3 +cache_post_test3: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_DINVALIDATE() + +	/* Cache the test area */ +	CACHE_POST_DTOUCH() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DSTORE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write-back mode test. + * Write 0xff pattern, store the cache, write zeroes. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ +	.global cache_post_test4 +cache_post_test4: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Cache the test area */ +	CACHE_POST_DTOUCH() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_DSTORE() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions. + * Check that the original instructions are executed. + */ +	.global cache_post_test5 +cache_post_test5: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_IINVALIDATE() + +	/* Compute r13 = cache_post_test_inst */ +	bl	cache_post_test5_reloc +cache_post_test5_reloc: +	mflr	r13 +	lis	r0, (cache_post_test_inst - cache_post_test5_reloc)@h +	ori	r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l +	add	r13, r13, r0 + +	/* Copy the test instructions to the test area */ +	lwz	r0, 0(r13) +	stw	r0, 0(r11) +	lwz	r0, 8(r13) +	stw	r0, 4(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl + +	/* Replace the test instruction */ +	lwz	r0, 4(r13) +	stw	r0, 0(r11) +	sync + +	/* Do not invalidate the cache line */ +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl +	mr	r13, r3 + +	CACHE_POST_IINVALIDATE() +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions and invalidate the cache. + * Check that the replaced instructions are executed. + */ +	.global cache_post_test6 +cache_post_test6: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_IINVALIDATE() + +	/* Compute r13 = cache_post_test_inst */ +	bl	cache_post_test6_reloc +cache_post_test6_reloc: +	mflr	r13 +	lis	r0, (cache_post_test_inst - cache_post_test6_reloc)@h +	ori	r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l +	add	r13, r13, r0 + +	/* Copy the test instructions to the test area */ +	lwz	r0, 4(r13) +	stw	r0, 0(r11) +	lwz	r0, 8(r13) +	stw	r0, 4(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl + +	/* Replace the test instruction */ +	lwz	r0, 0(r13) +	stw	r0, 0(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl +	mr	r13, r3 + +	CACHE_POST_IINVALIDATE() +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* Test instructions. + */ +cache_post_test_inst: +	li	r3, 0 +	li	r3, -1 +	blr + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */ diff --git a/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c b/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c new file mode 100644 index 00000000..1190739a --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/denali_ecc.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2007 + * Developed for DENX Software Engineering GmbH. + * + * Author: Pavel Kolesnikov <concord@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <watchdog.h> + +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ECC + +/* + * MEMORY ECC test + * + * This test performs the checks ECC facility of memory. + */ +#include <asm/processor.h> +#include <asm/mmu.h> +#include <asm/io.h> +#include <asm/ppc440.h> + +DECLARE_GLOBAL_DATA_PTR; + +const static uint8_t syndrome_codes[] = { +	0xF4, 0XF1, 0XEC, 0XEA, 0XE9, 0XE6, 0XE5, 0XE3, +	0XDC, 0XDA, 0XD9, 0XD6, 0XD5, 0XD3, 0XCE, 0XCB, +	0xB5, 0XB0, 0XAD, 0XAB, 0XA8, 0XA7, 0XA4, 0XA2, +	0X9D, 0X9B, 0X98, 0X97, 0X94, 0X92, 0X8F, 0X8A, +	0x75, 0x70, 0X6D, 0X6B, 0X68, 0X67, 0X64, 0X62, +	0X5E, 0X5B, 0X58, 0X57, 0X54, 0X52, 0X4F, 0X4A, +	0x34, 0x31, 0X2C, 0X2A, 0X29, 0X26, 0X25, 0X23, +	0X1C, 0X1A, 0X19, 0X16, 0X15, 0X13, 0X0E, 0X0B, +	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +#define ECC_START_ADDR		0x10 +#define ECC_STOP_ADDR		0x2000 +#define ECC_PATTERN		0x01010101 +#define ECC_PATTERN_CORR	0x11010101 +#define ECC_PATTERN_UNCORR	0x61010101 + +inline static void disable_ecc(void) +{ +	uint32_t value; + +	sync(); /* Wait for any pending memory accesses to complete. */ +	mfsdram(DDR0_22, value); +	mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) +		| DDR0_22_CTRL_RAW_ECC_DISABLE); +} + +inline static void clear_and_enable_ecc(void) +{ +	uint32_t value; + +	sync(); /* Wait for any pending memory accesses to complete. */ +	mfsdram(DDR0_00, value); +	mtsdram(DDR0_00, value | DDR0_00_INT_ACK_ALL); +	mfsdram(DDR0_22, value); +	mtsdram(DDR0_22, (value & ~DDR0_22_CTRL_RAW_MASK) +		| DDR0_22_CTRL_RAW_ECC_ENABLE); +} + +static uint32_t get_ecc_status(void) +{ +	uint32_t int_status; +#if defined(DEBUG) +	uint8_t syndrome; +	uint32_t hdata, ldata, haddr, laddr; +	uint32_t value; +#endif + +	mfsdram(DDR0_00, int_status); +	int_status &= DDR0_00_INT_STATUS_MASK; + +#if defined(DEBUG) +	if (int_status & (DDR0_00_INT_STATUS_BIT0 | DDR0_00_INT_STATUS_BIT1)) { +		mfsdram(DDR0_32, laddr); +		mfsdram(DDR0_33, haddr); +		haddr &= 0x00000001; +		if (int_status & DDR0_00_INT_STATUS_BIT1) +			debug("Multiple accesses"); +		else +			debug("A single access"); + +		debug(" outside the defined physical memory space detected\n" +		      "        addr = 0x%01x%08x\n", haddr, laddr); +	} +	if (int_status & (DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT3)) { +		unsigned int bit; + +		mfsdram(DDR0_23, value); +		syndrome = (value >> 16) & 0xff; +		for (bit = 0; bit < sizeof(syndrome_codes); bit++) +			if (syndrome_codes[bit] == syndrome) +				break; + +		mfsdram(DDR0_38, laddr); +		mfsdram(DDR0_39, haddr); +		haddr &= 0x00000001; +		mfsdram(DDR0_40, ldata); +		mfsdram(DDR0_41, hdata); +		if (int_status & DDR0_00_INT_STATUS_BIT3) +			debug("Multiple correctable ECC events"); +		else +			debug("Single correctable ECC event"); + +		debug(" detected\n        0x%01x%08x - 0x%08x%08x, bit - %d\n", +		      haddr, laddr, hdata, ldata, bit); +	} +	if (int_status & (DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT5)) { +		mfsdram(DDR0_23, value); +		syndrome = (value >> 8) & 0xff; +		mfsdram(DDR0_34, laddr); +		mfsdram(DDR0_35, haddr); +		haddr &= 0x00000001; +		mfsdram(DDR0_36, ldata); +		mfsdram(DDR0_37, hdata); +		if (int_status & DDR0_00_INT_STATUS_BIT5) +			debug("Multiple uncorrectable ECC events"); +		else +			debug("Single uncorrectable ECC event"); + +		debug(" detected\n        0x%01x%08x - 0x%08x%08x, " +		      "syndrome - 0x%02x\n", +		      haddr, laddr, hdata, ldata, syndrome); +	} +	if (int_status & DDR0_00_INT_STATUS_BIT6) +		debug("DRAM initialization complete\n"); +#endif /* defined(DEBUG) */ + +	return int_status; +} + +static int test_ecc(uint32_t ecc_addr) +{ +	uint32_t value; +	volatile uint32_t *const ecc_mem = (volatile uint32_t *)ecc_addr; +	int ret = 0; + +	WATCHDOG_RESET(); + +	debug("Entering test_ecc(0x%08x)\n", ecc_addr); +	/* Set up correct ECC in memory */ +	disable_ecc(); +	clear_and_enable_ecc(); +	out_be32(ecc_mem, ECC_PATTERN); +	out_be32(ecc_mem + 1, ECC_PATTERN); +	ppcDcbf((u32)ecc_mem); + +	/* Verify no ECC error reading back */ +	value = in_be32(ecc_mem); +	disable_ecc(); +	if (ECC_PATTERN != value) { +		debug("Data read error (no-error case): " +		      "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); +		ret = 1; +	} +	value = get_ecc_status(); +	if (0x00000000 != value) { +		/* Expected no ECC status reported */ +		debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", +		      0x00000000, value); +		ret = 1; +	} + +	/* Test for correctable error by creating a one-bit error */ +	out_be32(ecc_mem, ECC_PATTERN_CORR); +	ppcDcbf((u32)ecc_mem); +	clear_and_enable_ecc(); +	value = in_be32(ecc_mem); +	disable_ecc(); +	/* Test that the corrected data was read */ +	if (ECC_PATTERN != value) { +		debug("Data read error (correctable-error case): " +		      "expected 0x%08x, read 0x%08x\n", ECC_PATTERN, value); +		ret = 1; +	} +	value = get_ecc_status(); +	if ((DDR0_00_INT_STATUS_BIT2 | DDR0_00_INT_STATUS_BIT7) != value) { +		/* Expected a single correctable error reported */ +		debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", +		      DDR0_00_INT_STATUS_BIT2, value); +		ret = 1; +	} + +	/* Test for uncorrectable error by creating a two-bit error */ +	out_be32(ecc_mem, ECC_PATTERN_UNCORR); +	ppcDcbf((u32)ecc_mem); +	clear_and_enable_ecc(); +	value = in_be32(ecc_mem); +	disable_ecc(); +	/* Test that the corrected data was read */ +	if (ECC_PATTERN_UNCORR != value) { +		debug("Data read error (uncorrectable-error case): " +		      "expected 0x%08x, read 0x%08x\n", ECC_PATTERN_UNCORR, +		      value); +		ret = 1; +	} +	value = get_ecc_status(); +	if ((DDR0_00_INT_STATUS_BIT4 | DDR0_00_INT_STATUS_BIT7) != value) { +		/* Expected a single uncorrectable error reported */ +		debug("get_ecc_status(): expected 0x%08x, got 0x%08x\n", +		      DDR0_00_INT_STATUS_BIT4, value); +		ret = 1; +	} + +	/* Remove error from SDRAM and enable ECC. */ +	out_be32(ecc_mem, ECC_PATTERN); +	ppcDcbf((u32)ecc_mem); +	clear_and_enable_ecc(); + +	return ret; +} + +int ecc_post_test(int flags) +{ +	int ret = 0; +	uint32_t value; +	uint32_t iaddr; + +	mfsdram(DDR0_22, value); +	if (0x3 != DDR0_22_CTRL_RAW_DECODE(value)) { +		debug("SDRAM ECC not enabled, skipping ECC POST.\n"); +		return 0; +	} + +	/* Mask all interrupts. */ +	mfsdram(DDR0_01, value); +	mtsdram(DDR0_01, (value & ~DDR0_01_INT_MASK_MASK) +		| DDR0_01_INT_MASK_ALL_OFF); + +	for (iaddr = ECC_START_ADDR; iaddr <= ECC_STOP_ADDR; iaddr += iaddr) { +		ret = test_ecc(iaddr); +		if (ret) +			break; +	} +	/* +	 * Clear possible errors resulting from ECC testing.  (If not done, we +	 * we could get an interrupt later on when exceptions are enabled.) +	 */ +	set_mcsr(get_mcsr()); +	debug("ecc_post_test() returning %d\n", ret); +	return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_ECC */ +#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */ diff --git a/roms/u-boot/post/cpu/ppc4xx/ether.c b/roms/u-boot/post/cpu/ppc4xx/ether.c new file mode 100644 index 00000000..4c9a39b5 --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/ether.c @@ -0,0 +1,419 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * Ethernet test + * + * The Ethernet Media Access Controllers (EMAC) are tested in the + * internal loopback mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + *   MIN_PACKET_LENGTH - minimum size of packet to transmit + *   MAX_PACKET_LENGTH - maximum size of packet to transmit + *   CONFIG_SYS_POST_ETH_LOOPS - Number of test loops. Each loop + *     is tested with a different frame length. Starting with + *     MAX_PACKET_LENGTH and going down to MIN_PACKET_LENGTH. + *     Defaults to 10 and can be overriden in the board config header. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_ETHER + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/ppc4xx-mal.h> +#include <asm/ppc4xx-emac.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Get count of EMAC devices (doesn't have to be the max. possible number + * supported by the cpu) + * + * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the + * EMAC count is possible. As it is needed for the Kilauea/Haleakala + * 405EX/405EXr eval board, using the same binary. + */ +#if defined(CONFIG_BOARD_EMAC_COUNT) +#define LAST_EMAC_NUM	board_emac_count() +#else /* CONFIG_BOARD_EMAC_COUNT */ +#if defined(CONFIG_HAS_ETH3) +#define LAST_EMAC_NUM	4 +#elif defined(CONFIG_HAS_ETH2) +#define LAST_EMAC_NUM	3 +#elif defined(CONFIG_HAS_ETH1) +#define LAST_EMAC_NUM	2 +#else +#define LAST_EMAC_NUM	1 +#endif +#endif /* CONFIG_BOARD_EMAC_COUNT */ + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n)	((0x01<<27) / (n+1)) +#endif + +#define MIN_PACKET_LENGTH	64 +#define MAX_PACKET_LENGTH	1514 +#ifndef CONFIG_SYS_POST_ETH_LOOPS +#define CONFIG_SYS_POST_ETH_LOOPS	10 +#endif +#define PACKET_INCR	((MAX_PACKET_LENGTH - MIN_PACKET_LENGTH) / \ +			 CONFIG_SYS_POST_ETH_LOOPS) + +static volatile mal_desc_t tx __cacheline_aligned; +static volatile mal_desc_t rx __cacheline_aligned; +static char *tx_buf; +static char *rx_buf; + +int board_emac_count(void); + +static void ether_post_init (int devnum, int hw_addr) +{ +	int i; +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	unsigned mode_reg; +	sys_info_t sysinfo; +#endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) +	unsigned long mfr; +#endif + +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	/* Need to get the OPB frequency so we can access the PHY */ +	get_sys_info (&sysinfo); +#endif + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	/* provide clocks for EMAC internal loopback  */ +	mfsdr (SDR0_MFR, mfr); +	mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); +	mtsdr (SDR0_MFR, mfr); +	sync (); +#endif +	/* reset emac */ +	out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); +	sync (); + +	for (i = 0;; i++) { +		if (!(in_be32 ((void*)(EMAC0_MR0 + hw_addr)) & EMAC_MR0_SRST)) +			break; +		if (i >= 1000) { +			printf ("Timeout resetting EMAC\n"); +			break; +		} +		udelay (1000); +	} +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	/* Whack the M1 register */ +	mode_reg = 0x0; +	if (sysinfo.freqOPB <= 50000000); +	else if (sysinfo.freqOPB <= 66666667) +		mode_reg |= EMAC_MR1_OBCI_66; +	else if (sysinfo.freqOPB <= 83333333) +		mode_reg |= EMAC_MR1_OBCI_83; +	else if (sysinfo.freqOPB <= 100000000) +		mode_reg |= EMAC_MR1_OBCI_100; +	else +		mode_reg |= EMAC_MR1_OBCI_GT100; + +	out_be32 ((void*)(EMAC0_MR1 + hw_addr), mode_reg); + +#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ + +	/* set the Mal configuration reg */ +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | +	       MAL_CR_PLBLT_DEFAULT | 0x00330000); +#else +	mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); +	/* Errata 1.12: MAL_1 -- Disable MAL bursting */ +	if (get_pvr() == PVR_440GP_RB) { +		mtdcr (MAL0_CFG, mfdcr(MAL0_CFG) & ~MAL_CR_PLBB); +	} +#endif +	/* setup buffer descriptors */ +	tx.ctrl = MAL_TX_CTRL_WRAP; +	tx.data_len = 0; +	tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf); + +	rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY; +	rx.data_len = 0; +	rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf); +	flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); +	flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); + +	switch (devnum) { +	case 1: +		/* setup MAL tx & rx channel pointers */ +#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) +		mtdcr (MAL0_TXCTP2R, &tx); +#else +		mtdcr (MAL0_TXCTP1R, &tx); +#endif +#if defined(CONFIG_440) +		mtdcr (MAL0_TXBADDR, 0x0); +		mtdcr (MAL0_RXBADDR, 0x0); +#endif +		mtdcr (MAL0_RXCTP1R, &rx); +		/* set RX buffer size */ +		mtdcr (MAL0_RCBS1, PKTSIZE_ALIGN / 16); +		break; +	case 0: +	default: +		/* setup MAL tx & rx channel pointers */ +#if defined(CONFIG_440) +		mtdcr (MAL0_TXBADDR, 0x0); +		mtdcr (MAL0_RXBADDR, 0x0); +#endif +		mtdcr (MAL0_TXCTP0R, &tx); +		mtdcr (MAL0_RXCTP0R, &rx); +		/* set RX buffer size */ +		mtdcr (MAL0_RCBS0, PKTSIZE_ALIGN / 16); +		break; +	} + +	/* Enable MAL transmit and receive channels */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +	mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> (devnum*2))); +#else +	mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> devnum)); +#endif +	mtdcr (MAL0_RXCASR, (MAL_TXRX_CASR >> devnum)); + +	/* set internal loopback mode */ +#ifdef CONFIG_SYS_POST_ETHER_EXT_LOOPBACK +	out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | 0 | +		  EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | +		  EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | +		  in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#else +	out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | EMAC_MR1_ILE | +		  EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K | +		  EMAC_MR1_MF_100MBPS | EMAC_MR1_IST | +		  in_be32 ((void*)(EMAC0_MR1 + hw_addr))); +#endif + +	/* set transmit enable & receive enable */ +	out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_TXE | EMAC_MR0_RXE); + +	/* enable broadcast address */ +	out_be32 ((void*)(EMAC0_RXM + hw_addr), EMAC_RMR_BAE); + +	/* set transmit request threshold register */ +	out_be32 ((void*)(EMAC0_TRTR + hw_addr), 0x18000000);	/* 256 byte threshold */ + +	/* set receive	low/high water mark register */ +#if defined(CONFIG_440) +	/* 440s has a 64 byte burst length */ +	out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x80009000); +#else +	/* 405s have a 16 byte burst length */ +	out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x0f002000); +#endif /* defined(CONFIG_440) */ +	out_be32 ((void*)(EMAC0_TMR1 + hw_addr), 0xf8640000); + +	/* Set fifo limit entry in tx mode 0 */ +	out_be32 ((void*)(EMAC0_TMR0 + hw_addr), 0x00000003); +	/* Frame gap set */ +	out_be32 ((void*)(EMAC0_I_FRAME_GAP_REG + hw_addr), 0x00000008); +	sync (); +} + +static void ether_post_halt (int devnum, int hw_addr) +{ +	int i = 0; +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	unsigned long mfr; +#endif + +	/* 1st reset MAL channel */ +	/* Note: writing a 0 to a channel has no effect */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +	mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> (devnum * 2)); +#else +	mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> devnum); +#endif +	mtdcr (MAL0_RXCARR, MAL_TXRX_CASR >> devnum); + +	/* wait for reset */ +	while (mfdcr (MAL0_RXCASR) & (MAL_TXRX_CASR >> devnum)) { +		if (i++ >= 1000) +			break; +		udelay (1000); +	} +	/* emac reset */ +	out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST); + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	/* remove clocks for EMAC internal loopback  */ +	mfsdr (SDR0_MFR, mfr); +	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); +	mtsdr (SDR0_MFR, mfr); +#endif +} + +static void ether_post_send (int devnum, int hw_addr, void *packet, int length) +{ +	int i = 0; + +	while (tx.ctrl & MAL_TX_CTRL_READY) { +		if (i++ > 100) { +			printf ("TX timeout\n"); +			return; +		} +		udelay (1000); +		invalidate_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); +	} +	tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST | +		EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP; +	tx.data_len = length; +	memcpy (tx.data_ptr, packet, length); +	flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t)); +	flush_dcache_range((u32)tx.data_ptr, (u32)tx.data_ptr + length); +	sync (); + +	out_be32 ((void*)(EMAC0_TMR0 + hw_addr), in_be32 ((void*)(EMAC0_TMR0 + hw_addr)) | EMAC_TMR0_GNP0); +	sync (); +} + +static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length) +{ +	int length; +	int i = 0; + +	while (rx.ctrl & MAL_RX_CTRL_EMPTY) { +		if (i++ > 100) { +			printf ("RX timeout\n"); +			return 0; +		} +		udelay (1000); +		invalidate_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); +	} +	length = rx.data_len - 4; +	if (length <= max_length) { +		invalidate_dcache_range((u32)rx.data_ptr, (u32)rx.data_ptr + length); +		memcpy(packet, rx.data_ptr, length); +	} +	sync (); + +	rx.ctrl |= MAL_RX_CTRL_EMPTY; +	flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t)); +	sync (); + +	return length; +} + +  /* +   * Test routines +   */ + +static void packet_fill (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	/* set up ethernet header */ +	memset (packet, 0xff, 14); + +	for (i = 14; i < length; i++) { +		packet[i] = c++; +	} +} + +static int packet_check (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	for (i = 14; i < length; i++) { +		if (packet[i] != c++) +			return -1; +	} + +	return 0; +} + +	char packet_send[MAX_PACKET_LENGTH]; +	char packet_recv[MAX_PACKET_LENGTH]; +static int test_ctlr (int devnum, int hw_addr) +{ +	int res = -1; +	int length; +	int l; + +	ether_post_init (devnum, hw_addr); + +	for (l = MAX_PACKET_LENGTH; l >= MIN_PACKET_LENGTH; +	     l -= PACKET_INCR) { +		packet_fill (packet_send, l); + +		ether_post_send (devnum, hw_addr, packet_send, l); + +		length = ether_post_recv (devnum, hw_addr, packet_recv, +					  sizeof (packet_recv)); + +		if (length != l || packet_check (packet_recv, length) < 0) { +			goto Done; +		} +	} + +	res = 0; + +Done: + +	ether_post_halt (devnum, hw_addr); + +	if (res != 0) { +		post_log ("EMAC%d test failed\n", devnum); +	} + +	return res; +} + +int ether_post_test (int flags) +{ +	int res = 0; +	int i; + +	/* Allocate tx & rx packet buffers */ +	tx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); +	rx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE); + +	if (!tx_buf || !rx_buf) { +		printf ("Failed to allocate packet buffers\n"); +		res = -1; +		goto out_free; +	} + +	for (i = 0; i < LAST_EMAC_NUM; i++) { +		if (test_ctlr (i, i*0x100)) +			res = -1; +	} + +out_free: +	free (tx_buf); +	free (rx_buf); + +	return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */ diff --git a/roms/u-boot/post/cpu/ppc4xx/fpu.c b/roms/u-boot/post/cpu/ppc4xx/fpu.c new file mode 100644 index 00000000..51e53ff2 --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/fpu.c @@ -0,0 +1,41 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> + +#if defined(CONFIG_440EP) || \ +    defined(CONFIG_440EPX) + +#include <asm/processor.h> +#include <asm/ppc4xx.h> + + +int fpu_status(void) +{ +	if (mfspr(SPRN_CCR0) & CCR0_DAPUIB) +		return 0; /* Disabled */ +	else +		return 1; /* Enabled */ +} + + +void fpu_disable(void) +{ +	mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) | CCR0_DAPUIB); +	mtmsr(mfmsr() & ~MSR_FP); +} + + +void fpu_enable(void) +{ +	mtspr(SPRN_CCR0, mfspr(SPRN_CCR0) & ~CCR0_DAPUIB); +	mtmsr(mfmsr() | MSR_FP); +} + +#endif diff --git a/roms/u-boot/post/cpu/ppc4xx/ocm.c b/roms/u-boot/post/cpu/ppc4xx/ocm.c new file mode 100644 index 00000000..bbf2d9a8 --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/ocm.c @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2008 Ilya Yanok, EmCraft Systems, yanok@emcraft.com + * + * Developed for DENX Software Engineering GmbH + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#include <common.h> + +/* + * This test attempts to verify on-chip memory (OCM). Result is written + * to the scratch register and if test succeed it won't be run till next + * power on. + */ + +#include <post.h> + +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define OCM_TEST_PATTERN1	0x55555555 +#define OCM_TEST_PATTERN2	0xAAAAAAAA + +#if CONFIG_POST & CONFIG_SYS_POST_OCM + +static uint ocm_status_read(void) +{ +	return in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & +		CONFIG_SYS_OCM_STATUS_MASK; +} + +static void ocm_status_write(uint value) +{ +	out_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR, value | +		(in_be32((void *)CONFIG_SYS_OCM_STATUS_ADDR) & +			~CONFIG_SYS_OCM_STATUS_MASK)); +} + +static inline int ocm_test_word(uint value, uint *address) +{ +	uint read_value; + +	*address = value; +	sync(); +	read_value = *address; + +	return (read_value != value); +} + +int ocm_post_test(int flags) +{ +	uint   old_value; +	int    ret = 0; +	uint  *address = (uint*)CONFIG_SYS_OCM_BASE; + +	if (ocm_status_read() == CONFIG_SYS_OCM_STATUS_OK) +		return 0; +	for (; address < (uint*)(CONFIG_SYS_OCM_BASE + CONFIG_SYS_OCM_SIZE); address++) { +		old_value = *address; +		if (ocm_test_word(OCM_TEST_PATTERN1, address) || +				ocm_test_word(OCM_TEST_PATTERN2, address)) { +			ret = 1; +			*address = old_value; +			printf("OCM POST failed at %p!\n", address); +			break; +		} +		*address = old_value; +	} +	ocm_status_write(ret ? CONFIG_SYS_OCM_STATUS_FAIL : CONFIG_SYS_OCM_STATUS_OK); +	return ret; +} +#endif /* CONFIG_POST & CONFIG_SYS_POST_OCM */ diff --git a/roms/u-boot/post/cpu/ppc4xx/spr.c b/roms/u-boot/post/cpu/ppc4xx/spr.c new file mode 100644 index 00000000..9a3cdb3c --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/spr.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 */ diff --git a/roms/u-boot/post/cpu/ppc4xx/uart.c b/roms/u-boot/post/cpu/ppc4xx/uart.c new file mode 100644 index 00000000..545b054c --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/uart.c @@ -0,0 +1,92 @@ +/* + * (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 + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/ppc4xx.h> +#include <ns16550.h> +#include <asm/io.h> +#include <serial.h> + +/* + * UART test + * + * The controllers are configured to loopback mode and several + * characters are transmitted. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_UART + +/* + * This table defines the UART's that should be tested and can + * be overridden in the board config file + */ +#ifndef CONFIG_SYS_POST_UART_TABLE +#define CONFIG_SYS_POST_UART_TABLE	{ CONFIG_SYS_NS16550_COM1, \ +			CONFIG_SYS_NS16550_COM2, CONFIG_SYS_NS16550_COM3, \ +			CONFIG_SYS_NS16550_COM4	} +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static int test_ctlr (struct NS16550 *com_port, int index) +{ +	int res = -1; +	char test_str[] = "*** UART Test String ***\r\n"; +	int i; +	int divisor; + +	divisor = (get_serial_clock() + (gd->baudrate * (16 / 2))) / +		(16 * gd->baudrate); +	NS16550_init(com_port, divisor); + +	/* +	 * Set internal loopback mode in UART +	 */ +	out_8(&com_port->mcr, in_8(&com_port->mcr) | UART_MCR_LOOP); + +	/* Reset FIFOs */ +	out_8(&com_port->fcr, UART_FCR_RXSR | UART_FCR_TXSR); +	udelay(100); + +	/* Flush RX-FIFO */ +	while (NS16550_tstc(com_port)) +		NS16550_getc(com_port); + +	for (i = 0; i < sizeof (test_str) - 1; i++) { +		NS16550_putc(com_port, test_str[i]); +		if (NS16550_getc(com_port) != test_str[i]) +			goto done; +	} +	res = 0; +done: +	if (res) +		post_log ("uart%d test failed\n", index); + +	return res; +} + +int uart_post_test (int flags) +{ +	int i, res = 0; +	static unsigned long base[] = CONFIG_SYS_POST_UART_TABLE; + +	for (i = 0; i < ARRAY_SIZE(base); i++) { +		if (test_ctlr((struct NS16550 *)base[i], i)) +			res = -1; +	} +	serial_reinit_all (); + +	return res; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_UART */ diff --git a/roms/u-boot/post/cpu/ppc4xx/watchdog.c b/roms/u-boot/post/cpu/ppc4xx/watchdog.c new file mode 100644 index 00000000..24e80939 --- /dev/null +++ b/roms/u-boot/post/cpu/ppc4xx/watchdog.c @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * Watchdog test + * + * The test verifies the watchdog timer operation. + * On the first iteration, the test routine disables interrupts and + * makes a 10-second delay. If the system does not reboot during this delay, + * the watchdog timer is not operational and the test fails. If the system + * reboots, on the second iteration the test routine reports a success. + */ + +#include <post.h> + +#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG + +#include <watchdog.h> + +int watchdog_post_test (int flags) +{ +	if (flags & POST_REBOOT) { +		/* Test passed */ +		return 0; +	} +	else { +		/* 10-second delay */ +		int ints = disable_interrupts (); +		ulong base = post_time_ms (0); + +		while (post_time_ms (base) < 10000) +			; +		if (ints) +			enable_interrupts (); + +		/* +		 * If we have reached this point, the watchdog timer +		 * does not work +		 */ +		return -1; +	} +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ diff --git a/roms/u-boot/post/drivers/Makefile b/roms/u-boot/post/drivers/Makefile new file mode 100644 index 00000000..1abfb1ff --- /dev/null +++ b/roms/u-boot/post/drivers/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += flash.o i2c.o memory.o rtc.o diff --git a/roms/u-boot/post/drivers/flash.c b/roms/u-boot/post/drivers/flash.c new file mode 100644 index 00000000..07eab332 --- /dev/null +++ b/roms/u-boot/post/drivers/flash.c @@ -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 diff --git a/roms/u-boot/post/drivers/i2c.c b/roms/u-boot/post/drivers/i2c.c new file mode 100644 index 00000000..95da2ebd --- /dev/null +++ b/roms/u-boot/post/drivers/i2c.c @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * 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; +		if (i2c_ignore_device(i2c_addr_list[i])) +			continue; +		post_log("I2C: addr %02x did not respond\n", i2c_addr_list[i]); +		ret = -1; +	} + +	return ret; +#endif +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_I2C */ diff --git a/roms/u-boot/post/drivers/memory.c b/roms/u-boot/post/drivers/memory.c new file mode 100644 index 00000000..d94a4374 --- /dev/null +++ b/roms/u-boot/post/drivers/memory.c @@ -0,0 +1,550 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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) */ diff --git a/roms/u-boot/post/drivers/rtc.c b/roms/u-boot/post/drivers/rtc.c new file mode 100644 index 00000000..cd19f756 --- /dev/null +++ b/roms/u-boot/post/drivers/rtc.c @@ -0,0 +1,179 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * RTC test + * + * The Real Time Clock (RTC) operation is verified by this test. + * The following features are verified: + *   o) RTC Power Fault + *	This is verified by analyzing the rtc_get() return status. + *   o) Time uniformity + *      This is verified by reading RTC in polling within + *      a short period of time. + *   o) Passing month boundaries + *      This is checked by setting RTC to a second before + *      a month boundary and reading it after its passing the + *      boundary. The test is performed for both leap- and + *      nonleap-years. + */ + +#include <post.h> +#include <rtc.h> + +#if CONFIG_POST & CONFIG_SYS_POST_RTC + +static int rtc_post_skip (ulong * diff) +{ +	struct rtc_time tm1; +	struct rtc_time tm2; +	ulong start1; +	ulong start2; + +	rtc_get (&tm1); +	start1 = get_timer (0); + +	while (1) { +		rtc_get (&tm2); +		start2 = get_timer (0); +		if (tm1.tm_sec != tm2.tm_sec) +			break; +		if (start2 - start1 > 1500) +			break; +	} + +	if (tm1.tm_sec != tm2.tm_sec) { +		*diff = start2 - start1; + +		return 0; +	} else { +		return -1; +	} +} + +static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) +{ +	time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, +					   tm->tm_min, tm->tm_sec) + sec; +	struct rtc_time ntm; + +	to_tm (t, &ntm); + +	rtc_set (&ntm); +} + +int rtc_post_test (int flags) +{ +	ulong diff; +	unsigned int i; +	struct rtc_time svtm; +	static unsigned int daysnl[] = +			{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +	static unsigned int daysl[] = +			{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +	unsigned int ynl = 1999; +	unsigned int yl = 2000; +	unsigned int skipped = 0; +	int reliable; + +	/* Time reliability */ +	reliable = rtc_get (&svtm); + +	/* Time uniformity */ +	if (rtc_post_skip (&diff) != 0) { +		post_log ("Timeout while waiting for a new second !\n"); + +		return -1; +	} + +	for (i = 0; i < 5; i++) { +		if (rtc_post_skip (&diff) != 0) { +			post_log ("Timeout while waiting for a new second !\n"); + +			return -1; +		} + +		if (diff < 950 || diff > 1050) { +			post_log ("Invalid second duration !\n"); + +			return -1; +		} +	} + +	/* Passing month boundaries */ + +	if (rtc_post_skip (&diff) != 0) { +		post_log ("Timeout while waiting for a new second !\n"); + +		return -1; +	} +	rtc_get (&svtm); + +	for (i = 0; i < 12; i++) { +		time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); +		struct rtc_time tm; + +		to_tm (t, &tm); +		rtc_set (&tm); + +		skipped++; +		if (rtc_post_skip (&diff) != 0) { +			rtc_post_restore (&svtm, skipped); +			post_log ("Timeout while waiting for a new second !\n"); + +			return -1; +		} + +		rtc_get (&tm); +		if (tm.tm_mon == i + 1) { +			rtc_post_restore (&svtm, skipped); +			post_log ("Month %d boundary is not passed !\n", i + 1); + +			return -1; +		} +	} + +	for (i = 0; i < 12; i++) { +		time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); +		struct rtc_time tm; + +		to_tm (t, &tm); +		rtc_set (&tm); + +		skipped++; +		if (rtc_post_skip (&diff) != 0) { +			rtc_post_restore (&svtm, skipped); +			post_log ("Timeout while waiting for a new second !\n"); + +			return -1; +		} + +		rtc_get (&tm); +		if (tm.tm_mon == i + 1) { +			rtc_post_restore (&svtm, skipped); +			post_log ("Month %d boundary is not passed !\n", i + 1); + +			return -1; +		} +	} +	rtc_post_restore (&svtm, skipped); + +	/* If come here, then RTC operates correcty, check the correctness +	 * of the time it reports. +	 */ +	if (reliable < 0) { +		post_log ("RTC Time is not reliable! Power fault? \n"); + +		return -1; +	} + +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */ diff --git a/roms/u-boot/post/lib_powerpc/Makefile b/roms/u-boot/post/lib_powerpc/Makefile new file mode 100644 index 00000000..0cbb6b6b --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += asm.o +obj-y += cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o +obj-y += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o +obj-y += store.o load.o cr.o b.o multi.o string.o complex.o + +obj-y += fpu/ diff --git a/roms/u-boot/post/lib_powerpc/andi.c b/roms/u-boot/post/lib_powerpc/andi.c new file mode 100644 index 00000000..8a4b89b9 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/andi.c @@ -0,0 +1,103 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/asm.S b/roms/u-boot/post/lib_powerpc/asm.S new file mode 100644 index 00000000..76d2822b --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/asm.S @@ -0,0 +1,342 @@ +/* + *  Copyright (C) 2002 Wolfgang Denk <wd@denx.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */ +	.global	cpu_post_exec_02 +cpu_post_exec_02: +	isync +	mflr	r0 +	stwu	r0, -4(r1) + +	subi	r1, r1, 104 +	stmw	r6, 0(r1) + +	mtlr	r3 +	mr	r3, r4 +	mr	r4, r5 +	blrl + +	lmw	r6, 0(r1) +	addi	r1, r1, 104 + +	lwz	r0, 0(r1) +	addi	r1, r1, 4 +	mtlr	r0 +	blr + +/* void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, ulong op4); */ +	.global	cpu_post_exec_04 +cpu_post_exec_04: +	isync +	mflr	r0 +	stwu	r0, -4(r1) + +	subi	r1, r1, 96 +	stmw	r8, 0(r1) + +	mtlr	r3 +	mr	r3, r4 +	mr	r4, r5 +	mr	r5, r6 +	mtxer	r7 +	blrl + +	lmw	r8, 0(r1) +	addi	r1, r1, 96 + +	lwz	r0, 0(r1) +	addi	r1, r1, 4 +	mtlr	r0 +	blr + +/* void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); */ +	.global	cpu_post_exec_12 +cpu_post_exec_12: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) + +	mtlr	r3 +	mr	r3, r5 +	mr	r4, r6 +	blrl + +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 4(r1) +	addi	r1, r1, 8 +	mtlr	r0 +	blr + +/* void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); */ +	.global	cpu_post_exec_11 +cpu_post_exec_11: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) + +	mtlr	r3 +	mr	r3, r5 +	blrl + +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 4(r1) +	addi	r1, r1, 8 +	mtlr	r0 +	blr + +/* void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); */ +	.global	cpu_post_exec_21 +cpu_post_exec_21: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r5, -4(r1) + +	li	r0, 0 +	mtxer	r0 +	lwz	r0, 0(r4) +	mtcr	r0 + +	mtlr	r3 +	mr	r3, r6 +	blrl + +	mfcr	r0 +	lwz	r4, 4(r1) +	stw	r0, 0(r4) +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 8(r1) +	addi	r1, r1, 12 +	mtlr	r0 +	blr + +/* void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, +    ulong op2); */ +	.global	cpu_post_exec_22 +cpu_post_exec_22: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r5, -4(r1) + +	li	r0, 0 +	mtxer	r0 +	lwz	r0, 0(r4) +	mtcr	r0 + +	mtlr	r3 +	mr	r3, r6 +	mr	r4, r7 +	blrl + +	mfcr	r0 +	lwz	r4, 4(r1) +	stw	r0, 0(r4) +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 8(r1) +	addi	r1, r1, 12 +	mtlr	r0 +	blr + +/* void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); */ +	.global	cpu_post_exec_12w +cpu_post_exec_12w: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) + +	mtlr	r3 +	lwz	r3, 0(r4) +	mr	r4, r5 +	mr	r5, r6 +	blrl + +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 4(r1) +	addi	r1, r1, 8 +	mtlr	r0 +	blr + +/* void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); */ +	.global	cpu_post_exec_11w +cpu_post_exec_11w: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) + +	mtlr	r3 +	lwz	r3, 0(r4) +	mr	r4, r5 +	blrl + +	lwz	r4, 0(r1) +	stw	r3, 0(r4) + +	lwz	r0, 4(r1) +	addi	r1, r1, 8 +	mtlr	r0 +	blr + +/* void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); */ +	.global	cpu_post_exec_22w +cpu_post_exec_22w: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r6, -4(r1) + +	mtlr	r3 +	lwz	r3, 0(r4) +	mr	r4, r5 +	blrl + +	lwz	r4, 4(r1) +	stw	r3, 0(r4) +	lwz	r4, 0(r1) +	stw	r5, 0(r4) + +	lwz	r0, 8(r1) +	addi	r1, r1, 12 +	mtlr	r0 +	blr + +/* void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); */ +	.global	cpu_post_exec_21w +cpu_post_exec_21w: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r5, -4(r1) + +	mtlr	r3 +	lwz	r3, 0(r4) +	blrl + +	lwz	r5, 4(r1) +	stw	r3, 0(r5) +	lwz	r5, 0(r1) +	stw	r4, 0(r5) + +	lwz	r0, 8(r1) +	addi	r1, r1, 12 +	mtlr	r0 +	blr + +/* void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); */ +	.global	cpu_post_exec_21x +cpu_post_exec_21x: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r5, -4(r1) + +	mtlr	r3 +	mr	r3, r6 +	blrl + +	lwz	r5, 4(r1) +	stw	r3, 0(r5) +	lwz	r5, 0(r1) +	stw	r4, 0(r5) + +	lwz	r0, 8(r1) +	addi	r1, r1, 12 +	mtlr	r0 +	blr + +/* void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, +    ulong cr); */ +	.global	cpu_post_exec_31 +cpu_post_exec_31: +	isync +	mflr	r0 +	stwu	r0, -4(r1) +	stwu	r4, -4(r1) +	stwu	r5, -4(r1) +	stwu	r6, -4(r1) + +	mtlr	r3 +	lwz	r3, 0(r4) +	lwz	r4, 0(r5) +	mr	r6, r7 + +	mfcr	r7 +	blrl +	mtcr	r7 + +	lwz	r7, 8(r1) +	stw	r3, 0(r7) +	lwz	r7, 4(r1) +	stw	r4, 0(r7) +	lwz	r7, 0(r1) +	stw	r5, 0(r7) + +	lwz	r0, 12(r1) +	addi	r1, r1, 16 +	mtlr	r0 +	blr + +/* int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); */ +	.global	cpu_post_complex_1_asm +cpu_post_complex_1_asm: +	li	r9,0 +	cmpw	r9,r7 +	bge	cpu_post_complex_1_done +	mtctr	r7 +cpu_post_complex_1_loop: +	mullw	r0,r3,r4 +	subf	r0,r5,r0 +	divw	r0,r0,r6 +	add	r9,r9,r0 +	bdnz	cpu_post_complex_1_loop +cpu_post_complex_1_done: +	mr	r3,r9 +	blr + +/* int cpu_post_complex_2_asm (int x, int n); */ +	.global	cpu_post_complex_2_asm +cpu_post_complex_2_asm: +	mr.	r0,r4 +	mtctr	r0 +	mr	r0,r3 +	li	r3,1 +	li	r4,1 +	blelr +cpu_post_complex_2_loop: +	mullw	r3,r3,r0 +	add	r3,r3,r4 +	bdnz	cpu_post_complex_2_loop +blr + +#endif diff --git a/roms/u-boot/post/lib_powerpc/b.c b/roms/u-boot/post/lib_powerpc/b.c new file mode 100644 index 00000000..43b4c353 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/b.c @@ -0,0 +1,182 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * CPU test + * Branch instructions:		b, bl, bc + * + * The first 2 instructions (b, bl) are verified by jumping + * to a fixed address and checking whether control was transfered + * to that very point. For the bl instruction the value of the + * link register is checked as well (using mfspr). + * To verify the bc instruction various combinations of the BI/BO + * fields, the CTR and the condition register values are + * checked. The list of such combinations is pre-built and + * linked in U-Boot at build time. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); +extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, +    ulong cr); + +static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, +    int pjump, int decr, int link, ulong pctr, ulong cr) +{ +    int ret = 0; +    ulong lr = 0; +    ulong ctr = pctr; +    ulong jump; + +    unsigned long code[] = +    { +	ASM_MTCR(6), +	ASM_MFLR(6), +	ASM_MTCTR(3), +	ASM_MTLR(4), +	ASM_LI(5, 1), +	ASM_3O(cmd, bo, bi, 8), +	ASM_LI(5, 0), +	ASM_MFCTR(3), +	ASM_MFLR(4), +	ASM_MTLR(6), +	ASM_BLR, +    }; + +    cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); + +    if (ret == 0) +	ret = pjump == jump ? 0 : -1; +    if (ret == 0) +    { +	if (decr) +	    ret = pctr == ctr + 1 ? 0 : -1; +	else +	    ret = pctr == ctr ? 0 : -1; +    } +    if (ret == 0) +    { +	if (link) +	    ret = lr == (ulong) code + 24 ? 0 : -1; +	else +	    ret = lr == 0 ? 0 : -1; +    } + +    return ret; +} + +int cpu_post_test_b (void) +{ +    int ret = 0; +    unsigned int i; +    int flag = disable_interrupts(); + +    if (ret == 0) +    { +	ulong code[] = +	{ +	   ASM_MFLR(4), +	   ASM_MTLR(3), +	   ASM_B(4), +	   ASM_MFLR(3), +	   ASM_MTLR(4), +	   ASM_BLR, +	}; +	ulong res; + +	cpu_post_exec_11 (code, &res, 0); + +	ret = res == 0 ? 0 : -1; + +	if (ret != 0) +	{ +	    post_log ("Error at b1 test !\n"); +	} +    } + +    if (ret == 0) +    { +	ulong code[] = +	{ +	   ASM_MFLR(4), +	   ASM_MTLR(3), +	   ASM_BL(4), +	   ASM_MFLR(3), +	   ASM_MTLR(4), +	   ASM_BLR, +	}; +	ulong res; + +	cpu_post_exec_11 (code, &res, 0); + +	ret = res == (ulong)code + 12 ? 0 : -1; + +	if (ret != 0) +	{ +	    post_log ("Error at b2 test !\n"); +	} +    } + +    if (ret == 0) +    { +	ulong cc, cd; +	int cond; +	ulong ctr; +	int link; + +	i = 0; + +	for (cc = 0; cc < 4 && ret == 0; cc++) +	{ +	    for (cd = 0; cd < 4 && ret == 0; cd++) +	    { +		for (link = 0; link <= 1 && ret == 0; link++) +		{ +		    for (cond = 0; cond <= 1 && ret == 0; cond++) +		    { +			for (ctr = 1; ctr <= 2 && ret == 0; ctr++) +			{ +			    int decr = cd < 2; +			    int cr = cond ? 0x80000000 : 0x00000000; +			    int jumpc = cc >= 2 || +					(cc == 0 && !cond) || +					(cc == 1 && cond); +			    int jumpd = cd >= 2 || +					(cd == 0 && ctr != 1) || +					(cd == 1 && ctr == 1); +			    int jump = jumpc && jumpd; + +			    ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, +				(cc << 3) + (cd << 1), 0, jump, decr, link, +				ctr, cr); + +			    if (ret != 0) +			    { +				post_log ("Error at b3 test %d !\n", i); +			    } + +			    i++; +			} +		    } +		} +	    } +	} +    } + +    if (flag) +	enable_interrupts(); + +    return ret; +} + +#endif diff --git a/roms/u-boot/post/lib_powerpc/cmp.c b/roms/u-boot/post/lib_powerpc/cmp.c new file mode 100644 index 00000000..9d32c20c --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/cmp.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/cmpi.c b/roms/u-boot/post/lib_powerpc/cmpi.c new file mode 100644 index 00000000..5fd182f6 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/cmpi.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/complex.c b/roms/u-boot/post/lib_powerpc/complex.c new file mode 100644 index 00000000..593bbf73 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/complex.c @@ -0,0 +1,111 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * CPU test + * Complex calculations + * + * The calculations in this test are just a combination of simpler + * calculations, but probably under different timing conditions, etc. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +extern int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); +extern int cpu_post_complex_2_asm (int x, int n); + +  /* +   *     n +   *	SUM (a1 * a2 - a3) / a4 = n * result +   *    i=1 +   */ +static int cpu_post_test_complex_1 (void) +{ +    int a1 = 666; +    int a2 = 667; +    int a3 = 668; +    int a4 = 66; +    int n = 100; +    int result = 6720; /* (a1 * a2 - a3) / a4 */ + +    if (cpu_post_complex_1_asm(a1, a2, a3, a4, n) != n * result) +    { +	return -1; +    } + +    return 0; +} + +  /*	(1 + x + x^2 + ... + x^n) * (1 - x) = 1 - x^(n+1) +   */ +static int cpu_post_test_complex_2 (void) +{ +    int ret = -1; +    int x; +    int n; +    int k; +    int left; +    int right; + +    for (x = -8; x <= 8; x ++) +    { +	n = 9; + +	left = cpu_post_complex_2_asm(x, n); +	left *= 1 - x; + +	right = 1; +	for (k = 0; k <= n; k ++) +	{ +	    right *= x; +	} +	right = 1 - right; + +	if (left != right) +	{ +	    goto Done; +	} +    } + +    ret = 0; +    Done: + +    return ret; +} + +int cpu_post_test_complex (void) +{ +    int ret = 0; +    int flag = disable_interrupts(); + +    if (ret == 0) +    { +	ret = cpu_post_test_complex_1(); +    } + +    if (ret == 0) +    { +	ret = cpu_post_test_complex_2(); +    } + +    if (ret != 0) +    { +	post_log ("Error at complex test !\n"); +    } + +    if (flag) +	enable_interrupts(); + +    return ret; +} + +#endif diff --git a/roms/u-boot/post/lib_powerpc/cpu.c b/roms/u-boot/post/lib_powerpc/cpu.c new file mode 100644 index 00000000..63a861e4 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/cpu.c @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * CPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#include <watchdog.h> +#include <post.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +extern int cpu_post_test_cmp (void); +extern int cpu_post_test_cmpi (void); +extern int cpu_post_test_two (void); +extern int cpu_post_test_twox (void); +extern int cpu_post_test_three (void); +extern int cpu_post_test_threex (void); +extern int cpu_post_test_threei (void); +extern int cpu_post_test_andi (void); +extern int cpu_post_test_srawi (void); +extern int cpu_post_test_rlwnm (void); +extern int cpu_post_test_rlwinm (void); +extern int cpu_post_test_rlwimi (void); +extern int cpu_post_test_store (void); +extern int cpu_post_test_load (void); +extern int cpu_post_test_cr (void); +extern int cpu_post_test_b (void); +extern int cpu_post_test_multi (void); +extern int cpu_post_test_string (void); +extern int cpu_post_test_complex (void); + +DECLARE_GLOBAL_DATA_PTR; + +ulong cpu_post_makecr (long v) +{ +	ulong cr = 0; + +	if (v < 0) +		cr |= 0x80000000; +	if (v > 0) +		cr |= 0x40000000; +	if (v == 0) +		cr |= 0x20000000; + +	return cr; +} + +int cpu_post_test (int flags) +{ +	int ic = icache_status (); +	int ret = 0; + +	WATCHDOG_RESET(); +	if (ic) +		icache_disable (); +#ifdef CONFIG_4xx_DCACHE +	/* disable cache */ +	change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); +#endif + +	if (ret == 0) +		ret = cpu_post_test_cmp (); +	if (ret == 0) +		ret = cpu_post_test_cmpi (); +	if (ret == 0) +		ret = cpu_post_test_two (); +	if (ret == 0) +		ret = cpu_post_test_twox (); +	WATCHDOG_RESET(); +	if (ret == 0) +		ret = cpu_post_test_three (); +	if (ret == 0) +		ret = cpu_post_test_threex (); +	if (ret == 0) +		ret = cpu_post_test_threei (); +	if (ret == 0) +		ret = cpu_post_test_andi (); +	WATCHDOG_RESET(); +	if (ret == 0) +		ret = cpu_post_test_srawi (); +	if (ret == 0) +		ret = cpu_post_test_rlwnm (); +	if (ret == 0) +		ret = cpu_post_test_rlwinm (); +	if (ret == 0) +		ret = cpu_post_test_rlwimi (); +	WATCHDOG_RESET(); +	if (ret == 0) +		ret = cpu_post_test_store (); +	if (ret == 0) +		ret = cpu_post_test_load (); +	if (ret == 0) +		ret = cpu_post_test_cr (); +	if (ret == 0) +		ret = cpu_post_test_b (); +	WATCHDOG_RESET(); +	if (ret == 0) +		ret = cpu_post_test_multi (); +	WATCHDOG_RESET(); +	if (ret == 0) +		ret = cpu_post_test_string (); +	if (ret == 0) +		ret = cpu_post_test_complex (); +	WATCHDOG_RESET(); + +	if (ic) +		icache_enable (); +#ifdef CONFIG_4xx_DCACHE +	/* enable cache */ +	change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif + +	WATCHDOG_RESET(); + +	return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_CPU */ diff --git a/roms/u-boot/post/lib_powerpc/cpu_asm.h b/roms/u-boot/post/lib_powerpc/cpu_asm.h new file mode 100644 index 00000000..b5c58891 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/cpu_asm.h @@ -0,0 +1,208 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#ifndef _CPU_ASM_H +#define _CPU_ASM_H + +#define BIT_C				0x00000001 + +#define OP_BLR				0x4e800020 +#define OP_EXTSB			0x7c000774 +#define OP_EXTSH			0x7c000734 +#define OP_NEG				0x7c0000d0 +#define OP_CNTLZW			0x7c000034 +#define OP_ADD				0x7c000214 +#define OP_ADDC				0x7c000014 +#define OP_ADDME			0x7c0001d4 +#define OP_ADDZE			0x7c000194 +#define OP_ADDE				0x7c000114 +#define OP_ADDI				0x38000000 +#define OP_SUBF				0x7c000050 +#define OP_SUBFC			0x7c000010 +#define OP_SUBFE			0x7c000110 +#define OP_SUBFME			0x7c0001d0 +#define OP_SUBFZE			0x7c000190 +#define OP_MFCR				0x7c000026 +#define OP_MTCR				0x7c0ff120 +#define OP_MFXER			0x7c0102a6 +#define OP_MTXER			0x7c0103a6 +#define OP_MCRXR			0x7c000400 +#define OP_MCRF				0x4c000000 +#define OP_CRAND			0x4c000202 +#define OP_CRANDC			0x4c000102 +#define OP_CROR				0x4c000382 +#define OP_CRORC			0x4c000342 +#define OP_CRXOR			0x4c000182 +#define OP_CRNAND			0x4c0001c2 +#define OP_CRNOR			0x4c000042 +#define OP_CREQV			0x4c000242 +#define OP_CMPW				0x7c000000 +#define OP_CMPLW			0x7c000040 +#define OP_CMPWI			0x2c000000 +#define OP_CMPLWI			0x28000000 +#define OP_MULLW			0x7c0001d6 +#define OP_MULHW			0x7c000096 +#define OP_MULHWU			0x7c000016 +#define OP_DIVW				0x7c0003d6 +#define OP_DIVWU			0x7c000396 +#define OP_OR				0x7c000378 +#define OP_ORC				0x7c000338 +#define OP_XOR				0x7c000278 +#define OP_NAND				0x7c0003b8 +#define OP_NOR				0x7c0000f8 +#define OP_EQV				0x7c000238 +#define OP_SLW				0x7c000030 +#define OP_SRW				0x7c000430 +#define OP_SRAW				0x7c000630 +#define OP_ORI				0x60000000 +#define OP_ORIS				0x64000000 +#define OP_XORI				0x68000000 +#define OP_XORIS			0x6c000000 +#define OP_ANDI_			0x70000000 +#define OP_ANDIS_			0x74000000 +#define OP_SRAWI			0x7c000670 +#define OP_RLWINM			0x54000000 +#define OP_RLWNM			0x5c000000 +#define OP_RLWIMI			0x50000000 +#define OP_LWZ				0x80000000 +#define OP_LHZ				0xa0000000 +#define OP_LHA				0xa8000000 +#define OP_LBZ				0x88000000 +#define OP_LWZU				0x84000000 +#define OP_LHZU				0xa4000000 +#define OP_LHAU				0xac000000 +#define OP_LBZU				0x8c000000 +#define OP_LWZX				0x7c00002e +#define OP_LHZX				0x7c00022e +#define OP_LHAX				0x7c0002ae +#define OP_LBZX				0x7c0000ae +#define OP_LWZUX			0x7c00006e +#define OP_LHZUX			0x7c00026e +#define OP_LHAUX			0x7c0002ee +#define OP_LBZUX			0x7c0000ee +#define OP_STW				0x90000000 +#define OP_STH				0xb0000000 +#define OP_STB				0x98000000 +#define OP_STWU				0x94000000 +#define OP_STHU				0xb4000000 +#define OP_STBU				0x9c000000 +#define OP_STWX				0x7c00012e +#define OP_STHX				0x7c00032e +#define OP_STBX				0x7c0001ae +#define OP_STWUX			0x7c00016e +#define OP_STHUX			0x7c00036e +#define OP_STBUX			0x7c0001ee +#define OP_B				0x48000000 +#define OP_BL				0x48000001 +#define OP_BC				0x40000000 +#define OP_BCL				0x40000001 +#define OP_MTLR				0x7c0803a6 +#define OP_MFLR				0x7c0802a6 +#define OP_MTCTR			0x7c0903a6 +#define OP_MFCTR			0x7c0902a6 +#define OP_LMW				0xb8000000 +#define OP_STMW				0xbc000000 +#define OP_LSWI				0x7c0004aa +#define OP_LSWX				0x7c00042a +#define OP_STSWI			0x7c0005aa +#define OP_STSWX			0x7c00052a + +#define ASM_0(opcode)			(opcode) +#define ASM_1(opcode, rd)		((opcode) +		\ +					 ((rd) << 21)) +#define ASM_1C(opcode, cr)		((opcode) +		\ +					 ((cr) << 23)) +#define ASM_11(opcode, rd, rs)		((opcode) +		\ +					 ((rd) << 21) +		\ +					 ((rs) << 16)) +#define ASM_11C(opcode, cd, cs)		((opcode) +		\ +					 ((cd) << 23) +		\ +					 ((cs) << 18)) +#define ASM_11X(opcode, rd, rs)		((opcode) +		\ +					 ((rs) << 21) +		\ +					 ((rd) << 16)) +#define ASM_11I(opcode, rd, rs, simm)	((opcode) +		\ +					 ((rd) << 21) +		\ +					 ((rs) << 16) +		\ +					 ((simm) & 0xffff)) +#define ASM_11IF(opcode, rd, rs, simm)	((opcode) +		\ +					 ((rd) << 21) +		\ +					 ((rs) << 16) +		\ +					 ((simm) << 11)) +#define ASM_11S(opcode, rd, rs, sh)	((opcode) +		\ +					 ((rs) << 21) +		\ +					 ((rd) << 16) +		\ +					 ((sh) << 11)) +#define ASM_11IX(opcode, rd, rs, imm)	((opcode) +		\ +					 ((rs) << 21) +		\ +					 ((rd) << 16) +		\ +					 ((imm) & 0xffff)) +#define ASM_12(opcode, rd, rs1, rs2)	((opcode) +		\ +					 ((rd) << 21) +		\ +					 ((rs1) << 16) +	\ +					 ((rs2) << 11)) +#define ASM_12F(opcode, fd, fs1, fs2)	((opcode) +		\ +					 ((fd) << 21) +		\ +					 ((fs1) << 16) +	\ +					 ((fs2) << 11)) +#define ASM_12X(opcode, rd, rs1, rs2)	((opcode) +		\ +					 ((rs1) << 21) +	\ +					 ((rd) << 16) +		\ +					 ((rs2) << 11)) +#define ASM_2C(opcode, cr, rs1, rs2)	((opcode) +		\ +					 ((cr) << 23) +		\ +					 ((rs1) << 16) +	\ +					 ((rs2) << 11)) +#define ASM_1IC(opcode, cr, rs, imm)	((opcode) +		\ +					 ((cr) << 23) +		\ +					 ((rs) << 16) +		\ +					 ((imm) & 0xffff)) +#define ASM_122(opcode, rd, rs1, rs2, imm1, imm2)		\ +					((opcode) +		\ +					 ((rs1) << 21) +	\ +					 ((rd) << 16) +		\ +					 ((rs2) << 11) +	\ +					 ((imm1) << 6) +	\ +					 ((imm2) << 1)) +#define ASM_113(opcode, rd, rs, imm1, imm2, imm3)		\ +					((opcode) +		\ +					 ((rs) << 21) +		\ +					 ((rd) << 16) +		\ +					 ((imm1) << 11) +	\ +					 ((imm2) << 6) +	\ +					 ((imm3) << 1)) +#define ASM_1O(opcode, off)		((opcode) + (off)) +#define ASM_3O(opcode, bo, bi, off)	((opcode) +		\ +					 ((bo) << 21) +		\ +					 ((bi) << 16) +		\ +					 (off)) + +#define ASM_ADDI(rd, rs, simm)		ASM_11I(OP_ADDI, rd, rs, simm) +#define ASM_BLR				ASM_0(OP_BLR) +#define ASM_STW(rd, rs, simm)		ASM_11I(OP_STW, rd, rs, simm) +#define ASM_LWZ(rd, rs, simm)		ASM_11I(OP_LWZ, rd, rs, simm) +#define ASM_MFCR(rd)			ASM_1(OP_MFCR, rd) +#define ASM_MTCR(rd)			ASM_1(OP_MTCR, rd) +#define ASM_MFXER(rd)			ASM_1(OP_MFXER, rd) +#define ASM_MTXER(rd)			ASM_1(OP_MTXER, rd) +#define ASM_MFCTR(rd)			ASM_1(OP_MFCTR, rd) +#define ASM_MTCTR(rd)			ASM_1(OP_MTCTR, rd) +#define ASM_MCRXR(cr)			ASM_1C(OP_MCRXR, cr) +#define ASM_MCRF(cd, cs)		ASM_11C(OP_MCRF, cd, cs) +#define ASM_B(off)			ASM_1O(OP_B, off) +#define ASM_BL(off)			ASM_1O(OP_BL, off) +#define ASM_MFLR(rd)			ASM_1(OP_MFLR, rd) +#define ASM_MTLR(rd)			ASM_1(OP_MTLR, rd) +#define ASM_LI(rd, imm)			ASM_ADDI(rd, 0, imm) +#define ASM_LMW(rd, rs, simm)		ASM_11I(OP_LMW, rd, rs, simm) +#define ASM_STMW(rd, rs, simm)		ASM_11I(OP_STMW, rd, rs, simm) +#define ASM_LSWI(rd, rs, simm)		ASM_11IF(OP_LSWI, rd, rs, simm) +#define ASM_LSWX(rd, rs1, rs2)		ASM_12(OP_LSWX, rd, rs1, rs2) +#define ASM_STSWI(rd, rs, simm)		ASM_11IF(OP_STSWI, rd, rs, simm) +#define ASM_STSWX(rd, rs1, rs2)		ASM_12(OP_STSWX, rd, rs1, rs2) + + +#endif /* _CPU_ASM_H */ diff --git a/roms/u-boot/post/lib_powerpc/cr.c b/roms/u-boot/post/lib_powerpc/cr.c new file mode 100644 index 00000000..19d930fa --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/cr.c @@ -0,0 +1,337 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c b/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c new file mode 100644 index 00000000..caf52970 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20001122-1.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * 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 */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c b/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c new file mode 100644 index 00000000..96e25c46 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20010114-2.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static float rintf (float x) +{ +	volatile float TWO23 = 8388608.0; + +	if (__builtin_fabs (x) < TWO23) +	{ +		if (x > 0.0) +		{ +			x += TWO23; +			x -= TWO23; +		} +		else if (x < 0.0) +		{ +			x = TWO23 - x; +			x = -(x - TWO23); +		} +	} + +	return x; +} + +int fpu_post_test_math2 (void) +{ +	if (rintf (-1.5) != -2.0) { +		post_log ("Error in FPU math2 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c b/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c new file mode 100644 index 00000000..57a21e48 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/20010226-1.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math3 (void) +{ +	volatile long double dfrom = 1.1; +	volatile long double m1; +	volatile long double m2; +	volatile unsigned long mant_long; + +	m1 = dfrom / 2.0; +	m2 = m1 * 4294967296.0; +	mant_long = ((unsigned long) m2) & 0xffffffff; + +	if (mant_long != 0x8ccccccc) { +		post_log ("Error in FPU math3 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/980619-1.c b/roms/u-boot/post/lib_powerpc/fpu/980619-1.c new file mode 100644 index 00000000..bf6c2ab5 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/980619-1.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +int fpu_post_test_math4 (void) +{ +	volatile float reale = 1.0f; +	volatile float oneplus; +	int i; + +	if (sizeof (float) != 4) +		return 0; + +	for (i = 0; ; i++) +	{ +		oneplus = 1.0f + reale; +		if (oneplus == 1.0f) +			break; +		reale = reale / 2.0f; +	} +	/* Assumes ieee754 accurate arithmetic above.  */ +	if (i != 24) { +		post_log ("Error in FPU math4 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/Makefile b/roms/u-boot/post/lib_powerpc/fpu/Makefile new file mode 100644 index 00000000..5c2e804d --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/Makefile @@ -0,0 +1,23 @@ +# +# (C) Copyright 2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +objs-before-objcopy := 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o \ +	acc1.o compare-fp-1.o fpu.o mul-subnormal-single-1.o darwin-ldouble.o +targets += $(objs-before-objcopy) + +# remove -msoft-float flag +$(foreach m, $(objs-before-objcopy), $(eval CFLAGS_REMOVE_$m := -msoft-float)) +ccflags-y := -mhard-float -fkeep-inline-functions + +# Do not delete intermidiate files (*.o) +.SECONDARY: $(call objectify, $(objs-before-objcopy)) + +obj-y := $(objs-before-objcopy:.o=_.o) + +OBJCOPYFLAGS := -R .gnu.attributes +$(obj)/%_.o: $(obj)/%.o FORCE +	$(call if_changed,objcopy) diff --git a/roms/u-boot/post/lib_powerpc/fpu/acc1.c b/roms/u-boot/post/lib_powerpc/fpu/acc1.c new file mode 100644 index 00000000..22d28f91 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/acc1.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static double func (const double *array) +{ +	double d = *array; + +	if (d == 0.0) +		return d; +	else +		return d + func (array + 1); +} + +int fpu_post_test_math5 (void) +{ +	double values[] = { 0.1e-100, 1.0, -1.0, 0.0 }; + +	if (func (values) != 0.1e-100) { +		post_log ("Error in FPU math5 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c b/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c new file mode 100644 index 00000000..f23c7ed8 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/compare-fp-1.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * Test for correctness of composite floating-point comparisons. + * Written by Paolo Bonzini, 26th May 2004. + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +static int failed; + +#define TEST(c) if ((c) != ok) failed++ +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b))) +#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b))) +#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b))) +#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b))) +#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b))) +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) + +static float pinf; +static float ninf; +static float NaN; + +static void iuneq (float x, float y, int ok) +{ +	TEST (UNEQ (x, y)); +	TEST (!LTGT (x, y)); +	TEST (UNLE (x, y) && UNGE (x,y)); +} + +static void ieq (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNEQ (x, y)); +} + +static void iltgt (float x, float y, int ok) +{ +	TEST (!UNEQ (x, y)); /* Not optimizable. */ +	TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */ +	TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y))); +} + +static void ine (float x, float y, int ok) +{ +	TEST (UNLT (x, y) || UNGT (x, y)); +} + +static void iunlt (float x, float y, int ok) +{ +	TEST (UNLT (x, y)); +	TEST (UNORD (x, y) || (x < y)); +} + +static void ilt (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */ +	TEST ((x <= y) && (x != y)); +	TEST ((x <= y) && (y != x)); +	TEST ((x != y) && (x <= y)); /* Not optimized */ +	TEST ((y != x) && (x <= y)); /* Not optimized */ +} + +static void iunle (float x, float y, int ok) +{ +	TEST (UNLE (x, y)); +	TEST (UNORD (x, y) || (x <= y)); +} + +static void ile (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */ +	TEST ((x < y) || (x == y)); +	TEST ((y > x) || (x == y)); +	TEST ((x == y) || (x < y)); /* Not optimized */ +	TEST ((y == x) || (x < y)); /* Not optimized */ +} + +static void iungt (float x, float y, int ok) +{ +	TEST (UNGT (x, y)); +	TEST (UNORD (x, y) || (x > y)); +} + +static void igt (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */ +	TEST ((x >= y) && (x != y)); +	TEST ((x >= y) && (y != x)); +	TEST ((x != y) && (x >= y)); /* Not optimized */ +	TEST ((y != x) && (x >= y)); /* Not optimized */ +} + +static void iunge (float x, float y, int ok) +{ +	TEST (UNGE (x, y)); +	TEST (UNORD (x, y) || (x >= y)); +} + +static void ige (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */ +	TEST ((x > y) || (x == y)); +	TEST ((y < x) || (x == y)); +	TEST ((x == y) || (x > y)); /* Not optimized */ +	TEST ((y == x) || (x > y)); /* Not optimized */ +} + +int fpu_post_test_math6 (void) +{ +	pinf = __builtin_inf (); +	ninf = -__builtin_inf (); +	NaN = __builtin_nan (""); + +	iuneq (ninf, pinf, 0); +	iuneq (NaN, NaN, 1); +	iuneq (pinf, ninf, 0); +	iuneq (1, 4, 0); +	iuneq (3, 3, 1); +	iuneq (5, 2, 0); + +	ieq (1, 4, 0); +	ieq (3, 3, 1); +	ieq (5, 2, 0); + +	iltgt (ninf, pinf, 1); +	iltgt (NaN, NaN, 0); +	iltgt (pinf, ninf, 1); +	iltgt (1, 4, 1); +	iltgt (3, 3, 0); +	iltgt (5, 2, 1); + +	ine (1, 4, 1); +	ine (3, 3, 0); +	ine (5, 2, 1); + +	iunlt (NaN, ninf, 1); +	iunlt (pinf, NaN, 1); +	iunlt (pinf, ninf, 0); +	iunlt (pinf, pinf, 0); +	iunlt (ninf, ninf, 0); +	iunlt (1, 4, 1); +	iunlt (3, 3, 0); +	iunlt (5, 2, 0); + +	ilt (1, 4, 1); +	ilt (3, 3, 0); +	ilt (5, 2, 0); + +	iunle (NaN, ninf, 1); +	iunle (pinf, NaN, 1); +	iunle (pinf, ninf, 0); +	iunle (pinf, pinf, 1); +	iunle (ninf, ninf, 1); +	iunle (1, 4, 1); +	iunle (3, 3, 1); +	iunle (5, 2, 0); + +	ile (1, 4, 1); +	ile (3, 3, 1); +	ile (5, 2, 0); + +	iungt (NaN, ninf, 1); +	iungt (pinf, NaN, 1); +	iungt (pinf, ninf, 1); +	iungt (pinf, pinf, 0); +	iungt (ninf, ninf, 0); +	iungt (1, 4, 0); +	iungt (3, 3, 0); +	iungt (5, 2, 1); + +	igt (1, 4, 0); +	igt (3, 3, 0); +	igt (5, 2, 1); + +	iunge (NaN, ninf, 1); +	iunge (pinf, NaN, 1); +	iunge (ninf, pinf, 0); +	iunge (pinf, pinf, 1); +	iunge (ninf, ninf, 1); +	iunge (1, 4, 0); +	iunge (3, 3, 1); +	iunge (5, 2, 1); + +	ige (1, 4, 0); +	ige (3, 3, 1); +	ige (5, 2, 1); + +	if (failed) { +		post_log ("Error in FPU math6 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c b/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c new file mode 100644 index 00000000..faf9a94e --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/darwin-ldouble.c @@ -0,0 +1,120 @@ +/* + * 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. + + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * 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; +} diff --git a/roms/u-boot/post/lib_powerpc/fpu/fpu.c b/roms/u-boot/post/lib_powerpc/fpu/fpu.c new file mode 100644 index 00000000..1e7ed31b --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/fpu.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * FPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#include <post.h> + +GNU_FPOST_ATTR + +#if CONFIG_POST & CONFIG_SYS_POST_FPU + +#include <watchdog.h> + +extern int fpu_status (void); +extern void fpu_enable (void); +extern void fpu_disable (void); + +extern int fpu_post_test_math1 (void); +extern int fpu_post_test_math2 (void); +extern int fpu_post_test_math3 (void); +extern int fpu_post_test_math4 (void); +extern int fpu_post_test_math5 (void); +extern int fpu_post_test_math6 (void); +extern int fpu_post_test_math7 (void); + +int fpu_post_test (int flags) +{ +	int fpu = fpu_status (); + +	int ret = 0; + +	WATCHDOG_RESET (); + +	if (!fpu) +		fpu_enable (); + +	if (ret == 0) +		ret = fpu_post_test_math1 (); +	if (ret == 0) +		ret = fpu_post_test_math2 (); +	if (ret == 0) +		ret = fpu_post_test_math3 (); +	if (ret == 0) +		ret = fpu_post_test_math4 (); +	if (ret == 0) +		ret = fpu_post_test_math5 (); +	if (ret == 0) +		ret = fpu_post_test_math6 (); +	if (ret == 0) +		ret = fpu_post_test_math7 (); + +	if (!fpu) +		fpu_disable (); + +	WATCHDOG_RESET (); + +	return ret; +} + +#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */ diff --git a/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c b/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c new file mode 100644 index 00000000..2815a303 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/fpu/mul-subnormal-single-1.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +/* + * 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 */ diff --git a/roms/u-boot/post/lib_powerpc/load.c b/roms/u-boot/post/lib_powerpc/load.c new file mode 100644 index 00000000..f233587c --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/load.c @@ -0,0 +1,239 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/multi.c b/roms/u-boot/post/lib_powerpc/multi.c new file mode 100644 index 00000000..9c315dfc --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/multi.c @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/rlwimi.c b/roms/u-boot/post/lib_powerpc/rlwimi.c new file mode 100644 index 00000000..6bd53d06 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/rlwimi.c @@ -0,0 +1,142 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/rlwinm.c b/roms/u-boot/post/lib_powerpc/rlwinm.c new file mode 100644 index 00000000..35a1a40f --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/rlwinm.c @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/rlwnm.c b/roms/u-boot/post/lib_powerpc/rlwnm.c new file mode 100644 index 00000000..6e828939 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/rlwnm.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/srawi.c b/roms/u-boot/post/lib_powerpc/srawi.c new file mode 100644 index 00000000..3723e339 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/srawi.c @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/store.c b/roms/u-boot/post/lib_powerpc/store.c new file mode 100644 index 00000000..aa2dc99b --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/store.c @@ -0,0 +1,219 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/string.c b/roms/u-boot/post/lib_powerpc/string.c new file mode 100644 index 00000000..930193b2 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/string.c @@ -0,0 +1,91 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> + +/* + * CPU test + * Load/store string instructions:	lswi, stswi, lswx, stswx + * + * Several consecutive bytes from a source memory buffer are loaded + * left to right into GPRs. After that, the bytes are stored + * from the GPRs into a target memory buffer. The contents + * of the source and target buffers are then compared. + */ + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CONFIG_SYS_POST_CPU + +extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); +extern void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, +    ulong op4); + +#include <bedbug/regs.h> +int cpu_post_test_string (void) +{ +    int ret = 0; +    unsigned int i; +    int flag = disable_interrupts(); + +    if (ret == 0) +    { +	char src [31], dst [31]; + +	ulong code[] = +	{ +	    ASM_LSWI(5, 3, 31), +	    ASM_STSWI(5, 4, 31), +	    ASM_BLR, +	}; + +	for (i = 0; i < sizeof(src); i ++) +	{ +	    src[i] = (char) i; +	    dst[i] = 0; +	} + +	cpu_post_exec_02(code, (ulong)src, (ulong)dst); + +	ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1; +    } + +    if (ret == 0) +    { +	char src [95], dst [95]; + +	ulong code[] = +	{ +	    ASM_LSWX(8, 3, 5), +	    ASM_STSWX(8, 4, 5), +	    ASM_BLR, +	}; + +	for (i = 0; i < sizeof(src); i ++) +	{ +	    src[i] = (char) i; +	    dst[i] = 0; +	} + +	cpu_post_exec_04(code, (ulong)src, (ulong)dst, 0, sizeof(src)); + +	ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1; +    } + +    if (ret != 0) +    { +	post_log ("Error at string test !\n"); +    } + +    if (flag) +	enable_interrupts(); + +    return ret; +} + +#endif diff --git a/roms/u-boot/post/lib_powerpc/three.c b/roms/u-boot/post/lib_powerpc/three.c new file mode 100644 index 00000000..c3e7f681 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/three.c @@ -0,0 +1,239 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/threei.c b/roms/u-boot/post/lib_powerpc/threei.c new file mode 100644 index 00000000..1d40e1af --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/threei.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/threex.c b/roms/u-boot/post/lib_powerpc/threex.c new file mode 100644 index 00000000..ce1edf89 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/threex.c @@ -0,0 +1,209 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/two.c b/roms/u-boot/post/lib_powerpc/two.c new file mode 100644 index 00000000..c6f7de44 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/two.c @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/lib_powerpc/twox.c b/roms/u-boot/post/lib_powerpc/twox.c new file mode 100644 index 00000000..9549dbb7 --- /dev/null +++ b/roms/u-boot/post/lib_powerpc/twox.c @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 diff --git a/roms/u-boot/post/post.c b/roms/u-boot/post/post.c new file mode 100644 index 00000000..4af5355f --- /dev/null +++ b/roms/u-boot/post/post.c @@ -0,0 +1,489 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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 +} diff --git a/roms/u-boot/post/tests.c b/roms/u-boot/post/tests.c new file mode 100644 index 00000000..a4d41654 --- /dev/null +++ b/roms/u-boot/post/tests.c @@ -0,0 +1,320 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + * + * 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, +	ðer_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_ETHER +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SPI +    { +	"SPI test", +	"spi", +	"This test verifies the SPI operation.", +	POST_RAM | POST_ALWAYS | POST_MANUAL, +	&spi_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_SPI +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_USB +    { +	"USB test", +	"usb", +	"This test verifies the USB operation.", +	POST_RAM | POST_ALWAYS | POST_MANUAL, +	&usb_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_USB +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SPR +    { +	"SPR test", +	"spr", +	"This test checks SPR contents.", +	POST_RAM | POST_ALWAYS, +	&spr_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_SPR +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_SYSMON +    { +	"SYSMON test", +	"sysmon", +	"This test monitors system hardware.", +	POST_RAM | POST_ALWAYS, +	&sysmon_post_test, +	&sysmon_init_f, +	&sysmon_reloc, +	CONFIG_SYS_POST_SYSMON +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_DSP +    { +	"DSP test", +	"dsp", +	"This test checks any connected DSP(s).", +	POST_RAM | POST_ALWAYS | POST_MANUAL, +	&dsp_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_DSP +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_CODEC +    { +	"CODEC test", +	"codec", +	"This test checks any connected codec(s).", +	POST_RAM | POST_MANUAL, +	&codec_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_CODEC +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_ECC +    { +	"ECC test", +	"ecc", +	"This test checks the ECC facility of memory.", +	POST_ROM | POST_ALWAYS | POST_PREREL, +	&ecc_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_ECC +    }, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC1 +	CONFIG_POST_BSPEC1, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC2 +	CONFIG_POST_BSPEC2, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC3 +	CONFIG_POST_BSPEC3, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC4 +	CONFIG_POST_BSPEC4, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_BSPEC5 +	CONFIG_POST_BSPEC5, +#endif +#if CONFIG_POST & CONFIG_SYS_POST_COPROC +    { +	"Coprocessors communication test", +	"coproc_com", +	"This test checks communication with coprocessors.", +	POST_RAM | POST_ALWAYS | POST_CRITICAL, +	&coprocessor_post_test, +	NULL, +	NULL, +	CONFIG_SYS_POST_COPROC +    }, +#endif +#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);  | 
