* [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes
@ 2013-05-17 11:50 Gupta, Pekon
2013-05-17 11:50 ` [PATCH 1/4 v2] mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe Gupta, Pekon
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-17 11:50 UTC (permalink / raw)
To: linux-mtd, linux-omap
Cc: Gupta, Pekon, avinashphilip, arnd, tony, balbi, jp.francois
From: "Gupta, Pekon" <pekon@ti.com>
[Change v1 -> v2]
added [PATCH 3/4] and [PATCH 4/4]
[PATCH 1/4]: clean-up and optimization for supported ECC schemes.
[PATCH 2/4]: add separate DT options each supported ECC scheme.
[PATCH 3/4]: update BCH4 ECC implementation (using ELM or using lib/bch.h)
[PATCH 4/4]: update DT attribute for ti,nand-ecc-opt
After this patch series, omap2-nand driver will supports following ECC schemes:
+---------------------------------------+---------------+---------------+
| ECC scheme |ECC calculation|Error detection|
+---------------------------------------+---------------+---------------+
|OMAP_ECC_HAMMING_CODE_DEFAULT |S/W |S/W |
|OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W |
|OMAP_ECC_HAMMING_CODE_HW_ROMCODE |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|OMAP_ECC_BCH4_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
|OMAP_ECC_BCH4_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
|OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
|OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
- Selection of OMAP_ECC_BCHx_CODE_HW_DETECTION_SW requires,
Kconfig: CONFIG_MTD_NAND_ECC_BCH: enables S/W based BCH ECC algorithm.
- Selection of OMAP_ECC_BCHx_CODE_HW requires,
Kconfig: CONFIG_MTD_NAND_OMAP_BCH: enables ELM H/W module.
Gupta, Pekon (4):
mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in
device_probe
ARM: OMAP2+: cleaned-up DT support of various ECC schemes
mtd:nand:omap2: updated support for BCH4 ECC scheme
ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT
.../devicetree/bindings/mtd/gpmc-nand.txt | 52 ++-
arch/arm/boot/dts/am335x-evm.dts | 2 +-
arch/arm/mach-omap2/gpmc.c | 17 +-
drivers/mtd/nand/Kconfig | 1 -
drivers/mtd/nand/omap2.c | 413 +++++++++------------
include/linux/platform_data/elm.h | 4 +
include/linux/platform_data/mtd-nand-omap2.h | 22 +-
7 files changed, 253 insertions(+), 258 deletions(-)
--
1.8.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4 v2] mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
@ 2013-05-17 11:50 ` Gupta, Pekon
2013-05-17 11:50 ` [PATCH 2/4 v2] ARM: OMAP2+: cleaned-up DT support of various ECC schemes Gupta, Pekon
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-17 11:50 UTC (permalink / raw)
To: linux-mtd, linux-omap
Cc: Gupta, Pekon, avinashphilip, arnd, tony, balbi, jp.francois
From: "Gupta, Pekon" <pekon@ti.com>
ECC scheme on NAND devices can be implemented in multiple ways.Some using
Software algorithm, while others using in-build Hardware engines.
omap2-nand driver currently supports following flavours of ECC schemes.
+---------------------------------------+---------------+---------------+
| ECC scheme |ECC calculation|Error detection|
+---------------------------------------+---------------+---------------+
|OMAP_ECC_HAMMING_CODE_DEFAULT |S/W |S/W |
|OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W |
|OMAP_ECC_HAMMING_CODE_HW_ROMCODE |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|(requires CONFIG_MTD_NAND_ECC_BCH) | | |
|OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|(requires CONFIG_MTD_NAND_OMAP_BCH) | | |
|OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
This patch
- separates the configurations for various ECC schemes.
- fixes dependency issues based on Kconfig options.
- cleans up redundant code
Signed-off-by: Gupta, Pekon <pekon@ti.com>
---
drivers/mtd/nand/omap2.c | 432 +++++++++++++--------------
include/linux/platform_data/elm.h | 4 +
include/linux/platform_data/mtd-nand-omap2.h | 22 +-
3 files changed, 224 insertions(+), 234 deletions(-)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 8e820dd..167f8d4 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -25,8 +25,10 @@
#include <linux/of.h>
#include <linux/of_device.h>
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
+#ifdef CONFIG_MTD_NAND_ECC_BCH
#include <linux/bch.h>
+#endif
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
#include <linux/platform_data/elm.h>
#endif
@@ -141,6 +143,9 @@
#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */
#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */
+#define BADBLOCK_MARKER_LENGTH 0x2
+#define OMAP_ECC_BCH8_POLYNOMIAL 0x201b
+
#ifdef CONFIG_MTD_NAND_OMAP_BCH
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
@@ -182,14 +187,11 @@ struct omap_nand_info {
u_char *buf;
int buf_len;
struct gpmc_nand_regs reg;
-
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
- struct bch_control *bch;
- struct nand_ecclayout ecclayout;
+ /* fields specific for BCHx_HW ECC scheme */
+ struct bch_control *bch;
bool is_elm_used;
struct device *elm_dev;
struct device_node *of_node;
-#endif
};
/**
@@ -1058,8 +1060,6 @@ static int omap_dev_ready(struct mtd_info *mtd)
}
}
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
-
/**
* omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
* @mtd: MTD device structure
@@ -1141,6 +1141,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
+#ifdef CONFIG_MTD_NAND_ECC_BCH
/**
* omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes
* @mtd: MTD device structure
@@ -1227,6 +1228,62 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
}
/**
+ * omap3_correct_data_bch - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ int i, count;
+ /* cannot correct more than 8 errors */
+ unsigned int errloc[8];
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+
+ count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL,
+ errloc);
+ if (count > 0) {
+ /* correct errors */
+ for (i = 0; i < count; i++) {
+ /* correct data only, not ecc bytes */
+ if (errloc[i] < 8*512)
+ data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+ pr_debug("corrected bitflip %u\n", errloc[i]);
+ }
+ } else if (count < 0) {
+ pr_err("ecc unrecoverable error\n");
+ }
+ return count;
+}
+
+/**
+ * omap3_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
+ */
+static void omap3_free_bch(struct mtd_info *mtd)
+{
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+ if (info->bch) {
+ free_bch(info->bch);
+ info->bch = NULL;
+ }
+}
+
+#else
+
+static void omap3_free_bch(struct mtd_info *mtd)
+{
+}
+
+#endif /* CONFIG_MTD_NAND_ECC_BCH */
+
+
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+/**
* omap3_calculate_ecc_bch - Generate bytes of ECC bytes
* @mtd: MTD device structure
* @dat: The pointer to data on which ecc is computed
@@ -1519,38 +1576,6 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
}
/**
- * omap3_correct_data_bch - Decode received data and correct errors
- * @mtd: MTD device structure
- * @data: page data
- * @read_ecc: ecc read from nand flash
- * @calc_ecc: ecc read from HW ECC registers
- */
-static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int i, count;
- /* cannot correct more than 8 errors */
- unsigned int errloc[8];
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
-
- count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL,
- errloc);
- if (count > 0) {
- /* correct errors */
- for (i = 0; i < count; i++) {
- /* correct data only, not ecc bytes */
- if (errloc[i] < 8*512)
- data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
- pr_debug("corrected bitflip %u\n", errloc[i]);
- }
- } else if (count < 0) {
- pr_err("ecc unrecoverable error\n");
- }
- return count;
-}
-
-/**
* omap_write_page_bch - BCH ecc based write page function for entire page
* @mtd: mtd info structure
* @chip: nand chip info structure
@@ -1637,194 +1662,45 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * omap3_free_bch - Release BCH ecc resources
- * @mtd: MTD device structure
- */
-static void omap3_free_bch(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- if (info->bch) {
- free_bch(info->bch);
- info->bch = NULL;
- }
-}
-
-/**
- * omap3_init_bch - Initialize BCH ECC
- * @mtd: MTD device structure
- * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW)
+ * is_elm_present - checks for presence of ELM module by scanning DT nodes
+ * @omap_nand_info: NAND device structure containing platform data
+ * @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16
*/
-static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
+static int is_elm_present(struct omap_nand_info *info, int bch_type)
{
- int max_errors;
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
-#ifdef CONFIG_MTD_NAND_OMAP_BCH8
- const int hw_errors = BCH8_MAX_ERROR;
-#else
- const int hw_errors = BCH4_MAX_ERROR;
-#endif
- enum bch_ecc bch_type;
const __be32 *parp;
int lenp;
struct device_node *elm_node;
-
- info->bch = NULL;
-
- max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ?
- BCH8_MAX_ERROR : BCH4_MAX_ERROR;
- if (max_errors != hw_errors) {
- pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported",
- max_errors, hw_errors);
- goto fail;
- }
-
- info->nand.ecc.size = 512;
- info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
- info->nand.ecc.mode = NAND_ECC_HW;
- info->nand.ecc.strength = max_errors;
-
- if (hw_errors == BCH8_MAX_ERROR)
- bch_type = BCH8_ECC;
- else
- bch_type = BCH4_ECC;
+ struct platform_device *pdev;
+ info->is_elm_used = false;
/* Detect availability of ELM module */
parp = of_get_property(info->of_node, "elm_id", &lenp);
if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
pr_err("Missing elm_id property, fall back to Software BCH\n");
- info->is_elm_used = false;
} else {
- struct platform_device *pdev;
-
elm_node = of_find_node_by_phandle(be32_to_cpup(parp));
pdev = of_find_device_by_node(elm_node);
info->elm_dev = &pdev->dev;
+ /* ELM module available, now configure it */
elm_config(info->elm_dev, bch_type);
info->is_elm_used = true;
+ return 0;
}
- if (info->is_elm_used && (mtd->writesize <= 4096)) {
-
- if (hw_errors == BCH8_MAX_ERROR)
- info->nand.ecc.bytes = BCH8_SIZE;
- else
- info->nand.ecc.bytes = BCH4_SIZE;
-
- info->nand.ecc.correct = omap_elm_correct_data;
- info->nand.ecc.calculate = omap3_calculate_ecc_bch;
- info->nand.ecc.read_page = omap_read_page_bch;
- info->nand.ecc.write_page = omap_write_page_bch;
- } else {
- /*
- * software bch library is only used to detect and
- * locate errors
- */
- info->bch = init_bch(13, max_errors,
- 0x201b /* hw polynomial */);
- if (!info->bch)
- goto fail;
-
- info->nand.ecc.correct = omap3_correct_data_bch;
-
- /*
- * The number of corrected errors in an ecc block that will
- * trigger block scrubbing defaults to the ecc strength (4 or 8)
- * Set mtd->bitflip_threshold here to define a custom threshold.
- */
-
- if (max_errors == 8) {
- info->nand.ecc.bytes = 13;
- info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
- } else {
- info->nand.ecc.bytes = 7;
- info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
- }
- }
-
- pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors);
- return 0;
-fail:
- omap3_free_bch(mtd);
- return -1;
-}
-
-/**
- * omap3_init_bch_tail - Build an oob layout for BCH ECC correction.
- * @mtd: MTD device structure
- */
-static int omap3_init_bch_tail(struct mtd_info *mtd)
-{
- int i, steps, offset;
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- struct nand_ecclayout *layout = &info->ecclayout;
-
- /* build oob layout */
- steps = mtd->writesize/info->nand.ecc.size;
- layout->eccbytes = steps*info->nand.ecc.bytes;
-
- /* do not bother creating special oob layouts for small page devices */
- if (mtd->oobsize < 64) {
- pr_err("BCH ecc is not supported on small page devices\n");
- goto fail;
- }
-
- /* reserve 2 bytes for bad block marker */
- if (layout->eccbytes+2 > mtd->oobsize) {
- pr_err("no oob layout available for oobsize %d eccbytes %u\n",
- mtd->oobsize, layout->eccbytes);
- goto fail;
- }
-
- /* ECC layout compatible with RBL for BCH8 */
- if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
- offset = 2;
- else
- offset = mtd->oobsize - layout->eccbytes;
-
- /* put ecc bytes at oob tail */
- for (i = 0; i < layout->eccbytes; i++)
- layout->eccpos[i] = offset + i;
-
- if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
- layout->oobfree[0].offset = 2 + layout->eccbytes * steps;
- else
- layout->oobfree[0].offset = 2;
-
- layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
- info->nand.ecc.layout = layout;
-
- if (!(info->nand.options & NAND_BUSWIDTH_16))
- info->nand.badblock_pattern = &bb_descrip_flashbased;
- return 0;
-fail:
- omap3_free_bch(mtd);
- return -1;
-}
-
-#else
-static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
-{
- pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n");
- return -1;
-}
-static int omap3_init_bch_tail(struct mtd_info *mtd)
-{
- return -1;
-}
-static void omap3_free_bch(struct mtd_info *mtd)
-{
+ return -ENODEV;
}
#endif /* CONFIG_MTD_NAND_OMAP_BCH */
+
static int omap_nand_probe(struct platform_device *pdev)
{
struct omap_nand_info *info;
struct omap_nand_platform_data *pdata;
int err;
- int i, offset;
+ int i;
+ int offset = BADBLOCK_MARKER_LENGTH;
+ unsigned int eccsteps;
dma_cap_mask_t mask;
unsigned sig;
struct resource *res;
@@ -1991,11 +1867,14 @@ static int omap_nand_probe(struct platform_device *pdev)
goto out_release_mem_region;
}
- /* select the ecc type */
- if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
+ /* populate MTD interface based on ECC scheme */
+ switch (pdata->ecc_opt) {
+ case OMAP_ECC_HAMMING_CODE_DEFAULT:
info->nand.ecc.mode = NAND_ECC_SOFT;
- else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
- (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
+ break;
+
+ case OMAP_ECC_HAMMING_CODE_HW:
+ case OMAP_ECC_HAMMING_CODE_HW_ROMCODE:
info->nand.ecc.bytes = 3;
info->nand.ecc.size = 512;
info->nand.ecc.strength = 1;
@@ -2003,13 +1882,72 @@ static int omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.hwctl = omap_enable_hwecc;
info->nand.ecc.correct = omap_correct_data;
info->nand.ecc.mode = NAND_ECC_HW;
- } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
- (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
- err = omap3_init_bch(&info->mtd, pdata->ecc_opt);
- if (err) {
+ info->bch = NULL;
+ break;
+
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+ case OMAP_ECC_BCH8_CODE_HW:
+ /* check if ELM module is present on SoC */
+ if (is_elm_present(info, ECC_TYPE_BCH8) < 0) {
+ pr_err("ELM module not detected, required for ECC\n");
err = -EINVAL;
goto out_release_mem_region;
}
+ info->nand.ecc.mode = NAND_ECC_HW;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.bytes = 14;
+ info->nand.ecc.strength = 8;
+ info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+ info->nand.ecc.correct = omap_elm_correct_data;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch;
+ info->nand.ecc.read_page = omap_read_page_bch;
+ info->nand.ecc.write_page = omap_write_page_bch;
+ info->bch = NULL;
+ break;
+#endif
+#ifdef CONFIG_MTD_NAND_ECC_BCH
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+ info->nand.ecc.mode = NAND_ECC_HW;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.bytes = 13;
+ info->nand.ecc.strength = 8;
+ info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+ info->nand.ecc.correct = omap3_correct_data_bch;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
+ /* software bch library is used for locating errors */
+ info->bch = init_bch(info->nand.ecc.bytes,
+ info->nand.ecc.strength,
+ OMAP_ECC_BCH8_POLYNOMIAL);
+ if (!info->bch) {
+ pr_err("unable initialize S/W BCH logic\n");
+ err = -EINVAL;
+ goto out_release_mem_region;
+ }
+ break;
+
+ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+ info->nand.ecc.mode = NAND_ECC_HW;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.bytes = 7;
+ info->nand.ecc.strength = 4;
+ info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+ info->nand.ecc.correct = omap3_correct_data_bch;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
+ /* software bch library is used for locating errors */
+ info->bch = init_bch(info->nand.ecc.bytes,
+ info->nand.ecc.strength,
+ OMAP_ECC_BCH8_POLYNOMIAL);
+ if (!info->bch) {
+ pr_err("unable initialize S/W BCH logic\n");
+ err = -EINVAL;
+ goto out_release_mem_region;
+ }
+ break;
+#endif
+ default:
+ pr_err("selected ECC scheme not supported or not enabled\n");
+ err = -EINVAL;
+ goto out_release_mem_region;
}
/* DIP switches on some boards change between 8 and 16 bit
@@ -2022,35 +1960,73 @@ static int omap_nand_probe(struct platform_device *pdev)
goto out_release_mem_region;
}
}
+ eccsteps = info->mtd.writesize / info->nand.ecc.size;
+
+ /* check if NAND OOBSIZE meets ECC scheme requirement */
+ omap_oobinfo.eccbytes = eccsteps * info->nand.ecc.bytes;
- /* rom code layout */
- if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
+ if (info->mtd.oobsize < (omap_oobinfo.eccbytes +
+ BADBLOCK_MARKER_LENGTH)) {
+ pr_err("not enough OOB bytes required = %d, available=%d",
+ info->mtd.oobsize, omap_oobinfo.eccbytes);
+ err = -EINVAL;
+ goto out_release_mem_region;
+ }
+ /* populate ECC layout information based on ECC scheme */
+ switch (pdata->ecc_opt) {
+ case OMAP_ECC_HAMMING_CODE_HW_ROMCODE:
if (info->nand.options & NAND_BUSWIDTH_16)
offset = 2;
- else {
+ else
offset = 1;
- info->nand.badblock_pattern = &bb_descrip_flashbased;
+ omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
+ break;
+
+ case OMAP_ECC_BCH4_CODE_HW:
+ case OMAP_ECC_BCH8_CODE_HW:
+ /* check for small page devices */
+ if (info->mtd.oobsize < 64) {
+ pr_err("small page devices are not supported\n");
+ err = -EINVAL;
+ goto out_release_mem_region;
}
- omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
- for (i = 0; i < omap_oobinfo.eccbytes; i++)
- omap_oobinfo.eccpos[i] = i+offset;
+ /* ECC layout compatible with RBL for BCH8 */
+ offset = BADBLOCK_MARKER_LENGTH;
+ omap_oobinfo.oobfree->offset = BADBLOCK_MARKER_LENGTH +
+ omap_oobinfo.eccbytes;
+ break;
- omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
- omap_oobinfo.oobfree->length = info->mtd.oobsize -
- (offset + omap_oobinfo.eccbytes);
-
- info->nand.ecc.layout = &omap_oobinfo;
- } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
- (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
- /* build OOB layout for BCH ECC correction */
- err = omap3_init_bch_tail(&info->mtd);
- if (err) {
+ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+ /* check for small page devices */
+ if (info->mtd.oobsize < 64) {
+ pr_err("small page devices are not supported\n");
err = -EINVAL;
goto out_release_mem_region;
}
+ offset = info->mtd.oobsize - omap_oobinfo.eccbytes;
+ omap_oobinfo.oobfree->offset = BADBLOCK_MARKER_LENGTH;
+ break;
+
+ default:
+ pr_info("using default ecc layout for NAND device");
+ goto scan_tail;
}
+ /* populate other ecc_layout information based on ECC scheme */
+ if (!(info->nand.options & NAND_BUSWIDTH_16))
+ info->nand.badblock_pattern = &bb_descrip_flashbased;
+
+ omap_oobinfo.oobfree->length = info->mtd.oobsize -
+ (BADBLOCK_MARKER_LENGTH + omap_oobinfo.eccbytes);
+
+ for (i = 0; i < omap_oobinfo.eccbytes; i++)
+ omap_oobinfo.eccpos[i] = offset + i;
+
+ info->nand.ecc.layout = &omap_oobinfo;
+
+scan_tail:
/* second phase scan */
if (nand_scan_tail(&info->mtd)) {
err = -ENXIO;
@@ -2074,11 +2050,13 @@ out_release_mem_region:
free_irq(info->gpmc_irq_fifo, info);
release_mem_region(info->phys_base, info->mem_size);
out_free_info:
+ omap3_free_bch(&info->mtd);
kfree(info);
return err;
}
+
static int omap_nand_remove(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
index 1bd5244..9dfb2ed 100644
--- a/include/linux/platform_data/elm.h
+++ b/include/linux/platform_data/elm.h
@@ -23,6 +23,10 @@ enum bch_ecc {
BCH8_ECC,
};
+#define ECC_TYPE_BCH4 (0x0 << 0)
+#define ECC_TYPE_BCH8 (0x1 << 0)
+#define ECC_TYPE_BCH16 (0x2 << 0)
+
/* ELM support 8 error syndrome process */
#define ERROR_VECTOR_MAX 8
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 6bf9ef4..ce74576 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -23,13 +23,21 @@ enum nand_io {
};
enum omap_ecc {
- /* 1-bit ecc: stored at end of spare area */
- OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
- OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
- /* 1-bit ecc: stored at beginning of spare area as romcode */
- OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
- OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
- OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
+ /* 1-bit ECC calculation by Software, Error detection by Software */
+ OMAP_ECC_HAMMING_CODE_DEFAULT = 0,
+ /* 1-bit ECC calculation by GPMC, Error detection by Software */
+ OMAP_ECC_HAMMING_CODE_HW,
+ /* 1-bit ECC calculation by GPMC, Error detection by Software */
+ /* ECC layout compatible to legacy ROMCODE. */
+ OMAP_ECC_HAMMING_CODE_HW_ROMCODE,
+ /* 4-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH4_CODE_HW,
+ /* 4-bit ECC calculation by GPMC, Error detection by Software */
+ OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
+ /* 8-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH8_CODE_HW,
+ /* 8-bit ECC calculation by GPMC, Error detection by Software */
+ OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
};
struct gpmc_nand_regs {
--
1.8.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4 v2] ARM: OMAP2+: cleaned-up DT support of various ECC schemes
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
2013-05-17 11:50 ` [PATCH 1/4 v2] mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe Gupta, Pekon
@ 2013-05-17 11:50 ` Gupta, Pekon
2013-05-17 11:50 ` [PATCH 3/4 v2] mtd:nand:omap2: updated support for BCH4 ECC scheme Gupta, Pekon
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-17 11:50 UTC (permalink / raw)
To: linux-mtd, linux-omap
Cc: Gupta, Pekon, avinashphilip, arnd, tony, balbi, jp.francois
From: "Gupta, Pekon" <pekon@ti.com>
ECC scheme on NAND devices can be implemented in multiple ways.Some using
Software algorithm, while others using in-build Hardware engines.
omap2-nand driver currently supports following flavours of ECC schemes,
selectable via DTB.
+---------------------------------------+---------------+---------------+
| ECC scheme |ECC calculation|Error detection|
+---------------------------------------+---------------+---------------+
|OMAP_ECC_HAMMING_CODE_DEFAULT |S/W |S/W |
|OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W |
|OMAP_ECC_HAMMING_CODE_HW_ROMCODE |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|(requires CONFIG_MTD_NAND_ECC_BCH) | | |
|OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|(requires CONFIG_MTD_NAND_OMAP_BCH) | | |
|OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
Selection of some ECC schemes also require enabling following Kconfig options.
This was done to optimize footprint of omap2-nand driver.
-Kconfig:CONFIG_MTD_NAND_ECC_BCH enables S/W based BCH ECC algorithm
-Kconfig:CONFIG_MTD_NAND_OMAP_BCH enables H/W based BCH ECC algorithm
Signed-off-by: Gupta, Pekon <pekon@ti.com>
---
.../devicetree/bindings/mtd/gpmc-nand.txt | 37 +++++++++++++++-------
arch/arm/boot/dts/am335x-evm.dts | 2 +-
arch/arm/mach-omap2/gpmc.c | 12 ++++---
3 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index e7f8d7e..de180be 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -17,20 +17,35 @@ Required properties:
Optional properties:
- - nand-bus-width: Set this numeric value to 16 if the hardware
- is wired that way. If not specified, a bus
- width of 8 is assumed.
+ - nand-bus-width: Determines data-width of the connected device
+ x16 = "16"
+ x8 = "8" (default)
- - ti,nand-ecc-opt: A string setting the ECC layout to use. One of:
- "sw" Software method (default)
- "hw" Hardware method
- "hw-romcode" gpmc hamming mode method & romcode layout
- "bch4" 4-bit BCH ecc code
- "bch8" 8-bit BCH ecc code
+ - ti,nand-ecc-opt: Determines the ECC scheme used by driver.
+ It can be any of the following strings:
+
+ "hamming_sw" 1-bit Hamming ECC using software
+
+ "hamming_hw" 1-bit Hamming ECC using hardware
+
+ "hamming_hw_romcode" 1-bit Hamming ECC using hardware
+ - ECC layout compatible to ROM code
+
+ "bch8_hw_detection_sw" 8-bit BCH with ECC calculation in hardware
+ and error detection in software
+ - requires Kconfig CONFIG_MTD_NAND_ECC_BCH
+
+ "bch8_hw" 8-bit BCH with ECC calculation in hardware
+ and error detection in hardware
+ - requires <elm_id> to be specified
+ - requires Kconfig CONFIG_MTD_NAND_OMAP_BCH
+
+
+
+ - elm_id: Specifies elm device node. This is required to
+ support some BCH ECC schemes mentioned above.
- - elm_id: Specifies elm device node. This is required to support BCH
- error correction using ELM module.
For inline partiton table parsing (optional):
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 0b8f161..60e8f59 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -135,7 +135,7 @@
nand@0,0 {
reg = <0 0 0>; /* CS0, offset 0 */
nand-bus-width = <8>;
- ti,nand-ecc-opt = "bch8";
+ ti,nand-ecc-opt = "bch8_hw";
gpmc,sync-clk = <0>;
gpmc,cs-on = <0>;
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 410e1ba..03b8027 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1205,11 +1205,13 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
#ifdef CONFIG_MTD_NAND
static const char * const nand_ecc_opts[] = {
- [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
- [OMAP_ECC_HAMMING_CODE_HW] = "hw",
- [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
- [OMAP_ECC_BCH4_CODE_HW] = "bch4",
- [OMAP_ECC_BCH8_CODE_HW] = "bch8",
+ [OMAP_ECC_HAMMING_CODE_DEFAULT] = "hamming_sw",
+ [OMAP_ECC_HAMMING_CODE_HW] = "hamming_hw",
+ [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hamming_hw_romcode",
+ [OMAP_ECC_BCH4_CODE_HW] = "bch4_hw",
+ [OMAP_ECC_BCH4_CODE_HW_DETECTION_SW] = "bch4_hw_detection_sw",
+ [OMAP_ECC_BCH8_CODE_HW] = "bch8_hw",
+ [OMAP_ECC_BCH8_CODE_HW_DETECTION_SW] = "bch8_hw_detection_sw"
};
static int gpmc_probe_nand_child(struct platform_device *pdev,
--
1.8.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4 v2] mtd:nand:omap2: updated support for BCH4 ECC scheme
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
2013-05-17 11:50 ` [PATCH 1/4 v2] mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe Gupta, Pekon
2013-05-17 11:50 ` [PATCH 2/4 v2] ARM: OMAP2+: cleaned-up DT support of various ECC schemes Gupta, Pekon
@ 2013-05-17 11:50 ` Gupta, Pekon
2013-05-17 11:50 ` [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT Gupta, Pekon
2013-05-24 13:01 ` [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes jean-philippe francois
4 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-17 11:50 UTC (permalink / raw)
To: linux-mtd, linux-omap
Cc: Gupta, Pekon, avinashphilip, arnd, tony, balbi, jp.francois
From: "Gupta, Pekon" <pekon@ti.com>
This patch adds following two flavours of BCH4 ECC scheme in omap2-nand driver
- OMAP_ECC_BCH4_CODE_HW_DETECTION_SW
- uses GPMC H/W engine for calculating ECC.
- uses software library (lib/bch.h & nand_bch.h) for error correction.
- OMAP_ECC_BCH4_CODE_HW
- uses GPMC H/W engine for calculating ECC.
- uses ELM H/W engine for error correction.
With this patch omap2-nand driver supports following ECC schemes:
+---------------------------------------+---------------+---------------+
| ECC scheme |ECC calculation|Error detection|
+---------------------------------------+---------------+---------------+
|OMAP_ECC_HAMMING_CODE_DEFAULT |S/W |S/W |
|OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W |
|OMAP_ECC_HAMMING_CODE_HW_ROMCODE |H/W (GPMC) |S/W |
+---------------------------------------+---------------+---------------+
|OMAP_ECC_BCH4_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
|OMAP_ECC_BCH4_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
|OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
|OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
+---------------------------------------+---------------+---------------+
Important:
- Selection of OMAP_ECC_BCHx_CODE_HW_DETECTION_SW requires,
Kconfig: CONFIG_MTD_NAND_ECC_BCH: enables S/W based BCH ECC algorithm.
- Selection of OMAP_ECC_BCHx_CODE_HW requires,
Kconfig: CONFIG_MTD_NAND_OMAP_BCH: enables ELM H/W module.
Signed-off-by: Gupta, Pekon <pekon@ti.com>
---
drivers/mtd/nand/Kconfig | 1 -
drivers/mtd/nand/omap2.c | 159 +++++++++++----------------
include/linux/platform_data/mtd-nand-omap2.h | 10 +-
3 files changed, 70 insertions(+), 100 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 81bf5e5..b8196a1 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -112,7 +112,6 @@ config MTD_NAND_OMAP_BCH
bool "Enable support for hardware BCH error correction"
default n
select BCH
- select BCH_CONST_PARAMS
help
Support for hardware BCH error correction.
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 167f8d4..43e4dd4 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,6 +27,7 @@
#ifdef CONFIG_MTD_NAND_ECC_BCH
#include <linux/bch.h>
+#include <linux/mtd/nand_bch.h>
#endif
#ifdef CONFIG_MTD_NAND_OMAP_BCH
#include <linux/platform_data/elm.h>
@@ -185,10 +186,9 @@ struct omap_nand_info {
OMAP_NAND_IO_WRITE, /* write */
} iomode;
u_char *buf;
- int buf_len;
+ int buf_len;
struct gpmc_nand_regs reg;
/* fields specific for BCHx_HW ECC scheme */
- struct bch_control *bch;
bool is_elm_used;
struct device *elm_dev;
struct device_node *of_node;
@@ -1227,58 +1227,6 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
return 0;
}
-/**
- * omap3_correct_data_bch - Decode received data and correct errors
- * @mtd: MTD device structure
- * @data: page data
- * @read_ecc: ecc read from nand flash
- * @calc_ecc: ecc read from HW ECC registers
- */
-static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int i, count;
- /* cannot correct more than 8 errors */
- unsigned int errloc[8];
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
-
- count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL,
- errloc);
- if (count > 0) {
- /* correct errors */
- for (i = 0; i < count; i++) {
- /* correct data only, not ecc bytes */
- if (errloc[i] < 8*512)
- data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
- pr_debug("corrected bitflip %u\n", errloc[i]);
- }
- } else if (count < 0) {
- pr_err("ecc unrecoverable error\n");
- }
- return count;
-}
-
-/**
- * omap3_free_bch - Release BCH ecc resources
- * @mtd: MTD device structure
- */
-static void omap3_free_bch(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- if (info->bch) {
- free_bch(info->bch);
- info->bch = NULL;
- }
-}
-
-#else
-
-static void omap3_free_bch(struct mtd_info *mtd)
-{
-}
-
#endif /* CONFIG_MTD_NAND_ECC_BCH */
@@ -1735,6 +1683,7 @@ static int omap_nand_probe(struct platform_device *pdev)
#ifdef CONFIG_MTD_NAND_OMAP_BCH
info->of_node = pdata->of_node;
#endif
+ info->nand.ecc.priv = NULL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
@@ -1882,27 +1831,36 @@ static int omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.hwctl = omap_enable_hwecc;
info->nand.ecc.correct = omap_correct_data;
info->nand.ecc.mode = NAND_ECC_HW;
- info->bch = NULL;
break;
-
+#ifdef CONFIG_MTD_NAND_ECC_BCH
+ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+ info->nand.ecc.mode = NAND_ECC_HW;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.bytes = 7;
+ info->nand.ecc.strength = 4;
+ info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+ info->nand.ecc.correct = nand_bch_correct_data;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
+ break;
+#endif
#ifdef CONFIG_MTD_NAND_OMAP_BCH
- case OMAP_ECC_BCH8_CODE_HW:
+ case OMAP_ECC_BCH4_CODE_HW:
/* check if ELM module is present on SoC */
- if (is_elm_present(info, ECC_TYPE_BCH8) < 0) {
+ if (is_elm_present(info, ECC_TYPE_BCH4) < 0) {
pr_err("ELM module not detected, required for ECC\n");
err = -EINVAL;
goto out_release_mem_region;
}
info->nand.ecc.mode = NAND_ECC_HW;
info->nand.ecc.size = 512;
- info->nand.ecc.bytes = 14;
- info->nand.ecc.strength = 8;
+ /* 8th bit is kept reserved for ROM-code compatibility */
+ info->nand.ecc.bytes = 7 + 1;
+ info->nand.ecc.strength = 4;
info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
info->nand.ecc.correct = omap_elm_correct_data;
info->nand.ecc.calculate = omap3_calculate_ecc_bch;
info->nand.ecc.read_page = omap_read_page_bch;
info->nand.ecc.write_page = omap_write_page_bch;
- info->bch = NULL;
break;
#endif
#ifdef CONFIG_MTD_NAND_ECC_BCH
@@ -1912,36 +1870,28 @@ static int omap_nand_probe(struct platform_device *pdev)
info->nand.ecc.bytes = 13;
info->nand.ecc.strength = 8;
info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
- info->nand.ecc.correct = omap3_correct_data_bch;
+ info->nand.ecc.correct = nand_bch_correct_data;
info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
- /* software bch library is used for locating errors */
- info->bch = init_bch(info->nand.ecc.bytes,
- info->nand.ecc.strength,
- OMAP_ECC_BCH8_POLYNOMIAL);
- if (!info->bch) {
- pr_err("unable initialize S/W BCH logic\n");
+ break;
+#endif
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+ case OMAP_ECC_BCH8_CODE_HW:
+ /* check if ELM module is present on SoC */
+ if (is_elm_present(info, ECC_TYPE_BCH8) < 0) {
+ pr_err("ELM module not detected, required for ECC\n");
err = -EINVAL;
goto out_release_mem_region;
}
- break;
-
- case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
info->nand.ecc.mode = NAND_ECC_HW;
info->nand.ecc.size = 512;
- info->nand.ecc.bytes = 7;
- info->nand.ecc.strength = 4;
+ /* 14th bit is kept reserved for ROM-code compatibility */
+ info->nand.ecc.bytes = 13 + 1;
+ info->nand.ecc.strength = 8;
info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
- info->nand.ecc.correct = omap3_correct_data_bch;
- info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
- /* software bch library is used for locating errors */
- info->bch = init_bch(info->nand.ecc.bytes,
- info->nand.ecc.strength,
- OMAP_ECC_BCH8_POLYNOMIAL);
- if (!info->bch) {
- pr_err("unable initialize S/W BCH logic\n");
- err = -EINVAL;
- goto out_release_mem_region;
- }
+ info->nand.ecc.correct = omap_elm_correct_data;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch;
+ info->nand.ecc.read_page = omap_read_page_bch;
+ info->nand.ecc.write_page = omap_write_page_bch;
break;
#endif
default:
@@ -1964,7 +1914,6 @@ static int omap_nand_probe(struct platform_device *pdev)
/* check if NAND OOBSIZE meets ECC scheme requirement */
omap_oobinfo.eccbytes = eccsteps * info->nand.ecc.bytes;
-
if (info->mtd.oobsize < (omap_oobinfo.eccbytes +
BADBLOCK_MARKER_LENGTH)) {
pr_err("not enough OOB bytes required = %d, available=%d",
@@ -1983,6 +1932,7 @@ static int omap_nand_probe(struct platform_device *pdev)
omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
break;
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
case OMAP_ECC_BCH4_CODE_HW:
case OMAP_ECC_BCH8_CODE_HW:
/* check for small page devices */
@@ -1996,7 +1946,8 @@ static int omap_nand_probe(struct platform_device *pdev)
omap_oobinfo.oobfree->offset = BADBLOCK_MARKER_LENGTH +
omap_oobinfo.eccbytes;
break;
-
+#endif
+#ifdef CONFIG_MTD_NAND_ECC_BCH
case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
/* check for small page devices */
@@ -2005,16 +1956,26 @@ static int omap_nand_probe(struct platform_device *pdev)
err = -EINVAL;
goto out_release_mem_region;
}
- offset = info->mtd.oobsize - omap_oobinfo.eccbytes;
- omap_oobinfo.oobfree->offset = BADBLOCK_MARKER_LENGTH;
+ /* software bch library is used for locating errors */
+ info->nand.ecc.priv = nand_bch_init(&info->mtd,
+ info->nand.ecc.size,
+ info->nand.ecc.bytes,
+ &info->nand.ecc.layout);
+ if (!info->nand.ecc.priv) {
+ pr_err("unable initialize S/W BCH logic\n");
+ err = -EINVAL;
+ goto out_release_mem_region;
+ }
+ pr_info("using default ecc layout in nand_bch_init");
+ goto scan_tail;
break;
-
+#endif
default:
- pr_info("using default ecc layout for NAND device");
+ pr_info("using default ecc layout in generic driver");
goto scan_tail;
}
- /* populate other ecc_layout information based on ECC scheme */
+ /* populate other information for custom ecc layout */
if (!(info->nand.options & NAND_BUSWIDTH_16))
info->nand.badblock_pattern = &bb_descrip_flashbased;
@@ -2049,8 +2010,14 @@ out_release_mem_region:
if (info->gpmc_irq_fifo > 0)
free_irq(info->gpmc_irq_fifo, info);
release_mem_region(info->phys_base, info->mem_size);
+
out_free_info:
- omap3_free_bch(&info->mtd);
+#ifdef CONFIG_MTD_NAND_ECC_BCH
+ if (info->nand.ecc.priv) {
+ nand_bch_free(info->nand.ecc.priv);
+ info->nand.ecc.priv = NULL;
+ }
+#endif
kfree(info);
return err;
@@ -2062,8 +2029,12 @@ static int omap_nand_remove(struct platform_device *pdev)
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- omap3_free_bch(&info->mtd);
-
+#ifdef CONFIG_MTD_NAND_ECC_BCH
+ if (info->nand.ecc.priv) {
+ nand_bch_free(info->nand.ecc.priv);
+ info->nand.ecc.priv = NULL;
+ }
+#endif
platform_set_drvdata(pdev, NULL);
if (info->dma)
dma_release_channel(info->dma);
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index ce74576..9fcee61 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -30,14 +30,14 @@ enum omap_ecc {
/* 1-bit ECC calculation by GPMC, Error detection by Software */
/* ECC layout compatible to legacy ROMCODE. */
OMAP_ECC_HAMMING_CODE_HW_ROMCODE,
- /* 4-bit ECC calculation by GPMC, Error detection by ELM */
- OMAP_ECC_BCH4_CODE_HW,
/* 4-bit ECC calculation by GPMC, Error detection by Software */
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
- /* 8-bit ECC calculation by GPMC, Error detection by ELM */
- OMAP_ECC_BCH8_CODE_HW,
+ /* 4-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH4_CODE_HW,
/* 8-bit ECC calculation by GPMC, Error detection by Software */
- OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
+ OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
+ /* 8-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH8_CODE_HW
};
struct gpmc_nand_regs {
--
1.8.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
` (2 preceding siblings ...)
2013-05-17 11:50 ` [PATCH 3/4 v2] mtd:nand:omap2: updated support for BCH4 ECC scheme Gupta, Pekon
@ 2013-05-17 11:50 ` Gupta, Pekon
2013-05-17 12:46 ` Arnd Bergmann
2013-05-24 13:01 ` [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes jean-philippe francois
4 siblings, 1 reply; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-17 11:50 UTC (permalink / raw)
To: linux-mtd, linux-omap
Cc: Gupta, Pekon, avinashphilip, arnd, tony, balbi, jp.francois
From: "Gupta, Pekon" <pekon@ti.com>
Updates ECC scheme selection string same to same as used in omap2-driver code.
This makes the DT configurations easy to understand and map to actual code.
Signed-off-by: Gupta, Pekon <pekon@ti.com>
---
.../devicetree/bindings/mtd/gpmc-nand.txt | 47 ++++++++++++++--------
arch/arm/boot/dts/am335x-evm.dts | 2 +-
arch/arm/mach-omap2/gpmc.c | 19 +++++----
3 files changed, 43 insertions(+), 25 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index de180be..c7a4add 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -25,22 +25,37 @@ Optional properties:
- ti,nand-ecc-opt: Determines the ECC scheme used by driver.
It can be any of the following strings:
- "hamming_sw" 1-bit Hamming ECC using software
-
- "hamming_hw" 1-bit Hamming ECC using hardware
-
- "hamming_hw_romcode" 1-bit Hamming ECC using hardware
- - ECC layout compatible to ROM code
-
- "bch8_hw_detection_sw" 8-bit BCH with ECC calculation in hardware
- and error detection in software
- - requires Kconfig CONFIG_MTD_NAND_ECC_BCH
-
- "bch8_hw" 8-bit BCH with ECC calculation in hardware
- and error detection in hardware
- - requires <elm_id> to be specified
- - requires Kconfig CONFIG_MTD_NAND_OMAP_BCH
-
+ "OMAP_ECC_HAMMING_CODE_SW"
+ 1-bit Hamming ECC using software.
+
+ "OMAP_ECC_HAMMING_CODE_HW"
+ 1-bit Hamming ECC using hardware.
+
+ "OMAP_ECC_HAMMING_CODE_HW_ROMCODE"
+ 1-bit Hamming ECC using hardware with
+ ECC layout compatible to ROM code.
+
+ "OMAP_ECC_BCH4_CODE_HW_DETECTION_SW"
+ 4-bit BCH with ECC calculation in
+ hardware & error detection in software.
+ - requires CONFIG_MTD_NAND_ECC_BCH
+
+ "OMAP_ECC_BCH4_CODE_HW"
+ 4-bit BCH with ECC calculation in
+ hardware & error detection in hardware.
+ - requires CONFIG_MTD_NAND_OMAP_BCH
+ - requires <elm_id> to be specified
+
+ "OMAP_ECC_BCH8_CODE_HW_DETECTION_SW"
+ 8-bit BCH with ECC calculation in
+ hardware & error detection in software.
+ - requires CONFIG_MTD_NAND_ECC_BCH
+
+ "OMAP_ECC_BCH8_CODE_HW"
+ 8-bit BCH with ECC calculation in
+ hardware & error detection in hardware.
+ - requires CONFIG_MTD_NAND_OMAP_BCH
+ - requires <elm_id> to be specified
- elm_id: Specifies elm device node. This is required to
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 60e8f59..1107761 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -135,7 +135,7 @@
nand@0,0 {
reg = <0 0 0>; /* CS0, offset 0 */
nand-bus-width = <8>;
- ti,nand-ecc-opt = "bch8_hw";
+ ti,nand-ecc-opt = "OMAP_ECC_BCH8_CODE_HW";
gpmc,sync-clk = <0>;
gpmc,cs-on = <0>;
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 03b8027..e3146c3 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1205,13 +1205,16 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
#ifdef CONFIG_MTD_NAND
static const char * const nand_ecc_opts[] = {
- [OMAP_ECC_HAMMING_CODE_DEFAULT] = "hamming_sw",
- [OMAP_ECC_HAMMING_CODE_HW] = "hamming_hw",
- [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hamming_hw_romcode",
- [OMAP_ECC_BCH4_CODE_HW] = "bch4_hw",
- [OMAP_ECC_BCH4_CODE_HW_DETECTION_SW] = "bch4_hw_detection_sw",
- [OMAP_ECC_BCH8_CODE_HW] = "bch8_hw",
- [OMAP_ECC_BCH8_CODE_HW_DETECTION_SW] = "bch8_hw_detection_sw"
+ [OMAP_ECC_HAMMING_CODE_DEFAULT] = "OMAP_ECC_HAMMING_CODE_SW",
+ [OMAP_ECC_HAMMING_CODE_HW] = "OMAP_ECC_HAMMING_CODE_HW",
+ [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] =
+ "OMAP_ECC_HAMMING_CODE_HW_ROMCODE",
+ [OMAP_ECC_BCH4_CODE_HW_DETECTION_SW] =
+ "OMAP_ECC_BCH4_CODE_HW_DETECTION_SW",
+ [OMAP_ECC_BCH4_CODE_HW] = "OMAP_ECC_BCH4_CODE_HW",
+ [OMAP_ECC_BCH8_CODE_HW_DETECTION_SW] =
+ "OMAP_ECC_BCH8_CODE_HW_DETECTION_SW",
+ [OMAP_ECC_BCH8_CODE_HW] = "OMAP_ECC_BCH8_CODE_HW"
};
static int gpmc_probe_nand_child(struct platform_device *pdev,
@@ -1238,7 +1241,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
- if (!strcasecmp(s, nand_ecc_opts[val])) {
+ if (!strcmp(s, nand_ecc_opts[val])) {
gpmc_nand_data->ecc_opt = val;
break;
}
--
1.8.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT
2013-05-17 11:50 ` [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT Gupta, Pekon
@ 2013-05-17 12:46 ` Arnd Bergmann
2013-05-18 11:05 ` Gupta, Pekon
0 siblings, 1 reply; 8+ messages in thread
From: Arnd Bergmann @ 2013-05-17 12:46 UTC (permalink / raw)
To: Gupta, Pekon
Cc: linux-mtd, linux-omap, avinashphilip, tony, balbi, jp.francois
On Friday 17 May 2013, Gupta, Pekon wrote:
> From: "Gupta, Pekon" <pekon@ti.com>
>
> Updates ECC scheme selection string same to same as used in omap2-driver code.
> This makes the DT configurations easy to understand and map to actual code.
>
> Signed-off-by: Gupta, Pekon <pekon@ti.com>
This moves the binding in the wrong direction. First of all, you should never
make incompatible changes to a specification document.
> - "bch8_hw_detection_sw" 8-bit BCH with ECC calculation in hardware
> - and error detection in software
> - - requires Kconfig CONFIG_MTD_NAND_ECC_BCH
The binding before your change is already broken since it refers to
Linux-specific Kconfig symbols, and you fail to fix that.
> + "OMAP_ECC_BCH4_CODE_HW_DETECTION_SW"
> + 4-bit BCH with ECC calculation in
> + hardware & error detection in software.
> + - requires CONFIG_MTD_NAND_ECC_BCH
Instead you make it worse by using /more/ Linux-isms in the binding.
Arnd
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT
2013-05-17 12:46 ` Arnd Bergmann
@ 2013-05-18 11:05 ` Gupta, Pekon
0 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2013-05-18 11:05 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-mtd@lists.infradead.org, linux-omap@vger.kernel.org,
Philip, Avinash, tony@atomide.com, Balbi, Felipe,
jp.francois@cynove.com
> On Friday 17 May 2013, Gupta, Pekon wrote:
> > From: "Gupta, Pekon" <pekon@ti.com>
> >
> > Updates ECC scheme selection string same to same as used in omap2-
> driver code.
> > This makes the DT configurations easy to understand and map to actual
> code.
> >
> > Signed-off-by: Gupta, Pekon <pekon@ti.com>
>
> This moves the binding in the wrong direction. First of all, you should
> never
> make incompatible changes to a specification document.
>
> > - "bch8_hw_detection_sw" 8-bit BCH with ECC calculation in
> hardware
> > - and error detection in software
> > - - requires Kconfig
> CONFIG_MTD_NAND_ECC_BCH
>
> The binding before your change is already broken since it refers to
> Linux-specific Kconfig symbols, and you fail to fix that.
>
[Pekon]: There are two constrains due to which I could not remove
Kconfig dependency
(1) Some BCHx ECC schemes are using generic lib/bch.h and nand_bch.h
generic libraries, which further depend on 'CONFIG_MTD_NAND_ECC_BCH'.
So I have to include that dependency, so that incorrect ECC scheme
selection In DT does not break linker.
(2) Other alternative could have been to always include lib/bch.h and
nand_bch.h. But that would have bloated the omap2-driver footprint,
especially when 80% of the time these libraries were not getting used.
(3) I did not want to change things so drastically that it breaks on legacy
devices. Some users are now migrating to latest kernel from older
versions. I din't want to make migration more tough :-)
However, I tried to fix some existing issues due to incorrect selection of
Kconfigs, and I tried making things simpler from user's point-of-view.
Like, if you don't select a correct Kconfig along with matching ECC scheme
Then your device_initialization would cleanly exit giving you msg:
pr_err("selected ECC scheme not supported or not enabled\n");
when running the linker.> > +
> "OMAP_ECC_BCH4_CODE_HW_DETECTION_SW"
> > + 4-bit BCH with ECC calculation in
> > + hardware & error detection in
> software.
> > + - requires
> CONFIG_MTD_NAND_ECC_BCH
>
> Instead you make it worse by using /more/ Linux-isms in the binding.
>
> Arnd
[Pekon]: The update binding attribute string is done for following reasons:
(1) make it more user-friendly. The string you put in the DT is same,
You see while browsing thru the driver code.
My assessment was that most mainline user are much tech-savy
they themselves try to dig into the code and analyze the issue.
Thus for them, reducing the gap between driver nomenclature and
DT bindings was my way of thinking.
(2) prefix of 'OMAP_ECC_xx' was required because I wanted to
Differentiate Some ECC schemes implementations from the ones
already present in generic driver (nand_base.c)
Example: there are following favours of same BCH-ECC scheme now..
- NAND_ECC_SOFT_BCH: purely S/W based ECC scheme
- OMAP_ECC_BCH4_HW_DETECTION_SW: partly S/w partly H/W based
- OMAP_ECC_BCH4_MODE_HW: fully H/W based ECC scheme.
Anyway these are just my way of thinking..
If you have some suggestions, in following a particular nomenclature
OR particular way of streamlining the driver, please elaborate..
Any feedbacks would help to improve..
With regards, pekon
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
` (3 preceding siblings ...)
2013-05-17 11:50 ` [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT Gupta, Pekon
@ 2013-05-24 13:01 ` jean-philippe francois
4 siblings, 0 replies; 8+ messages in thread
From: jean-philippe francois @ 2013-05-24 13:01 UTC (permalink / raw)
To: Gupta, Pekon
Cc: linux-mtd@lists.infradead.org, linux-omap@vger.kernel.org,
Philip, Avinash, Arnd Bergmann, Tony Lindgren, Balbi, Felipe
2013/5/17 Gupta, Pekon <pekon@ti.com>:
> From: "Gupta, Pekon" <pekon@ti.com>
>
> [Change v1 -> v2]
> added [PATCH 3/4] and [PATCH 4/4]
>
> [PATCH 1/4]: clean-up and optimization for supported ECC schemes.
> [PATCH 2/4]: add separate DT options each supported ECC scheme.
> [PATCH 3/4]: update BCH4 ECC implementation (using ELM or using lib/bch.h)
> [PATCH 4/4]: update DT attribute for ti,nand-ecc-opt
>
> After this patch series, omap2-nand driver will supports following ECC schemes:
> +---------------------------------------+---------------+---------------+
> | ECC scheme |ECC calculation|Error detection|
> +---------------------------------------+---------------+---------------+
> |OMAP_ECC_HAMMING_CODE_DEFAULT |S/W |S/W |
> |OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W |
> |OMAP_ECC_HAMMING_CODE_HW_ROMCODE |H/W (GPMC) |S/W |
> +---------------------------------------+---------------+---------------+
> |OMAP_ECC_BCH4_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
> |OMAP_ECC_BCH4_CODE_HW |H/W (GPMC) |H/W (ELM) |
> +---------------------------------------+---------------+---------------+
> |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W (lib/bch.h)|
> |OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) |
> +---------------------------------------+---------------+---------------+
> - Selection of OMAP_ECC_BCHx_CODE_HW_DETECTION_SW requires,
> Kconfig: CONFIG_MTD_NAND_ECC_BCH: enables S/W based BCH ECC algorithm.
>
> - Selection of OMAP_ECC_BCHx_CODE_HW requires,
> Kconfig: CONFIG_MTD_NAND_OMAP_BCH: enables ELM H/W module.
>
>
Hi,
Thank you for not dropping BCH4 with software detection.
BCH4_CODE_HW_DETECTION_SW tested sucessfully on an existing nand with BCH4 ECC.
- Linux flashed kernel was read by u-boot sucessfully.
- existing ubifs sucessfully mounted.
Regards,
Jean-Philippe François
> Gupta, Pekon (4):
> mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in
> device_probe
> ARM: OMAP2+: cleaned-up DT support of various ECC schemes
> mtd:nand:omap2: updated support for BCH4 ECC scheme
> ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT
>
> .../devicetree/bindings/mtd/gpmc-nand.txt | 52 ++-
> arch/arm/boot/dts/am335x-evm.dts | 2 +-
> arch/arm/mach-omap2/gpmc.c | 17 +-
> drivers/mtd/nand/Kconfig | 1 -
> drivers/mtd/nand/omap2.c | 413 +++++++++------------
> include/linux/platform_data/elm.h | 4 +
> include/linux/platform_data/mtd-nand-omap2.h | 22 +-
> 7 files changed, 253 insertions(+), 258 deletions(-)
>
> --
> 1.8.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-05-24 13:01 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-17 11:50 [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes Gupta, Pekon
2013-05-17 11:50 ` [PATCH 1/4 v2] mtd:nand:omap2: clean-up BCHx_HW and BCHx_SW ECC configurations in device_probe Gupta, Pekon
2013-05-17 11:50 ` [PATCH 2/4 v2] ARM: OMAP2+: cleaned-up DT support of various ECC schemes Gupta, Pekon
2013-05-17 11:50 ` [PATCH 3/4 v2] mtd:nand:omap2: updated support for BCH4 ECC scheme Gupta, Pekon
2013-05-17 11:50 ` [PATCH 4/4 v2] ARM: OMAP2+: updated ECC scheme attributes for omap2-nand DT Gupta, Pekon
2013-05-17 12:46 ` Arnd Bergmann
2013-05-18 11:05 ` Gupta, Pekon
2013-05-24 13:01 ` [PATCH 0/4 v2] mtd:nand:omap2: clean-up of supported ECC schemes jean-philippe francois
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox