summaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch')
-rw-r--r--target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch172
1 files changed, 172 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch b/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch
new file mode 100644
index 0000000000..c310effadf
--- /dev/null
+++ b/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch
@@ -0,0 +1,172 @@
+From 3677d22ed7e3a631f35e2addc4e2181f6215e4b0 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:29 -0300
+Subject: [PATCH 143/203] mtd: nand: pxa3xx: Add driver-specific ECC BCH
+ support
+
+This commit adds the BCH ECC support available in NFCv2 controller.
+Depending on the detected required strength the respective ECC layout
+is selected.
+
+This commit adds an empty ECC layout, since support to access large
+pages is first required. Once that support is added, a proper ECC
+layout will be added as well.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 86 +++++++++++++++++++++++++++++++++---------
+ 1 file changed, 69 insertions(+), 17 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -58,6 +58,7 @@
+ #define NDPCR (0x18) /* Page Count Register */
+ #define NDBDR0 (0x1C) /* Bad Block Register 0 */
+ #define NDBDR1 (0x20) /* Bad Block Register 1 */
++#define NDECCCTRL (0x28) /* ECC control */
+ #define NDDB (0x40) /* Data Buffer */
+ #define NDCB0 (0x48) /* Command Buffer0 */
+ #define NDCB1 (0x4C) /* Command Buffer1 */
+@@ -198,6 +199,7 @@ struct pxa3xx_nand_info {
+
+ int cs;
+ int use_ecc; /* use HW ECC ? */
++ int ecc_bch; /* using BCH ECC? */
+ int use_dma; /* use DMA ? */
+ int use_spare; /* use spare ? */
+ int need_wait;
+@@ -205,6 +207,8 @@ struct pxa3xx_nand_info {
+ unsigned int fifo_size; /* max. data size in the FIFO */
+ unsigned int data_size; /* data to be read from FIFO */
+ unsigned int oob_size;
++ unsigned int spare_size;
++ unsigned int ecc_size;
+ int retcode;
+
+ /* cached register value */
+@@ -339,19 +343,12 @@ static void pxa3xx_set_datasize(struct p
+ int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+
+ info->data_size = info->fifo_size;
+- if (!oob_enable) {
+- info->oob_size = 0;
++ if (!oob_enable)
+ return;
+- }
+
+- switch (info->fifo_size) {
+- case 2048:
+- info->oob_size = (info->use_ecc) ? 40 : 64;
+- break;
+- case 512:
+- info->oob_size = (info->use_ecc) ? 8 : 16;
+- break;
+- }
++ info->oob_size = info->spare_size;
++ if (!info->use_ecc)
++ info->oob_size += info->ecc_size;
+ }
+
+ /**
+@@ -366,10 +363,15 @@ static void pxa3xx_nand_start(struct pxa
+
+ ndcr = info->reg_ndcr;
+
+- if (info->use_ecc)
++ if (info->use_ecc) {
+ ndcr |= NDCR_ECC_EN;
+- else
++ if (info->ecc_bch)
++ nand_writel(info, NDECCCTRL, 0x1);
++ } else {
+ ndcr &= ~NDCR_ECC_EN;
++ if (info->ecc_bch)
++ nand_writel(info, NDECCCTRL, 0x0);
++ }
+
+ if (info->use_dma)
+ ndcr |= NDCR_DMA_EN;
+@@ -1071,6 +1073,41 @@ static int pxa3xx_nand_sensing(struct px
+ return 0;
+ }
+
++static int pxa_ecc_init(struct pxa3xx_nand_info *info,
++ struct nand_ecc_ctrl *ecc,
++ int strength, int page_size)
++{
++ /*
++ * We don't use strength here as the PXA variant
++ * is used with non-ONFI compliant devices.
++ */
++ if (page_size == 2048) {
++ info->spare_size = 40;
++ info->ecc_size = 24;
++ ecc->mode = NAND_ECC_HW;
++ ecc->size = 512;
++ ecc->strength = 1;
++ return 1;
++
++ } else if (page_size == 512) {
++ info->spare_size = 8;
++ info->ecc_size = 8;
++ ecc->mode = NAND_ECC_HW;
++ ecc->size = 512;
++ ecc->strength = 1;
++ return 1;
++ }
++ return 0;
++}
++
++static int armada370_ecc_init(struct pxa3xx_nand_info *info,
++ struct nand_ecc_ctrl *ecc,
++ int strength, int page_size)
++{
++ /* Unimplemented yet */
++ return 0;
++}
++
+ static int pxa3xx_nand_scan(struct mtd_info *mtd)
+ {
+ struct pxa3xx_nand_host *host = mtd->priv;
+@@ -1141,13 +1178,13 @@ static int pxa3xx_nand_scan(struct mtd_i
+ pxa3xx_flash_ids[1].name = NULL;
+ def = pxa3xx_flash_ids;
+ KEEP_CONFIG:
+- chip->ecc.mode = NAND_ECC_HW;
+- chip->ecc.size = info->fifo_size;
+- chip->ecc.strength = 1;
+-
+ if (info->reg_ndcr & NDCR_DWIDTH_M)
+ chip->options |= NAND_BUSWIDTH_16;
+
++ /* Device detection must be done with ECC disabled */
++ if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
++ nand_writel(info, NDECCCTRL, 0x0);
++
+ if (nand_scan_ident(mtd, 1, def))
+ return -ENODEV;
+
+@@ -1162,6 +1199,21 @@ KEEP_CONFIG:
+ chip->bbt_md = &bbt_mirror_descr;
+ }
+
++ if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
++ ret = armada370_ecc_init(info, &chip->ecc,
++ chip->ecc_strength_ds,
++ mtd->writesize);
++ else
++ ret = pxa_ecc_init(info, &chip->ecc,
++ chip->ecc_strength_ds,
++ mtd->writesize);
++ if (!ret) {
++ dev_err(&info->pdev->dev,
++ "ECC strength %d at page size %d is not supported\n",
++ chip->ecc_strength_ds, mtd->writesize);
++ return -ENODEV;
++ }
++
+ /* calculate addressing information */
+ if (mtd->writesize >= 2048)
+ host->col_addr_cycles = 2;