+
+ case OMAP_ECC_HAM1_CODE_HW:
+ debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ bch_priv.control = NULL;
+ bch_priv.type = 0;
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 1;
+ nand->ecc.size = SECTOR_BYTES;
+ 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 * eccsteps;
+ for (i = 0; i < ecclayout->eccbytes; i++) {
+ if (nand->options & NAND_BUSWIDTH_16)
+ ecclayout->eccpos[i] = i + 2;
+ else
+ ecclayout->eccpos[i] = i + 1;
+ }
+ 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;
+
+ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+#ifdef CONFIG_BCH
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* check if BCH S/W library can be 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;
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 13;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data_bch_sw;
+ nand->ecc.calculate = omap_calculate_ecc;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
+ for (i = 1; i < ecclayout->eccbytes; i++) {
+ if (i % nand->ecc.bytes)
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 1;
+ else
+ ecclayout->eccpos[i] =
+ ecclayout->eccpos[i - 1] + 2;
+ }
+ 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_DETECTION_SW;
+ break;
+#else
+ printf("nand: error: CONFIG_BCH required for ECC\n");
+ return -EINVAL;
+#endif
+
+ case OMAP_ECC_BCH8_CODE_HW:
+#ifdef CONFIG_NAND_OMAP_ELM
+ debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
+ /* check ecc-scheme requirements before updating ecc info */
+ if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+ printf("nand: error: insufficient OOB: require=%d\n", (
+ (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+ return -EINVAL;
+ }
+ /* intialize ELM for ECC error detection */
+ elm_init();
+ bch_priv.type = ECC_BCH8;
+ /* populate ecc specific fields */
+ memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.strength = 8;
+ nand->ecc.size = SECTOR_BYTES;
+ nand->ecc.bytes = 14;
+ nand->ecc.hwctl = omap_enable_hwecc;
+ nand->ecc.correct = omap_correct_data_bch;
+ nand->ecc.calculate = omap_calculate_ecc;
+ nand->ecc.read_page = omap_read_page_bch;
+ /* define ecc-layout */
+ ecclayout->eccbytes = nand->ecc.bytes * eccsteps;
+ 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;