
5 Oct
2013
5 Oct
'13
12:30 a.m.
On Mon, 2013-09-30 at 19:43 +0530, Pekon Gupta wrote:
+Platform specific options +=========================
- CONFIG_NAND_OMAP_ECCSCHEME
- On OMAP platforms, this specifies NAND ECC scheme.
- 1 - HAM1_SW 1-bit Hamming code using software library
(for legacy devices only)
- 2 - HAM1_HW 1-bit Hamming code using GPMC hardware engine
(for legacy devices only)
- 3 - BCH4_SW 4-bit BCH code (unsupported)
- 4 - BCH4_HW 4-bit BCH code (unsupported)
- 5 - BCH8_SW 8-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using software library.
- requires CONFIG_BCH to enable software BCH library
(For legacy device which do not have ELM h/w engine)
- 6 - BCH8_HW 8-bit BCH code with
- ecc calculation using GPMC hardware engine,
- error detection using ELM hardware engine.
You should document the symbols, not the numbers that happen to be assigned to them.
+/**
- 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) {
s/int ecc_scheme/enum omap_ecc ecc_scheme/
- struct nand_bch_priv *bch = nand->priv;
- struct nand_ecclayout *ecclayout = nand->ecc.layout;
- int i;
- 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:
debug("nand: selected OMAP_ECC_HAM1_CODE_HW\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 - ecclayout->eccbytes -
BADBLOCK_MARKER_LENGTH;
bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW;
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;
}
bch_priv.type = ECC_BCH8;
/* 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 - ecclayout->eccbytes -
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;
nand->ecc.read_page = omap_read_page_bch;
/* ELM is used for ECC error detection */
elm_init();
bch_priv.type = ECC_BCH8;
/* 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 - ecclayout->eccbytes -
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;
- }
- /* check if NAND spare/OOB has enough bytes to accomodate ecclayout */
- if ((ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH) > oobsize) {
printf("nand: error: insufficient OOB bytes. require=%d\n", (
ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH));
return -EINVAL;
- }
Check this before you make any changes to the current ECC setup.
err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
mtd->writesize, mtd->oobsize);
- }
- if (err) {
printf("nand: error: could not switch ecc, reverting\n");
omap_select_ecc_scheme(nand, bch->ecc_scheme,
mtd->writesize, mtd->oobsize);
}return -EINVAL;
You won't need to "revert" here if omap_select_ecc_scheme doesn't damage anything in error cases.
-Scott