Skip to content

Commit

Permalink
mtd: nand: force drivers to explicitly send READ/PROG commands
Browse files Browse the repository at this point in the history
The core currently send the READ0 and SEQIN+PAGEPROG commands in
nand_do_read/write_ops(). This is inconsistent with
->read/write_oob[_raw]() hooks behavior which are expected to send
these commands.

There's already a flag (NAND_ECC_CUSTOM_PAGE_ACCESS) to inform the core
that a specific controller wants to send the READ/SEQIN+PAGEPROG
commands on its own, but it's an opt-in flag, and existing drivers are
unlikely to be updated to pass it.

Moreover, some controllers cannot dissociate the READ/PAGEPROG commands
from the associated data transfer and ECC engine activation, and
developers have to hack things in their ->cmdfunc() implementation to
handle such complex cases, or have to accept the perf penalty of sending
twice the same command.
To address this problem we are planning on adding a new interface which
is passed all information about a NAND operation (including the amount
of data to transfer) and replacing all calls to ->cmdfunc() to calls to
this new ->exec_op() hook. But, in order to do that, we need to have all
->cmdfunc() calls placed near their associated ->read/write_buf/byte()
calls.

Modify the core and relevant drivers to make NAND_ECC_CUSTOM_PAGE_ACCESS
the default case, and remove this flag.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
[miquel.raynal@free-electrons.com: tested, fixed and rebased on nand/next]
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 97d90da commit 25f815f
Show file tree
Hide file tree
Showing 24 changed files with 171 additions and 198 deletions.
7 changes: 5 additions & 2 deletions drivers/mtd/nand/atmel/nand-controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
struct atmel_nand *nand = to_atmel_nand(chip);
int ret;

nand_prog_page_begin_op(chip, page, 0, NULL, 0);

ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
if (ret)
return ret;
Expand All @@ -857,7 +859,7 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,

atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
Expand All @@ -881,6 +883,8 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;

nand_read_page_op(chip, page, 0, NULL, 0);

ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
if (ret)
return ret;
Expand Down Expand Up @@ -1178,7 +1182,6 @@ static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
chip->ecc.write_page = atmel_hsmc_nand_pmecc_write_page;
chip->ecc.read_page_raw = atmel_hsmc_nand_pmecc_read_page_raw;
chip->ecc.write_page_raw = atmel_hsmc_nand_pmecc_write_page_raw;
chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS;

return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/mtd/nand/bf5xx_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,8 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
nand_read_page_op(chip, page, 0, NULL, 0);

bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);

Expand All @@ -582,10 +584,10 @@ static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, int oob_required,
int page)
{
bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

/*
Expand Down
13 changes: 10 additions & 3 deletions drivers/mtd/nand/brcmnand/brcmnand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,6 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
sas = mtd->oobsize / chip->ecc.steps;

/* read without ecc for verification */
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 @@ -1793,6 +1792,8 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct brcmnand_host *host = nand_get_controller_data(chip);
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;

nand_read_page_op(chip, page, 0, NULL, 0);

return brcmnand_read(mtd, chip, host->last_addr,
mtd->writesize >> FC_SHIFT, (u32 *)buf, oob);
}
Expand All @@ -1804,6 +1805,8 @@ static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
int ret;

nand_read_page_op(chip, page, 0, NULL, 0);

brcmnand_set_ecc_enabled(host, 0);
ret = brcmnand_read(mtd, chip, host->last_addr,
mtd->writesize >> FC_SHIFT, (u32 *)buf, oob);
Expand Down Expand Up @@ -1909,8 +1912,10 @@ static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
struct brcmnand_host *host = nand_get_controller_data(chip);
void *oob = oob_required ? chip->oob_poi : NULL;

nand_prog_page_begin_op(chip, page, 0, NULL, 0);
brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob);
return 0;

return nand_prog_page_end_op(chip);
}

static int brcmnand_write_page_raw(struct mtd_info *mtd,
Expand All @@ -1920,10 +1925,12 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd,
struct brcmnand_host *host = nand_get_controller_data(chip);
void *oob = oob_required ? chip->oob_poi : NULL;

nand_prog_page_begin_op(chip, page, 0, NULL, 0);
brcmnand_set_ecc_enabled(host, 0);
brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob);
brcmnand_set_ecc_enabled(host, 1);
return 0;

return nand_prog_page_end_op(chip);
}

static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
Expand Down
6 changes: 3 additions & 3 deletions drivers/mtd/nand/cafe_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
cafe_readl(cafe, NAND_ECC_RESULT),
cafe_readl(cafe, NAND_ECC_SYN01));

chip->read_buf(mtd, buf, mtd->writesize);
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);

if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
Expand Down Expand Up @@ -541,13 +541,13 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
{
struct cafe_priv *cafe = nand_get_controller_data(chip);

chip->write_buf(mtd, buf, mtd->writesize);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);

/* Set up ECC autogeneration */
cafe->ctl2 |= (1<<30);

return 0;
return nand_prog_page_end_op(chip);
}

static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
Expand Down
1 change: 0 additions & 1 deletion drivers/mtd/nand/denali.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,6 @@ int denali_init(struct denali_nand_info *denali)
chip->read_buf = denali_read_buf;
chip->write_buf = denali_write_buf;
}
chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS;
chip->ecc.read_page = denali_read_page;
chip->ecc.read_page_raw = denali_read_page_raw;
chip->ecc.write_page = denali_write_page;
Expand Down
12 changes: 8 additions & 4 deletions drivers/mtd/nand/docg4.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,8 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,

dev_dbg(doc->dev, "%s: page %08x\n", __func__, page);

nand_read_page_op(nand, page, 0, NULL, 0);

writew(DOC_ECCCONF0_READ_MODE |
DOC_ECCCONF0_ECC_ENABLE |
DOC_ECCCONF0_UNKNOWN |
Expand Down Expand Up @@ -948,14 +950,16 @@ static int docg4_erase_block(struct mtd_info *mtd, int page)
}

static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf, bool use_ecc)
const uint8_t *buf, int page, bool use_ecc)
{
struct docg4_priv *doc = nand_get_controller_data(nand);
void __iomem *docptr = doc->virtadr;
uint8_t ecc_buf[8];

dev_dbg(doc->dev, "%s...\n", __func__);

nand_prog_page_begin_op(nand, page, 0, NULL, 0);

writew(DOC_ECCCONF0_ECC_ENABLE |
DOC_ECCCONF0_UNKNOWN |
DOCG4_BCH_SIZE,
Expand Down Expand Up @@ -1000,19 +1004,19 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
writew(0, docptr + DOC_DATAEND);
write_nop(docptr);

return 0;
return nand_prog_page_end_op(nand);
}

static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf, int oob_required, int page)
{
return write_page(mtd, nand, buf, false);
return write_page(mtd, nand, buf, page, false);
}

static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf, int oob_required, int page)
{
return write_page(mtd, nand, buf, true);
return write_page(mtd, nand, buf, page, true);
}

static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
Expand Down
10 changes: 5 additions & 5 deletions drivers/mtd/nand/fsl_elbc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct fsl_lbc_ctrl *ctrl = priv->ctrl;
struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;

fsl_elbc_read_buf(mtd, buf, mtd->writesize);
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);

Expand All @@ -729,10 +729,10 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

/* ECC will be calculated automatically, and errors will be detected in
Expand All @@ -742,10 +742,10 @@ static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, uint32_t data_len,
const uint8_t *buf, int oob_required, int page)
{
nand_prog_page_begin_op(chip, page, 0, NULL, 0);
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
Expand Down
6 changes: 3 additions & 3 deletions drivers/mtd/nand/fsl_ifc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;

fsl_ifc_read_buf(mtd, buf, mtd->writesize);
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);

Expand All @@ -711,10 +711,10 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required, int page)
{
fsl_ifc_write_buf(mtd, buf, mtd->writesize);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
Expand Down
31 changes: 16 additions & 15 deletions drivers/mtd/nand/gpmi-nand/gpmi-nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
unsigned int max_bitflips = 0;
int ret;

nand_read_page_op(chip, page, 0, NULL, 0);

dev_dbg(this->dev, "page number is : %d\n", page);
ret = read_page_prepare(this, buf, nfc_geo->payload_size,
this->payload_virt, this->payload_phys,
Expand Down Expand Up @@ -1220,12 +1222,12 @@ 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;
nand_change_read_column_op(chip, col, NULL, 0, false);

meta = 0;
buf = buf + first * size;
}

nand_read_page_op(chip, page, col, NULL, 0);

/* Save the old environment */
r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0);
r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1);
Expand Down Expand Up @@ -1277,6 +1279,9 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
int ret;

dev_dbg(this->dev, "ecc write page.\n");

nand_prog_page_begin_op(chip, page, 0, NULL, 0);

if (this->swap_block_mark) {
/*
* If control arrives here, we're doing block mark swapping.
Expand Down Expand Up @@ -1338,7 +1343,10 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
payload_virt, payload_phys);
}

return 0;
if (ret)
return ret;

return nand_prog_page_end_op(chip);
}

/*
Expand Down Expand Up @@ -1472,8 +1480,8 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
uint8_t *oob = chip->oob_poi;
int step;

chip->read_buf(mtd, tmp_buf,
mtd->writesize + mtd->oobsize);
nand_read_page_op(chip, page, 0, tmp_buf,
mtd->writesize + mtd->oobsize);

/*
* If required, swap the bad block marker and the data stored in the
Expand Down Expand Up @@ -1609,24 +1617,19 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
if (this->swap_block_mark)
swap(tmp_buf[0], tmp_buf[mtd->writesize]);

chip->write_buf(mtd, tmp_buf, mtd->writesize + mtd->oobsize);

return 0;
return nand_prog_page_op(chip, page, 0, tmp_buf,
mtd->writesize + mtd->oobsize);
}

static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
int 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)
{
nand_prog_page_begin_op(chip, page, 0, NULL, 0);

return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
}

Expand Down Expand Up @@ -1798,9 +1801,7 @@ 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);

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);
status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
if (status)
dev_err(dev, "[%s] Write failed.\n", __func__);
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/mtd/nand/hisi504_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc;
int stat_1, stat_2;

chip->read_buf(mtd, buf, mtd->writesize);
nand_read_page_op(chip, page, 0, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);

/* errors which can not be corrected by ECC */
Expand Down Expand Up @@ -589,11 +589,11 @@ static int hisi_nand_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, int oob_required,
int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
if (oob_required)
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);

return 0;
return nand_prog_page_end_op(chip);
}

static void hisi_nfc_host_init(struct hinfc_host *host)
Expand Down
5 changes: 4 additions & 1 deletion drivers/mtd/nand/lpc32xx_mlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,8 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
memcpy(dma_buf, buf, mtd->writesize);
}

nand_prog_page_begin_op(chip, page, 0, NULL, 0);

for (i = 0; i < host->mlcsubpages; i++) {
/* Start Encode */
writeb(0x00, MLC_ECC_ENC_REG(host->io_base));
Expand Down Expand Up @@ -550,7 +552,8 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
/* Wait for Controller Ready */
lpc32xx_waitfunc_controller(mtd, chip);
}
return 0;

return nand_prog_page_end_op(chip);
}

static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
Expand Down
Loading

0 comments on commit 25f815f

Please sign in to comment.