diff options
Diffstat (limited to 'drivers/mtd/nand/nand_util.c')
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 133 | 
1 files changed, 66 insertions, 67 deletions
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 52b3d21b8..6ba52b30c 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -78,9 +78,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)  	const char *mtd_device = meminfo->name;  	struct mtd_oob_ops oob_opts;  	struct nand_chip *chip = meminfo->priv; -	uint8_t buf[64]; -	memset(buf, 0, sizeof(buf));  	memset(&erase, 0, sizeof(erase));  	memset(&oob_opts, 0, sizeof(oob_opts)); @@ -89,13 +87,9 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)  	erase.addr = opts->offset;  	erase_length = opts->length; -  	cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);  	cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);  	cleanmarker.totlen = cpu_to_je32(8); -	cleanmarker.hdr_crc = cpu_to_je32( -	crc32_no_comp(0, (unsigned char *) &cleanmarker, -	sizeof(struct jffs2_unknown_node) - 4));  	/* scrub option allows to erase badblock. To prevent internal  	 * check from erase() method, set block check method to dummy @@ -154,23 +148,21 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)  		}  		/* format for JFFS2 ? */ -		if (opts->jffs2) { - -			chip->ops.len = chip->ops.ooblen = 64; +		if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) { +			chip->ops.ooblen = 8;  			chip->ops.datbuf = NULL; -			chip->ops.oobbuf = buf; -			chip->ops.ooboffs = chip->badblockpos & ~0x01; +			chip->ops.oobbuf = (uint8_t *)&cleanmarker; +			chip->ops.ooboffs = 0; +			chip->ops.mode = MTD_OOB_AUTO;  			result = meminfo->write_oob(meminfo, -							erase.addr + meminfo->oobsize, -							&chip->ops); +			                            erase.addr, +			                            &chip->ops);  			if (result != 0) {  				printf("\n%s: MTD writeoob failure: %d\n", -				mtd_device, result); +				       mtd_device, result);  				continue;  			} -			else -				printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );  		}  		if (!opts->quiet) { @@ -190,11 +182,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)  				percent_complete = percent;  				printf("\rErasing at 0x%x -- %3d%% complete.", -				erase.addr, percent); +				       erase.addr, percent);  				if (opts->jffs2 && result == 0) -				printf(" Cleanmarker written at 0x%x.", -				erase.addr); +					printf(" Cleanmarker written at 0x%x.", +					       erase.addr);  			}  		}  	} @@ -246,7 +238,8 @@ static struct nand_ecclayout autoplace_ecclayout = {  #endif  /* XXX U-BOOT XXX */ -#if 0 +#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK +  /******************************************************************************   * Support for locking / unlocking operations of some NAND devices   *****************************************************************************/ @@ -261,7 +254,7 @@ static struct nand_ecclayout autoplace_ecclayout = {   * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT   *	      state   * - * @param meminfo	nand mtd instance + * @param mtd		nand mtd instance   * @param tight		bring device in lock tight mode   *   * @return		0 on success, -1 in case of error @@ -278,21 +271,21 @@ static struct nand_ecclayout autoplace_ecclayout = {   *   calls will fail. It is only posible to leave lock-tight state by   *   an hardware signal (low pulse on _WP pin) or by power down.   */ -int nand_lock(nand_info_t *meminfo, int tight) +int nand_lock(struct mtd_info *mtd, int tight)  {  	int ret = 0;  	int status; -	struct nand_chip *this = meminfo->priv; +	struct nand_chip *chip = mtd->priv;  	/* select the NAND device */ -	this->select_chip(meminfo, 0); +	chip->select_chip(mtd, 0); -	this->cmdfunc(meminfo, +	chip->cmdfunc(mtd,  		      (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),  		      -1, -1);  	/* call wait ready function */ -	status = this->waitfunc(meminfo, this, FL_WRITING); +	status = chip->waitfunc(mtd, chip);  	/* see if device thinks it succeeded */  	if (status & 0x01) { @@ -300,7 +293,7 @@ int nand_lock(nand_info_t *meminfo, int tight)  	}  	/* de-select the NAND device */ -	this->select_chip(meminfo, -1); +	chip->select_chip(mtd, -1);  	return ret;  } @@ -308,7 +301,7 @@ int nand_lock(nand_info_t *meminfo, int tight)   * nand_get_lock_status: - query current lock state from one page of NAND   *			   flash   * - * @param meminfo	nand mtd instance + * @param mtd		nand mtd instance   * @param offset	page address to query (muss be page aligned!)   *   * @return		-1 in case of error @@ -319,19 +312,19 @@ int nand_lock(nand_info_t *meminfo, int tight)   *			  NAND_LOCK_STATUS_UNLOCK: page unlocked   *   */ -int nand_get_lock_status(nand_info_t *meminfo, ulong offset) +int nand_get_lock_status(struct mtd_info *mtd, ulong offset)  {  	int ret = 0;  	int chipnr;  	int page; -	struct nand_chip *this = meminfo->priv; +	struct nand_chip *chip = mtd->priv;  	/* select the NAND device */ -	chipnr = (int)(offset >> this->chip_shift); -	this->select_chip(meminfo, chipnr); +	chipnr = (int)(offset >> chip->chip_shift); +	chip->select_chip(mtd, chipnr); -	if ((offset & (meminfo->writesize - 1)) != 0) { +	if ((offset & (mtd->writesize - 1)) != 0) {  		printf ("nand_get_lock_status: "  			"Start address must be beginning of "  			"nand page!\n"); @@ -340,16 +333,16 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset)  	}  	/* check the Lock Status */ -	page = (int)(offset >> this->page_shift); -	this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask); +	page = (int)(offset >> chip->page_shift); +	chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask); -	ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT +	ret = chip->read_byte(mtd) & (NAND_LOCK_STATUS_TIGHT  					  | NAND_LOCK_STATUS_LOCK  					  | NAND_LOCK_STATUS_UNLOCK);   out:  	/* de-select the NAND device */ -	this->select_chip(meminfo, -1); +	chip->select_chip(mtd, -1);  	return ret;  } @@ -357,59 +350,65 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset)   * nand_unlock: - Unlock area of NAND pages   *		  only one consecutive area can be unlocked at one time!   * - * @param meminfo	nand mtd instance + * @param mtd		nand mtd instance   * @param start		start byte address   * @param length	number of bytes to unlock (must be a multiple of   *			page size nand->writesize)   *   * @return		0 on success, -1 in case of error   */ -int nand_unlock(nand_info_t *meminfo, ulong start, ulong length) +int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)  {  	int ret = 0;  	int chipnr;  	int status;  	int page; -	struct nand_chip *this = meminfo->priv; +	struct nand_chip *chip = mtd->priv;  	printf ("nand_unlock: start: %08x, length: %d!\n",  		(int)start, (int)length);  	/* select the NAND device */ -	chipnr = (int)(start >> this->chip_shift); -	this->select_chip(meminfo, chipnr); +	chipnr = (int)(start >> chip->chip_shift); +	chip->select_chip(mtd, chipnr);  	/* check the WP bit */ -	this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1); -	if ((this->read_byte(meminfo) & 0x80) == 0) { +	chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); +	if (!(chip->read_byte(mtd) & NAND_STATUS_WP)) {  		printf ("nand_unlock: Device is write protected!\n");  		ret = -1;  		goto out;  	} -	if ((start & (meminfo->writesize - 1)) != 0) { +	if ((start & (mtd->erasesize - 1)) != 0) {  		printf ("nand_unlock: Start address must be beginning of " -			"nand page!\n"); +			"nand block!\n");  		ret = -1;  		goto out;  	} -	if (length == 0 || (length & (meminfo->writesize - 1)) != 0) { -		printf ("nand_unlock: Length must be a multiple of nand page " -			"size!\n"); +	if (length == 0 || (length & (mtd->erasesize - 1)) != 0) { +		printf ("nand_unlock: Length must be a multiple of nand block " +			"size %08x!\n", mtd->erasesize);  		ret = -1;  		goto out;  	} +	/* +	 * Set length so that the last address is set to the +	 * starting address of the last block +	 */ +	length -= mtd->erasesize; +  	/* submit address of first page to unlock */ -	page = (int)(start >> this->page_shift); -	this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask); +	page = (int)(start >> chip->page_shift); +	chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);  	/* submit ADDRESS of LAST page to unlock */ -	page += (int)(length >> this->page_shift) - 1; -	this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask); +	page += (int)(length >> chip->page_shift); +	chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1, page & chip->pagemask);  	/* call wait ready function */ -	status = this->waitfunc(meminfo, this, FL_WRITING); +	status = chip->waitfunc(mtd, chip);  	/* see if device thinks it succeeded */  	if (status & 0x01) {  		/* there was an error */ @@ -419,7 +418,7 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)   out:  	/* de-select the NAND device */ -	this->select_chip(meminfo, -1); +	chip->select_chip(mtd, -1);  	return ret;  }  #endif @@ -495,11 +494,11 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  	if (len_incl_bad == *length) {  		rval = nand_write (nand, offset, length, buffer); -		if (rval != 0) { -			printf ("NAND write to offset %x failed %d\n", +		if (rval != 0) +			printf ("NAND write to offset %zx failed %d\n",  				offset, rval); -			return rval; -		} + +		return rval;  	}  	while (left_to_write > 0) { @@ -507,7 +506,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  		size_t write_size;  		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { -			printf ("Skip bad block 0x%08x\n", +			printf ("Skip bad block 0x%08zx\n",  				offset & ~(nand->erasesize - 1));  			offset += nand->erasesize - block_offset;  			continue; @@ -520,7 +519,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  		rval = nand_write (nand, offset, &write_size, p_buffer);  		if (rval != 0) { -			printf ("NAND write to offset %x failed %d\n", +			printf ("NAND write to offset %zx failed %d\n",  				offset, rval);  			*length -= left_to_write;  			return rval; @@ -565,11 +564,11 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  	if (len_incl_bad == *length) {  		rval = nand_read (nand, offset, length, buffer); -		if (rval != 0) { -			printf ("NAND read from offset %x failed %d\n", +		if (rval != 0) +			printf ("NAND read from offset %zx failed %d\n",  				offset, rval); -			return rval; -		} + +		return rval;  	}  	while (left_to_read > 0) { @@ -577,7 +576,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  		size_t read_length;  		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { -			printf ("Skipping bad block 0x%08x\n", +			printf ("Skipping bad block 0x%08zx\n",  				offset & ~(nand->erasesize - 1));  			offset += nand->erasesize - block_offset;  			continue; @@ -590,7 +589,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,  		rval = nand_read (nand, offset, &read_length, p_buffer);  		if (rval != 0) { -			printf ("NAND read from offset %x failed %d\n", +			printf ("NAND read from offset %zx failed %d\n",  				offset, rval);  			*length -= left_to_read;  			return rval;  |