LS1021A NAND driver does not support raw read/write operations

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LS1021A NAND driver does not support raw read/write operations

788 Views
keestrommel
Contributor IV

The LS1021A Linux NAND driver provided with the QorIQ Linux SDK 2.0 does not provide raw read/write operations. E.g. the following command does not return the page data with bit flips but with the bit flips corrected:

nanddump -n -o -s 0 -l 4096 -f /tmp/page0-oob /dev/mtd1

and the following command re-calculates the ECCs in the OOB rather than writing the OOB provided in the file page0-oob-8f:

nandwrite -n -o -s 0x2ff000 /dev/mtd1 page0-oob-8f

Note: page0-oob-8f is page0-oob of the nanddump command but with 8 bit flips edited by an hex editor.

Labels (1)
0 Kudos
1 Reply

581 Views
keestrommel
Contributor IV

The following patch file add support for raw read/write operations:

From 6fcc13592d8b639a850d20f40046127d65ccd55d Mon Sep 17 00:00:00 2001
From: Kees Trommel <ctrommel@linvm302.aimsys.nl>
Date: Tue, 15 Nov 2016 17:03:49 +0100
Subject: [PATCH] fsl_ifc_nand-linux-raw-read-write

Signed-off-by: Kees Trommel <ctrommel@linvm302.aimsys.nl>
---
drivers/mtd/nand/fsl_ifc_nand.c | 58 +++++++++++++++++++++++++++++++++++++----
1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index ca36b35..31f7094 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -64,6 +64,7 @@ struct fsl_ifc_nand_ctrl {
unsigned int eccread; /* Non zero for a full-page ECC read */
unsigned int counter; /* counter for the initializations */
unsigned int max_bitflips; /* Saved during READ0 cmd */
+ unsigned int raw; /* Non zero if operating raw (no ECC) */
};

static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl;
@@ -422,15 +423,21 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
switch (command) {
/* READ0 read the entire buffer to use hardware ECC. */
case NAND_CMD_READ0:
- ifc_out32(0, &ifc->ifc_nand.nand_fbcr);
+ if (chip->ecc.mode == NAND_ECC_HW && !ifc_nand_ctrl->raw)
+ ifc_nand_ctrl->eccread = 1;
+
+ if (ifc_nand_ctrl->raw) {
+ /* If BC (fbcr) != 0 then ECC is disabled */
+ ifc_out32(mtd->writesize + mtd->oobsize, &ifc->ifc_nand.nand_fbcr);
+ ifc_nand_ctrl->raw = 0;
+ } else {
+ ifc_out32(0, &ifc->ifc_nand.nand_fbcr);
+ }
set_addr(mtd, 0, page_addr, 0);

ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
ifc_nand_ctrl->index += column;

- if (chip->ecc.mode == NAND_ECC_HW)
- ifc_nand_ctrl->eccread = 1;
-
fsl_ifc_do_read(chip, 0, mtd);
fsl_ifc_run_command(mtd);
return;
@@ -560,10 +567,12 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,

/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
case NAND_CMD_PAGEPROG: {
- if (ifc_nand_ctrl->oob) {
+ if (ifc_nand_ctrl->oob || ifc_nand_ctrl->raw) {
+ /* If BC (fbcr) != 0 then ECC is disabled */
ifc_out32(ifc_nand_ctrl->index -
ifc_nand_ctrl->column,
&ifc->ifc_nand.nand_fbcr);
+ ifc_nand_ctrl->raw = 0;
} else {
ifc_out32(0, &ifc->ifc_nand.nand_fbcr);
}
@@ -780,6 +789,43 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}

+/* ECC will be disabled
+ */
+
+static int fsl_ifc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ struct fsl_ifc_mtd *priv = chip->priv;
+ struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+ struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
+
+ /* the READ0 command but this time with the raw flag set */
+ ifc_nand_ctrl->raw = 1;
+ fsl_ifc_cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+
+ fsl_ifc_read_buf(mtd, buf, mtd->writesize);
+ if (oob_required)
+ fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+ mtd->ecc_stats.failed++;
+
+ return nctrl->max_bitflips;
+}
+
+static int fsl_ifc_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
+{
+ fsl_ifc_write_buf(mtd, buf, mtd->writesize);
+ if (oob_required)
+ {
+ fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+ }
+ ifc_nand_ctrl->raw = 1;
+
+ return 0;
+}
+
static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
@@ -923,7 +969,9 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
chip->priv = priv;

chip->ecc.read_page = fsl_ifc_read_page;
+ chip->ecc.read_page_raw = fsl_ifc_read_page_raw;
chip->ecc.write_page = fsl_ifc_write_page;
+ chip->ecc.write_page_raw = fsl_ifc_write_page_raw;

csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor);

--
2.5.5

0 Kudos