diff options
Diffstat (limited to 'common/cmd_onenand.c')
| -rw-r--r-- | common/cmd_onenand.c | 41 | 
1 files changed, 36 insertions, 5 deletions
| diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c index cb2ba7051..a27adaa61 100644 --- a/common/cmd_onenand.c +++ b/common/cmd_onenand.c @@ -112,8 +112,32 @@ static int onenand_block_read(loff_t from, size_t len,  	return 0;  } +static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf, +					  size_t *retlen) +{ +	struct mtd_oob_ops ops = { +		.len = mtd->writesize, +		.ooblen = mtd->oobsize, +		.mode = MTD_OOB_AUTO, +	}; +	int page, ret = 0; +	for (page = 0; page < (mtd->erasesize / mtd->writesize); page ++) { +		ops.datbuf = (u_char *)buf; +		buf += mtd->writesize; +		ops.oobbuf = (u_char *)buf; +		buf += mtd->oobsize; +		ret = mtd->write_oob(mtd, to, &ops); +		if (ret) +			break; +		to += mtd->writesize; +	} + +	*retlen = (ret) ? 0 : mtd->erasesize; +	return ret; +} +  static int onenand_block_write(loff_t to, size_t len, -			       size_t *retlen, const u_char * buf) +			       size_t *retlen, const u_char * buf, int withoob)  {  	struct onenand_chip *this = mtd->priv;  	int blocks = len >> this->erase_shift; @@ -140,7 +164,10 @@ static int onenand_block_write(loff_t to, size_t len,  			goto next;  		} -		ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf); +		if (!withoob) +			ret = mtd->write(mtd, ofs, blocksize, &_retlen, buf); +		else +			ret = onenand_write_oneblock_withoob(ofs, buf, &_retlen);  		if (ret) {  			printk("Write failed 0x%x, %d", (u32)ofs, ret);  			skip_ofs += blocksize; @@ -386,19 +413,22 @@ static int do_onenand_write(cmd_tbl_t * cmdtp, int flag, int argc, char * const  {  	ulong addr, ofs;  	size_t len; -	int ret = 0; +	int ret = 0, withoob = 0;  	size_t retlen = 0;  	if (argc < 3)  		return cmd_usage(cmdtp); +	if (strncmp(argv[0] + 6, "yaffs", 5) == 0) +		withoob = 1; +  	addr = (ulong)simple_strtoul(argv[1], NULL, 16);  	printf("\nOneNAND write: ");  	if (arg_off_size(argc - 2, argv + 2, &ofs, &len) != 0)  		return 1; -	ret = onenand_block_write(ofs, len, &retlen, (u8 *)addr); +	ret = onenand_block_write(ofs, len, &retlen, (u8 *)addr, withoob);  	printf(" %d bytes written: %s\n", retlen, ret ? "ERROR" : "OK"); @@ -521,6 +551,7 @@ static cmd_tbl_t cmd_onenand_sub[] = {  	U_BOOT_CMD_MKENT(bad, 1, 0, do_onenand_bad, "", ""),  	U_BOOT_CMD_MKENT(read, 4, 0, do_onenand_read, "", ""),  	U_BOOT_CMD_MKENT(write, 4, 0, do_onenand_write, "", ""), +	U_BOOT_CMD_MKENT(write.yaffs, 4, 0, do_onenand_write, "", ""),  	U_BOOT_CMD_MKENT(erase, 3, 0, do_onenand_erase, "", ""),  	U_BOOT_CMD_MKENT(test, 3, 0, do_onenand_test, "", ""),  	U_BOOT_CMD_MKENT(dump, 2, 0, do_onenand_dump, "", ""), @@ -560,7 +591,7 @@ U_BOOT_CMD(  	"info - show available OneNAND devices\n"  	"onenand bad - show bad blocks\n"  	"onenand read[.oob] addr off size\n" -	"onenand write addr off size\n" +	"onenand write[.yaffs] addr off size\n"  	"    read/write 'size' bytes starting at offset 'off'\n"  	"    to/from memory address 'addr', skipping bad blocks.\n"  	"onenand erase [force] [off size] - erase 'size' bytes from\n" |