public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* On-die ECC support
@ 2017-01-09 21:37 Peter Rosin
  2017-01-09 21:46 ` Richard Weinberger
  0 siblings, 1 reply; 12+ messages in thread
From: Peter Rosin @ 2017-01-09 21:37 UTC (permalink / raw)
  To: Richard Weinberger, linux-mtd

Hi!

AFAICT, on-die ECC support [1] (continues in [2]) was never upstreamed
and the patches no longer applies. I wonder if someone has done the
work to forward port them to recent kernels?

Cheers,
peda

[1] [RFC] On-die ECC support
    http://lists.infradead.org/pipermail/linux-mtd/2015-March/058458.html

    [PATCH 1/3] mtd: nand: Add on-die ECC support
    http://lists.infradead.org/pipermail/linux-mtd/2015-March/058459.html

    [PATCH 2/3] mtd: nand: Add support for raw access when using on-die ECC
    http://lists.infradead.org/pipermail/linux-mtd/2015-March/058457.html

    [PATCH 3/3] mtd: nand: Wire up on-die ECC support
    http://lists.infradead.org/pipermail/linux-mtd/2015-March/058456.html

[2] http://lists.infradead.org/pipermail/linux-mtd/2015-April/058846.html

^ permalink raw reply	[flat|nested] 12+ messages in thread
[parent not found: <CACwUX0M-04vCTkA8WwNR9si=7N-xuYOTy6aWO7ty8xa1+S3rUw@mail.gmail.com>]
* on-die ECC support
@ 2013-03-15 16:08 David Mosberger-Tang
  2013-03-15 16:17 ` David Mosberger-Tang
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: David Mosberger-Tang @ 2013-03-15 16:08 UTC (permalink / raw)
  To: linux-mtd

[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]

We need to be able to support 4-bit-correcting ECC with a
micro-controller that doesn't have hardware-support for that.  We are
planning to use the on-die ECC controller supported by Micron flash
chips.  I suppose we could use the BCH swecc support in the Linux
kernel, but I'm concerned about the performance implication of that
and we'd also have to add BCH ecc to our bootloader, which would mean
more development and testing.

For backwards-compatibility, we need to be able to support a
subpage-size of 512 bytes.  From the Micron data sheets, it's not
clear to me whether the on-die controller really supports reading 512
byte subpages but the attached patch certainly *seems* to work fine so
far.

I'd love to get some feedback as to whether I'm on the right track
here or whether I should pursue a different path.  The patch does the
following:

 - Add NAND_ECC_HW_ON_DIE ecc mode
 - Add nand_read_subpage_raw() to read a subpage without worrying about ECC
 - Hack atmel_nand.c to use on-die ECC.

Thanks,

  --david

[-- Attachment #2: on-die-ecc.diff --]
[-- Type: application/octet-stream, Size: 5001 bytes --]

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 92623ac..8043fde 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1462,7 +1462,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	}
 
 	nand_chip->ecc.mode = host->board.ecc_mode;
+nand_chip->ecc.mode = NAND_ECC_HW_ON_DIE;	// XXX
+nand_chip->ecc.size = 512;	// XXX
+nand_chip->ecc.strength = 4;	// XXX
+printk("nand_chip->ecc.mode=%d\n", nand_chip->ecc.mode);
 	nand_chip->chip_delay = 20;		/* 20us command delay time */
+	nand_chip->chip_delay = 70;	// XXX t_R_ECC
 
 	if (host->board.bus_width_16)	/* 16-bit bus width */
 		nand_chip->options |= NAND_BUSWIDTH_16;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 1a03b7f..88ee536 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -711,6 +711,29 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
 			       NAND_NCE | NAND_CTRL_CHANGE);
 
+		if (1) {
+			u8 status;
+
+			udelay(chip->chip_delay);
+
+			chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+			status = chip->read_byte(mtd);
+
+			if (status & 0x01) {
+				printk("ERROR: on-die ECC read failure\n");
+			} else if (status & 0x08) {
+				// bit flip
+				printk("ERROR: on-die ECC rewrite recommended\n"
+);
+			}
+
+			chip->cmd_ctrl(mtd, NAND_CMD_READ0,
+				       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+			chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+				       NAND_NCE | NAND_CTRL_CHANGE);
+			return;
+		}
+
 		/* This applies to read commands */
 	default:
 		/*
@@ -1222,6 +1245,42 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
+ * nand_read_subpage_raw - [REPLACEABLE] raw sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @data_offs: offset of requested data within the page
+ * @readlen: data length
+ * @bufpoi: buffer to store read data
+ */
+static int nand_read_subpage_raw(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
+{
+	int start_step, end_step, num_steps;
+	uint8_t *p;
+	int data_col_addr;
+	int datafrag_len;
+	unsigned int max_bitflips = 0;
+
+	/* Column address within the page aligned to ECC size */
+	start_step = data_offs / chip->ecc.size;
+	end_step = (data_offs + readlen - 1) / chip->ecc.size;
+	num_steps = end_step - start_step + 1;
+
+	/* Data size aligned to ECC ecc.size */
+	datafrag_len = num_steps * chip->ecc.size;
+
+	data_col_addr = start_step * chip->ecc.size;
+	/* If we read not a page aligned data */
+	if (data_col_addr != 0)
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
+
+	p = bufpoi + data_col_addr;
+	chip->read_buf(mtd, p, datafrag_len);
+
+	return max_bitflips;
+}
+
+/**
  * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
@@ -3530,6 +3589,21 @@ int nand_scan_tail(struct mtd_info *mtd)
 			chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
 		break;
 
+	case NAND_ECC_HW_ON_DIE:
+		chip->ecc.read_page = nand_read_page_raw;
+		chip->ecc.read_subpage = nand_read_subpage_raw;
+		chip->ecc.write_page = nand_write_page_raw;
+		chip->ecc.read_oob = nand_read_oob_std;
+		chip->ecc.read_page_raw = nand_read_page_raw;
+		chip->ecc.write_page_raw = nand_write_page_raw;
+		chip->ecc.write_oob = nand_write_oob_std;
+		chip->ecc.bytes = 0;
+/*
+		chip->ecc.size = mtd->writesize;
+		chip->ecc.strength = 0;
+*/
+		break;
+
 	case NAND_ECC_NONE:
 		pr_warn("NAND_ECC_NONE selected by board driver. "
 			   "This is not recommended!\n");
@@ -3591,6 +3665,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 			break;
 		}
 	}
+mtd->subpage_sft = 2;	// XXX
 	chip->subpagesize = mtd->writesize >> mtd->subpage_sft;
 
 	/* Initialize state */
@@ -3603,7 +3678,9 @@ int nand_scan_tail(struct mtd_info *mtd)
 	chip->pagebuf = -1;
 
 	/* Large page NAND with SOFT_ECC should support subpage reads */
-	if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
+	if (((chip->ecc.mode == NAND_ECC_SOFT)
+	     || (chip->ecc.mode == NAND_ECC_HW_ON_DIE))
+	    && (chip->page_shift > 9))
 		chip->options |= NAND_SUBPAGE_READ;
 
 	/* Fill in remaining MTD driver data */
diff --git a/drivers/of/of_mtd.c b/drivers/of/of_mtd.c
index a27ec94..79ea026 100644
--- a/drivers/of/of_mtd.c
+++ b/drivers/of/of_mtd.c
@@ -23,6 +23,7 @@ static const char *nand_ecc_modes[] = {
 	[NAND_ECC_HW_SYNDROME]	= "hw_syndrome",
 	[NAND_ECC_HW_OOB_FIRST]	= "hw_oob_first",
 	[NAND_ECC_SOFT_BCH]	= "soft_bch",
+	[NAND_ECC_HW_ON_DIE]	= "hw_on_die",
 };
 
 /**
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 24e9159..2c62b2a 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -143,6 +143,7 @@ typedef enum {
 	NAND_ECC_HW_SYNDROME,
 	NAND_ECC_HW_OOB_FIRST,
 	NAND_ECC_SOFT_BCH,
+	NAND_ECC_HW_ON_DIE,
 } nand_ecc_modes_t;
 
 /*

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-01-10 15:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-09 21:37 On-die ECC support Peter Rosin
2017-01-09 21:46 ` Richard Weinberger
2017-01-10 14:54   ` Peter Rosin
2017-01-10 15:30     ` Richard Weinberger
2017-01-10 15:43       ` Boris Brezillon
     [not found] <CACwUX0M-04vCTkA8WwNR9si=7N-xuYOTy6aWO7ty8xa1+S3rUw@mail.gmail.com>
2013-03-22  8:21 ` on-die " Peter Horton
2013-03-22 21:14   ` David Mosberger-Tang
2013-03-23 19:27     ` Peter Horton
  -- strict thread matches above, loose matches on Subject: below --
2013-03-15 16:08 David Mosberger-Tang
2013-03-15 16:17 ` David Mosberger-Tang
2013-03-15 17:58 ` Peter Horton
2013-03-20 17:46 ` David Mosberger-Tang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox