diff options
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.patch | 172 |
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; |