mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-16 07:35:14 +00:00
mtd: nand: provide several helpers to do common NAND operations
This is part of the process of removing direct calls to ->cmdfunc() outside of the core in order to introduce a better interface to execute NAND operations. Here we provide several helpers and make use of them to remove all direct calls to ->cmdfunc(). This way, we can easily modify those helpers to make use of the new ->exec_op() interface when available. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> [miquel.raynal@free-electrons.com: rebased and fixed some conflicts] Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com> Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
parent
eb94555e9e
commit
97d90da8a8
24 changed files with 1131 additions and 431 deletions
|
@ -1000,7 +1000,7 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
|
||||||
* to the non-optimized one.
|
* to the non-optimized one.
|
||||||
*/
|
*/
|
||||||
if (nand->activecs->rb.type != ATMEL_NAND_NATIVE_RB) {
|
if (nand->activecs->rb.type != ATMEL_NAND_NATIVE_RB) {
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page,
|
return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page,
|
||||||
raw);
|
raw);
|
||||||
|
|
|
@ -1071,7 +1071,7 @@ static void brcmnand_wp(struct mtd_info *mtd, int wp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
brcmnand_set_wp(ctrl, wp);
|
brcmnand_set_wp(ctrl, wp);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
|
nand_status_op(chip, NULL);
|
||||||
/* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */
|
/* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */
|
||||||
ret = bcmnand_ctrl_poll_status(ctrl,
|
ret = bcmnand_ctrl_poll_status(ctrl,
|
||||||
NAND_CTRL_RDY |
|
NAND_CTRL_RDY |
|
||||||
|
@ -1453,7 +1453,7 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
|
||||||
|
|
||||||
/* At FC_BYTES boundary, switch to next column */
|
/* At FC_BYTES boundary, switch to next column */
|
||||||
if (host->last_byte > 0 && offs == 0)
|
if (host->last_byte > 0 && offs == 0)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1);
|
nand_change_read_column_op(chip, addr, NULL, 0, false);
|
||||||
|
|
||||||
ret = ctrl->flash_cache[offs];
|
ret = ctrl->flash_cache[offs];
|
||||||
break;
|
break;
|
||||||
|
@ -1689,7 +1689,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
|
||||||
sas = mtd->oobsize / chip->ecc.steps;
|
sas = mtd->oobsize / chip->ecc.steps;
|
||||||
|
|
||||||
/* read without ecc for verification */
|
/* read without ecc for verification */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
|
ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2369,12 +2369,11 @@ static int brcmnand_resume(struct device *dev)
|
||||||
|
|
||||||
list_for_each_entry(host, &ctrl->host_list, node) {
|
list_for_each_entry(host, &ctrl->host_list, node) {
|
||||||
struct nand_chip *chip = &host->chip;
|
struct nand_chip *chip = &host->chip;
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
|
||||||
|
|
||||||
brcmnand_save_restore_cs_config(host, 1);
|
brcmnand_save_restore_cs_config(host, 1);
|
||||||
|
|
||||||
/* Reset the chip, required by some chips after power-up */
|
/* Reset the chip, required by some chips after power-up */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
nand_reset_op(chip);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -353,23 +353,15 @@ static void cafe_nand_bug(struct mtd_info *mtd)
|
||||||
static int cafe_nand_write_oob(struct mtd_info *mtd,
|
static int cafe_nand_write_oob(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip, int page)
|
struct nand_chip *chip, int page)
|
||||||
{
|
{
|
||||||
int status = 0;
|
return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
|
||||||
|
mtd->oobsize);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
|
|
||||||
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't use -- use nand_read_oob_std for now */
|
/* Don't use -- use nand_read_oob_std for now */
|
||||||
static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
|
||||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
|
* cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
|
||||||
|
|
|
@ -645,8 +645,6 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page, int write)
|
int page, int write)
|
||||||
{
|
{
|
||||||
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
||||||
unsigned int start_cmd = write ? NAND_CMD_SEQIN : NAND_CMD_READ0;
|
|
||||||
unsigned int rnd_cmd = write ? NAND_CMD_RNDIN : NAND_CMD_RNDOUT;
|
|
||||||
int writesize = mtd->writesize;
|
int writesize = mtd->writesize;
|
||||||
int oobsize = mtd->oobsize;
|
int oobsize = mtd->oobsize;
|
||||||
uint8_t *bufpoi = chip->oob_poi;
|
uint8_t *bufpoi = chip->oob_poi;
|
||||||
|
@ -658,11 +656,11 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int i, pos, len;
|
int i, pos, len;
|
||||||
|
|
||||||
/* BBM at the beginning of the OOB area */
|
/* BBM at the beginning of the OOB area */
|
||||||
chip->cmdfunc(mtd, start_cmd, writesize, page);
|
|
||||||
if (write)
|
if (write)
|
||||||
chip->write_buf(mtd, bufpoi, oob_skip);
|
nand_prog_page_begin_op(chip, page, writesize, bufpoi,
|
||||||
|
oob_skip);
|
||||||
else
|
else
|
||||||
chip->read_buf(mtd, bufpoi, oob_skip);
|
nand_read_page_op(chip, page, writesize, bufpoi, oob_skip);
|
||||||
bufpoi += oob_skip;
|
bufpoi += oob_skip;
|
||||||
|
|
||||||
/* OOB ECC */
|
/* OOB ECC */
|
||||||
|
@ -675,30 +673,35 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
else if (pos + len > writesize)
|
else if (pos + len > writesize)
|
||||||
len = writesize - pos;
|
len = writesize - pos;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, rnd_cmd, pos, -1);
|
|
||||||
if (write)
|
if (write)
|
||||||
chip->write_buf(mtd, bufpoi, len);
|
nand_change_write_column_op(chip, pos, bufpoi, len,
|
||||||
|
false);
|
||||||
else
|
else
|
||||||
chip->read_buf(mtd, bufpoi, len);
|
nand_change_read_column_op(chip, pos, bufpoi, len,
|
||||||
|
false);
|
||||||
bufpoi += len;
|
bufpoi += len;
|
||||||
if (len < ecc_bytes) {
|
if (len < ecc_bytes) {
|
||||||
len = ecc_bytes - len;
|
len = ecc_bytes - len;
|
||||||
chip->cmdfunc(mtd, rnd_cmd, writesize + oob_skip, -1);
|
|
||||||
if (write)
|
if (write)
|
||||||
chip->write_buf(mtd, bufpoi, len);
|
nand_change_write_column_op(chip, writesize +
|
||||||
|
oob_skip, bufpoi,
|
||||||
|
len, false);
|
||||||
else
|
else
|
||||||
chip->read_buf(mtd, bufpoi, len);
|
nand_change_read_column_op(chip, writesize +
|
||||||
|
oob_skip, bufpoi,
|
||||||
|
len, false);
|
||||||
bufpoi += len;
|
bufpoi += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OOB free */
|
/* OOB free */
|
||||||
len = oobsize - (bufpoi - chip->oob_poi);
|
len = oobsize - (bufpoi - chip->oob_poi);
|
||||||
chip->cmdfunc(mtd, rnd_cmd, size - len, -1);
|
|
||||||
if (write)
|
if (write)
|
||||||
chip->write_buf(mtd, bufpoi, len);
|
nand_change_write_column_op(chip, size - len, bufpoi, len,
|
||||||
|
false);
|
||||||
else
|
else
|
||||||
chip->read_buf(mtd, bufpoi, len);
|
nand_change_read_column_op(chip, size - len, bufpoi, len,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
|
@ -788,16 +791,12 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
struct denali_nand_info *denali = mtd_to_denali(mtd);
|
||||||
int status;
|
|
||||||
|
|
||||||
denali_reset_irq(denali);
|
denali_reset_irq(denali);
|
||||||
|
|
||||||
denali_oob_xfer(mtd, chip, page, 1);
|
denali_oob_xfer(mtd, chip, page, 1);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
|
|
|
@ -448,7 +448,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
DoC_WaitReady(doc);
|
DoC_WaitReady(doc);
|
||||||
this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
|
nand_status_op(this, NULL);
|
||||||
DoC_WaitReady(doc);
|
DoC_WaitReady(doc);
|
||||||
status = (int)this->read_byte(mtd);
|
status = (int)this->read_byte(mtd);
|
||||||
|
|
||||||
|
@ -595,7 +595,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
|
||||||
|
|
||||||
/* Assert ChipEnable and deassert WriteProtect */
|
/* Assert ChipEnable and deassert WriteProtect */
|
||||||
WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
|
WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
|
||||||
this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
nand_reset_op(this);
|
||||||
|
|
||||||
doc->curchip = chip;
|
doc->curchip = chip;
|
||||||
doc->curfloor = floor;
|
doc->curfloor = floor;
|
||||||
|
|
|
@ -864,7 +864,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
|
||||||
|
|
||||||
dev_dbg(doc->dev, "%s: page %x\n", __func__, page);
|
dev_dbg(doc->dev, "%s: page %x\n", __func__, page);
|
||||||
|
|
||||||
docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
|
nand_read_page_op(nand, page, nand->ecc.size, NULL, 0);
|
||||||
|
|
||||||
writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
|
writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
|
||||||
write_nop(docptr);
|
write_nop(docptr);
|
||||||
|
|
|
@ -697,7 +697,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
unsigned int max_bitflips = 0;
|
unsigned int max_bitflips = 0;
|
||||||
|
|
||||||
for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
|
for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
|
nand_read_page_op(chip, page, s * eccsize, NULL, 0);
|
||||||
chip->ecc.hwctl(mtd, NAND_ECC_READ);
|
chip->ecc.hwctl(mtd, NAND_ECC_READ);
|
||||||
chip->read_buf(mtd, p, eccsize);
|
chip->read_buf(mtd, p, eccsize);
|
||||||
|
|
||||||
|
@ -720,8 +720,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
if (chip->options & NAND_BUSWIDTH_16)
|
if (chip->options & NAND_BUSWIDTH_16)
|
||||||
len = roundup(len, 2);
|
len = roundup(len, 2);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
|
nand_read_oob_op(chip, page, off, oob + j, len);
|
||||||
chip->read_buf(mtd, oob + j, len);
|
|
||||||
j += len;
|
j += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1097,8 +1097,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
|
eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
|
||||||
offset /= 8;
|
offset /= 8;
|
||||||
eccbytes -= offset;
|
eccbytes -= offset;
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
|
nand_change_read_column_op(chip, offset, eccbuf,
|
||||||
chip->read_buf(mtd, eccbuf, eccbytes);
|
eccbytes, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ECC data are not byte aligned and we may have
|
* ECC data are not byte aligned and we may have
|
||||||
|
@ -1220,7 +1220,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
meta = geo->metadata_size;
|
meta = geo->metadata_size;
|
||||||
if (first) {
|
if (first) {
|
||||||
col = meta + (size + ecc_parity_size) * first;
|
col = meta + (size + ecc_parity_size) * first;
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
|
nand_change_read_column_op(chip, col, NULL, 0, false);
|
||||||
|
|
||||||
meta = 0;
|
meta = 0;
|
||||||
buf = buf + first * size;
|
buf = buf + first * size;
|
||||||
|
@ -1411,7 +1411,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
memset(chip->oob_poi, ~0, mtd->oobsize);
|
memset(chip->oob_poi, ~0, mtd->oobsize);
|
||||||
|
|
||||||
/* Read out the conventional OOB. */
|
/* Read out the conventional OOB. */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
|
nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
|
||||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1421,7 +1421,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
*/
|
*/
|
||||||
if (GPMI_IS_MX23(this)) {
|
if (GPMI_IS_MX23(this)) {
|
||||||
/* Read the block mark into the first byte of the OOB buffer. */
|
/* Read the block mark into the first byte of the OOB buffer. */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
chip->oob_poi[0] = chip->read_byte(mtd);
|
chip->oob_poi[0] = chip->read_byte(mtd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1432,7 +1432,6 @@ static int
|
||||||
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
|
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
|
||||||
{
|
{
|
||||||
struct mtd_oob_region of = { };
|
struct mtd_oob_region of = { };
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
/* Do we have available oob area? */
|
/* Do we have available oob area? */
|
||||||
mtd_ooblayout_free(mtd, 0, &of);
|
mtd_ooblayout_free(mtd, 0, &of);
|
||||||
|
@ -1442,12 +1441,8 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
|
||||||
if (!nand_is_slc(chip))
|
if (!nand_is_slc(chip))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of.offset, page);
|
return nand_prog_page_op(chip, page, mtd->writesize + of.offset,
|
||||||
chip->write_buf(mtd, chip->oob_poi + of.offset, of.length);
|
chip->oob_poi + of.offset, of.length);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1622,7 +1617,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
|
||||||
static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page);
|
return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page);
|
||||||
}
|
}
|
||||||
|
@ -1630,7 +1625,7 @@ static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
|
return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
|
||||||
}
|
}
|
||||||
|
@ -1641,7 +1636,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||||
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
struct gpmi_nand_data *this = nand_get_controller_data(chip);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint8_t *block_mark;
|
uint8_t *block_mark;
|
||||||
int column, page, status, chipnr;
|
int column, page, chipnr;
|
||||||
|
|
||||||
chipnr = (int)(ofs >> chip->chip_shift);
|
chipnr = (int)(ofs >> chip->chip_shift);
|
||||||
chip->select_chip(mtd, chipnr);
|
chip->select_chip(mtd, chipnr);
|
||||||
|
@ -1655,13 +1650,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||||
/* Shift to get page */
|
/* Shift to get page */
|
||||||
page = (int)(ofs >> chip->page_shift);
|
page = (int)(ofs >> chip->page_shift);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
|
ret = nand_prog_page_op(chip, page, column, block_mark, 1);
|
||||||
chip->write_buf(mtd, block_mark, 1);
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
if (status & NAND_STATUS_FAIL)
|
|
||||||
ret = -EIO;
|
|
||||||
|
|
||||||
chip->select_chip(mtd, -1);
|
chip->select_chip(mtd, -1);
|
||||||
|
|
||||||
|
@ -1729,7 +1718,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
|
||||||
* Read the NCB fingerprint. The fingerprint is four bytes long
|
* Read the NCB fingerprint. The fingerprint is four bytes long
|
||||||
* and starts in the 12th byte of the page.
|
* and starts in the 12th byte of the page.
|
||||||
*/
|
*/
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 12, page);
|
nand_read_page_op(chip, page, 12, NULL, 0);
|
||||||
chip->read_buf(mtd, buffer, strlen(fingerprint));
|
chip->read_buf(mtd, buffer, strlen(fingerprint));
|
||||||
|
|
||||||
/* Look for the fingerprint. */
|
/* Look for the fingerprint. */
|
||||||
|
@ -1789,17 +1778,10 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
|
||||||
dev_dbg(dev, "Erasing the search area...\n");
|
dev_dbg(dev, "Erasing the search area...\n");
|
||||||
|
|
||||||
for (block = 0; block < search_area_size_in_blocks; block++) {
|
for (block = 0; block < search_area_size_in_blocks; block++) {
|
||||||
/* Compute the page address. */
|
|
||||||
page = block * block_size_in_pages;
|
|
||||||
|
|
||||||
/* Erase this block. */
|
/* Erase this block. */
|
||||||
dev_dbg(dev, "\tErasing block 0x%x\n", block);
|
dev_dbg(dev, "\tErasing block 0x%x\n", block);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
|
status = nand_erase_op(chip, block);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
|
if (status)
|
||||||
|
|
||||||
/* Wait for the erase to finish. */
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
if (status & NAND_STATUS_FAIL)
|
|
||||||
dev_err(dev, "[%s] Erase failed.\n", __func__);
|
dev_err(dev, "[%s] Erase failed.\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1815,13 +1797,11 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
|
||||||
|
|
||||||
/* Write the first page of the current stride. */
|
/* Write the first page of the current stride. */
|
||||||
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
|
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
|
|
||||||
chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
|
||||||
|
|
||||||
/* Wait for the write to finish. */
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
status = chip->waitfunc(mtd, chip);
|
chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
|
||||||
if (status & NAND_STATUS_FAIL)
|
status = nand_prog_page_end_op(chip);
|
||||||
|
if (status)
|
||||||
dev_err(dev, "[%s] Write failed.\n", __func__);
|
dev_err(dev, "[%s] Write failed.\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1876,7 +1856,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
|
||||||
|
|
||||||
/* Send the command to read the conventional block mark. */
|
/* Send the command to read the conventional block mark. */
|
||||||
chip->select_chip(mtd, chipnr);
|
chip->select_chip(mtd, chipnr);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
|
nand_read_page_op(chip, page, mtd->writesize, NULL, 0);
|
||||||
block_mark = chip->read_byte(mtd);
|
block_mark = chip->read_byte(mtd);
|
||||||
chip->select_chip(mtd, -1);
|
chip->select_chip(mtd, -1);
|
||||||
|
|
||||||
|
|
|
@ -574,8 +574,7 @@ static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
{
|
{
|
||||||
struct hinfc_host *host = nand_get_controller_data(chip);
|
struct hinfc_host *host = nand_get_controller_data(chip);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
|
||||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
|
|
||||||
if (host->irq_status & HINFC504_INTS_UE) {
|
if (host->irq_status & HINFC504_INTS_UE) {
|
||||||
host->irq_status = 0;
|
host->irq_status = 0;
|
||||||
|
|
|
@ -313,6 +313,7 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
|
||||||
uint32_t ctrl;
|
uint32_t ctrl;
|
||||||
struct nand_chip *chip = &nand->chip;
|
struct nand_chip *chip = &nand->chip;
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
|
u8 id[2];
|
||||||
|
|
||||||
/* Request I/O resource. */
|
/* Request I/O resource. */
|
||||||
sprintf(res_name, "bank%d", bank);
|
sprintf(res_name, "bank%d", bank);
|
||||||
|
@ -335,17 +336,16 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
|
||||||
|
|
||||||
/* Retrieve the IDs from the first chip. */
|
/* Retrieve the IDs from the first chip. */
|
||||||
chip->select_chip(mtd, 0);
|
chip->select_chip(mtd, 0);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
nand_reset_op(chip);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
nand_readid_op(chip, 0, id, sizeof(id));
|
||||||
*nand_maf_id = chip->read_byte(mtd);
|
*nand_maf_id = id[0];
|
||||||
*nand_dev_id = chip->read_byte(mtd);
|
*nand_dev_id = id[1];
|
||||||
} else {
|
} else {
|
||||||
/* Detect additional chip. */
|
/* Detect additional chip. */
|
||||||
chip->select_chip(mtd, chipnr);
|
chip->select_chip(mtd, chipnr);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
nand_reset_op(chip);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
nand_readid_op(chip, 0, id, sizeof(id));
|
||||||
if (*nand_maf_id != chip->read_byte(mtd)
|
if (*nand_maf_id != id[0] || *nand_dev_id != id[1]) {
|
||||||
|| *nand_dev_id != chip->read_byte(mtd)) {
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto notfound_id;
|
goto notfound_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,7 +461,7 @@ static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Writing Command and Address */
|
/* Writing Command and Address */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
/* For all sub-pages */
|
/* For all sub-pages */
|
||||||
for (i = 0; i < host->mlcsubpages; i++) {
|
for (i = 0; i < host->mlcsubpages; i++) {
|
||||||
|
|
|
@ -399,10 +399,7 @@ static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int
|
||||||
static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd,
|
static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip, int page)
|
struct nand_chip *chip, int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
|
||||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -411,17 +408,8 @@ static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd,
|
||||||
static int lpc32xx_nand_write_oob_syndrome(struct mtd_info *mtd,
|
static int lpc32xx_nand_write_oob_syndrome(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip, int page)
|
struct nand_chip *chip, int page)
|
||||||
{
|
{
|
||||||
int status;
|
return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
|
||||||
|
mtd->oobsize);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
|
|
||||||
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
|
|
||||||
/* Send command to program the OOB data */
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -632,7 +620,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd,
|
||||||
uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE];
|
uint8_t *oobecc, tmpecc[LPC32XX_ECC_SAVE_SIZE];
|
||||||
|
|
||||||
/* Issue read command */
|
/* Issue read command */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
/* Read data and oob, calculate ECC */
|
/* Read data and oob, calculate ECC */
|
||||||
status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1);
|
status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1);
|
||||||
|
@ -675,7 +663,7 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
/* Issue read command */
|
/* Issue read command */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
/* Raw reads can just use the FIFO interface */
|
/* Raw reads can just use the FIFO interface */
|
||||||
chip->read_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
|
chip->read_buf(mtd, buf, chip->ecc.size * chip->ecc.steps);
|
||||||
|
|
|
@ -834,16 +834,13 @@ static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
ret = mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page);
|
ret = mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
ret = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return ret & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
|
static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
|
||||||
|
@ -893,7 +890,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
buf = bufpoi + start * chip->ecc.size;
|
buf = bufpoi + start * chip->ecc.size;
|
||||||
|
|
||||||
if (column != 0)
|
if (column != 0)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, column, -1);
|
nand_change_read_column_op(chip, column, NULL, 0, false);
|
||||||
|
|
||||||
addr = dma_map_single(nfc->dev, buf, len, DMA_FROM_DEVICE);
|
addr = dma_map_single(nfc->dev, buf, len, DMA_FROM_DEVICE);
|
||||||
rc = dma_mapping_error(nfc->dev, addr);
|
rc = dma_mapping_error(nfc->dev, addr);
|
||||||
|
@ -1016,7 +1013,7 @@ static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page);
|
return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -66,16 +66,35 @@ struct hynix_read_retry_otp {
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
|
static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
|
||||||
|
{
|
||||||
|
u8 jedecid[5] = { };
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nand_readid_op(chip, 0x40, jedecid, sizeof(jedecid));
|
||||||
|
if (ret)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !strncmp("JEDEC", jedecid, sizeof(jedecid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
u8 jedecid[6] = { };
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
|
chip->cmdfunc(mtd, cmd, -1, -1);
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
jedecid[i] = chip->read_byte(mtd);
|
|
||||||
|
|
||||||
return !strcmp("JEDEC", jedecid);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val)
|
||||||
|
{
|
||||||
|
struct mtd_info *mtd = nand_to_mtd(chip);
|
||||||
|
u16 column = ((u16)addr << 8) | addr;
|
||||||
|
|
||||||
|
chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
|
||||||
|
chip->write_byte(mtd, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
||||||
|
@ -83,13 +102,15 @@ static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
||||||
struct nand_chip *chip = mtd_to_nand(mtd);
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||||
struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
|
struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
|
||||||
const u8 *values;
|
const u8 *values;
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
values = hynix->read_retry->values +
|
values = hynix->read_retry->values +
|
||||||
(retry_mode * hynix->read_retry->nregs);
|
(retry_mode * hynix->read_retry->nregs);
|
||||||
|
|
||||||
/* Enter 'Set Hynix Parameters' mode */
|
/* Enter 'Set Hynix Parameters' mode */
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, -1, -1);
|
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure the NAND in the requested read-retry mode.
|
* Configure the NAND in the requested read-retry mode.
|
||||||
|
@ -101,17 +122,14 @@ static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
||||||
* probably tweaked at production in this case).
|
* probably tweaked at production in this case).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < hynix->read_retry->nregs; i++) {
|
for (i = 0; i < hynix->read_retry->nregs; i++) {
|
||||||
int column = hynix->read_retry->regs[i];
|
ret = hynix_nand_reg_write_op(chip, hynix->read_retry->regs[i],
|
||||||
|
values[i]);
|
||||||
column |= column << 8;
|
if (ret)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
|
return ret;
|
||||||
chip->write_byte(mtd, values[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply the new settings. */
|
/* Apply the new settings. */
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
|
return hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,40 +185,63 @@ static int hynix_read_rr_otp(struct nand_chip *chip,
|
||||||
const struct hynix_read_retry_otp *info,
|
const struct hynix_read_retry_otp *info,
|
||||||
void *buf)
|
void *buf)
|
||||||
{
|
{
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
int i, ret;
|
||||||
int i;
|
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
ret = nand_reset_op(chip);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, -1, -1);
|
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
for (i = 0; i < info->nregs; i++) {
|
for (i = 0; i < info->nregs; i++) {
|
||||||
int column = info->regs[i];
|
ret = hynix_nand_reg_write_op(chip, info->regs[i],
|
||||||
|
info->values[i]);
|
||||||
column |= column << 8;
|
if (ret)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
|
return ret;
|
||||||
chip->write_byte(mtd, info->values[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
|
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Sequence to enter OTP mode? */
|
/* Sequence to enter OTP mode? */
|
||||||
chip->cmdfunc(mtd, 0x17, -1, -1);
|
ret = hynix_nand_cmd_op(chip, 0x17);
|
||||||
chip->cmdfunc(mtd, 0x04, -1, -1);
|
if (ret)
|
||||||
chip->cmdfunc(mtd, 0x19, -1, -1);
|
return ret;
|
||||||
|
|
||||||
|
ret = hynix_nand_cmd_op(chip, 0x4);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hynix_nand_cmd_op(chip, 0x19);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Now read the page */
|
/* Now read the page */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, info->page);
|
ret = nand_read_page_op(chip, info->page, 0, buf, info->size);
|
||||||
chip->read_buf(mtd, buf, info->size);
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Put everything back to normal */
|
/* Put everything back to normal */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
ret = nand_reset_op(chip);
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, 0x38, -1);
|
if (ret)
|
||||||
chip->write_byte(mtd, 0x0);
|
return ret;
|
||||||
chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, -1);
|
|
||||||
|
|
||||||
return 0;
|
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_SET_PARAMS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hynix_nand_reg_write_op(chip, 0x38, 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hynix_nand_cmd_op(chip, NAND_HYNIX_CMD_APPLY_PARAMS);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return nand_read_page_op(chip, 0, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NAND_HYNIX_1XNM_RR_COUNT_OFFS 0
|
#define NAND_HYNIX_1XNM_RR_COUNT_OFFS 0
|
||||||
|
|
|
@ -117,16 +117,28 @@ micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
uint8_t *buf, int oob_required,
|
uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
int status;
|
u8 status;
|
||||||
int max_bitflips = 0;
|
int ret, max_bitflips = 0;
|
||||||
|
|
||||||
micron_nand_on_die_ecc_setup(chip, true);
|
ret = micron_nand_on_die_ecc_setup(chip, true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = nand_status_op(chip, &status);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = nand_exit_status_op(chip);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
|
|
||||||
status = chip->read_byte(mtd);
|
|
||||||
if (status & NAND_STATUS_FAIL)
|
if (status & NAND_STATUS_FAIL)
|
||||||
mtd->ecc_stats.failed++;
|
mtd->ecc_stats.failed++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The internal ECC doesn't tell us the number of bitflips
|
* The internal ECC doesn't tell us the number of bitflips
|
||||||
* that have been corrected, but tells us if it recommends to
|
* that have been corrected, but tells us if it recommends to
|
||||||
|
@ -137,13 +149,12 @@ micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
else if (status & NAND_STATUS_WRITE_RECOMMENDED)
|
else if (status & NAND_STATUS_WRITE_RECOMMENDED)
|
||||||
max_bitflips = chip->ecc.strength;
|
max_bitflips = chip->ecc.strength;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1);
|
ret = nand_read_page_raw(mtd, chip, buf, oob_required, page);
|
||||||
|
|
||||||
nand_read_page_raw(mtd, chip, buf, oob_required, page);
|
|
||||||
|
|
||||||
|
out:
|
||||||
micron_nand_on_die_ecc_setup(chip, false);
|
micron_nand_on_die_ecc_setup(chip, false);
|
||||||
|
|
||||||
return max_bitflips;
|
return ret ? ret : max_bitflips;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -151,18 +162,26 @@ micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
const uint8_t *buf, int oob_required,
|
const uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
|
|
||||||
micron_nand_on_die_ecc_setup(chip, true);
|
ret = micron_nand_on_die_ecc_setup(chip, true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
|
ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
nand_write_page_raw(mtd, chip, buf, oob_required, page);
|
if (ret)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
goto out;
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
|
ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = nand_prog_page_end_op(chip);
|
||||||
|
|
||||||
|
out:
|
||||||
micron_nand_on_die_ecc_setup(chip, false);
|
micron_nand_on_die_ecc_setup(chip, false);
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -171,10 +190,13 @@ micron_nand_read_page_raw_on_die_ecc(struct mtd_info *mtd,
|
||||||
uint8_t *buf, int oob_required,
|
uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
|
int ret;
|
||||||
nand_read_page_raw(mtd, chip, buf, oob_required, page);
|
|
||||||
|
|
||||||
return 0;
|
ret = nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return nand_read_page_raw(mtd, chip, buf, oob_required, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -183,14 +205,17 @@ micron_nand_write_page_raw_on_die_ecc(struct mtd_info *mtd,
|
||||||
const uint8_t *buf, int oob_required,
|
const uint8_t *buf, int oob_required,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
|
ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
nand_write_page_raw(mtd, chip, buf, oob_required, page);
|
if (ret)
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return ret;
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return nand_prog_page_end_op(chip);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -1647,10 +1647,10 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
chip->read_buf(mtd, buf, mtd->writesize);
|
chip->read_buf(mtd, buf, mtd->writesize);
|
||||||
|
|
||||||
/* Read oob bytes */
|
/* Read oob bytes */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
nand_change_read_column_op(chip,
|
||||||
mtd->writesize + BADBLOCK_MARKER_LENGTH, -1);
|
mtd->writesize + BADBLOCK_MARKER_LENGTH,
|
||||||
chip->read_buf(mtd, chip->oob_poi + BADBLOCK_MARKER_LENGTH,
|
chip->oob_poi + BADBLOCK_MARKER_LENGTH,
|
||||||
chip->ecc.total);
|
chip->ecc.total, false);
|
||||||
|
|
||||||
/* Calculate ecc bytes */
|
/* Calculate ecc bytes */
|
||||||
omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
|
omap_calculate_ecc_bch_multi(mtd, buf, ecc_calc);
|
||||||
|
|
|
@ -520,15 +520,13 @@ static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
|
||||||
struct nand_chip *chip = &host->chip;
|
struct nand_chip *chip = &host->chip;
|
||||||
struct pxa3xx_nand_info *info = host->info_data;
|
struct pxa3xx_nand_info *info = host->info_data;
|
||||||
const struct pxa3xx_nand_flash *f = NULL;
|
const struct pxa3xx_nand_flash *f = NULL;
|
||||||
struct mtd_info *mtd = nand_to_mtd(&host->chip);
|
|
||||||
int i, id, ntypes;
|
int i, id, ntypes;
|
||||||
|
u8 idbuf[2];
|
||||||
|
|
||||||
ntypes = ARRAY_SIZE(builtin_flash_types);
|
ntypes = ARRAY_SIZE(builtin_flash_types);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
nand_readid_op(chip, 0, idbuf, sizeof(idbuf));
|
||||||
|
id = idbuf[0] | (idbuf[1] << 8);
|
||||||
id = chip->read_byte(mtd);
|
|
||||||
id |= chip->read_byte(mtd) << 0x8;
|
|
||||||
|
|
||||||
for (i = 0; i < ntypes; i++) {
|
for (i = 0; i < ntypes; i++) {
|
||||||
f = &builtin_flash_types[i];
|
f = &builtin_flash_types[i];
|
||||||
|
|
|
@ -1990,7 +1990,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||||
u8 *oob = chip->oob_poi;
|
u8 *oob = chip->oob_poi;
|
||||||
int data_size, oob_size;
|
int data_size, oob_size;
|
||||||
int ret, status = 0;
|
int ret;
|
||||||
|
|
||||||
host->use_ecc = true;
|
host->use_ecc = true;
|
||||||
|
|
||||||
|
@ -2027,11 +2027,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
|
static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
|
||||||
|
@ -2081,7 +2077,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||||
struct qcom_nand_host *host = to_qcom_nand_host(chip);
|
struct qcom_nand_host *host = to_qcom_nand_host(chip);
|
||||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
||||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||||
int page, ret, status = 0;
|
int page, ret;
|
||||||
|
|
||||||
clear_read_regs(nandc);
|
clear_read_regs(nandc);
|
||||||
clear_bam_transaction(nandc);
|
clear_bam_transaction(nandc);
|
||||||
|
@ -2114,11 +2110,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -364,7 +364,7 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||||
struct r852_device *dev = nand_get_controller_data(chip);
|
struct r852_device *dev = nand_get_controller_data(chip);
|
||||||
|
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
int status;
|
u8 status;
|
||||||
|
|
||||||
timeout = jiffies + (chip->state == FL_ERASING ?
|
timeout = jiffies + (chip->state == FL_ERASING ?
|
||||||
msecs_to_jiffies(400) : msecs_to_jiffies(20));
|
msecs_to_jiffies(400) : msecs_to_jiffies(20));
|
||||||
|
@ -373,8 +373,7 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||||
if (chip->dev_ready(mtd))
|
if (chip->dev_ready(mtd))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
|
nand_status_op(chip, &status);
|
||||||
status = (int)chip->read_byte(mtd);
|
|
||||||
|
|
||||||
/* Unfortunelly, no way to send detailed error status... */
|
/* Unfortunelly, no way to send detailed error status... */
|
||||||
if (dev->dma_error) {
|
if (dev->dma_error) {
|
||||||
|
@ -522,9 +521,7 @@ static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat,
|
||||||
static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
|
||||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1046,7 +1043,7 @@ static int r852_resume(struct device *device)
|
||||||
if (dev->card_registred) {
|
if (dev->card_registred) {
|
||||||
r852_engine_enable(dev);
|
r852_engine_enable(dev);
|
||||||
dev->chip->select_chip(mtd, 0);
|
dev->chip->select_chip(mtd, 0);
|
||||||
dev->chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
nand_reset_op(dev->chip);
|
||||||
dev->chip->select_chip(mtd, -1);
|
dev->chip->select_chip(mtd, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -958,12 +958,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (*cur_off != data_off)
|
if (*cur_off != data_off)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
|
nand_change_read_column_op(nand, data_off, NULL, 0, false);
|
||||||
|
|
||||||
sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
|
sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
|
||||||
|
|
||||||
if (data_off + ecc->size != oob_off)
|
if (data_off + ecc->size != oob_off)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
|
nand_change_read_column_op(nand, oob_off, NULL, 0, false);
|
||||||
|
|
||||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -991,16 +991,15 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
|
||||||
* Re-read the data with the randomizer disabled to identify
|
* Re-read the data with the randomizer disabled to identify
|
||||||
* bitflips in erased pages.
|
* bitflips in erased pages.
|
||||||
*/
|
*/
|
||||||
if (nand->options & NAND_NEED_SCRAMBLING) {
|
if (nand->options & NAND_NEED_SCRAMBLING)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
|
nand_change_read_column_op(nand, data_off, data,
|
||||||
nand->read_buf(mtd, data, ecc->size);
|
ecc->size, false);
|
||||||
} else {
|
else
|
||||||
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
|
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
|
||||||
ecc->size);
|
ecc->size);
|
||||||
}
|
|
||||||
|
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
|
nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4,
|
||||||
nand->read_buf(mtd, oob, ecc->bytes + 4);
|
false);
|
||||||
|
|
||||||
ret = nand_check_erased_ecc_chunk(data, ecc->size,
|
ret = nand_check_erased_ecc_chunk(data, ecc->size,
|
||||||
oob, ecc->bytes + 4,
|
oob, ecc->bytes + 4,
|
||||||
|
@ -1011,7 +1010,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
|
||||||
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
|
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
|
||||||
|
|
||||||
if (oob_required) {
|
if (oob_required) {
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
|
nand_change_read_column_op(nand, oob_off, NULL, 0,
|
||||||
|
false);
|
||||||
sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
|
sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
|
||||||
true, page);
|
true, page);
|
||||||
|
|
||||||
|
@ -1038,8 +1038,8 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!cur_off || *cur_off != offset)
|
if (!cur_off || *cur_off != offset)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
nand_change_read_column_op(nand, mtd->writesize, NULL, 0,
|
||||||
offset + mtd->writesize, -1);
|
false);
|
||||||
|
|
||||||
if (!randomize)
|
if (!randomize)
|
||||||
sunxi_nfc_read_buf(mtd, oob + offset, len);
|
sunxi_nfc_read_buf(mtd, oob + offset, len);
|
||||||
|
@ -1116,9 +1116,9 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
|
||||||
|
|
||||||
if (oob_required && !erased) {
|
if (oob_required && !erased) {
|
||||||
/* TODO: use DMA to retrieve OOB */
|
/* TODO: use DMA to retrieve OOB */
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
nand_change_read_column_op(nand,
|
||||||
mtd->writesize + oob_off, -1);
|
mtd->writesize + oob_off,
|
||||||
nand->read_buf(mtd, oob, ecc->bytes + 4);
|
oob, ecc->bytes + 4, false);
|
||||||
|
|
||||||
sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i,
|
sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i,
|
||||||
!i, page);
|
!i, page);
|
||||||
|
@ -1143,18 +1143,17 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
|
||||||
/*
|
/*
|
||||||
* Re-read the data with the randomizer disabled to
|
* Re-read the data with the randomizer disabled to
|
||||||
* identify bitflips in erased pages.
|
* identify bitflips in erased pages.
|
||||||
|
* TODO: use DMA to read page in raw mode
|
||||||
*/
|
*/
|
||||||
if (randomized) {
|
if (randomized)
|
||||||
/* TODO: use DMA to read page in raw mode */
|
nand_change_read_column_op(nand, data_off,
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
data, ecc->size,
|
||||||
data_off, -1);
|
false);
|
||||||
nand->read_buf(mtd, data, ecc->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: use DMA to retrieve OOB */
|
/* TODO: use DMA to retrieve OOB */
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
nand_change_read_column_op(nand,
|
||||||
mtd->writesize + oob_off, -1);
|
mtd->writesize + oob_off,
|
||||||
nand->read_buf(mtd, oob, ecc->bytes + 4);
|
oob, ecc->bytes + 4, false);
|
||||||
|
|
||||||
ret = nand_check_erased_ecc_chunk(data, ecc->size,
|
ret = nand_check_erased_ecc_chunk(data, ecc->size,
|
||||||
oob, ecc->bytes + 4,
|
oob, ecc->bytes + 4,
|
||||||
|
@ -1187,12 +1186,12 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (data_off != *cur_off)
|
if (data_off != *cur_off)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
|
nand_change_write_column_op(nand, data_off, NULL, 0, false);
|
||||||
|
|
||||||
sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
|
sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
|
||||||
|
|
||||||
if (data_off + ecc->size != oob_off)
|
if (data_off + ecc->size != oob_off)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
|
nand_change_write_column_op(nand, oob_off, NULL, 0, false);
|
||||||
|
|
||||||
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1228,8 +1227,8 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!cur_off || *cur_off != offset)
|
if (!cur_off || *cur_off != offset)
|
||||||
nand->cmdfunc(mtd, NAND_CMD_RNDIN,
|
nand_change_write_column_op(nand, offset + mtd->writesize,
|
||||||
offset + mtd->writesize, -1);
|
NULL, 0, false);
|
||||||
|
|
||||||
sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
|
sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
|
||||||
|
|
||||||
|
@ -1285,7 +1284,7 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Fallback to PIO mode */
|
/* Fallback to PIO mode */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
|
nand_change_read_column_op(chip, 0, NULL, 0, false);
|
||||||
|
|
||||||
return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page);
|
return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page);
|
||||||
}
|
}
|
||||||
|
@ -1335,7 +1334,7 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Fallback to PIO mode */
|
/* Fallback to PIO mode */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, -1);
|
nand_change_read_column_op(chip, 0, NULL, 0, false);
|
||||||
|
|
||||||
return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen,
|
return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen,
|
||||||
buf, page);
|
buf, page);
|
||||||
|
@ -1540,7 +1539,7 @@ static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip,
|
struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
chip->pagebuf = -1;
|
chip->pagebuf = -1;
|
||||||
|
|
||||||
|
@ -1551,9 +1550,9 @@ static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
|
||||||
struct nand_chip *chip,
|
struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
int ret, status;
|
int ret;
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
chip->pagebuf = -1;
|
chip->pagebuf = -1;
|
||||||
|
|
||||||
|
@ -1563,11 +1562,7 @@ static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Send command to program the OOB data */
|
/* Send command to program the OOB data */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
|
|
||||||
return status & NAND_STATUS_FAIL ? -EIO : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const s32 tWB_lut[] = {6, 12, 16, 20};
|
static const s32 tWB_lut[] = {6, 12, 16, 20};
|
||||||
|
|
|
@ -329,7 +329,7 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
|
||||||
|
|
||||||
if (!*buf) {
|
if (!*buf) {
|
||||||
/* skip over "len" bytes */
|
/* skip over "len" bytes */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, *pos, -1);
|
nand_change_read_column_op(chip, *pos, NULL, 0, false);
|
||||||
} else {
|
} else {
|
||||||
tango_read_buf(mtd, *buf, len);
|
tango_read_buf(mtd, *buf, len);
|
||||||
*buf += len;
|
*buf += len;
|
||||||
|
@ -344,7 +344,7 @@ static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
|
||||||
|
|
||||||
if (!*buf) {
|
if (!*buf) {
|
||||||
/* skip over "len" bytes */
|
/* skip over "len" bytes */
|
||||||
chip->cmdfunc(mtd, NAND_CMD_RNDIN, *pos, -1);
|
nand_change_write_column_op(chip, *pos, NULL, 0, false);
|
||||||
} else {
|
} else {
|
||||||
tango_write_buf(mtd, *buf, len);
|
tango_write_buf(mtd, *buf, len);
|
||||||
*buf += len;
|
*buf += len;
|
||||||
|
@ -427,7 +427,7 @@ static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
|
||||||
static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
u8 *buf, int oob_required, int page)
|
u8 *buf, int oob_required, int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
raw_read(chip, buf, chip->oob_poi);
|
raw_read(chip, buf, chip->oob_poi);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -435,23 +435,15 @@ static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
const u8 *buf, int oob_required, int page)
|
const u8 *buf, int oob_required, int page)
|
||||||
{
|
{
|
||||||
int status;
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
|
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
|
|
||||||
raw_write(chip, buf, chip->oob_poi);
|
raw_write(chip, buf, chip->oob_poi);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
|
|
||||||
status = chip->waitfunc(mtd, chip);
|
|
||||||
if (status & NAND_STATUS_FAIL)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
nand_read_page_op(chip, page, 0, NULL, 0);
|
||||||
raw_read(chip, NULL, chip->oob_poi);
|
raw_read(chip, NULL, chip->oob_poi);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -459,11 +451,9 @@ static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
int page)
|
int page)
|
||||||
{
|
{
|
||||||
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
|
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
|
||||||
raw_write(chip, NULL, chip->oob_poi);
|
raw_write(chip, NULL, chip->oob_poi);
|
||||||
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
|
return nand_prog_page_end_op(chip);
|
||||||
chip->waitfunc(mtd, chip);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int oob_ecc(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
|
static int oob_ecc(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
|
||||||
|
|
|
@ -192,6 +192,7 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
|
||||||
{
|
{
|
||||||
struct tmio_nand *tmio = mtd_to_tmio(mtd);
|
struct tmio_nand *tmio = mtd_to_tmio(mtd);
|
||||||
long timeout;
|
long timeout;
|
||||||
|
u8 status;
|
||||||
|
|
||||||
/* enable RDYREQ interrupt */
|
/* enable RDYREQ interrupt */
|
||||||
tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR);
|
tmio_iowrite8(0x0f, tmio->fcr + FCR_ISR);
|
||||||
|
@ -212,8 +213,8 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip)
|
||||||
dev_warn(&tmio->dev->dev, "timeout waiting for interrupt\n");
|
dev_warn(&tmio->dev->dev, "timeout waiting for interrupt\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
|
nand_status_op(nand_chip, &status);
|
||||||
return nand_chip->read_byte(mtd);
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1316,6 +1316,35 @@ int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
||||||
/* Reset and initialize a NAND device */
|
/* Reset and initialize a NAND device */
|
||||||
int nand_reset(struct nand_chip *chip, int chipnr);
|
int nand_reset(struct nand_chip *chip, int chipnr);
|
||||||
|
|
||||||
|
/* NAND operation helpers */
|
||||||
|
int nand_reset_op(struct nand_chip *chip);
|
||||||
|
int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
|
||||||
|
unsigned int len);
|
||||||
|
int nand_status_op(struct nand_chip *chip, u8 *status);
|
||||||
|
int nand_exit_status_op(struct nand_chip *chip);
|
||||||
|
int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock);
|
||||||
|
int nand_read_page_op(struct nand_chip *chip, unsigned int page,
|
||||||
|
unsigned int offset_in_page, void *buf, unsigned int len);
|
||||||
|
int nand_change_read_column_op(struct nand_chip *chip,
|
||||||
|
unsigned int offset_in_page, void *buf,
|
||||||
|
unsigned int len, bool force_8bit);
|
||||||
|
int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
|
||||||
|
unsigned int offset_in_page, void *buf, unsigned int len);
|
||||||
|
int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
|
||||||
|
unsigned int offset_in_page, const void *buf,
|
||||||
|
unsigned int len);
|
||||||
|
int nand_prog_page_end_op(struct nand_chip *chip);
|
||||||
|
int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
|
||||||
|
unsigned int offset_in_page, const void *buf,
|
||||||
|
unsigned int len);
|
||||||
|
int nand_change_write_column_op(struct nand_chip *chip,
|
||||||
|
unsigned int offset_in_page, const void *buf,
|
||||||
|
unsigned int len, bool force_8bit);
|
||||||
|
int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
|
||||||
|
bool force_8bit);
|
||||||
|
int nand_write_data_op(struct nand_chip *chip, const void *buf,
|
||||||
|
unsigned int len, bool force_8bit);
|
||||||
|
|
||||||
/* Free resources held by the NAND device */
|
/* Free resources held by the NAND device */
|
||||||
void nand_cleanup(struct nand_chip *chip);
|
void nand_cleanup(struct nand_chip *chip);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue