diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
| -rw-r--r-- | drivers/mtd/nand/nand_base.c | 1654 | 
1 files changed, 925 insertions, 729 deletions
| diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 3d846592c..9e05cef41 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -21,7 +21,7 @@   *  TODO:   *	Enable cached programming for 2k page size chips   *	Check, if mtd->ecctype should be set to MTD_ECC_HW - *	if we have HW ecc support. + *	if we have HW ECC support.   *	The AG-AND chips have nice features for speed improvement,   *	which are not supported yet. Read / program 4 pages in one go.   *	BBT table is not serialized, has to be fixed @@ -134,21 +134,14 @@ static int check_offs_len(struct mtd_info *mtd,  		ret = -EINVAL;  	} -	/* Do not allow past end of device */ -	if (ofs + len > mtd->size) { -		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n", -					__func__); -		ret = -EINVAL; -	} -  	return ret;  }  /**   * nand_release_device - [GENERIC] release chip - * @mtd:	MTD device structure + * @mtd: MTD device structure   * - * Deselect, release chip lock and wake up anyone waiting on the device + * Deselect, release chip lock and wake up anyone waiting on the device.   */  static void nand_release_device(struct mtd_info *mtd)  { @@ -160,9 +153,9 @@ static void nand_release_device(struct mtd_info *mtd)  /**   * nand_read_byte - [DEFAULT] read one byte from the chip - * @mtd:	MTD device structure + * @mtd: MTD device structure   * - * Default read function for 8bit buswith + * Default read function for 8bit buswidth.   */  uint8_t nand_read_byte(struct mtd_info *mtd)  { @@ -172,10 +165,11 @@ uint8_t nand_read_byte(struct mtd_info *mtd)  /**   * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip - * @mtd:	MTD device structure + * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip + * @mtd: MTD device structure + * + * Default read function for 16bit buswidth with endianness conversion.   * - * Default read function for 16bit buswith with - * endianess conversion   */  static uint8_t nand_read_byte16(struct mtd_info *mtd)  { @@ -185,10 +179,9 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)  /**   * nand_read_word - [DEFAULT] read one word from the chip - * @mtd:	MTD device structure + * @mtd: MTD device structure   * - * Default read function for 16bit buswith without - * endianess conversion + * Default read function for 16bit buswidth without endianness conversion.   */  static u16 nand_read_word(struct mtd_info *mtd)  { @@ -198,8 +191,8 @@ static u16 nand_read_word(struct mtd_info *mtd)  /**   * nand_select_chip - [DEFAULT] control CE line - * @mtd:	MTD device structure - * @chipnr:	chipnumber to select, -1 for deselect + * @mtd: MTD device structure + * @chipnr: chipnumber to select, -1 for deselect   *   * Default select function for 1 chip devices.   */ @@ -221,11 +214,11 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)  /**   * nand_write_buf - [DEFAULT] write buffer to chip - * @mtd:	MTD device structure - * @buf:	data buffer - * @len:	number of bytes to write + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write   * - * Default write function for 8bit buswith + * Default write function for 8bit buswidth.   */  void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)  { @@ -238,11 +231,11 @@ void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)  /**   * nand_read_buf - [DEFAULT] read chip data into buffer - * @mtd:	MTD device structure - * @buf:	buffer to store date - * @len:	number of bytes to read + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read   * - * Default read function for 8bit buswith + * Default read function for 8bit buswidth.   */  void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)  { @@ -255,11 +248,11 @@ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)  /**   * nand_verify_buf - [DEFAULT] Verify chip data against buffer - * @mtd:	MTD device structure - * @buf:	buffer containing the data to compare - * @len:	number of bytes to compare + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare   * - * Default verify function for 8bit buswith + * Default verify function for 8bit buswidth.   */  static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)  { @@ -274,11 +267,11 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)  /**   * nand_write_buf16 - [DEFAULT] write buffer to chip - * @mtd:	MTD device structure - * @buf:	data buffer - * @len:	number of bytes to write + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write   * - * Default write function for 16bit buswith + * Default write function for 16bit buswidth.   */  void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)  { @@ -294,11 +287,11 @@ void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)  /**   * nand_read_buf16 - [DEFAULT] read chip data into buffer - * @mtd:	MTD device structure - * @buf:	buffer to store date - * @len:	number of bytes to read + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read   * - * Default read function for 16bit buswith + * Default read function for 16bit buswidth.   */  void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)  { @@ -313,11 +306,11 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)  /**   * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer - * @mtd:	MTD device structure - * @buf:	buffer containing the data to compare - * @len:	number of bytes to compare + * @mtd: MTD device structure + * @buf: buffer containing the data to compare + * @len: number of bytes to compare   * - * Default verify function for 16bit buswith + * Default verify function for 16bit buswidth.   */  static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)  { @@ -335,19 +328,19 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)  /**   * nand_block_bad - [DEFAULT] Read bad block marker from the chip - * @mtd:	MTD device structure - * @ofs:	offset from device start - * @getchip:	0, if the chip is already selected + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected   *   * Check, if the block is bad.   */  static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  { -	int page, chipnr, res = 0; +	int page, chipnr, res = 0, i = 0;  	struct nand_chip *chip = mtd->priv;  	u16 bad; -	if (chip->options & NAND_BBT_SCANLASTPAGE) +	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)  		ofs += mtd->erasesize - mtd->writesize;  	page = (int)(ofs >> chip->page_shift) & chip->pagemask; @@ -361,23 +354,29 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  		chip->select_chip(mtd, chipnr);  	} -	if (chip->options & NAND_BUSWIDTH_16) { -		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, -			      page); -		bad = cpu_to_le16(chip->read_word(mtd)); -		if (chip->badblockpos & 0x1) -			bad >>= 8; -		else -			bad &= 0xFF; -	} else { -		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); -		bad = chip->read_byte(mtd); -	} +	do { +		if (chip->options & NAND_BUSWIDTH_16) { +			chip->cmdfunc(mtd, NAND_CMD_READOOB, +					chip->badblockpos & 0xFE, page); +			bad = cpu_to_le16(chip->read_word(mtd)); +			if (chip->badblockpos & 0x1) +				bad >>= 8; +			else +				bad &= 0xFF; +		} else { +			chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, +					page); +			bad = chip->read_byte(mtd); +		} -	if (likely(chip->badblockbits == 8)) -		res = bad != 0xFF; -	else -		res = hweight8(bad) < chip->badblockbits; +		if (likely(chip->badblockbits == 8)) +			res = bad != 0xFF; +		else +			res = hweight8(bad) < chip->badblockbits; +		ofs += mtd->writesize; +		page = (int)(ofs >> chip->page_shift) & chip->pagemask; +		i++; +	} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));  	if (getchip)  		nand_release_device(mtd); @@ -387,57 +386,83 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  /**   * nand_default_block_markbad - [DEFAULT] mark a block bad - * @mtd:	MTD device structure - * @ofs:	offset from device start + * @mtd: MTD device structure + * @ofs: offset from device start   * - * This is the default implementation, which can be overridden by - * a hardware specific driver. + * This is the default implementation, which can be overridden by a hardware + * specific driver. We try operations in the following order, according to our + * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): + *  (1) erase the affected block, to allow OOB marker to be written cleanly + *  (2) update in-memory BBT + *  (3) write bad block marker to OOB area of affected block + *  (4) update flash-based BBT + * Note that we retain the first error encountered in (3) or (4), finish the + * procedures, and dump the error in the end.  */  static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)  {  	struct nand_chip *chip = mtd->priv;  	uint8_t buf[2] = { 0, 0 }; -	int block, ret, i = 0; +	int block, res, ret = 0, i = 0; +	int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); -	if (chip->options & NAND_BBT_SCANLASTPAGE) -		ofs += mtd->erasesize - mtd->writesize; +	if (write_oob) { +		struct erase_info einfo; + +		/* Attempt erase before marking OOB */ +		memset(&einfo, 0, sizeof(einfo)); +		einfo.mtd = mtd; +		einfo.addr = ofs; +		einfo.len = 1 << chip->phys_erase_shift; +		nand_erase_nand(mtd, &einfo, 0); +	}  	/* Get block number */  	block = (int)(ofs >> chip->bbt_erase_shift); +	/* Mark block bad in memory-based BBT */  	if (chip->bbt)  		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); -	/* Do we have a flash based bad block table ? */ -	if (chip->options & NAND_USE_FLASH_BBT) -		ret = nand_update_bbt(mtd, ofs); -	else { +	/* Write bad block marker to OOB */ +	if (write_oob) { +		struct mtd_oob_ops ops; +		loff_t wr_ofs = ofs; +  		nand_get_device(chip, mtd, FL_WRITING); -		/* Write to first two pages and to byte 1 and 6 if necessary. -		 * If we write to more than one location, the first error -		 * encountered quits the procedure. We write two bytes per -		 * location, so we dont have to mess with 16 bit access. -		 */ -		do { -			chip->ops.len = chip->ops.ooblen = 2; -			chip->ops.datbuf = NULL; -			chip->ops.oobbuf = buf; -			chip->ops.ooboffs = chip->badblockpos & ~0x01; +		ops.datbuf = NULL; +		ops.oobbuf = buf; +		ops.ooboffs = chip->badblockpos; +		if (chip->options & NAND_BUSWIDTH_16) { +			ops.ooboffs &= ~0x01; +			ops.len = ops.ooblen = 2; +		} else { +			ops.len = ops.ooblen = 1; +		} +		ops.mode = MTD_OPS_PLACE_OOB; -			ret = nand_do_write_oob(mtd, ofs, &chip->ops); +		/* Write to first/last page(s) if necessary */ +		if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) +			wr_ofs += mtd->erasesize - mtd->writesize; +		do { +			res = nand_do_write_oob(mtd, wr_ofs, &ops); +			if (!ret) +				ret = res; -			if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) { -				chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS -					& ~0x01; -				ret = nand_do_write_oob(mtd, ofs, &chip->ops); -			}  			i++; -			ofs += mtd->writesize; -		} while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) && -				i < 2); +			wr_ofs += mtd->writesize; +		} while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);  		nand_release_device(mtd);  	} + +	/* Update flash-based bad block table */ +	if (chip->bbt_options & NAND_BBT_USE_FLASH) { +		res = nand_update_bbt(mtd, ofs); +		if (!ret) +			ret = res; +	} +  	if (!ret)  		mtd->ecc_stats.badblocks++; @@ -446,16 +471,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)  /**   * nand_check_wp - [GENERIC] check if the chip is write protected - * @mtd:	MTD device structure - * Check, if the device is write protected + * @mtd: MTD device structure   * - * The function expects, that the device is already selected + * Check, if the device is write protected. The function expects, that the + * device is already selected.   */  static int nand_check_wp(struct mtd_info *mtd)  {  	struct nand_chip *chip = mtd->priv; -	/* broken xD cards report WP despite being writable */ +	/* Broken xD cards report WP despite being writable */  	if (chip->options & NAND_BROKEN_XD)  		return 0; @@ -466,10 +491,10 @@ static int nand_check_wp(struct mtd_info *mtd)  /**   * nand_block_checkbad - [GENERIC] Check if a block is marked bad - * @mtd:	MTD device structure - * @ofs:	offset from device start - * @getchip:	0, if the chip is already selected - * @allowbbt:	1, if its allowed to access the bbt area + * @mtd: MTD device structure + * @ofs: offset from device start + * @getchip: 0, if the chip is already selected + * @allowbbt: 1, if its allowed to access the bbt area   *   * Check, if the block is bad. Either by reading the bad block table or   * calling of the scan function. @@ -491,10 +516,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,  	return nand_isbad_bbt(mtd, ofs, allowbbt);  } -/* - * Wait for the ready pin, after a command - * The timeout is catched later. - */ +/* Wait for the ready pin, after a command. The timeout is caught later. */  void nand_wait_ready(struct mtd_info *mtd)  {  	struct nand_chip *chip = mtd->priv; @@ -503,7 +525,7 @@ void nand_wait_ready(struct mtd_info *mtd)  	time_start = get_timer(0); -	/* wait until command is processed or timeout occures */ +	/* Wait until command is processed or timeout occurs */  	while (get_timer(time_start) < timeo) {  		if (chip->dev_ready)  			if (chip->dev_ready(mtd)) @@ -513,13 +535,13 @@ void nand_wait_ready(struct mtd_info *mtd)  /**   * nand_command - [DEFAULT] Send command to NAND device - * @mtd:	MTD device structure - * @command:	the command to be sent - * @column:	the column address for this command, -1 if none - * @page_addr:	the page address for this command, -1 if none + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none   * - * Send command to NAND device. This function is used for small page - * devices (256/512 Bytes per page) + * Send command to NAND device. This function is used for small page devices + * (256/512 Bytes per page).   */  static void nand_command(struct mtd_info *mtd, unsigned int command,  			 int column, int page_addr) @@ -528,9 +550,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,  	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;  	uint32_t rst_sts_cnt = CONFIG_SYS_NAND_RESET_CNT; -	/* -	 * Write out the command to the device. -	 */ +	/* Write out the command to the device */  	if (command == NAND_CMD_SEQIN) {  		int readcmd; @@ -550,9 +570,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,  	}  	chip->cmd_ctrl(mtd, command, ctrl); -	/* -	 * Address cycle, when necessary -	 */ +	/* Address cycle, when necessary */  	ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;  	/* Serially input address */  	if (column != -1) { @@ -573,8 +591,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,  	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);  	/* -	 * program and erase have their own busy handlers -	 * status and sequential in needs no delay +	 * Program and erase have their own busy handlers status and sequential +	 * in needs no delay  	 */  	switch (command) { @@ -608,8 +626,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,  			return;  		}  	} -	/* Apply this short delay always to ensure that we do wait tWB in -	 * any case on any machine. */ +	/* +	 * Apply this short delay always to ensure that we do wait tWB in +	 * any case on any machine. +	 */  	ndelay(100);  	nand_wait_ready(mtd); @@ -617,14 +637,14 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,  /**   * nand_command_lp - [DEFAULT] Send command to NAND large page device - * @mtd:	MTD device structure - * @command:	the command to be sent - * @column:	the column address for this command, -1 if none - * @page_addr:	the page address for this command, -1 if none + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none   *   * Send command to NAND device. This is the version for the new large page - * devices We dont have the separate regions as we have in the small page - * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible. + * devices. We don't have the separate regions as we have in the small page + * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.   */  static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  			    int column, int page_addr) @@ -667,8 +687,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);  	/* -	 * program and erase have their own busy handlers -	 * status, sequential in, and deplete1 need no delay +	 * Program and erase have their own busy handlers status, sequential +	 * in, and deplete1 need no delay.  	 */  	switch (command) { @@ -682,14 +702,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  	case NAND_CMD_DEPLETE1:  		return; -		/* -		 * read error status commands require only a short delay -		 */  	case NAND_CMD_STATUS_ERROR:  	case NAND_CMD_STATUS_ERROR0:  	case NAND_CMD_STATUS_ERROR1:  	case NAND_CMD_STATUS_ERROR2:  	case NAND_CMD_STATUS_ERROR3: +		/* Read error status commands require only a short delay */  		udelay(chip->chip_delay);  		return; @@ -723,7 +741,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  	default:  		/*  		 * If we don't have access to the busy pin, we apply the given -		 * command delay +		 * command delay.  		 */  		if (!chip->dev_ready) {  			udelay(chip->chip_delay); @@ -731,8 +749,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  		}  	} -	/* Apply this short delay always to ensure that we do wait tWB in -	 * any case on any machine. */ +	/* +	 * Apply this short delay always to ensure that we do wait tWB in +	 * any case on any machine. +	 */  	ndelay(100);  	nand_wait_ready(mtd); @@ -740,9 +760,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,  /**   * nand_get_device - [GENERIC] Get chip for selected access - * @chip:	the nand chip descriptor - * @mtd:	MTD device structure - * @new_state:	the state which is requested + * @chip: the nand chip descriptor + * @mtd: MTD device structure + * @new_state: the state which is requested   *   * Get the device and lock it for exclusive access   */ @@ -754,13 +774,13 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)  }  /** - * nand_wait - [DEFAULT]  wait until the command is done - * @mtd:	MTD device structure - * @chip:	NAND chip structure + * nand_wait - [DEFAULT] wait until the command is done + * @mtd: MTD device structure + * @chip: NAND chip structure   * - * Wait for command done. This applies to erase and program only - * Erase can take up to 400ms and program up to 20ms according to - * general NAND and SmartMedia specs + * Wait for command done. This applies to erase and program only. Erase can + * take up to 400ms and program up to 20ms according to general NAND and + * SmartMedia specs.   */  static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)  { @@ -804,34 +824,37 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)  }  /** - * nand_read_page_raw - [Intern] read raw page data without ecc - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_raw - [INTERN] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   * - * Not for syndrome calculating ecc controllers, which use a special oob layout + * Not for syndrome calculating ECC controllers, which use a special oob layout.   */  static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, -			      uint8_t *buf, int page) +			      uint8_t *buf, int oob_required, int page)  {  	chip->read_buf(mtd, buf, mtd->writesize); -	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); +	if (oob_required) +		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);  	return 0;  }  /** - * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   *   * We need a special oob layout and handling even when OOB isn't used.   */  static int nand_read_page_raw_syndrome(struct mtd_info *mtd, -					struct nand_chip *chip, -					uint8_t *buf, int page) +				       struct nand_chip *chip, uint8_t *buf, +				       int oob_required, int page)  {  	int eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -864,14 +887,15 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,  }  /** - * nand_read_page_swecc - [REPLACABLE] software ecc based page read function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   */  static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, -				uint8_t *buf, int page) +				uint8_t *buf, int oob_required, int page)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -881,7 +905,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,  	uint8_t *ecc_code = chip->buffers->ecccode;  	uint32_t *eccpos = chip->ecc.layout->eccpos; -	chip->ecc.read_page_raw(mtd, chip, buf, page); +	chip->ecc.read_page_raw(mtd, chip, buf, 1, page);  	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)  		chip->ecc.calculate(mtd, p, &ecc_calc[i]); @@ -905,12 +929,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,  }  /** - * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @data_offs:	offset of requested data within the page - * @readlen:	data length - * @bufpoi:	buffer to store read data + * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @data_offs: offset of requested data within the page + * @readlen: data length + * @bufpoi: buffer to store read data   */  static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,  			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) @@ -923,12 +947,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,  	int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;  	int index = 0; -	/* Column address wihin the page aligned to ECC size (256bytes). */ +	/* Column address within the page aligned to ECC size (256bytes) */  	start_step = data_offs / chip->ecc.size;  	end_step = (data_offs + readlen - 1) / chip->ecc.size;  	num_steps = end_step - start_step + 1; -	/* Data size aligned to ECC ecc.size*/ +	/* Data size aligned to ECC ecc.size */  	datafrag_len = num_steps * chip->ecc.size;  	eccfrag_len = num_steps * chip->ecc.bytes; @@ -940,13 +964,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,  	p = bufpoi + data_col_addr;  	chip->read_buf(mtd, p, datafrag_len); -	/* Calculate  ECC */ +	/* Calculate ECC */  	for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)  		chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]); -	/* The performance is faster if to position offsets -	   according to ecc.pos. Let make sure here that -	   there are no gaps in ecc positions */ +	/* +	 * The performance is faster if we position offsets according to +	 * ecc.pos. Let's make sure that there are no gaps in ECC positions. +	 */  	for (i = 0; i < eccfrag_len - 1; i++) {  		if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=  			eccpos[i + start_step * chip->ecc.bytes + 1]) { @@ -958,8 +983,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,  		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);  		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);  	} else { -		/* send the command to read the particular ecc bytes */ -		/* take care about buswidth alignment in read_buf */ +		/* +		 * Send the command to read the particular ECC bytes take care +		 * about buswidth alignment in read_buf. +		 */  		index = start_step * chip->ecc.bytes;  		aligned_pos = eccpos[index] & ~(busw - 1); @@ -992,16 +1019,17 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,  }  /** - * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   * - * Not for syndrome calculating ecc controllers which need a special oob layout + * Not for syndrome calculating ECC controllers which need a special oob layout.   */  static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, -				uint8_t *buf, int page) +				uint8_t *buf, int oob_required, int page)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1037,21 +1065,21 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,  }  /** - * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   * - * Hardware ECC for large page chips, require OOB to be read first. - * For this ECC mode, the write_page method is re-used from ECC_HW. - * These methods read/write ECC from the OOB area, unlike the - * ECC_HW_SYNDROME support with multiple ECC steps, follows the - * "infix ECC" scheme and reads/writes ECC from the data area, by - * overwriting the NAND manufacturer bad block markings. + * Hardware ECC for large page chips, require OOB to be read first. For this + * ECC mode, the write_page method is re-used from ECC_HW. These methods + * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with + * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from + * the data area, by overwriting the NAND manufacturer bad block markings.   */  static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, -	struct nand_chip *chip, uint8_t *buf, int page) +	struct nand_chip *chip, uint8_t *buf, int oob_required, int page)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1086,17 +1114,18 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,  }  /** - * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	buffer to store read data - * @page:	page number to read + * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read   * - * The hw generator calculates the error syndrome automatically. Therefor - * we need a special oob layout and handling. + * The hw generator calculates the error syndrome automatically. Therefore we + * need a special oob layout and handling.   */  static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, -				   uint8_t *buf, int page) +				   uint8_t *buf, int oob_required, int page)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1141,29 +1170,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,  }  /** - * nand_transfer_oob - [Internal] Transfer oob to client buffer - * @chip:	nand chip structure - * @oob:	oob destination address - * @ops:	oob ops structure - * @len:	size of oob to transfer + * nand_transfer_oob - [INTERN] Transfer oob to client buffer + * @chip: nand chip structure + * @oob: oob destination address + * @ops: oob ops structure + * @len: size of oob to transfer   */  static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,  				  struct mtd_oob_ops *ops, size_t len)  {  	switch (ops->mode) { -	case MTD_OOB_PLACE: -	case MTD_OOB_RAW: +	case MTD_OPS_PLACE_OOB: +	case MTD_OPS_RAW:  		memcpy(oob, chip->oob_poi + ops->ooboffs, len);  		return oob + len; -	case MTD_OOB_AUTO: { +	case MTD_OPS_AUTO_OOB: {  		struct nand_oobfree *free = chip->ecc.layout->oobfree;  		uint32_t boffs = 0, roffs = ops->ooboffs;  		size_t bytes = 0;  		for (; free->length && len; free++, len -= bytes) { -			/* Read request not from offset 0 ? */ +			/* Read request not from offset 0? */  			if (unlikely(roffs)) {  				if (roffs >= free->length) {  					roffs -= free->length; @@ -1189,26 +1218,23 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,  }  /** - * nand_do_read_ops - [Internal] Read data with ECC - * - * @mtd:	MTD device structure - * @from:	offset to read from - * @ops:	oob ops structure + * nand_do_read_ops - [INTERN] Read data with ECC + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob ops structure   *   * Internal function. Called with chip held.   */  static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  			    struct mtd_oob_ops *ops)  { -	int chipnr, page, realpage, col, bytes, aligned; +	int chipnr, page, realpage, col, bytes, aligned, oob_required;  	struct nand_chip *chip = mtd->priv;  	struct mtd_ecc_stats stats; -	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; -	int sndcmd = 1;  	int ret = 0;  	uint32_t readlen = ops->len;  	uint32_t oobreadlen = ops->ooblen; -	uint32_t max_oobsize = ops->mode == MTD_OOB_AUTO ? +	uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?  		mtd->oobavail : mtd->oobsize;  	uint8_t *bufpoi, *oob, *buf; @@ -1225,6 +1251,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  	buf = ops->datbuf;  	oob = ops->oobbuf; +	oob_required = oob ? 1 : 0;  	while (1) {  		WATCHDOG_RESET(); @@ -1232,41 +1259,46 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  		bytes = min(mtd->writesize - col, readlen);  		aligned = (bytes == mtd->writesize); -		/* Is the current page in the buffer ? */ +		/* Is the current page in the buffer? */  		if (realpage != chip->pagebuf || oob) {  			bufpoi = aligned ? buf : chip->buffers->databuf; -			if (likely(sndcmd)) { -				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); -				sndcmd = 0; -			} +			chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);  			/* Now read the page into the buffer */ -			if (unlikely(ops->mode == MTD_OOB_RAW)) -				ret = chip->ecc.read_page_raw(mtd, chip, -							      bufpoi, page); +			if (unlikely(ops->mode == MTD_OPS_RAW)) +				ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, +							      oob_required, +							      page);  			else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&  			    !oob)  				ret = chip->ecc.read_subpage(mtd, chip,  							col, bytes, bufpoi);  			else  				ret = chip->ecc.read_page(mtd, chip, bufpoi, -							  page); -			if (ret < 0) +							  oob_required, page); +			if (ret < 0) { +				if (!aligned) +					/* Invalidate page cache */ +					chip->pagebuf = -1;  				break; +			}  			/* Transfer not aligned data */  			if (!aligned) {  				if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && -				    !(mtd->ecc_stats.failed - stats.failed)) +				    !(mtd->ecc_stats.failed - stats.failed) && +				    (ops->mode != MTD_OPS_RAW))  					chip->pagebuf = realpage; +				else +					/* Invalidate page cache */ +					chip->pagebuf = -1;  				memcpy(buf, chip->buffers->databuf + col, bytes);  			}  			buf += bytes;  			if (unlikely(oob)) { -  				int toread = min(oobreadlen, max_oobsize);  				if (toread) { @@ -1275,20 +1307,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  					oobreadlen -= toread;  				}  			} - -			if (!(chip->options & NAND_NO_READRDY)) { -				/* -				 * Apply delay or wait for ready/busy pin. Do -				 * this before the AUTOINCR check, so no -				 * problems arise if a chip which does auto -				 * increment is marked as NOAUTOINCR by the -				 * board driver. -				 */ -				if (!chip->dev_ready) -					udelay(chip->chip_delay); -				else -					nand_wait_ready(mtd); -			}  		} else {  			memcpy(buf, chip->buffers->databuf + col, bytes);  			buf += bytes; @@ -1299,7 +1317,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  		if (!readlen)  			break; -		/* For subsequent reads align to page boundary. */ +		/* For subsequent reads align to page boundary */  		col = 0;  		/* Increment page address */  		realpage++; @@ -1311,12 +1329,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  			chip->select_chip(mtd, -1);  			chip->select_chip(mtd, chipnr);  		} - -		/* Check, if the chip supports auto page increment -		 * or if we have hit a block boundary. -		 */ -		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) -			sndcmd = 1;  	}  	ops->retlen = ops->len - (size_t) readlen; @@ -1334,69 +1346,55 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,  /**   * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc - * @mtd:	MTD device structure - * @from:	offset to read from - * @len:	number of bytes to read - * @retlen:	pointer to variable to store the number of read bytes - * @buf:	the databuffer to put data + * @mtd: MTD device structure + * @from: offset to read from + * @len: number of bytes to read + * @retlen: pointer to variable to store the number of read bytes + * @buf: the databuffer to put data   * - * Get hold of the chip and call nand_do_read + * Get hold of the chip and call nand_do_read.   */  static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,  		     size_t *retlen, uint8_t *buf)  {  	struct nand_chip *chip = mtd->priv; +	struct mtd_oob_ops ops;  	int ret; -	/* Do not allow reads past end of device */ -	if ((from + len) > mtd->size) -		return -EINVAL; -	if (!len) -		return 0; -  	nand_get_device(chip, mtd, FL_READING); - -	chip->ops.len = len; -	chip->ops.datbuf = buf; -	chip->ops.oobbuf = NULL; - -	ret = nand_do_read_ops(mtd, from, &chip->ops); - -	*retlen = chip->ops.retlen; - +	ops.len = len; +	ops.datbuf = buf; +	ops.oobbuf = NULL; +	ops.mode = MTD_OPS_PLACE_OOB; +	ret = nand_do_read_ops(mtd, from, &ops); +	*retlen = ops.retlen;  	nand_release_device(mtd); -  	return ret;  }  /** - * nand_read_oob_std - [REPLACABLE] the most common OOB data read function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @page:	page number to read - * @sndcmd:	flag whether to issue read command or not + * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read   */  static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, -			     int page, int sndcmd) +			     int page)  { -	if (sndcmd) { -		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); -		sndcmd = 0; -	} +	chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);  	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); -	return sndcmd; +	return 0;  }  /** - * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC + * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC   *			    with syndromes - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @page:	page number to read - * @sndcmd:	flag whether to issue read command or not + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read   */  static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, -				  int page, int sndcmd) +				  int page)  {  	uint8_t *buf = chip->oob_poi;  	int length = mtd->oobsize; @@ -1423,14 +1421,14 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,  	if (length > 0)  		chip->read_buf(mtd, bufpoi, length); -	return 1; +	return 0;  }  /** - * nand_write_oob_std - [REPLACABLE] the most common OOB data write function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @page:	page number to write + * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write   */  static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,  			      int page) @@ -1450,11 +1448,11 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,  }  /** - * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC - *			     with syndrome - only for large page flash ! - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @page:	page number to write + * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC + *			     with syndrome - only for large page flash + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write   */  static int nand_write_oob_syndrome(struct mtd_info *mtd,  				   struct nand_chip *chip, int page) @@ -1509,27 +1507,30 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,  }  /** - * nand_do_read_oob - [Intern] NAND read out-of-band - * @mtd:	MTD device structure - * @from:	offset to read from - * @ops:	oob operations description structure + * nand_do_read_oob - [INTERN] NAND read out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operations description structure   * - * NAND read out-of-band data from the spare area + * NAND read out-of-band data from the spare area.   */  static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,  			    struct mtd_oob_ops *ops)  { -	int page, realpage, chipnr, sndcmd = 1; +	int page, realpage, chipnr;  	struct nand_chip *chip = mtd->priv; -	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; +	struct mtd_ecc_stats stats;  	int readlen = ops->ooblen;  	int len;  	uint8_t *buf = ops->oobbuf; +	int ret = 0;  	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",  			__func__, (unsigned long long)from, readlen); -	if (ops->mode == MTD_OOB_AUTO) +	stats = mtd->ecc_stats; + +	if (ops->mode == MTD_OPS_AUTO_OOB)  		len = chip->ecc.layout->oobavail;  	else  		len = mtd->oobsize; @@ -1558,24 +1559,17 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,  	while (1) {  		WATCHDOG_RESET(); -		sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); +		if (ops->mode == MTD_OPS_RAW) +			ret = chip->ecc.read_oob_raw(mtd, chip, page); +		else +			ret = chip->ecc.read_oob(mtd, chip, page); + +		if (ret < 0) +			break;  		len = min(len, readlen);  		buf = nand_transfer_oob(chip, buf, ops, len); -		if (!(chip->options & NAND_NO_READRDY)) { -			/* -			 * Apply delay or wait for ready/busy pin. Do this -			 * before the AUTOINCR check, so no problems arise if a -			 * chip which does auto increment is marked as -			 * NOAUTOINCR by the board driver. -			 */ -			if (!chip->dev_ready) -				udelay(chip->chip_delay); -			else -				nand_wait_ready(mtd); -		} -  		readlen -= len;  		if (!readlen)  			break; @@ -1590,25 +1584,26 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,  			chip->select_chip(mtd, -1);  			chip->select_chip(mtd, chipnr);  		} - -		/* Check, if the chip supports auto page increment -		 * or if we have hit a block boundary. -		 */ -		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) -			sndcmd = 1;  	} -	ops->oobretlen = ops->ooblen; -	return 0; +	ops->oobretlen = ops->ooblen - readlen; + +	if (ret < 0) +		return ret; + +	if (mtd->ecc_stats.failed - stats.failed) +		return -EBADMSG; + +	return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;  }  /**   * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band - * @mtd:	MTD device structure - * @from:	offset to read from - * @ops:	oob operation description structure + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operation description structure   * - * NAND read data and/or out-of-band data + * NAND read data and/or out-of-band data.   */  static int nand_read_oob(struct mtd_info *mtd, loff_t from,  			 struct mtd_oob_ops *ops) @@ -1628,9 +1623,9 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,  	nand_get_device(chip, mtd, FL_READING);  	switch (ops->mode) { -	case MTD_OOB_PLACE: -	case MTD_OOB_AUTO: -	case MTD_OOB_RAW: +	case MTD_OPS_PLACE_OOB: +	case MTD_OPS_AUTO_OOB: +	case MTD_OPS_RAW:  		break;  	default: @@ -1649,31 +1644,36 @@ out:  /** - * nand_write_page_raw - [Intern] raw page write function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	data buffer + * nand_write_page_raw - [INTERN] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB   * - * Not for syndrome calculating ecc controllers, which use a special oob layout + * Not for syndrome calculating ECC controllers, which use a special oob layout.   */ -static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, -				const uint8_t *buf) +static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, +				const uint8_t *buf, int oob_required)  {  	chip->write_buf(mtd, buf, mtd->writesize); -	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +	if (oob_required) +		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + +	return 0;  }  /** - * nand_write_page_raw_syndrome - [Intern] raw page write function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	data buffer + * nand_write_page_raw_syndrome - [INTERN] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB   *   * We need a special oob layout and handling even when ECC isn't checked.   */ -static void nand_write_page_raw_syndrome(struct mtd_info *mtd, +static int nand_write_page_raw_syndrome(struct mtd_info *mtd,  					struct nand_chip *chip, -					const uint8_t *buf) +					const uint8_t *buf, int oob_required)  {  	int eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1701,15 +1701,18 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,  	size = mtd->oobsize - (oob - chip->oob_poi);  	if (size)  		chip->write_buf(mtd, oob, size); + +	return 0;  }  /** - * nand_write_page_swecc - [REPLACABLE] software ecc based page write function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	data buffer + * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB   */ -static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, -				  const uint8_t *buf) +static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, +				  const uint8_t *buf, int oob_required)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1718,24 +1721,25 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,  	const uint8_t *p = buf;  	uint32_t *eccpos = chip->ecc.layout->eccpos; -	/* Software ecc calculation */ +	/* Software ECC calculation */  	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)  		chip->ecc.calculate(mtd, p, &ecc_calc[i]);  	for (i = 0; i < chip->ecc.total; i++)  		chip->oob_poi[eccpos[i]] = ecc_calc[i]; -	chip->ecc.write_page_raw(mtd, chip, buf); +	return chip->ecc.write_page_raw(mtd, chip, buf, 1);  }  /** - * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	data buffer + * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB   */ -static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, -				  const uint8_t *buf) +static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, +				  const uint8_t *buf, int oob_required)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1754,19 +1758,23 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,  		chip->oob_poi[eccpos[i]] = ecc_calc[i];  	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + +	return 0;  }  /** - * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write - * @mtd:	mtd info structure - * @chip:	nand chip info structure - * @buf:	data buffer + * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB   * - * The hw generator calculates the error syndrome automatically. Therefor - * we need a special oob layout and handling. + * The hw generator calculates the error syndrome automatically. Therefore we + * need a special oob layout and handling.   */ -static void nand_write_page_syndrome(struct mtd_info *mtd, -				    struct nand_chip *chip, const uint8_t *buf) +static int nand_write_page_syndrome(struct mtd_info *mtd, +				    struct nand_chip *chip, +				    const uint8_t *buf, int oob_required)  {  	int i, eccsize = chip->ecc.size;  	int eccbytes = chip->ecc.bytes; @@ -1798,32 +1806,39 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,  	i = mtd->oobsize - (oob - chip->oob_poi);  	if (i)  		chip->write_buf(mtd, oob, i); + +	return 0;  }  /**   * nand_write_page - [REPLACEABLE] write one page - * @mtd:	MTD device structure - * @chip:	NAND chip descriptor - * @buf:	the data to write - * @page:	page number to write - * @cached:	cached programming - * @raw:	use _raw version of write_page + * @mtd: MTD device structure + * @chip: NAND chip descriptor + * @buf: the data to write + * @oob_required: must write chip->oob_poi to OOB + * @page: page number to write + * @cached: cached programming + * @raw: use _raw version of write_page   */  static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, -			   const uint8_t *buf, int page, int cached, int raw) +			   const uint8_t *buf, int oob_required, int page, +			   int cached, int raw)  {  	int status;  	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);  	if (unlikely(raw)) -		chip->ecc.write_page_raw(mtd, chip, buf); +		status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);  	else -		chip->ecc.write_page(mtd, chip, buf); +		status = chip->ecc.write_page(mtd, chip, buf, oob_required); + +	if (status < 0) +		return status;  	/* -	 * Cached progamming disabled for now, Not sure if its worth the -	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) +	 * Cached progamming disabled for now. Not sure if it's worth the +	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).  	 */  	cached = 0; @@ -1833,7 +1848,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,  		status = chip->waitfunc(mtd, chip);  		/*  		 * See if operation failed and additional status checks are -		 * available +		 * available.  		 */  		if ((status & NAND_STATUS_FAIL) && (chip->errstat))  			status = chip->errstat(mtd, chip, FL_WRITING, status, @@ -1852,34 +1867,45 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,  	if (chip->verify_buf(mtd, buf, mtd->writesize))  		return -EIO; + +	/* Make sure the next page prog is preceded by a status read */ +	chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);  #endif  	return 0;  }  /** - * nand_fill_oob - [Internal] Transfer client buffer to oob - * @chip:	nand chip structure - * @oob:	oob data buffer - * @len:	oob data write length - * @ops:	oob ops structure + * nand_fill_oob - [INTERN] Transfer client buffer to oob + * @mtd: MTD device structure + * @oob: oob data buffer + * @len: oob data write length + * @ops: oob ops structure   */ -static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, -						struct mtd_oob_ops *ops) +static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, +			      struct mtd_oob_ops *ops)  { +	struct nand_chip *chip = mtd->priv; + +	/* +	 * Initialise to all 0xFF, to avoid the possibility of left over OOB +	 * data from a previous OOB read. +	 */ +	memset(chip->oob_poi, 0xff, mtd->oobsize); +  	switch (ops->mode) { -	case MTD_OOB_PLACE: -	case MTD_OOB_RAW: +	case MTD_OPS_PLACE_OOB: +	case MTD_OPS_RAW:  		memcpy(chip->oob_poi + ops->ooboffs, oob, len);  		return oob + len; -	case MTD_OOB_AUTO: { +	case MTD_OPS_AUTO_OOB: {  		struct nand_oobfree *free = chip->ecc.layout->oobfree;  		uint32_t boffs = 0, woffs = ops->ooboffs;  		size_t bytes = 0;  		for (; free->length && len; free++, len -= bytes) { -			/* Write request not from offset 0 ? */ +			/* Write request not from offset 0? */  			if (unlikely(woffs)) {  				if (woffs >= free->length) {  					woffs -= free->length; @@ -1907,12 +1933,12 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,  #define NOTALIGNED(x)	((x & (chip->subpagesize - 1)) != 0)  /** - * nand_do_write_ops - [Internal] NAND write with ECC - * @mtd:	MTD device structure - * @to:		offset to write to - * @ops:	oob operations description structure + * nand_do_write_ops - [INTERN] NAND write with ECC + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operations description structure   * - * NAND write with ECC + * NAND write with ECC.   */  static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  			     struct mtd_oob_ops *ops) @@ -1922,12 +1948,13 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  	uint32_t writelen = ops->len;  	uint32_t oobwritelen = ops->ooblen; -	uint32_t oobmaxlen = ops->mode == MTD_OOB_AUTO ? +	uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?  				mtd->oobavail : mtd->oobsize;  	uint8_t *oob = ops->oobbuf;  	uint8_t *buf = ops->datbuf;  	int ret, subpage; +	int oob_required = oob ? 1 : 0;  	ops->retlen = 0;  	if (!writelen) @@ -1957,10 +1984,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  	    (chip->pagebuf << chip->page_shift) < (to + ops->len))  		chip->pagebuf = -1; -	/* If we're not given explicit OOB data, let it be 0xFF */ -	if (likely(!oob)) -		memset(chip->oob_poi, 0xff, mtd->oobsize); -  	/* Don't allow multipage oob writes with offset */  	if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))  		return -EINVAL; @@ -1972,7 +1995,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  		int cached = writelen > bytes && page != blockmask;  		uint8_t *wbuf = buf; -		/* Partial page write ? */ +		/* Partial page write? */  		if (unlikely(column || writelen < mtd->writesize)) {  			cached = 0;  			bytes = min_t(int, bytes - column, (int) writelen); @@ -1984,12 +2007,15 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  		if (unlikely(oob)) {  			size_t len = min(oobwritelen, oobmaxlen); -			oob = nand_fill_oob(chip, oob, len, ops); +			oob = nand_fill_oob(mtd, oob, len, ops);  			oobwritelen -= len; +		} else { +			/* We still need to erase leftover OOB data */ +			memset(chip->oob_poi, 0xff, mtd->oobsize);  		} -		ret = chip->write_page(mtd, chip, wbuf, page, cached, -				       (ops->mode == MTD_OOB_RAW)); +		ret = chip->write_page(mtd, chip, wbuf, oob_required, page, +				       cached, (ops->mode == MTD_OPS_RAW));  		if (ret)  			break; @@ -2018,48 +2044,39 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,  /**   * nand_write - [MTD Interface] NAND write with ECC - * @mtd:	MTD device structure - * @to:		offset to write to - * @len:	number of bytes to write - * @retlen:	pointer to variable to store the number of written bytes - * @buf:	the data to write + * @mtd: MTD device structure + * @to: offset to write to + * @len: number of bytes to write + * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write   * - * NAND write with ECC + * NAND write with ECC.   */  static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,  			  size_t *retlen, const uint8_t *buf)  {  	struct nand_chip *chip = mtd->priv; +	struct mtd_oob_ops ops;  	int ret; -	/* Do not allow writes past end of device */ -	if ((to + len) > mtd->size) -		return -EINVAL; -	if (!len) -		return 0; -  	nand_get_device(chip, mtd, FL_WRITING); - -	chip->ops.len = len; -	chip->ops.datbuf = (uint8_t *)buf; -	chip->ops.oobbuf = NULL; - -	ret = nand_do_write_ops(mtd, to, &chip->ops); - -	*retlen = chip->ops.retlen; - +	ops.len = len; +	ops.datbuf = (uint8_t *)buf; +	ops.oobbuf = NULL; +	ops.mode = MTD_OPS_PLACE_OOB; +	ret = nand_do_write_ops(mtd, to, &ops); +	*retlen = ops.retlen;  	nand_release_device(mtd); -  	return ret;  }  /**   * nand_do_write_oob - [MTD Interface] NAND write out-of-band - * @mtd:	MTD device structure - * @to:		offset to write to - * @ops:	oob operation description structure + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operation description structure   * - * NAND write out-of-band + * NAND write out-of-band.   */  static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  			     struct mtd_oob_ops *ops) @@ -2070,7 +2087,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",  			 __func__, (unsigned int)to, (int)ops->ooblen); -	if (ops->mode == MTD_OOB_AUTO) +	if (ops->mode == MTD_OPS_AUTO_OOB)  		len = chip->ecc.layout->oobavail;  	else  		len = mtd->oobsize; @@ -2120,10 +2137,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  	if (page == chip->pagebuf)  		chip->pagebuf = -1; -	memset(chip->oob_poi, 0xff, mtd->oobsize); -	nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops); -	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); -	memset(chip->oob_poi, 0xff, mtd->oobsize); +	nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops); + +	if (ops->mode == MTD_OPS_RAW) +		status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask); +	else +		status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);  	if (status)  		return status; @@ -2135,9 +2154,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  /**   * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band - * @mtd:	MTD device structure - * @to:		offset to write to - * @ops:	oob operation description structure + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operation description structure   */  static int nand_write_oob(struct mtd_info *mtd, loff_t to,  			  struct mtd_oob_ops *ops) @@ -2157,9 +2176,9 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,  	nand_get_device(chip, mtd, FL_WRITING);  	switch (ops->mode) { -	case MTD_OOB_PLACE: -	case MTD_OOB_AUTO: -	case MTD_OOB_RAW: +	case MTD_OPS_PLACE_OOB: +	case MTD_OPS_AUTO_OOB: +	case MTD_OPS_RAW:  		break;  	default: @@ -2177,11 +2196,11 @@ out:  }  /** - * single_erease_cmd - [GENERIC] NAND standard block erase command function - * @mtd:	MTD device structure - * @page:	the page address of the block which will be erased + * single_erase_cmd - [GENERIC] NAND standard block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased   * - * Standard erase command for NAND chips + * Standard erase command for NAND chips.   */  static void single_erase_cmd(struct mtd_info *mtd, int page)  { @@ -2192,12 +2211,11 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)  }  /** - * multi_erease_cmd - [GENERIC] AND specific block erase command function - * @mtd:	MTD device structure - * @page:	the page address of the block which will be erased + * multi_erase_cmd - [GENERIC] AND specific block erase command function + * @mtd: MTD device structure + * @page: the page address of the block which will be erased   * - * AND multi block erase command function - * Erase 4 consecutive blocks + * AND multi block erase command function. Erase 4 consecutive blocks.   */  static void multi_erase_cmd(struct mtd_info *mtd, int page)  { @@ -2212,10 +2230,10 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page)  /**   * nand_erase - [MTD Interface] erase block(s) - * @mtd:	MTD device structure - * @instr:	erase instruction + * @mtd: MTD device structure + * @instr: erase instruction   * - * Erase one ore more blocks + * Erase one ore more blocks.   */  static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)  { @@ -2224,12 +2242,12 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)  #define BBT_PAGE_MASK	0xffffff3f  /** - * nand_erase_nand - [Internal] erase block(s) - * @mtd:	MTD device structure - * @instr:	erase instruction - * @allowbbt:	allow erasing the bbt area + * nand_erase_nand - [INTERN] erase block(s) + * @mtd: MTD device structure + * @instr: erase instruction + * @allowbbt: allow erasing the bbt area   * - * Erase one ore more blocks + * Erase one ore more blocks.   */  int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  		    int allowbbt) @@ -2247,8 +2265,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  	if (check_offs_len(mtd, instr->addr, instr->len))  		return -EINVAL; -	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; -  	/* Grab the lock and see if the device is available */  	nand_get_device(chip, mtd, FL_ERASING); @@ -2274,7 +2290,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  	 * If BBT requires refresh, set the BBT page mask to see if the BBT  	 * should be rewritten. Otherwise the mask is set to 0xffffffff which  	 * can not be matched. This is also done when the bbt is actually -	 * erased to avoid recusrsive updates +	 * erased to avoid recursive updates.  	 */  	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)  		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK; @@ -2286,20 +2302,18 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  	while (len) {  		WATCHDOG_RESET(); -		/* -		 * heck if we have a bad block, we do not erase bad blocks ! -		 */ +		/* Check if we have a bad block, we do not erase bad blocks! */  		if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<  					chip->page_shift, 0, allowbbt)) { -			printk(KERN_WARNING "%s: attempt to erase a bad block " -					"at page 0x%08x\n", __func__, page); +			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", +				   __func__, page);  			instr->state = MTD_ERASE_FAILED;  			goto erase_exit;  		}  		/*  		 * Invalidate the page cache, if we erase the block which -		 * contains the current cached page +		 * contains the current cached page.  		 */  		if (page <= chip->pagebuf && chip->pagebuf <  		    (page + pages_per_block)) @@ -2329,7 +2343,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  		/*  		 * If BBT requires refresh, set the BBT rewrite flag to the -		 * page being erased +		 * page being erased.  		 */  		if (bbt_masked_page != 0xffffffff &&  		    (page & BBT_PAGE_MASK) == bbt_masked_page) @@ -2348,7 +2362,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  			/*  			 * If BBT requires refresh and BBT-PERCHIP, set the BBT -			 * page mask to see if this BBT should be rewritten +			 * page mask to see if this BBT should be rewritten.  			 */  			if (bbt_masked_page != 0xffffffff &&  			    (chip->bbt_td->options & NAND_BBT_PERCHIP)) @@ -2371,7 +2385,7 @@ erase_exit:  	/*  	 * If BBT requires refresh and erase was successful, rewrite any -	 * selected bad block tables +	 * selected bad block tables.  	 */  	if (bbt_masked_page == 0xffffffff || ret)  		return ret; @@ -2379,7 +2393,7 @@ erase_exit:  	for (chipnr = 0; chipnr < chip->numchips; chipnr++) {  		if (!rewrite_bbt[chipnr])  			continue; -		/* update the BBT for chip */ +		/* Update the BBT for chip */  		MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "  			"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,  			rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]); @@ -2392,9 +2406,9 @@ erase_exit:  /**   * nand_sync - [MTD Interface] sync - * @mtd:	MTD device structure + * @mtd: MTD device structure   * - * Sync is actually a wait for chip ready function + * Sync is actually a wait for chip ready function.   */  static void nand_sync(struct mtd_info *mtd)  { @@ -2410,22 +2424,18 @@ static void nand_sync(struct mtd_info *mtd)  /**   * nand_block_isbad - [MTD Interface] Check if block at offset is bad - * @mtd:	MTD device structure - * @offs:	offset relative to mtd start + * @mtd: MTD device structure + * @offs: offset relative to mtd start   */  static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)  { -	/* Check for invalid offset */ -	if (offs > mtd->size) -		return -EINVAL; -  	return nand_block_checkbad(mtd, offs, 1, 0);  }  /**   * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad - * @mtd:	MTD device structure - * @ofs:	offset relative to mtd start + * @mtd: MTD device structure + * @ofs: offset relative to mtd start   */  static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)  { @@ -2434,7 +2444,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)  	ret = nand_block_isbad(mtd, ofs);  	if (ret) { -		/* If it was bad already, return success and do nothing. */ +		/* If it was bad already, return success and do nothing */  		if (ret > 0)  			return 0;  		return ret; @@ -2443,9 +2453,51 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)  	return chip->block_markbad(mtd, ofs);  } -/* - * Set default functions + /** + * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand + * @mtd: MTD device structure + * @chip: nand chip info structure + * @addr: feature address. + * @subfeature_param: the subfeature parameters, a four bytes array. + */ +static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, +			int addr, uint8_t *subfeature_param) +{ +	int status; + +	if (!chip->onfi_version) +		return -EINVAL; + +	chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); +	chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); +	status = chip->waitfunc(mtd, chip); +	if (status & NAND_STATUS_FAIL) +		return -EIO; +	return 0; +} + +/** + * nand_onfi_get_features- [REPLACEABLE] get features for ONFI nand + * @mtd: MTD device structure + * @chip: nand chip info structure + * @addr: feature address. + * @subfeature_param: the subfeature parameters, a four bytes array.   */ +static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, +			int addr, uint8_t *subfeature_param) +{ +	if (!chip->onfi_version) +		return -EINVAL; + +	/* clear the sub feature parameters */ +	memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); + +	chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); +	chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); +	return 0; +} + +/* Set default functions */  static void nand_set_defaults(struct nand_chip *chip, int busw)  {  	/* check for proper chip_delay setup, set 20us if not */ @@ -2483,23 +2535,21 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)  }  #ifdef CONFIG_SYS_NAND_ONFI_DETECTION -/* - * sanitize ONFI strings so we can safely print them - */ +/* Sanitize ONFI strings so we can safely print them */  static void sanitize_string(char *s, size_t len)  {  	ssize_t i; -	/* null terminate */ +	/* Null terminate */  	s[len - 1] = 0; -	/* remove non printable chars */ +	/* Remove non printable chars */  	for (i = 0; i < len - 1; i++) {  		if (s[i] < ' ' || s[i] > 127)  			s[i] = '?';  	} -	/* remove trailing spaces */ +	/* Remove trailing spaces */  	strim(s);  } @@ -2516,7 +2566,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)  }  /* - * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise + * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.   */  static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  					int *busw) @@ -2525,20 +2575,18 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  	int i;  	int val; -	/* try ONFI for unknow chip or LP */ +	/* Try ONFI for unknown chip or LP */  	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);  	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||  		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')  		return 0; -	MTDDEBUG(MTD_DEBUG_LEVEL0, "ONFI flash detected\n");  	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);  	for (i = 0; i < 3; i++) {  		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));  		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==  				le16_to_cpu(p->crc)) { -			MTDDEBUG(MTD_DEBUG_LEVEL0, -				 "ONFI param page %d valid\n", i); +			pr_info("ONFI param page %d valid\n", i);  			break;  		}  	} @@ -2546,7 +2594,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  	if (i == 3)  		return 0; -	/* check version */ +	/* Check version */  	val = le16_to_cpu(p->revision);  	if (val & (1 << 5))  		chip->onfi_version = 23; @@ -2562,8 +2610,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  		chip->onfi_version = 0;  	if (!chip->onfi_version) { -		printk(KERN_INFO "%s: unsupported ONFI version: %d\n", -								__func__, val); +		pr_info("%s: unsupported ONFI version: %d\n", __func__, val);  		return 0;  	} @@ -2580,8 +2627,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,  	if (le16_to_cpu(p->features) & 1)  		*busw = NAND_BUSWIDTH_16; -	chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR; - +	pr_info("ONFI flash detected\n");  	return 1;  }  #else @@ -2594,7 +2640,248 @@ static inline int nand_flash_detect_onfi(struct mtd_info *mtd,  #endif  /* - * Get the flash and manufacturer id and lookup if the type is supported + * nand_id_has_period - Check if an ID string has a given wraparound period + * @id_data: the ID string + * @arrlen: the length of the @id_data array + * @period: the period of repitition + * + * Check if an ID string is repeated within a given sequence of bytes at + * specific repetition interval period (e.g., {0x20,0x01,0x7F,0x20} has a + * period of 2). This is a helper function for nand_id_len(). Returns non-zero + * if the repetition has a period of @period; otherwise, returns zero. + */ +static int nand_id_has_period(u8 *id_data, int arrlen, int period) +{ +	int i, j; +	for (i = 0; i < period; i++) +		for (j = i + period; j < arrlen; j += period) +			if (id_data[i] != id_data[j]) +				return 0; +	return 1; +} + +/* + * nand_id_len - Get the length of an ID string returned by CMD_READID + * @id_data: the ID string + * @arrlen: the length of the @id_data array + + * Returns the length of the ID string, according to known wraparound/trailing + * zero patterns. If no pattern exists, returns the length of the array. + */ +static int nand_id_len(u8 *id_data, int arrlen) +{ +	int last_nonzero, period; + +	/* Find last non-zero byte */ +	for (last_nonzero = arrlen - 1; last_nonzero >= 0; last_nonzero--) +		if (id_data[last_nonzero]) +			break; + +	/* All zeros */ +	if (last_nonzero < 0) +		return 0; + +	/* Calculate wraparound period */ +	for (period = 1; period < arrlen; period++) +		if (nand_id_has_period(id_data, arrlen, period)) +			break; + +	/* There's a repeated pattern */ +	if (period < arrlen) +		return period; + +	/* There are trailing zeros */ +	if (last_nonzero < arrlen - 1) +		return last_nonzero + 1; + +	/* No pattern detected */ +	return arrlen; +} + +/* + * Many new NAND share similar device ID codes, which represent the size of the + * chip. The rest of the parameters must be decoded according to generic or + * manufacturer-specific "extended ID" decoding patterns. + */ +static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, +				u8 id_data[8], int *busw) +{ +	int extid, id_len; +	/* The 3rd id byte holds MLC / multichip data */ +	chip->cellinfo = id_data[2]; +	/* The 4th id byte is the important one */ +	extid = id_data[3]; + +	id_len = nand_id_len(id_data, 8); + +	/* +	 * Field definitions are in the following datasheets: +	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) +	 * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) +	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22) +	 * +	 * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung +	 * ID to decide what to do. +	 */ +	if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && +			(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && +			id_data[5] != 0x00) { +		/* Calc pagesize */ +		mtd->writesize = 2048 << (extid & 0x03); +		extid >>= 2; +		/* Calc oobsize */ +		switch (((extid >> 2) & 0x04) | (extid & 0x03)) { +		case 1: +			mtd->oobsize = 128; +			break; +		case 2: +			mtd->oobsize = 218; +			break; +		case 3: +			mtd->oobsize = 400; +			break; +		case 4: +			mtd->oobsize = 436; +			break; +		case 5: +			mtd->oobsize = 512; +			break; +		case 6: +		default: /* Other cases are "reserved" (unknown) */ +			mtd->oobsize = 640; +			break; +		} +		extid >>= 2; +		/* Calc blocksize */ +		mtd->erasesize = (128 * 1024) << +			(((extid >> 1) & 0x04) | (extid & 0x03)); +		*busw = 0; +	} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && +			(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { +		unsigned int tmp; + +		/* Calc pagesize */ +		mtd->writesize = 2048 << (extid & 0x03); +		extid >>= 2; +		/* Calc oobsize */ +		switch (((extid >> 2) & 0x04) | (extid & 0x03)) { +		case 0: +			mtd->oobsize = 128; +			break; +		case 1: +			mtd->oobsize = 224; +			break; +		case 2: +			mtd->oobsize = 448; +			break; +		case 3: +			mtd->oobsize = 64; +			break; +		case 4: +			mtd->oobsize = 32; +			break; +		case 5: +			mtd->oobsize = 16; +			break; +		default: +			mtd->oobsize = 640; +			break; +		} +		extid >>= 2; +		/* Calc blocksize */ +		tmp = ((extid >> 1) & 0x04) | (extid & 0x03); +		if (tmp < 0x03) +			mtd->erasesize = (128 * 1024) << tmp; +		else if (tmp == 0x03) +			mtd->erasesize = 768 * 1024; +		else +			mtd->erasesize = (64 * 1024) << tmp; +		*busw = 0; +	} else { +		/* Calc pagesize */ +		mtd->writesize = 1024 << (extid & 0x03); +		extid >>= 2; +		/* Calc oobsize */ +		mtd->oobsize = (8 << (extid & 0x01)) * +			(mtd->writesize >> 9); +		extid >>= 2; +		/* Calc blocksize. Blocksize is multiples of 64KiB */ +		mtd->erasesize = (64 * 1024) << (extid & 0x03); +		extid >>= 2; +		/* Get buswidth information */ +		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; +	} +} + + /* + * Old devices have chip data hardcoded in the device ID table. nand_decode_id + * decodes a matching ID table entry and assigns the MTD size parameters for + * the chip. + */ +static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, +				const struct nand_flash_dev *type, u8 id_data[8], +				int *busw) +{ +	int maf_id = id_data[0]; + +	mtd->erasesize = type->erasesize; +	mtd->writesize = type->pagesize; +	mtd->oobsize = mtd->writesize / 32; +	*busw = type->options & NAND_BUSWIDTH_16; + +	/* +	 * Check for Spansion/AMD ID + repeating 5th, 6th byte since +	 * some Spansion chips have erasesize that conflicts with size +	 * listed in nand_ids table. +	 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) +	 */ +	if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00 +			&& id_data[6] == 0x00 && id_data[7] == 0x00 +			&& mtd->writesize == 512) { +		mtd->erasesize = 128 * 1024; +		mtd->erasesize <<= ((id_data[3] & 0x03) << 1); +	} +} + + /* + * Set the bad block marker/indicator (BBM/BBI) patterns according to some + * heuristic patterns using various detected parameters (e.g., manufacturer, + * page size, cell-type information). + */ +static void nand_decode_bbm_options(struct mtd_info *mtd, +				    struct nand_chip *chip, u8 id_data[8]) +{ +	int maf_id = id_data[0]; + +	/* Set the bad block position */ +	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) +		chip->badblockpos = NAND_LARGE_BADBLOCK_POS; +	else +		chip->badblockpos = NAND_SMALL_BADBLOCK_POS; + +	/* +	 * Bad block marker is stored in the last page of each block on Samsung +	 * and Hynix MLC devices; stored in first two pages of each block on +	 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, +	 * AMD/Spansion, and Macronix.  All others scan only the first page. +	 */ +	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && +			(maf_id == NAND_MFR_SAMSUNG || +			 maf_id == NAND_MFR_HYNIX)) +		chip->bbt_options |= NAND_BBT_SCANLASTPAGE; +	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && +				(maf_id == NAND_MFR_SAMSUNG || +				 maf_id == NAND_MFR_HYNIX || +				 maf_id == NAND_MFR_TOSHIBA || +				 maf_id == NAND_MFR_AMD || +				 maf_id == NAND_MFR_MACRONIX)) || +			(mtd->writesize == 2048 && +			 maf_id == NAND_MFR_MICRON)) +		chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; +} + +/* + * Get the flash and manufacturer id and lookup if the type is supported.   */  static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  						  struct nand_chip *chip, @@ -2605,14 +2892,13 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	const char *name;  	int i, maf_idx;  	u8 id_data[8]; -	int ret;  	/* Select the device */  	chip->select_chip(mtd, 0);  	/*  	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) -	 * after power-up +	 * after power-up.  	 */  	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); @@ -2623,7 +2909,8 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	*maf_id = chip->read_byte(mtd);  	*dev_id = chip->read_byte(mtd); -	/* Try again to make sure, as some systems the bus-hold or other +	/* +	 * Try again to make sure, as some systems the bus-hold or other  	 * interface concerns can cause random data which looks like a  	 * possibly credible NAND flash to appear. If the two results do  	 * not match, ignore the device completely. @@ -2631,13 +2918,14 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); -	for (i = 0; i < 2; i++) +	/* Read entire ID string */ +	for (i = 0; i < 8; i++)  		id_data[i] = chip->read_byte(mtd);  	if (id_data[0] != *maf_id || id_data[1] != *dev_id) { -		printk(KERN_INFO "%s: second ID read did not match " -		       "%02x,%02x against %02x,%02x\n", __func__, -		       *maf_id, *dev_id, id_data[0], id_data[1]); +		pr_info("%s: second ID read did not match " +			"%02x,%02x against %02x,%02x\n", __func__, +			*maf_id, *dev_id, id_data[0], id_data[1]);  		return ERR_PTR(-ENODEV);  	} @@ -2651,18 +2939,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	chip->onfi_version = 0;  	if (!type->name || !type->pagesize) {  		/* Check is chip is ONFI compliant */ -		ret = nand_flash_detect_onfi(mtd, chip, &busw); -		if (ret) +		if (nand_flash_detect_onfi(mtd, chip, &busw))  			goto ident_done;  	} -	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - -	/* Read entire ID string */ - -	for (i = 0; i < 8; i++) -		id_data[i] = chip->read_byte(mtd); -  	if (!type->name)  		return ERR_PTR(-ENODEV); @@ -2672,101 +2952,25 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	chip->chipsize = (uint64_t)type->chipsize << 20;  	if (!type->pagesize && chip->init_size) { -		/* set the pagesize, oobsize, erasesize by the driver*/ +		/* Set the pagesize, oobsize, erasesize by the driver */  		busw = chip->init_size(mtd, chip, id_data);  	} else if (!type->pagesize) { -		int extid; -		/* The 3rd id byte holds MLC / multichip data */ -		chip->cellinfo = id_data[2]; -		/* The 4th id byte is the important one */ -		extid = id_data[3]; - -		/* -		 * Field definitions are in the following datasheets: -		 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) -		 * New style   (6 byte ID): Samsung K9GBG08U0M (p.40) -		 * -		 * Check for wraparound + Samsung ID + nonzero 6th byte -		 * to decide what to do. -		 */ -		if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && -				id_data[0] == NAND_MFR_SAMSUNG && -				(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && -				id_data[5] != 0x00) { -			/* Calc pagesize */ -			mtd->writesize = 2048 << (extid & 0x03); -			extid >>= 2; -			/* Calc oobsize */ -			switch (extid & 0x03) { -			case 1: -				mtd->oobsize = 128; -				break; -			case 2: -				mtd->oobsize = 218; -				break; -			case 3: -				mtd->oobsize = 400; -				break; -			default: -				mtd->oobsize = 436; -				break; -			} -			extid >>= 2; -			/* Calc blocksize */ -			mtd->erasesize = (128 * 1024) << -				(((extid >> 1) & 0x04) | (extid & 0x03)); -			busw = 0; -		} else { -			/* Calc pagesize */ -			mtd->writesize = 1024 << (extid & 0x03); -			extid >>= 2; -			/* Calc oobsize */ -			mtd->oobsize = (8 << (extid & 0x01)) * -				(mtd->writesize >> 9); -			extid >>= 2; -			/* Calc blocksize. Blocksize is multiples of 64KiB */ -			mtd->erasesize = (64 * 1024) << (extid & 0x03); -			extid >>= 2; -			/* Get buswidth information */ -			busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; -		} +		/* Decode parameters from extended ID */ +		nand_decode_ext_id(mtd, chip, id_data, &busw);  	} else { -		/* -		 * Old devices have chip data hardcoded in the device id table -		 */ -		mtd->erasesize = type->erasesize; -		mtd->writesize = type->pagesize; -		mtd->oobsize = mtd->writesize / 32; -		busw = type->options & NAND_BUSWIDTH_16; - -		/* -		 * Check for Spansion/AMD ID + repeating 5th, 6th byte since -		 * some Spansion chips have erasesize that conflicts with size -		 * listed in nand_ids table -		 * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) -		 */ -		if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && -				id_data[5] == 0x00 && id_data[6] == 0x00 && -				id_data[7] == 0x00 && mtd->writesize == 512) { -			mtd->erasesize = 128 * 1024; -			mtd->erasesize <<= ((id_data[3] & 0x03) << 1); -		} +		nand_decode_id(mtd, chip, type, id_data, &busw);  	}  	/* Get chip options, preserve non chip based options */  	chip->options |= type->options; -	/* Check if chip is a not a samsung device. Do not clear the -	 * options for chips which are not having an extended id. +	/* +	 * Check if chip is not a Samsung device. Do not clear the +	 * options for chips which do not have an extended id.  	 */  	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)  		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;  ident_done: -	/* -	 * Set chip as a default. Board drivers can override it, if necessary -	 */ -	chip->options |= NAND_NO_AUTOINCR; -  	/* Try to identify manufacturer */  	for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {  		if (nand_manuf_ids[maf_idx].id == *maf_id) @@ -2775,21 +2979,23 @@ ident_done:  	/*  	 * Check, if buswidth is correct. Hardware drivers should set -	 * chip correct ! +	 * chip correct!  	 */  	if (busw != (chip->options & NAND_BUSWIDTH_16)) { -		printk(KERN_INFO "NAND device: Manufacturer ID:" -		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, -		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); -		printk(KERN_WARNING "NAND bus width %d instead %d bit\n", -		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, -		       busw ? 16 : 8); +		pr_info("NAND device: Manufacturer ID:" +			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, +			*dev_id, nand_manuf_ids[maf_idx].name, mtd->name); +		pr_warn("NAND bus width %d instead %d bit\n", +			   (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, +			   busw ? 16 : 8);  		return ERR_PTR(-EINVAL);  	} +	nand_decode_bbm_options(mtd, chip, id_data); +  	/* Calculate the address shift from the page size */  	chip->page_shift = ffs(mtd->writesize) - 1; -	/* Convert chipsize to number of pages per chip -1. */ +	/* Convert chipsize to number of pages per chip -1 */  	chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;  	chip->bbt_erase_shift = chip->phys_erase_shift = @@ -2803,73 +3009,38 @@ ident_done:  	chip->badblockbits = 8; -	/* Set the bad block position */ -	if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) -		chip->badblockpos = NAND_LARGE_BADBLOCK_POS; -	else -		chip->badblockpos = NAND_SMALL_BADBLOCK_POS; - -	/* -	 * Bad block marker is stored in the last page of each block -	 * on Samsung and Hynix MLC devices; stored in first two pages -	 * of each block on Micron devices with 2KiB pages and on -	 * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan -	 * only the first page. -	 */ -	if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && -			(*maf_id == NAND_MFR_SAMSUNG || -			 *maf_id == NAND_MFR_HYNIX)) -		chip->options |= NAND_BBT_SCANLASTPAGE; -	else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && -				(*maf_id == NAND_MFR_SAMSUNG || -				 *maf_id == NAND_MFR_HYNIX || -				 *maf_id == NAND_MFR_TOSHIBA || -				 *maf_id == NAND_MFR_AMD)) || -			(mtd->writesize == 2048 && -			 *maf_id == NAND_MFR_MICRON)) -		chip->options |= NAND_BBT_SCAN2NDPAGE; - -	/* -	 * Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6 -	 */ -	if (!(busw & NAND_BUSWIDTH_16) && -			*maf_id == NAND_MFR_STMICRO && -			mtd->writesize == 2048) { -		chip->options |= NAND_BBT_SCANBYTE1AND6; -		chip->badblockpos = 0; -	} -  	/* Check for AND chips with 4 page planes */  	if (chip->options & NAND_4PAGE_ARRAY)  		chip->erase_cmd = multi_erase_cmd;  	else  		chip->erase_cmd = single_erase_cmd; -	/* Do not replace user supplied command function ! */ +	/* Do not replace user supplied command function! */  	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)  		chip->cmdfunc = nand_command_lp; -	/* TODO onfi flash name */  	name = type->name;  #ifdef CONFIG_SYS_NAND_ONFI_DETECTION  	if (chip->onfi_version)  		name = chip->onfi_params.model;  #endif -	MTDDEBUG(MTD_DEBUG_LEVEL0, "NAND device: Manufacturer ID:" -		 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, -		 nand_manuf_ids[maf_idx].name, name); +	pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," +		" page size: %d, OOB size: %d\n", +		*maf_id, *dev_id, nand_manuf_ids[maf_idx].name, +		name, +		mtd->writesize, mtd->oobsize);  	return type;  }  /**   * nand_scan_ident - [NAND Interface] Scan for the NAND device - * @mtd:	     MTD device structure - * @maxchips:	     Number of chips to scan for - * @table:	     Alternative NAND ID table + * @mtd: MTD device structure + * @maxchips: number of chips to scan for + * @table: alternative NAND ID table   * - * This is the first phase of the normal nand_scan() function. It - * reads the flash ID and sets up MTD fields accordingly. + * This is the first phase of the normal nand_scan() function. It reads the + * flash ID and sets up MTD fields accordingly.   *   * The mtd->owner field must be set to the module of the caller.   */ @@ -2891,7 +3062,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,  	if (IS_ERR(type)) {  #ifndef CONFIG_SYS_NAND_QUIET_TEST -		printk(KERN_WARNING "No NAND device found!!!\n"); +		pr_warn("No NAND device found\n");  #endif  		chip->select_chip(mtd, -1);  		return PTR_ERR(type); @@ -2911,7 +3082,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,  	}  #ifdef DEBUG  	if (i > 1) -		printk(KERN_INFO "%d NAND chips detected\n", i); +		pr_info("%d NAND chips detected\n", i);  #endif  	/* Store the number of chips and calc total size for mtd */ @@ -2924,17 +3095,21 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,  /**   * nand_scan_tail - [NAND Interface] Scan for the NAND device - * @mtd:	    MTD device structure + * @mtd: MTD device structure   * - * This is the second phase of the normal nand_scan() function. It - * fills out all the uninitialized function pointers with the defaults - * and scans for a bad block table if appropriate. + * This is the second phase of the normal nand_scan() function. It fills out + * all the uninitialized function pointers with the defaults and scans for a + * bad block table if appropriate.   */  int nand_scan_tail(struct mtd_info *mtd)  {  	int i;  	struct nand_chip *chip = mtd->priv; +	/* New bad blocks should be marked in OOB, flash-based BBT, or both */ +	BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && +			!(chip->bbt_options & NAND_BBT_USE_FLASH)); +  	if (!(chip->options & NAND_OWN_BUFFERS))  		chip->buffers = memalign(ARCH_DMA_MINALIGN,  					 sizeof(*chip->buffers)); @@ -2945,7 +3120,7 @@ int nand_scan_tail(struct mtd_info *mtd)  	chip->oob_poi = chip->buffers->databuf + mtd->writesize;  	/* -	 * If no default placement scheme is given, select an appropriate one +	 * If no default placement scheme is given, select an appropriate one.  	 */  	if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {  		switch (mtd->oobsize) { @@ -2962,16 +3137,22 @@ int nand_scan_tail(struct mtd_info *mtd)  			chip->ecc.layout = &nand_oob_128;  			break;  		default: -			printk(KERN_WARNING "No oob scheme defined for " -			       "oobsize %d\n", mtd->oobsize); +			pr_warn("No oob scheme defined for oobsize %d\n", +				   mtd->oobsize);  		}  	}  	if (!chip->write_page)  		chip->write_page = nand_write_page; +	/* set for ONFI nand */ +	if (!chip->onfi_set_features) +		chip->onfi_set_features = nand_onfi_set_features; +	if (!chip->onfi_get_features) +		chip->onfi_get_features = nand_onfi_get_features; +  	/* -	 * check ECC mode, default to software if 3byte/512byte hardware ECC is +	 * Check ECC mode, default to software if 3byte/512byte hardware ECC is  	 * selected and we have 256 byte pagesize fallback to software ECC  	 */ @@ -2980,15 +3161,15 @@ int nand_scan_tail(struct mtd_info *mtd)  		/* Similar to NAND_ECC_HW, but a separate read_page handle */  		if (!chip->ecc.calculate || !chip->ecc.correct ||  		     !chip->ecc.hwctl) { -			printk(KERN_WARNING "No ECC functions supplied; " -			       "Hardware ECC not possible\n"); +			pr_warn("No ECC functions supplied; " +				   "hardware ECC not possible\n");  			BUG();  		}  		if (!chip->ecc.read_page)  			chip->ecc.read_page = nand_read_page_hwecc_oob_first;  	case NAND_ECC_HW: -		/* Use standard hwecc read page function ? */ +		/* Use standard hwecc read page function? */  		if (!chip->ecc.read_page)  			chip->ecc.read_page = nand_read_page_hwecc;  		if (!chip->ecc.write_page) @@ -3009,11 +3190,11 @@ int nand_scan_tail(struct mtd_info *mtd)  		     chip->ecc.read_page == nand_read_page_hwecc ||  		     !chip->ecc.write_page ||  		     chip->ecc.write_page == nand_write_page_hwecc)) { -			printk(KERN_WARNING "No ECC functions supplied; " -			       "Hardware ECC not possible\n"); +			pr_warn("No ECC functions supplied; " +				   "hardware ECC not possible\n");  			BUG();  		} -		/* Use standard syndrome read/write page function ? */ +		/* Use standard syndrome read/write page function? */  		if (!chip->ecc.read_page)  			chip->ecc.read_page = nand_read_page_syndrome;  		if (!chip->ecc.write_page) @@ -3027,11 +3208,16 @@ int nand_scan_tail(struct mtd_info *mtd)  		if (!chip->ecc.write_oob)  			chip->ecc.write_oob = nand_write_oob_syndrome; -		if (mtd->writesize >= chip->ecc.size) +		if (mtd->writesize >= chip->ecc.size) { +			if (!chip->ecc.strength) { +				pr_warn("Driver must set ecc.strength when using hardware ECC\n"); +				BUG(); +			}  			break; -		printk(KERN_WARNING "%d byte HW ECC not possible on " -		       "%d byte page size, fallback to SW ECC\n", -		       chip->ecc.size, mtd->writesize); +		} +		pr_warn("%d byte HW ECC not possible on " +			   "%d byte page size, fallback to SW ECC\n", +			   chip->ecc.size, mtd->writesize);  		chip->ecc.mode = NAND_ECC_SOFT;  	case NAND_ECC_SOFT: @@ -3047,11 +3233,12 @@ int nand_scan_tail(struct mtd_info *mtd)  		if (!chip->ecc.size)  			chip->ecc.size = 256;  		chip->ecc.bytes = 3; +		chip->ecc.strength = 1;  		break;  	case NAND_ECC_SOFT_BCH:  		if (!mtd_nand_has_bch()) { -			printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n"); +			pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");  			return -EINVAL;  		}  		chip->ecc.calculate = nand_bch_calculate_ecc; @@ -3066,8 +3253,8 @@ int nand_scan_tail(struct mtd_info *mtd)  		/*  		 * Board driver should supply ecc.size and ecc.bytes values to  		 * select how many bits are correctable; see nand_bch_init() -		 * for details. -		 * Otherwise, default to 4 bits for large page devices +		 * for details. Otherwise, default to 4 bits for large page +		 * devices.  		 */  		if (!chip->ecc.size && (mtd->oobsize >= 64)) {  			chip->ecc.size = 512; @@ -3078,13 +3265,14 @@ int nand_scan_tail(struct mtd_info *mtd)  					       chip->ecc.bytes,  					       &chip->ecc.layout);  		if (!chip->ecc.priv) -			printk(KERN_WARNING "BCH ECC initialization failed!\n"); - +			pr_warn("BCH ECC initialization failed!\n"); + 		chip->ecc.strength = +			chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);  		break;  	case NAND_ECC_NONE: -		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " -		       "This is not recommended !!\n"); +		pr_warn("NAND_ECC_NONE selected by board driver. " +		        "This is not recommended !!\n");  		chip->ecc.read_page = nand_read_page_raw;  		chip->ecc.write_page = nand_write_page_raw;  		chip->ecc.read_oob = nand_read_oob_std; @@ -3096,14 +3284,19 @@ int nand_scan_tail(struct mtd_info *mtd)  		break;  	default: -		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", -		       chip->ecc.mode); +		pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);  		BUG();  	} +	/* For many systems, the standard OOB write also works for raw */ +	if (!chip->ecc.read_oob_raw) +		chip->ecc.read_oob_raw = chip->ecc.read_oob; +	if (!chip->ecc.write_oob_raw) +		chip->ecc.write_oob_raw = chip->ecc.write_oob; +  	/*  	 * The number of bytes available for a client to place data into -	 * the out of band area +	 * the out of band area.  	 */  	chip->ecc.layout->oobavail = 0;  	for (i = 0; chip->ecc.layout->oobfree[i].length @@ -3114,19 +3307,16 @@ int nand_scan_tail(struct mtd_info *mtd)  	/*  	 * Set the number of read / write steps for one page depending on ECC -	 * mode +	 * mode.  	 */  	chip->ecc.steps = mtd->writesize / chip->ecc.size;  	if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { -		printk(KERN_WARNING "Invalid ecc parameters\n"); +		pr_warn("Invalid ECC parameters\n");  		BUG();  	}  	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; -	/* -	 * Allow subpage writes up to ecc.steps. Not possible for MLC -	 * FLASH. -	 */ +	/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */  	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&  	    !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {  		switch (chip->ecc.steps) { @@ -3159,21 +3349,29 @@ int nand_scan_tail(struct mtd_info *mtd)  	mtd->type = MTD_NANDFLASH;  	mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :  						MTD_CAP_NANDFLASH; -	mtd->erase = nand_erase; -	mtd->point = NULL; -	mtd->unpoint = NULL; -	mtd->read = nand_read; -	mtd->write = nand_write; -	mtd->read_oob = nand_read_oob; -	mtd->write_oob = nand_write_oob; -	mtd->sync = nand_sync; -	mtd->lock = NULL; -	mtd->unlock = NULL; -	mtd->block_isbad = nand_block_isbad; -	mtd->block_markbad = nand_block_markbad; +	mtd->_erase = nand_erase; +	mtd->_point = NULL; +	mtd->_unpoint = NULL; +	mtd->_read = nand_read; +	mtd->_write = nand_write; +	mtd->_read_oob = nand_read_oob; +	mtd->_write_oob = nand_write_oob; +	mtd->_sync = nand_sync; +	mtd->_lock = NULL; +	mtd->_unlock = NULL; +	mtd->_block_isbad = nand_block_isbad; +	mtd->_block_markbad = nand_block_markbad; -	/* propagate ecc.layout to mtd_info */ +	/* propagate ecc info to mtd_info */  	mtd->ecclayout = chip->ecc.layout; +	mtd->ecc_strength = chip->ecc.strength; +	/* +	 * Initialize bitflip_threshold to its default prior scan_bbt() call. +	 * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be +	 * properly set. +	 */ +	if (!mtd->bitflip_threshold) +		mtd->bitflip_threshold = mtd->ecc_strength;  	/* Check, if we should skip the bad block table scan */  	if (chip->options & NAND_SKIP_BBTSCAN) @@ -3184,15 +3382,13 @@ int nand_scan_tail(struct mtd_info *mtd)  /**   * nand_scan - [NAND Interface] Scan for the NAND device - * @mtd:	MTD device structure - * @maxchips:	Number of chips to scan for - * - * This fills out all the uninitialized function pointers - * with the defaults. - * The flash ID is read and the mtd/chip structures are - * filled with the appropriate values. - * The mtd->owner field must be set to the module of the caller + * @mtd: MTD device structure + * @maxchips: number of chips to scan for   * + * This fills out all the uninitialized function pointers with the defaults. + * The flash ID is read and the mtd/chip structures are filled with the + * appropriate values. The mtd->owner field must be set to the module of the + * caller.   */  int nand_scan(struct mtd_info *mtd, int maxchips)  { @@ -3206,8 +3402,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)  /**   * nand_release - [NAND Interface] Free resources held by the NAND device - * @mtd:	MTD device structure -*/ + * @mtd: MTD device structure + */  void nand_release(struct mtd_info *mtd)  {  	struct nand_chip *chip = mtd->priv; |