diff options
Diffstat (limited to 'common/cmd_nand.c')
| -rw-r--r-- | common/cmd_nand.c | 95 | 
1 files changed, 71 insertions, 24 deletions
| diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 0fd3a6c41..f060a317e 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -11,7 +11,7 @@   * Added 16-bit nand support   * (C) 2004 Texas Instruments   * - * Copyright 2010 Freescale Semiconductor + * Copyright 2010, 2012 Freescale Semiconductor   * The portions of this file whose copyright is held by Freescale and which   * are not considered a derived work of GPL v2-only code may be distributed   * and/or modified under the terms of the GNU General Public License as @@ -390,6 +390,41 @@ static void nand_print_and_set_info(int idx)  	setenv("nand_erasesize", buf);  } +static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, +			int read) +{ +	int ret = 0; +	size_t rwsize; + +	while (count--) { +		/* Raw access */ +		mtd_oob_ops_t ops = { +			.datbuf = (u8 *)addr, +			.oobbuf = ((u8 *)addr) + nand->writesize, +			.len = nand->writesize, +			.ooblen = nand->oobsize, +			.mode = MTD_OOB_RAW +		}; + +		rwsize = nand->writesize + nand->oobsize; +		if (read) +			ret = nand->read_oob(nand, off, &ops); +		else +			ret = nand->write_oob(nand, off, &ops); + +		if (ret) { +			printf("%s: error at offset %llx, ret %d\n", +				__func__, (long long)off, ret); +			break; +		} + +		addr += nand->writesize + nand->oobsize; +		off += nand->writesize; +	} + +	return ret; +} +  int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  {  	int i, ret = 0; @@ -568,7 +603,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {  		size_t rwsize; +		ulong pagecount = 1;  		int read; +		int raw;  		if (argc < 4)  			goto usage; @@ -577,13 +614,36 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */  		printf("\nNAND %s: ", read ? "read" : "write"); -		if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0) -			return 1;  		nand = &nand_info[dev]; -		rwsize = size;  		s = strchr(cmd, '.'); + +		if (!strcmp(s, ".raw")) { +			raw = 1; + +			if (arg_off(argv[3], &dev, &off, &size)) +				return 1; + +			if (argc > 4 && !str2long(argv[4], &pagecount)) { +				printf("'%s' is not a number\n", argv[4]); +				return 1; +			} + +			if (pagecount * nand->writesize > size) { +				puts("Size exceeds partition or device limit\n"); +				return -1; +			} + +			rwsize = pagecount * (nand->writesize + nand->oobsize); +		} else { +			if (arg_off_size(argc - 3, argv + 3, &dev, +						&off, &size) != 0) +				return 1; + +			rwsize = size; +		} +  		if (!s || !strcmp(s, ".jffs2") ||  		    !strcmp(s, ".e") || !strcmp(s, ".i")) {  			if (read) @@ -609,7 +669,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  				return 1;  			}  			ret = nand_write_skip_bad(nand, off, &rwsize, -						(u_char *)addr, WITH_YAFFS_OOB); +						(u_char *)addr, +						WITH_INLINE_OOB);  #endif  		} else if (!strcmp(s, ".oob")) {  			/* out-of-band data */ @@ -623,22 +684,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  				ret = nand->read_oob(nand, off, &ops);  			else  				ret = nand->write_oob(nand, off, &ops); -		} else if (!strcmp(s, ".raw")) { -			/* Raw access */ -			mtd_oob_ops_t ops = { -				.datbuf = (u8 *)addr, -				.oobbuf = ((u8 *)addr) + nand->writesize, -				.len = nand->writesize, -				.ooblen = nand->oobsize, -				.mode = MTD_OOB_RAW -			}; - -			rwsize = nand->writesize + nand->oobsize; - -			if (read) -				ret = nand->read_oob(nand, off, &ops); -			else -				ret = nand->write_oob(nand, off, &ops); +		} else if (raw) { +			ret = raw_access(nand, addr, off, pagecount, read);  		} else {  			printf("Unknown nand command suffix '%s'.\n", s);  			return 1; @@ -732,9 +779,9 @@ U_BOOT_CMD(  	"nand write - addr off|partition size\n"  	"    read/write 'size' bytes starting at offset 'off'\n"  	"    to/from memory address 'addr', skipping bad blocks.\n" -	"nand read.raw - addr off|partition\n" -	"nand write.raw - addr off|partition\n" -	"    Use read.raw/write.raw to avoid ECC and access the page as-is.\n" +	"nand read.raw - addr off|partition [count]\n" +	"nand write.raw - addr off|partition [count]\n" +	"    Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"  #ifdef CONFIG_CMD_NAND_TRIMFFS  	"nand write.trimffs - addr off|partition size\n"  	"    write 'size' bytes starting at offset 'off' from memory address\n" |