diff options
| -rw-r--r-- | README | 11 | ||||
| -rw-r--r-- | common/env_nand.c | 115 | ||||
| -rw-r--r-- | include/configs/delta.h | 1 | ||||
| -rw-r--r-- | include/environment.h | 12 | 
4 files changed, 126 insertions, 13 deletions
| @@ -1946,6 +1946,17 @@ to save the current settings.  	  These two #defines specify the offset and size of the environment  	  area within the first NAND device. +	- CFG_ENV_OFFSET_REDUND + +	  This setting describes a second storage area of CFG_ENV_SIZE +	  size used to hold a redundant copy of the environment data, +	  so that there is a valid backup copy in case there is a +	  power failure during a "saveenv" operation. + +	Note: CFG_ENV_OFFSET and CFG_ENV_OFFSET_REDUND must be aligned +	to a block boundary, and CFG_ENV_SIZE must be a multiple of +	the NAND devices block size. +  - CFG_SPI_INIT_OFFSET  	Defines offset to the initial SPI buffer area in DPRAM. The diff --git a/common/env_nand.c b/common/env_nand.c index 4ae68c5a2..2e1bfa666 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -36,21 +36,19 @@  #include <command.h>  #include <environment.h>  #include <linux/stddef.h> +#include <malloc.h>  #include <nand.h>  #if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND))  #define CMD_SAVEENV +#elif defined(CFG_ENV_OFFSET_REDUND) +#error Cannot use CFG_ENV_OFFSET_REDUND without CFG_CMD_ENV & CFG_CMD_NAND  #endif -#if defined(CFG_ENV_SIZE_REDUND) -#error CFG_ENV_SIZE_REDUND  not supported yet +#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND != CFG_ENV_SIZE) +#error CFG_ENV_SIZE_REDUND should be the same as CFG_ENV_SIZE  #endif -#if defined(CFG_ENV_ADDR_REDUND) -#error CFG_ENV_ADDR_REDUND and CFG_ENV_IS_IN_NAND not supported yet -#endif - -  #ifdef CONFIG_INFERNO  #error CONFIG_INFERNO not supported yet  #endif @@ -99,7 +97,7 @@ int env_init(void)  {  	DECLARE_GLOBAL_DATA_PTR; -  	gd->env_addr  = (ulong)&default_environment[0]; +	gd->env_addr  = (ulong)&default_environment[0];  	gd->env_valid = 1;  	return (0); @@ -110,9 +108,45 @@ int env_init(void)   * The legacy NAND code saved the environment in the first NAND device i.e.,   * nand_dev_desc + 0. This is also the behaviour using the new NAND code.   */ +#ifdef CFG_ENV_OFFSET_REDUND +int saveenv(void) +{ +	int total, ret = 0; + +	DECLARE_GLOBAL_DATA_PTR; + +	env_ptr->flags++; +	total = CFG_ENV_SIZE; + +	if(gd->env_valid == 1) { +		puts ("Erasing redundant Nand..."); +		if (nand_erase(&nand_info[0], +			       CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE)) +			return 1; +		puts ("Writing to redundant Nand... "); +		ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, +				 (u_char*) env_ptr); +	} else { +		puts ("Erasing Nand..."); +		if (nand_erase(&nand_info[0], +			       CFG_ENV_OFFSET, CFG_ENV_SIZE)) +			return 1; + +		puts ("Writing to Nand... "); +		ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, +				 (u_char*) env_ptr); +	} +	if (ret || total != CFG_ENV_SIZE) +		return 1; + +	puts ("done\n"); +	gd->env_valid = (gd->env_valid == 2 ? 1 : 2); +	return ret; +} +#else /* ! CFG_ENV_OFFSET_REDUND */  int saveenv(void)  { -	int	total, ret = 0; +	int total, ret = 0;  	puts ("Erasing Nand...");  	if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) @@ -128,9 +162,64 @@ int saveenv(void)  	puts ("done\n");  	return ret;  } +#endif /* CFG_ENV_OFFSET_REDUND */  #endif /* CMD_SAVEENV */ +#ifdef CFG_ENV_OFFSET_REDUND +void env_relocate_spec (void) +{ +#if !defined(ENV_IS_EMBEDDED) +	int crc1_ok = 0, crc2_ok = 0, total; +	env_t *tmp_env1, *tmp_env2; + +	DECLARE_GLOBAL_DATA_PTR; + +	total = CFG_ENV_SIZE; + +	tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE); +	tmp_env2 = (env_t *) malloc(CFG_ENV_SIZE); + +	nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, +		  (u_char*) tmp_env1); +	nand_read(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, +		  (u_char*) tmp_env2); + +	crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); +	crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); + +	if(!crc1_ok && !crc2_ok) +		return use_default(); +	else if(crc1_ok && !crc2_ok) +		gd->env_valid = 1; +	else if(!crc1_ok && crc2_ok) +		gd->env_valid = 2; +	else { +		/* both ok - check serial */ +		if(tmp_env1->flags == 255 && tmp_env2->flags == 0) +			gd->env_valid = 2; +		else if(tmp_env2->flags == 255 && tmp_env1->flags == 0) +			gd->env_valid = 1; +		else if(tmp_env1->flags > tmp_env2->flags) +			gd->env_valid = 1; +		else if(tmp_env2->flags > tmp_env1->flags) +			gd->env_valid = 2; +		else /* flags are equal - almost impossible */ +			gd->env_valid = 1; +	} + +	free(env_ptr); +	if(gd->env_valid == 1) { +		env_ptr = tmp_env1; +		free(tmp_env2); +	} else { +		env_ptr = tmp_env2; +		free(tmp_env1); +	} + +#endif /* ! ENV_IS_EMBEDDED */ +} +#else /* ! CFG_ENV_OFFSET_REDUND */  /*   * The legacy NAND code saved the environment in the first NAND device i.e.,   * nand_dev_desc + 0. This is also the behaviour using the new NAND code. @@ -143,14 +232,14 @@ void env_relocate_spec (void)  	total = CFG_ENV_SIZE;  	ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total,  			(u_char*) env_ptr); -  	if (ret || total != CFG_ENV_SIZE) +	if (ret || total != CFG_ENV_SIZE)  		return use_default();  	if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)  		return use_default();  #endif /* ! ENV_IS_EMBEDDED */ -  } +#endif /* CFG_ENV_OFFSET_REDUND */  static void use_default()  { @@ -158,7 +247,7 @@ static void use_default()  	puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); -  	if (default_environment_size > CFG_ENV_SIZE){ +	if (default_environment_size > CFG_ENV_SIZE){  		puts ("*** Error - default environment is too large\n\n");  		return;  	} @@ -168,7 +257,7 @@ static void use_default()  			default_environment,  			default_environment_size);  	env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); - 	gd->env_valid = 1; +	gd->env_valid = 1;  } diff --git a/include/configs/delta.h b/include/configs/delta.h index b42a7e2c1..f230b0385 100644 --- a/include/configs/delta.h +++ b/include/configs/delta.h @@ -282,6 +282,7 @@  /* #define CFG_ENV_IS_NOWHERE */  #define CFG_ENV_IS_IN_NAND	1  #define CFG_ENV_OFFSET		0x40000 +#define CFG_ENV_OFFSET_REDUND	0x44000  #define CFG_ENV_SIZE		0x4000  #endif	/* __CONFIG_H */ diff --git a/include/environment.h b/include/environment.h index bb109649f..422f80089 100644 --- a/include/environment.h +++ b/include/environment.h @@ -69,6 +69,18 @@  # endif  #endif	/* CFG_ENV_IS_IN_FLASH */ +#if defined(CFG_ENV_IS_IN_NAND) +# ifndef CFG_ENV_OFFSET +#  error "Need to define CFG_ENV_OFFSET when using CFG_ENV_IS_IN_NAND" +# endif +# ifndef CFG_ENV_SIZE +#  error "Need to define CFG_ENV_SIZE when using CFG_ENV_IS_IN_NAND" +# endif +# ifdef CFG_ENV_OFFSET_REDUND +#  define CFG_REDUNDAND_ENVIRONMENT +# endif +#endif /* CFG_ENV_IS_IN_NAND */ +  #ifdef CFG_REDUNDAND_ENVIRONMENT  # define ENV_HEADER_SIZE	(sizeof(unsigned long) + 1) |