diff options
| author | Nishanth Menon <menon.nishanth@gmail.com> | 2008-12-13 09:43:06 -0600 | 
|---|---|---|
| committer | Scott Wood <scottwood@freescale.com> | 2009-01-23 10:32:49 -0600 | 
| commit | 50657c273278f74378e1ac39b41d612b92fdffa0 (patch) | |
| tree | 2f4eb445a4aeddfe91737b889cda979fa1ba693f /drivers/mtd/nand/nand_util.c | |
| parent | 69fb8be4fc07162fdf6edf04bdc7233b0e9a920e (diff) | |
| download | olio-uboot-2014.01-50657c273278f74378e1ac39b41d612b92fdffa0.tar.xz olio-uboot-2014.01-50657c273278f74378e1ac39b41d612b92fdffa0.zip | |
NAND: Enable nand lock, unlock feature
Enable nand lock, unlock and status of lock feature.
Not every device and platform requires this, hence,
it is under define for CONFIG_CMD_NAND_LOCK_UNLOCK
Nand unlock and status operate on block boundary instead
of page boundary. Details in:
http://www.micron.com/products/partdetail?part=MT29C2G24MAKLAJG-6%20IT
Intial solution provided by Vikram Pandita <vikram.pandita@ti.com>
Includes preliminary suggestions from Scott Wood
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'drivers/mtd/nand/nand_util.c')
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 79 | 
1 files changed, 43 insertions, 36 deletions
| diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index d86c98737..77da53e26 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -238,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   *****************************************************************************/ @@ -253,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 @@ -270,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) { @@ -292,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;  } @@ -300,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 @@ -311,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"); @@ -332,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;  } @@ -349,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 */ @@ -411,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 |