[PATCH 21/22] mtd: rawnand: arasan: Workaround a misbehaving prog type with NV-DDR

Miquel Raynal miquel.raynal at bootlin.com
Wed May 5 14:37:49 PDT 2021


As explained in the comment introduced above the fix, the Arasan
controller driver starts an operation when the prog register is being
written with a "type" specific to the action to perform.

The prog type used until now to perform a CHANGE READ COLUMN with an SDR
interface was the PAGE READ type (CMD + ADDR + CMD +
DATA). Unfortunately, for an unknown reason (let's call this a silicon
bug) any CHANGE READ COLUMN performed this way in NV-DDR mode will fail:
the data ready flag will never be triggered, nor will be the transfer
complete flag. Forcefully, this leads to a timeout situation which is
not easy to handle.

Fortunately, it was spotted that sending the same commands through a
different prog register "type", CHANGE READ COLUMN ENHANCED, would work
all the time (even though this particular command is not supported by
the core and is only available in a limited set of devices - we only
care about the controller configuration and not the actual command which
is sent to the device). So let's use this type instead when a CHANGE
READ COLUMN is requested.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/raw/arasan-nand-controller.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index d5fab3cbaa54..307300eeb9cb 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -53,6 +53,7 @@
 #define   PROG_RST			BIT(8)
 #define   PROG_GET_FEATURE		BIT(9)
 #define   PROG_SET_FEATURE		BIT(10)
+#define   PROG_CHG_RD_COL_ENH		BIT(14)
 
 #define INTR_STS_EN_REG			0x14
 #define INTR_SIG_EN_REG			0x18
@@ -622,7 +623,23 @@ static int anfc_param_read_type_exec(struct nand_chip *chip,
 static int anfc_data_read_type_exec(struct nand_chip *chip,
 				    const struct nand_subop *subop)
 {
-	return anfc_misc_data_type_exec(chip, subop, PROG_PGRD);
+	u32 prog_reg = PROG_PGRD;
+
+	/*
+	 * Experience shows that while in SDR mode sending a CHANGE READ COLUMN
+	 * command through the READ PAGE "type" always works fine, when in
+	 * NV-DDR mode the same command simply fails. However, it was also
+	 * spotted that any CHANGE READ COLUMN command sent through the CHANGE
+	 * READ COLUMN ENHANCED "type" would correctly work in both cases (SDR
+	 * and NV-DDR). So, for simplicity, let's program the controller with
+	 * the CHANGE READ COLUMN ENHANCED "type" whenever we are requested to
+	 * perform a CHANGE READ COLUMN operation.
+	 */
+	if (subop->instrs[0].ctx.cmd.opcode == NAND_CMD_RNDOUT &&
+	    subop->instrs[2].ctx.cmd.opcode == NAND_CMD_RNDOUTSTART)
+		prog_reg = PROG_CHG_RD_COL_ENH;
+
+	return anfc_misc_data_type_exec(chip, subop, prog_reg);
 }
 
 static int anfc_param_write_type_exec(struct nand_chip *chip,
-- 
2.27.0




More information about the linux-mtd mailing list