Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25f815f6 authored by Boris Brezillon's avatar Boris Brezillon
Browse files

mtd: nand: force drivers to explicitly send READ/PROG commands



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: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
[miquel.raynal@free-electrons.com: tested, fixed and rebased on nand/next]
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@free-electrons.com>
Acked-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent 97d90da8
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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,
@@ -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;
@@ -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;
}
+4 −2
Original line number Diff line number Diff line
@@ -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);

@@ -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);
}

/*
+10 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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);
}
@@ -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);
@@ -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,
@@ -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,
+3 −3
Original line number Diff line number Diff line
@@ -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)) {
@@ -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)
+0 −1
Original line number Diff line number Diff line
@@ -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;
Loading