[U-Boot] [PATCH v4 1/5] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
Scott Wood
scottwood at freescale.com
Thu Sep 12 20:35:19 CEST 2013
On Tue, 2013-09-03 at 11:26 +0530, Pekon Gupta wrote:
> diff --git a/doc/README.nand b/doc/README.nand
> index 913e9b5..f72f618 100644
> --- a/doc/README.nand
> +++ b/doc/README.nand
> @@ -169,6 +169,19 @@ Configuration Options:
> Please convert your driver even if you don't need the extra
> flexibility, so that one day we can eliminate the old mechanism.
>
> + CONFIG_SYS_NAND_ONFI_DETECTION
> + Enables detection of ONFI compliant devices during probe.
> + And fetching device parameters flashed on device, by parsing
> + ONFI parameter page.
I don't see this used anywhere in the patch (defined in config headers,
yes, but not ifdeffed).
What does "DETECTION" add here, versus just CONFIG_NAND_ONFI?
It should be CONFIG rather than CONFIG_SYS because it just controls
whether the support is built, not making an assertion about the
hardware, right?
> + CONFIG_BCH
> + Enables software based BCH ECC algorithm present in lib/bch.c
> + This is used by SoC platforms which do not have in-build hardware
> + engine to calculate and correct BCH ECC.
s/in-build/a built-in/
> + CONFIG_SYS_NAND_ECCSCHEME
> + specifies which ECC scheme to use.
Specifies it how? What are the possible values?
If the answer involves "enum omap_ecc", then OMAP should be somewhere in
the name.
> +#define BADBLOCK_MARKER_LENGTH 0x2
> +#define SECTOR_BYTES 512
Why hex, especially since you don't use it on the larger number?
> +/**
> + * omap_select_ecc_scheme - configures driver for particular ecc-scheme
> + * @nand: NAND chip device structure
> + * @ecc_scheme: ecc scheme to configure
> + * @pagesize: number of main-area bytes per page of NAND device
> + * @oobsize: number of OOB/spare bytes per page of NAND device
> + */
> +static int omap_select_ecc_scheme(struct nand_chip *nand, int ecc_scheme,
> + unsigned int pagesize, unsigned int oobsize) {
> + struct nand_bch_priv *bch = nand->priv;
> + struct nand_ecclayout *ecclayout = nand->ecc.layout;
> + int i;
> +
> + /* Reset ecc interface */
> + nand->ecc.mode = NAND_ECC_NONE;
> + nand->ecc.read_page = NULL;
> + nand->ecc.write_page = NULL;
> + nand->ecc.read_oob = NULL;
> + nand->ecc.write_oob = NULL;
> + nand->ecc.hwctl = NULL;
> + nand->ecc.correct = NULL;
> + nand->ecc.calculate = NULL;
> +
> + switch (ecc_scheme) {
> + case OMAP_ECC_HAM1_CODE_SW:
> + debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
> + nand->ecc.mode = NAND_ECC_SOFT;
> + nand->ecc.layout = NULL;
> + nand->ecc.size = 0;
> + nand->ecc.strength = 1;
> + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW;
> + break;
> + case OMAP_ECC_HAM1_CODE_HW_ROMCODE:
> + debug("nand: selected OMAP_ECC_HAM1_CODE_HW_ROMCODE\n");
> + nand->ecc.mode = NAND_ECC_HW;
> + nand->ecc.strength = 1;
> + nand->ecc.size = 512;
> + nand->ecc.bytes = 3;
> + nand->ecc.hwctl = omap_enable_hwecc;
> + nand->ecc.correct = omap_correct_data;
> + nand->ecc.calculate = omap_calculate_ecc;
> + /* define ecc-layout */
> + ecclayout->eccbytes = nand->ecc.bytes *
> + (pagesize / SECTOR_BYTES);
> + for (i = 0; i < ecclayout->eccbytes; i++)
> + ecclayout->eccpos[i] = i +
> + BADBLOCK_MARKER_LENGTH;
> + ecclayout->oobfree[0].offset = i +
> + BADBLOCK_MARKER_LENGTH;
> + ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
> + BADBLOCK_MARKER_LENGTH;
> + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW_ROMCODE;
> + break;
> +#ifdef CONFIG_BCH
> + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
> + debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
> + nand->ecc.mode = NAND_ECC_HW;
> + nand->ecc.strength = 8;
> + nand->ecc.size = 512;
> + nand->ecc.bytes = 13;
> + nand->ecc.hwctl = omap_enable_ecc_bch;
> + nand->ecc.correct = omap_correct_data_bch_sw;
> + nand->ecc.calculate = omap_calculate_ecc_bch_sw;
> + /* BCH SW library is used for error detection */
> + bch_priv.control = init_bch(13, 8, 0x201b);
> + if (!bch_priv.control) {
> + printf("nand: error: could not init_bch()\n");
> + return -ENODEV;
> + }
> + /* define ecc-layout */
> + ecclayout->eccbytes = nand->ecc.bytes *
> + (pagesize / SECTOR_BYTES);
> + for (i = 0; i < ecclayout->eccbytes; i++)
> + ecclayout->eccpos[i] = i + (oobsize -
> + ecclayout->eccbytes);
> + ecclayout->oobfree[0].offset = BADBLOCK_MARKER_LENGTH;
> + ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
> + BADBLOCK_MARKER_LENGTH;
> + omap_hwecc_init_bch(nand, NAND_ECC_READ);
> + bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
> + break;
> +#endif
> + case OMAP_ECC_BCH8_CODE_HW:
> + debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
> + nand->ecc.mode = NAND_ECC_HW;
> + nand->ecc.strength = 8;
> + nand->ecc.size = 512;
> + nand->ecc.bytes = 14;
> + nand->ecc.hwctl = omap_enable_ecc_bch;
> + nand->ecc.correct = omap_correct_data_bch;
> + nand->ecc.calculate = omap_calculate_ecc_bch;
> + /* ELM is used for ECC error detection */
> + elm_init();
> + /* define ecc-layout */
> + ecclayout->eccbytes = nand->ecc.bytes *
> + (pagesize / SECTOR_BYTES);
> + for (i = 0; i < ecclayout->eccbytes; i++)
> + ecclayout->eccpos[i] = i +
> + BADBLOCK_MARKER_LENGTH;
> + ecclayout->oobfree[0].offset = i +
> + BADBLOCK_MARKER_LENGTH;
> + ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
> + BADBLOCK_MARKER_LENGTH;
> + bch->ecc_scheme = OMAP_ECC_BCH8_CODE_HW;
> + break;
> + default:
> + debug("nand: error: ecc scheme not enabled or supported\n");
> + return -EINVAL;
> + }
This will result in NAND_ECC_NONE and likely an eventual NULL pointer
dereference if a bad value is passed and the -EINVAL return path is
taken.
OK, I now see that you've got the caller patching this up in the error
case, but that's awkward and error prone.
> @@ -767,67 +811,41 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
> {
> struct nand_chip *nand;
> struct mtd_info *mtd;
> + struct nand_bch_priv *bch;
> + int err = 0;
>
> if (nand_curr_device < 0 ||
> nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
> !nand_info[nand_curr_device].name) {
> - printf("Error: Can't switch ecc, no devices available\n");
> + printf("nand: error: no devices available\n");
> return;
> }
Why are you making the error message less specific?
Better would be something like:
printf("%s: no devices available\n", __func__);
> /* Setup the ecc configurations again */
> - if (hardware) {
> + if (hardware)
> if (eccstrength == 1) {
The brace is required due to multiline bodies.
> diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
> index e0a87f8..c2d25a4 100644
> --- a/include/configs/am335x_evm.h
> +++ b/include/configs/am335x_evm.h
> @@ -259,6 +259,8 @@
>
> #define CONFIG_SYS_NAND_ECCSIZE 512
> #define CONFIG_SYS_NAND_ECCBYTES 14
> +#define CONFIG_SYS_NAND_ECCSCHEME 3
> +#define CONFIG_SYS_NAND_ONFI_DETECTION
>
> #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
> #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000
> diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
> index a9b2714..2b01486 100644
> --- a/include/configs/tricorder.h
> +++ b/include/configs/tricorder.h
> @@ -298,6 +298,8 @@
>
> #define CONFIG_SYS_NAND_ECCSIZE 512
> #define CONFIG_SYS_NAND_ECCBYTES 13
> +#define CONFIG_SYS_NAND_ECCSCHEME 3
> +#define CONFIG_SYS_NAND_ONFI_DETECTION
What does 3 mean? Please use a symbolic name.
-Scott
More information about the U-Boot
mailing list