OMAP NAND driver support multiple ECC scheme, which can used in following different flavours, depending on in-build Hardware engines supported by SoC. +---------------------------------------+---------------+---------------+ | ECC scheme |ECC calculation|Error detection| +---------------------------------------+---------------+---------------+ |OMAP_ECC_HAMMING_CODE_HW |H/W (GPMC) |S/W | +---------------------------------------+---------------+---------------+ |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W | |(requires CONFIG_MTD_NAND_ECC_BCH) | | | +---------------------------------------+---------------+---------------+ |OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) | |(requires CONFIG_MTD_NAND_OMAP_BCH && | | | | ti,elm-id in DT) | | | +---------------------------------------+---------------+---------------+ To optimize footprint of omap2-nand driver, selection of some ECC schemes also require enabling following Kconfigs, in addition to setting appropriate DT bindings - 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 This patch - updates DT binding for selection of ecc-scheme - updates DT binding for detection of ELM h/w engine - removes following obselete ECC schemes OMAP_ECC_HAMMING_CODE_DEFAULT (S/W based 1-bit Hamming ECC) OMAP_ECC_HAMMING_CODE_HW_ROMCODE (H/W based 1-bit Hamming ECC scheme) - updates DT binding documentation for mtd/gpmc-nand Signed-off-by: Pekon Gupta <pekon@xxxxxx> --- .../devicetree/bindings/mtd/gpmc-nand.txt | 14 +++---- arch/arm/mach-omap2/board-flash.c | 2 +- arch/arm/mach-omap2/gpmc.c | 47 +++++++++++++++------- include/linux/platform_data/mtd-nand-omap2.h | 23 +++++++---- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index df338cb..958e5d5 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -21,11 +21,8 @@ Optional properties: is wired that way. If not specified, a bus width of 8 is assumed. - - 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 + - ti,nand-ecc-scheme: A string setting the ECC layout to use. One of: + "ham1" 1-bit Hamming ecc code "bch4" 4-bit BCH ecc code "bch8" 8-bit BCH ecc code @@ -36,8 +33,11 @@ Optional properties: "prefetch-dma" Prefetch enabled sDMA mode "prefetch-irq" Prefetch enabled irq mode - - elm_id: Specifies elm device node. This is required to support BCH - error correction using ELM module. + - ti,elm-id: Specifies pHandle of the ELM devicetree node. + ELM is an on-chip hardware engine on TI SoC which is used for + locating ECC errors for BCHx algorithms. SoC devices which have + ELM hardware engines should specify this device node in .dtsi + Using ELM for ECC error correction frees some CPU cycles. For inline partiton table parsing (optional): diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index fc20a61..ac82512 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, board_nand_data.nr_parts = nr_parts; board_nand_data.devsize = nand_type; - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; + board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW; gpmc_nand_init(&board_nand_data, gpmc_t); } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9f4795a..6409884 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1340,15 +1340,6 @@ 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", -}; - static const char * const nand_xfer_types[] = { [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", [NAND_OMAP_POLLED] = "polled", @@ -1363,6 +1354,8 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, const char *s; struct gpmc_timings gpmc_t; struct omap_nand_platform_data *gpmc_nand_data; + const __be32 *parp; + int lenp; if (of_property_read_u32(child, "reg", &val) < 0) { dev_err(&pdev->dev, "%s has no 'reg' property\n", @@ -1378,12 +1371,36 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, gpmc_nand_data->cs = val; gpmc_nand_data->of_node = child; - 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])) { - gpmc_nand_data->ecc_opt = val; - break; - } + /* Detect availability of ELM module */ + parp = of_get_property(child, "ti,elm-id", &lenp); + if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { + pr_warn("%s: ti,elm-id property not found\n", __func__); + gpmc_nand_data->elm_of_node = NULL; + } else { + gpmc_nand_data->elm_of_node = + of_find_node_by_phandle(be32_to_cpup(parp)); + } + /* select NAND ecc-scheme */ + if (of_property_read_string(child, "ti,nand-ecc-scheme", &s)) { + pr_err("%s: valid ti,nand-ecc-scheme not found\n", __func__); + return -ENODEV; + } + if (!strcmp(s, "ham1")) + gpmc_nand_data->ecc_opt = OMAP_ECC_HAMMING_CODE_HW; + else if (!strcmp(s, "bch4")) + if (gpmc_nand_data->elm_of_node) + gpmc_nand_data->ecc_opt = OMAP_ECC_BCH4_CODE_HW; + else + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; + else if (!strcmp(s, "bch8")) + if (gpmc_nand_data->elm_of_node) + gpmc_nand_data->ecc_opt = OMAP_ECC_BCH8_CODE_HW; + else + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; + else + pr_err("%s: ti,ecc-scheme: invalid property value\n", __func__); if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 6bf9ef4..b4c2c5a 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 Software */ + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW, + /* 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, + /* 8-bit ECC calculation by GPMC, Error detection by ELM */ + OMAP_ECC_BCH8_CODE_HW, }; struct gpmc_nand_regs { @@ -63,5 +71,6 @@ struct omap_nand_platform_data { /* for passing the partitions */ struct device_node *of_node; + struct device_node *elm_of_node; }; #endif -- 1.8.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html