/*
* NAND write out-of-band
*/
static int
nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
int i, offset, page, status, ret;
struct nand_chip *this = mtd->priv;
DEBUG(MTD_DEBUG_LEVEL3,
__FUNCTION__"(): to = 0x%08x, len = %i\n", (unsigned int)to,
(int)len);
/* Shift to get page */
page = ((int)to) >> this->page_shift;
/* Mask to get column */
offset = to & 0x1f;
/* Initialize return length value */
*retlen = 0;
/* Do not allow write past end of page */
if ((offset + len) > mtd->oobsize) {
DEBUG(MTD_DEBUG_LEVEL0,
__FUNCTION__"(): Attempt to write past end of page\n");
return -EINVAL;
}
/* Select the NAND device */
nand_select();
/* Check the WP bit */
nand_command(mtd, NAND_CMD_STATUS, -1, -1);
this->wait_for_ready();
if (!(this->read_data() & SMC_STAT_NOT_WP)) {
DEBUG(MTD_DEBUG_LEVEL0,
__FUNCTION__"(): Device is write protected!!!\n");
ret = -EPERM;
goto nand_write_oob_err;
}
//0x80对页进行编程操作,用于写操作
/* Write out desired data */
nand_command(mtd, NAND_CMD_SEQIN, offset + mtd->oobblock, page);
this->hwcontrol(NAND_CTL_DAT_OUT);
for (i = 0; i < len; i++)
this->write_data(buf[i]);
this->hwcontrol(NAND_CTL_DAT_IN);
/* Send command to program the OOB data */
nand_command(mtd, NAND_CMD_PAGEPROG, -1, -1);
this->wait_for_ready();
/*
* Wait for program operation to complete. This could
* take up to 3000us (3ms) on some devices, so we try
* and exit as quickly as possible. * 注意解释的最后一句话,其中最后的if语句起到了关键的作用
*/
status = 0;
for (i = 0; i < 24; i++) {
/* Delay for 125us */
udelay(125);
/* Check the status */
nand_command(mtd, NAND_CMD_STATUS, -1, -1);
this->wait_for_ready();
status = (int)this->read_data();
if (status & SMC_STAT_READY)
break;
}
/* See if device thinks it succeeded */
if (status & SMC_STAT_WRITE_ERR) {
DEBUG(MTD_DEBUG_LEVEL0,
__FUNCTION__"(): Failed write, page 0x%08x\n", page);
ret = -EIO;
goto nand_write_oob_err;
}
#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
/* Send command to read back the data */
nand_command(mtd, NAND_CMD_READOOB, offset, page);
this->wait_for_ready();
/* Loop through and verify the data */
for (i = 0; i < len; i++) {
if (buf[i] != this->read_data()) {
DEBUG(MTD_DEBUG_LEVEL0,
__FUNCTION__"(): Failed write verify, page 0x%08x\n",
page);
ret = -EIO;
goto nand_write_oob_err;
}
}
#endif
/* Return happy */
*retlen = len;
ret = 0;
nand_write_oob_err:
/* De-select the NAND device */
nand_deselect();
return ret;
}
|