diff options
| -rw-r--r-- | common/cmd_nand.c | 13 | ||||
| -rw-r--r-- | doc/README.nand | 2 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 17 | ||||
| -rw-r--r-- | include/nand.h | 4 | 
4 files changed, 28 insertions, 8 deletions
| diff --git a/common/cmd_nand.c b/common/cmd_nand.c index a91ccf4df..f737c06f8 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -749,11 +749,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		return 0;  	} -	if (strcmp(cmd, "unlock") == 0) { +	if (strncmp(cmd, "unlock", 5) == 0) { +		int allexcept = 0; + +		s = strchr(cmd, '.'); + +		if (s && !strcmp(s, ".allexcept")) +			allexcept = 1; +  		if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)  			return 1; -		if (!nand_unlock(&nand_info[dev], off, size)) { +		if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {  			puts("NAND flash successfully unlocked\n");  		} else {  			puts("Error unlocking NAND flash, " @@ -807,7 +814,7 @@ U_BOOT_CMD(  	"\n"  	"nand lock [tight] [status]\n"  	"    bring nand to lock state or display locked pages\n" -	"nand unlock [offset] [size] - unlock section" +	"nand unlock[.allexcept] [offset] [size] - unlock section"  #endif  #ifdef CONFIG_ENV_OFFSET_OOB  	"\n" diff --git a/doc/README.nand b/doc/README.nand index 1602b5eee..c13018958 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -228,6 +228,8 @@ NAND locking command (for chips with active LOCKPRE pin)    "nand unlock [offset] [size]"    unlock consecutive area (can be called multiple times for different areas) +  "nand unlock.allexcept [offset] [size]" +  unlock all except specified consecutive area  I have tested the code with board containing 128MiB NAND large page chips  and 32MiB small page chips. diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 7ed8b1891..c66eeefcb 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -317,18 +317,20 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)   * @param start		start byte address   * @param length	number of bytes to unlock (must be a multiple of   *			page size nand->writesize) + * @param allexcept	if set, unlock everything not selected   *   * @return		0 on success, -1 in case of error   */ -int nand_unlock(struct mtd_info *mtd, ulong start, ulong length) +int nand_unlock(struct mtd_info *mtd, ulong start, ulong length, int allexcept)  {  	int ret = 0;  	int chipnr;  	int status;  	int page;  	struct nand_chip *chip = mtd->priv; -	printf ("nand_unlock: start: %08x, length: %d!\n", -		(int)start, (int)length); + +	debug("nand_unlock%s: start: %08x, length: %d!\n", +		allexcept ? " (allexcept)" : "", start, length);  	/* select the NAND device */  	chipnr = (int)(start >> chip->chip_shift); @@ -368,6 +370,15 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)  	/* submit ADDRESS of LAST page to unlock */  	page += (int)(length >> chip->page_shift); + +	/* +	 * Page addresses for unlocking are supposed to be block-aligned. +	 * At least some NAND chips use the low bit to indicate that the +	 * page range should be inverted. +	 */ +	if (allexcept) +		page |= 1; +  	chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask);  	/* call wait ready function */ diff --git a/include/nand.h b/include/nand.h index c554c552f..e9b47f1b2 100644 --- a/include/nand.h +++ b/include/nand.h @@ -144,8 +144,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);  #define NAND_LOCK_STATUS_LOCK	0x02  #define NAND_LOCK_STATUS_UNLOCK 0x04 -int nand_lock( nand_info_t *meminfo, int tight ); -int nand_unlock( nand_info_t *meminfo, ulong start, ulong length ); +int nand_lock(nand_info_t *meminfo, int tight); +int nand_unlock(nand_info_t *meminfo, ulong start, ulong length, int allexcept);  int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);  int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst); |