summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2020-05-07 12:52:37 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2020-05-11 09:51:43 +0200
commitc27842e7e11f97f0ba5f668953327acdb141c452 (patch)
treed33e664d40cf5fb8effd17edd24c499e8b47731b
parentmtd: rawnand: Give the possibility to verify a read operation is supported (diff)
downloadlinux-c27842e7e11f97f0ba5f668953327acdb141c452.tar.xz
linux-c27842e7e11f97f0ba5f668953327acdb141c452.zip
mtd: rawnand: onfi: Adapt the parameter page read to constraint controllers
We already know that there are controllers not able to read the three copies of the parameter page in one go. The workaround was to first request the controller to assert command and address cycles on the NAND bus to trigger a parameter page read, and then do a simple read operation for each page. But there are also controllers which are not able to split the parameter page read between the command/address cycles and the actual data operation. Let's use a regular PARAMETER PAGE READ operation for the first iteration and use either a CHANGE READ COLUMN or a simple DATA READ operation for the following copies, depending on what the controller supports. The default behavior for non-exec-op compliant drivers remains the same: DATA READ. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Link: https://lore.kernel.org/linux-mtd/20200507105241.14299-10-miquel.raynal@bootlin.com
-rw-r--r--drivers/mtd/nand/raw/nand_onfi.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
index e6ffbe8c9a0c..be3456627288 100644
--- a/drivers/mtd/nand/raw/nand_onfi.c
+++ b/drivers/mtd/nand/raw/nand_onfi.c
@@ -143,6 +143,7 @@ int nand_onfi_detect(struct nand_chip *chip)
struct nand_memory_organization *memorg;
struct nand_onfi_params *p = NULL, *pbuf;
struct onfi_params *onfi;
+ bool use_datain = false;
int onfi_version = 0;
char id[4];
int i, ret, val;
@@ -160,15 +161,21 @@ int nand_onfi_detect(struct nand_chip *chip)
if (!pbuf)
return -ENOMEM;
- ret = nand_read_param_page_op(chip, 0, NULL, 0);
- if (ret) {
- ret = 0;
- goto free_onfi_param_page;
- }
+ if (!nand_has_exec_op(chip) ||
+ !nand_read_data_op(chip, &pbuf[0], sizeof(*pbuf), true, true))
+ use_datain = true;
for (i = 0; i < ONFI_PARAM_PAGES; i++) {
- ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf), true,
- false);
+ if (!i)
+ ret = nand_read_param_page_op(chip, 0, &pbuf[i],
+ sizeof(*pbuf));
+ else if (use_datain)
+ ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf),
+ true, false);
+ else
+ ret = nand_change_read_column_op(chip, sizeof(*pbuf) * i,
+ &pbuf[i], sizeof(*pbuf),
+ true);
if (ret) {
ret = 0;
goto free_onfi_param_page;