Skip to content

Commit

Permalink
mtd: nand: provide several helpers to do common NAND operations
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Boris Brezillon committed Dec 14, 2017
1 parent eb94555 commit 97d90da
Show file tree
Hide file tree
Showing 24 changed files with 1,131 additions and 431 deletions.
2 changes: 1 addition & 1 deletion drivers/mtd/nand/atmel/nand-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,7 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
* to the non-optimized one.
*/
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,
raw);
Expand Down
9 changes: 4 additions & 5 deletions drivers/mtd/nand/brcmnand/brcmnand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ static void brcmnand_wp(struct mtd_info *mtd, int wp)
return;

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 */
ret = bcmnand_ctrl_poll_status(ctrl,
NAND_CTRL_RDY |
Expand Down Expand Up @@ -1453,7 +1453,7 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd)

/* At FC_BYTES boundary, switch to next column */
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];
break;
Expand Down Expand Up @@ -1689,7 +1689,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
sas = mtd->oobsize / chip->ecc.steps;

/* 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);
if (ret)
return ret;
Expand Down Expand Up @@ -2369,12 +2369,11 @@ static int brcmnand_resume(struct device *dev)

list_for_each_entry(host, &ctrl->host_list, node) {
struct nand_chip *chip = &host->chip;
struct mtd_info *mtd = nand_to_mtd(chip);

brcmnand_save_restore_cs_config(host, 1);

/* Reset the chip, required by some chips after power-up */
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_reset_op(chip);
}

return 0;
Expand Down
14 changes: 3 additions & 11 deletions drivers/mtd/nand/cafe_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,23 +353,15 @@ static void cafe_nand_bug(struct mtd_info *mtd)
static int cafe_nand_write_oob(struct mtd_info *mtd,
struct nand_chip *chip, int page)
{
int status = 0;

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;
return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
mtd->oobsize);
}

/* Don't use -- use nand_read_oob_std for now */
static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
{
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0;
return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
}
/**
* cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
Expand Down
37 changes: 18 additions & 19 deletions drivers/mtd/nand/denali.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,6 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
int page, int write)
{
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 oobsize = mtd->oobsize;
uint8_t *bufpoi = chip->oob_poi;
Expand All @@ -658,11 +656,11 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
int i, pos, len;

/* BBM at the beginning of the OOB area */
chip->cmdfunc(mtd, start_cmd, writesize, page);
if (write)
chip->write_buf(mtd, bufpoi, oob_skip);
nand_prog_page_begin_op(chip, page, writesize, bufpoi,
oob_skip);
else
chip->read_buf(mtd, bufpoi, oob_skip);
nand_read_page_op(chip, page, writesize, bufpoi, oob_skip);
bufpoi += oob_skip;

/* OOB ECC */
Expand All @@ -675,30 +673,35 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
else if (pos + len > writesize)
len = writesize - pos;

chip->cmdfunc(mtd, rnd_cmd, pos, -1);
if (write)
chip->write_buf(mtd, bufpoi, len);
nand_change_write_column_op(chip, pos, bufpoi, len,
false);
else
chip->read_buf(mtd, bufpoi, len);
nand_change_read_column_op(chip, pos, bufpoi, len,
false);
bufpoi += len;
if (len < ecc_bytes) {
len = ecc_bytes - len;
chip->cmdfunc(mtd, rnd_cmd, writesize + oob_skip, -1);
if (write)
chip->write_buf(mtd, bufpoi, len);
nand_change_write_column_op(chip, writesize +
oob_skip, bufpoi,
len, false);
else
chip->read_buf(mtd, bufpoi, len);
nand_change_read_column_op(chip, writesize +
oob_skip, bufpoi,
len, false);
bufpoi += len;
}
}

/* OOB free */
len = oobsize - (bufpoi - chip->oob_poi);
chip->cmdfunc(mtd, rnd_cmd, size - len, -1);
if (write)
chip->write_buf(mtd, bufpoi, len);
nand_change_write_column_op(chip, size - len, bufpoi, len,
false);
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,
Expand Down Expand Up @@ -788,16 +791,12 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
int page)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
int status;

denali_reset_irq(denali);

denali_oob_xfer(mtd, chip, page, 1);

chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
status = chip->waitfunc(mtd, chip);

return status & NAND_STATUS_FAIL ? -EIO : 0;
return nand_prog_page_end_op(chip);
}

static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
Expand Down
4 changes: 2 additions & 2 deletions drivers/mtd/nand/diskonchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
int status;

DoC_WaitReady(doc);
this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
nand_status_op(this, NULL);
DoC_WaitReady(doc);
status = (int)this->read_byte(mtd);

Expand Down Expand Up @@ -595,7 +595,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)

/* Assert ChipEnable and deassert WriteProtect */
WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_reset_op(this);

doc->curchip = chip;
doc->curfloor = floor;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/docg4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

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);
write_nop(docptr);
Expand Down
5 changes: 2 additions & 3 deletions drivers/mtd/nand/fsmc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
unsigned int max_bitflips = 0;

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->read_buf(mtd, p, eccsize);

Expand All @@ -720,8 +720,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
if (chip->options & NAND_BUSWIDTH_16)
len = roundup(len, 2);

chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
chip->read_buf(mtd, oob + j, len);
nand_read_oob_op(chip, page, off, oob + j, len);
j += len;
}

Expand Down
58 changes: 19 additions & 39 deletions drivers/mtd/nand/gpmi-nand/gpmi-nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
offset /= 8;
eccbytes -= offset;
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1);
chip->read_buf(mtd, eccbuf, eccbytes);
nand_change_read_column_op(chip, offset, eccbuf,
eccbytes, false);

/*
* ECC data are not byte aligned and we may have
Expand Down Expand Up @@ -1220,7 +1220,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
meta = geo->metadata_size;
if (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;
buf = buf + first * size;
Expand Down Expand Up @@ -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);

/* 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);

/*
Expand All @@ -1421,7 +1421,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
*/
if (GPMI_IS_MX23(this)) {
/* 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);
}

Expand All @@ -1432,7 +1432,6 @@ static int
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
{
struct mtd_oob_region of = { };
int status = 0;

/* Do we have available oob area? */
mtd_ooblayout_free(mtd, 0, &of);
Expand All @@ -1442,12 +1441,8 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
if (!nand_is_slc(chip))
return -EPERM;

chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of.offset, page);
chip->write_buf(mtd, 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;
return nand_prog_page_op(chip, page, mtd->writesize + of.offset,
chip->oob_poi + of.offset, of.length);
}

/*
Expand Down Expand Up @@ -1622,15 +1617,15 @@ 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,
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);
}

static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
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);
}
Expand All @@ -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);
int ret = 0;
uint8_t *block_mark;
int column, page, status, chipnr;
int column, page, chipnr;

chipnr = (int)(ofs >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
Expand All @@ -1655,13 +1650,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* Shift to get page */
page = (int)(ofs >> chip->page_shift);

chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page);
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;
ret = nand_prog_page_op(chip, page, column, block_mark, 1);

chip->select_chip(mtd, -1);

Expand Down Expand Up @@ -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
* 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));

/* Look for the fingerprint. */
Expand Down Expand Up @@ -1789,17 +1778,10 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
dev_dbg(dev, "Erasing the search area...\n");

for (block = 0; block < search_area_size_in_blocks; block++) {
/* Compute the page address. */
page = block * block_size_in_pages;

/* Erase this block. */
dev_dbg(dev, "\tErasing block 0x%x\n", block);
chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);

/* Wait for the erase to finish. */
status = chip->waitfunc(mtd, chip);
if (status & NAND_STATUS_FAIL)
status = nand_erase_op(chip, block);
if (status)
dev_err(dev, "[%s] Erase failed.\n", __func__);
}

Expand All @@ -1815,13 +1797,11 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)

/* Write the first page of the current stride. */
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. */
status = chip->waitfunc(mtd, chip);
if (status & NAND_STATUS_FAIL)
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
status = nand_prog_page_end_op(chip);
if (status)
dev_err(dev, "[%s] Write failed.\n", __func__);
}

Expand Down Expand Up @@ -1876,7 +1856,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this)

/* Send the command to read the conventional block mark. */
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);
chip->select_chip(mtd, -1);

Expand Down
3 changes: 1 addition & 2 deletions drivers/mtd/nand/hisi504_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);

if (host->irq_status & HINFC504_INTS_UE) {
host->irq_status = 0;
Expand Down
Loading

0 comments on commit 97d90da

Please sign in to comment.