411 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			411 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * (C) Copyright 2007
 | 
						|
 * Stefan Roese, DENX Software Engineering, sr@denx.de.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier:	GPL-2.0+
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <command.h>
 | 
						|
#include <malloc.h>
 | 
						|
#include <environment.h>
 | 
						|
#include <logbuff.h>
 | 
						|
#include <post.h>
 | 
						|
 | 
						|
#include <asm/processor.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#include <asm/ppc4xx-gpio.h>
 | 
						|
 | 
						|
DECLARE_GLOBAL_DATA_PTR;
 | 
						|
 | 
						|
#define REBOOT_MAGIC	0x07081967
 | 
						|
#define REBOOT_NOP	0x00000000
 | 
						|
#define REBOOT_DO_POST	0x00000001
 | 
						|
 | 
						|
extern flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips	*/
 | 
						|
 | 
						|
ulong flash_get_size(ulong base, int banknum);
 | 
						|
void env_crc_update(void);
 | 
						|
 | 
						|
static u32 start_time;
 | 
						|
 | 
						|
int board_early_init_f(void)
 | 
						|
{
 | 
						|
	mtdcr(UIC0SR, 0xFFFFFFFF);	/* clear all ints */
 | 
						|
	mtdcr(UIC0ER, 0x00000000);	/* disable all ints */
 | 
						|
	mtdcr(UIC0CR, 0x00000000);
 | 
						|
	mtdcr(UIC0PR, 0xFFFF7F00);	/* set int polarities */
 | 
						|
	mtdcr(UIC0TR, 0x00000000);	/* set int trigger levels */
 | 
						|
	mtdcr(UIC0SR, 0xFFFFFFFF);	/* clear all ints */
 | 
						|
	mtdcr(UIC0VCR, 0x00000001);	/* set vect base=0,INT0 highest priority */
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Configure CPC0_PCI to enable PerWE as output
 | 
						|
	 */
 | 
						|
	mtdcr(CPC0_PCI, CPC0_PCI_SPE);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int misc_init_r(void)
 | 
						|
{
 | 
						|
	u32 pbcr;
 | 
						|
	int size_val = 0;
 | 
						|
	u32 post_magic;
 | 
						|
	u32 post_val;
 | 
						|
 | 
						|
	post_magic = in_be32((void *)CONFIG_SYS_POST_MAGIC);
 | 
						|
	post_val = in_be32((void *)CONFIG_SYS_POST_VAL);
 | 
						|
	if ((post_magic == REBOOT_MAGIC) && (post_val == REBOOT_DO_POST)) {
 | 
						|
		/*
 | 
						|
		 * Set special bootline bootparameter to pass this POST boot
 | 
						|
		 * mode to Linux to reset the username/password
 | 
						|
		 */
 | 
						|
		setenv("addmisc", "setenv bootargs \\${bootargs} factory_reset=yes");
 | 
						|
 | 
						|
		/*
 | 
						|
		 * Normally don't run POST tests, only when enabled
 | 
						|
		 * via the sw-reset button. So disable further tests
 | 
						|
		 * upon next bootup here.
 | 
						|
		 */
 | 
						|
		out_be32((void *)CONFIG_SYS_POST_VAL, REBOOT_NOP);
 | 
						|
	} else {
 | 
						|
		/*
 | 
						|
		 * Only run POST when initiated via the sw-reset button mechanism
 | 
						|
		 */
 | 
						|
		post_word_store(0);
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Get current time
 | 
						|
	 */
 | 
						|
	start_time = get_timer(0);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * FLASH stuff...
 | 
						|
	 */
 | 
						|
 | 
						|
	/* Re-do sizing to get full correct info */
 | 
						|
 | 
						|
	/* adjust flash start and offset */
 | 
						|
	mfebc(PB0CR, pbcr);
 | 
						|
	switch (gd->bd->bi_flashsize) {
 | 
						|
	case 1 << 20:
 | 
						|
		size_val = 0;
 | 
						|
		break;
 | 
						|
	case 2 << 20:
 | 
						|
		size_val = 1;
 | 
						|
		break;
 | 
						|
	case 4 << 20:
 | 
						|
		size_val = 2;
 | 
						|
		break;
 | 
						|
	case 8 << 20:
 | 
						|
		size_val = 3;
 | 
						|
		break;
 | 
						|
	case 16 << 20:
 | 
						|
		size_val = 4;
 | 
						|
		break;
 | 
						|
	case 32 << 20:
 | 
						|
		size_val = 5;
 | 
						|
		break;
 | 
						|
	case 64 << 20:
 | 
						|
		size_val = 6;
 | 
						|
		break;
 | 
						|
	case 128 << 20:
 | 
						|
		size_val = 7;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17);
 | 
						|
	mtebc(PB0CR, pbcr);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Re-check to get correct base address
 | 
						|
	 */
 | 
						|
	flash_get_size(gd->bd->bi_flashstart, 0);
 | 
						|
 | 
						|
	/* Monitor protection ON by default */
 | 
						|
	(void)flash_protect(FLAG_PROTECT_SET,
 | 
						|
			    -CONFIG_SYS_MONITOR_LEN,
 | 
						|
			    0xffffffff,
 | 
						|
			    &flash_info[0]);
 | 
						|
 | 
						|
	/* Env protection ON by default */
 | 
						|
	(void)flash_protect(FLAG_PROTECT_SET,
 | 
						|
			    CONFIG_ENV_ADDR_REDUND,
 | 
						|
			    CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1,
 | 
						|
			    &flash_info[0]);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Check Board Identity:
 | 
						|
 */
 | 
						|
int checkboard(void)
 | 
						|
{
 | 
						|
	char buf[64];
 | 
						|
	int i = getenv_f("serial#", buf, sizeof(buf));
 | 
						|
 | 
						|
	puts("Board: Zeus-");
 | 
						|
 | 
						|
	if (in_be32((void *)GPIO0_IR) & GPIO_VAL(CONFIG_SYS_GPIO_ZEUS_PE))
 | 
						|
		puts("PE");
 | 
						|
	else
 | 
						|
		puts("CE");
 | 
						|
 | 
						|
	puts(" of BulletEndPoint");
 | 
						|
 | 
						|
	if (i > 0) {
 | 
						|
		puts(", serial# ");
 | 
						|
		puts(buf);
 | 
						|
	}
 | 
						|
	putc('\n');
 | 
						|
 | 
						|
	/* both LED's off */
 | 
						|
	gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 0);
 | 
						|
	gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 0);
 | 
						|
	udelay(10000);
 | 
						|
	/* and on again */
 | 
						|
	gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 1);
 | 
						|
	gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 1);
 | 
						|
 | 
						|
	return (0);
 | 
						|
}
 | 
						|
 | 
						|
static int default_env_var(char *buf, char *var)
 | 
						|
{
 | 
						|
	char *ptr;
 | 
						|
	char *val;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Find env variable
 | 
						|
	 */
 | 
						|
	ptr = strstr(buf + 4, var);
 | 
						|
	if (ptr == NULL) {
 | 
						|
		printf("ERROR: %s not found!\n", var);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	ptr += strlen(var) + 1;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Now the ethaddr needs to be updated in the "normal"
 | 
						|
	 * environment storage -> redundant flash.
 | 
						|
	 */
 | 
						|
	val = ptr;
 | 
						|
	setenv(var, val);
 | 
						|
	printf("Updated %s from eeprom to %s!\n", var, val);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int restore_default(void)
 | 
						|
{
 | 
						|
	char *buf;
 | 
						|
	char *buf_save;
 | 
						|
	u32 crc;
 | 
						|
 | 
						|
	set_default_env("");
 | 
						|
 | 
						|
	gd->env_valid = 1;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Read board specific values from I2C EEPROM
 | 
						|
	 * and set env variables accordingly
 | 
						|
	 * -> ethaddr, eth1addr, serial#
 | 
						|
	 */
 | 
						|
	buf = buf_save = malloc(FACTORY_RESET_ENV_SIZE);
 | 
						|
	if (buf == NULL) {
 | 
						|
		printf("ERROR: malloc() failed\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	if (eeprom_read(FACTORY_RESET_I2C_EEPROM, FACTORY_RESET_ENV_OFFS,
 | 
						|
			(u8 *)buf, FACTORY_RESET_ENV_SIZE)) {
 | 
						|
		puts("\nError reading EEPROM!\n");
 | 
						|
	} else {
 | 
						|
		crc = crc32(0, (u8 *)(buf + 4), FACTORY_RESET_ENV_SIZE - 4);
 | 
						|
		if (crc != *(u32 *)buf) {
 | 
						|
			printf("ERROR: crc mismatch %08x %08x\n", crc, *(u32 *)buf);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		default_env_var(buf, "ethaddr");
 | 
						|
		buf += 8 + 18;
 | 
						|
		default_env_var(buf, "eth1addr");
 | 
						|
		buf += 9 + 18;
 | 
						|
		default_env_var(buf, "serial#");
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Finally save updated env variables back to flash
 | 
						|
	 */
 | 
						|
	saveenv();
 | 
						|
 | 
						|
	free(buf_save);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int do_set_default(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 | 
						|
{
 | 
						|
	char *buf;
 | 
						|
	char *buf_save;
 | 
						|
	char str[32];
 | 
						|
	u32 crc;
 | 
						|
	char var[32];
 | 
						|
 | 
						|
	if (argc < 4) {
 | 
						|
		puts("ERROR!\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	buf = buf_save = malloc(FACTORY_RESET_ENV_SIZE);
 | 
						|
	memset(buf, 0, FACTORY_RESET_ENV_SIZE);
 | 
						|
 | 
						|
	strcpy(var, "ethaddr");
 | 
						|
	printf("Setting %s to %s\n", var, argv[1]);
 | 
						|
	sprintf(str, "%s=%s", var, argv[1]);
 | 
						|
	strcpy(buf + 4, str);
 | 
						|
	buf += strlen(str) + 1;
 | 
						|
 | 
						|
	strcpy(var, "eth1addr");
 | 
						|
	printf("Setting %s to %s\n", var, argv[2]);
 | 
						|
	sprintf(str, "%s=%s", var, argv[2]);
 | 
						|
	strcpy(buf + 4, str);
 | 
						|
	buf += strlen(str) + 1;
 | 
						|
 | 
						|
	strcpy(var, "serial#");
 | 
						|
	printf("Setting %s to %s\n", var, argv[3]);
 | 
						|
	sprintf(str, "%s=%s", var, argv[3]);
 | 
						|
	strcpy(buf + 4, str);
 | 
						|
 | 
						|
	crc = crc32(0, (u8 *)(buf_save + 4), FACTORY_RESET_ENV_SIZE - 4);
 | 
						|
	*(u32 *)buf_save = crc;
 | 
						|
 | 
						|
	if (eeprom_write(FACTORY_RESET_I2C_EEPROM, FACTORY_RESET_ENV_OFFS,
 | 
						|
			 (u8 *)buf_save, FACTORY_RESET_ENV_SIZE)) {
 | 
						|
		puts("\nError writing EEPROM!\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	free(buf_save);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
U_BOOT_CMD(
 | 
						|
	setdef,	4,	1,	do_set_default,
 | 
						|
	"write board-specific values to EEPROM (ethaddr...)",
 | 
						|
	"ethaddr eth1addr serial#\n    - write board-specific values to EEPROM"
 | 
						|
	);
 | 
						|
 | 
						|
static inline int sw_reset_pressed(void)
 | 
						|
{
 | 
						|
	return !(in_be32((void *)GPIO0_IR) & GPIO_VAL(CONFIG_SYS_GPIO_SW_RESET));
 | 
						|
}
 | 
						|
 | 
						|
int do_chkreset(cmd_tbl_t* cmdtp, int flag, int argc, char * const argv[])
 | 
						|
{
 | 
						|
	int delta;
 | 
						|
	int count = 0;
 | 
						|
	int post = 0;
 | 
						|
	int factory_reset = 0;
 | 
						|
 | 
						|
	if (!sw_reset_pressed()) {
 | 
						|
		printf("SW-Reset already high (Button released)\n");
 | 
						|
		printf("-> No action taken!\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	printf("Waiting for SW-Reset button to be released.");
 | 
						|
 | 
						|
	while (1) {
 | 
						|
		delta = get_timer(start_time);
 | 
						|
		if (!sw_reset_pressed())
 | 
						|
			break;
 | 
						|
 | 
						|
		if ((delta > CONFIG_SYS_TIME_POST) && !post) {
 | 
						|
			printf("\nWhen released now, POST tests will be started.");
 | 
						|
			gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 0);
 | 
						|
			post = 1;
 | 
						|
		}
 | 
						|
 | 
						|
		if ((delta > CONFIG_SYS_TIME_FACTORY_RESET) && !factory_reset) {
 | 
						|
			printf("\nWhen released now, factory default values"
 | 
						|
			       " will be restored.");
 | 
						|
			gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 0);
 | 
						|
			factory_reset = 1;
 | 
						|
		}
 | 
						|
 | 
						|
		udelay(1000);
 | 
						|
		if (!(count++ % 1000))
 | 
						|
			printf(".");
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	printf("\nSW-Reset Button released after %d milli-seconds!\n", delta);
 | 
						|
 | 
						|
	if (delta > CONFIG_SYS_TIME_FACTORY_RESET) {
 | 
						|
		printf("Starting factory reset value restoration...\n");
 | 
						|
 | 
						|
		/*
 | 
						|
		 * Restore default setting
 | 
						|
		 */
 | 
						|
		restore_default();
 | 
						|
 | 
						|
		/*
 | 
						|
		 * Reset the board for default to become valid
 | 
						|
		 */
 | 
						|
		do_reset(NULL, 0, 0, NULL);
 | 
						|
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (delta > CONFIG_SYS_TIME_POST) {
 | 
						|
		printf("Starting POST configuration...\n");
 | 
						|
 | 
						|
		/*
 | 
						|
		 * Enable POST upon next bootup
 | 
						|
		 */
 | 
						|
		out_be32((void *)CONFIG_SYS_POST_MAGIC, REBOOT_MAGIC);
 | 
						|
		out_be32((void *)CONFIG_SYS_POST_VAL, REBOOT_DO_POST);
 | 
						|
		post_bootmode_init();
 | 
						|
 | 
						|
		/*
 | 
						|
		 * Reset the logbuffer for a clean start
 | 
						|
		 */
 | 
						|
		logbuff_reset();
 | 
						|
 | 
						|
		do_reset(NULL, 0, 0, NULL);
 | 
						|
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
U_BOOT_CMD (
 | 
						|
	chkreset, 1, 1, do_chkreset,
 | 
						|
	"Check for status of SW-reset button and act accordingly",
 | 
						|
	""
 | 
						|
);
 | 
						|
 | 
						|
#if defined(CONFIG_POST)
 | 
						|
/*
 | 
						|
 * Returns 1 if keys pressed to start the power-on long-running tests
 | 
						|
 * Called from board_init_f().
 | 
						|
 */
 | 
						|
int post_hotkeys_pressed(void)
 | 
						|
{
 | 
						|
	u32 post_magic;
 | 
						|
	u32 post_val;
 | 
						|
 | 
						|
	post_magic = in_be32((void *)CONFIG_SYS_POST_MAGIC);
 | 
						|
	post_val = in_be32((void *)CONFIG_SYS_POST_VAL);
 | 
						|
 | 
						|
	if ((post_magic == REBOOT_MAGIC) && (post_val == REBOOT_DO_POST))
 | 
						|
		return 1;
 | 
						|
	else
 | 
						|
		return 0;
 | 
						|
}
 | 
						|
#endif /* CONFIG_POST */
 |