Lines Matching full:ecc
9 * Add Programmable Multibit ECC support for various AT91 SoC
30 #include "atmel_nand_ecc.h" /* Hardware ECC registers */
71 * Return number of ecc bytes per sector according to sector size and
97 /* ECC will occupy the last ecc_len bytes continuously */ in pmecc_config_ecc_layout()
225 * Programmable Multibit ECC Control (PMECC).
436 static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, in pmecc_correct_data() argument
467 err_byte = ecc[tmp]; in pmecc_correct_data()
468 ecc[tmp] ^= (1 << bit_pos); in pmecc_correct_data()
470 pos = tmp + nand_chip->ecc.layout->eccpos[0]; in pmecc_correct_data()
472 pos, bit_pos, err_byte, ecc[tmp]); in pmecc_correct_data()
483 u8 *ecc) in pmecc_correction() argument
494 eccbytes = nand_chip->ecc.bytes; in pmecc_correction()
496 if (ecc[i] != 0xff) in pmecc_correction()
517 pmecc_correct_data(mtd, buf_pos, ecc, i, in pmecc_correction()
532 int eccsize = chip->ecc.size; in atmel_nand_pmecc_read_page()
534 uint32_t *eccpos = chip->ecc.layout->eccpos; in atmel_nand_pmecc_read_page()
574 uint32_t *eccpos = chip->ecc.layout->eccpos; in atmel_nand_pmecc_write_page()
607 pmecc_readb(host->pmecc, ecc_port[i].ecc[j]); in atmel_nand_pmecc_write_page()
670 ecc_layout = nand_chip->ecc.layout; in atmel_pmecc_core_init()
683 * pmecc_choose_ecc - Get ecc requirement from ONFI parameters. If
685 * ONFI ECC parameters.
690 * @cap: store the ONFI ECC correct bits capbility
699 /* Get ECC requirement from ONFI parameters */ in pmecc_choose_ecc()
704 pr_debug("ONFI params, minimum required ECC: %d bits in %d bytes\n", in pmecc_choose_ecc()
717 /* use the most fitable ecc bits (the near bigger one ) */ in pmecc_choose_ecc()
813 nand->ecc.mode = NAND_ECC_HW; in atmel_pmecc_nand_init_params()
814 nand->ecc.calculate = NULL; in atmel_pmecc_nand_init_params()
815 nand->ecc.correct = NULL; in atmel_pmecc_nand_init_params()
816 nand->ecc.hwctl = NULL; in atmel_pmecc_nand_init_params()
827 /* Get ECC requirement of ONFI parameters. And if CONFIG_PMECC_CAP or in atmel_pmecc_nand_init_params()
832 dev_err(host->dev, "Required ECC %d bits in %d bytes not supported!\n", in atmel_pmecc_nand_init_params()
838 …dev_info(host->dev, "WARNING: Using different ecc correct bits(%d bit) from Nand ONFI ECC reqireme… in atmel_pmecc_nand_init_params()
841 …dev_info(host->dev, "WARNING: Using different ecc correct sector size (%d bytes) from Nand ONFI EC… in atmel_pmecc_nand_init_params()
883 /* ECC is calculated for the whole page (1 step) */ in atmel_pmecc_nand_init_params()
884 nand->ecc.size = mtd->writesize; in atmel_pmecc_nand_init_params()
886 /* set ECC page size and oob layout */ in atmel_pmecc_nand_init_params()
901 nand->ecc.steps = 1; in atmel_pmecc_nand_init_params()
902 nand->ecc.bytes = host->pmecc_bytes_per_sector * in atmel_pmecc_nand_init_params()
905 if (nand->ecc.bytes > MTD_MAX_ECCPOS_ENTRIES_LARGE) { in atmel_pmecc_nand_init_params()
906 dev_err(host->dev, "too large eccpos entries. max support ecc.bytes is %d\n", in atmel_pmecc_nand_init_params()
911 if (nand->ecc.bytes > mtd->oobsize - PMECC_OOB_RESERVED_BYTES) { in atmel_pmecc_nand_init_params()
912 dev_err(host->dev, "No room for ECC bytes\n"); in atmel_pmecc_nand_init_params()
917 nand->ecc.bytes); in atmel_pmecc_nand_init_params()
918 nand->ecc.layout = &atmel_pmecc_oobinfo; in atmel_pmecc_nand_init_params()
923 dev_err(host->dev, "Unsupported page size for PMECC, use Software ECC\n"); in atmel_pmecc_nand_init_params()
925 /* page size not handled by HW ECC */ in atmel_pmecc_nand_init_params()
926 /* switching back to soft ECC */ in atmel_pmecc_nand_init_params()
927 nand->ecc.mode = NAND_ECC_SOFT; in atmel_pmecc_nand_init_params()
928 nand->ecc.read_page = NULL; in atmel_pmecc_nand_init_params()
929 nand->ecc.postpad = 0; in atmel_pmecc_nand_init_params()
930 nand->ecc.prepad = 0; in atmel_pmecc_nand_init_params()
931 nand->ecc.bytes = 0; in atmel_pmecc_nand_init_params()
942 nand->ecc.read_page = atmel_nand_pmecc_read_page; in atmel_pmecc_nand_init_params()
943 nand->ecc.write_page = atmel_nand_pmecc_write_page; in atmel_pmecc_nand_init_params()
944 nand->ecc.strength = cap; in atmel_pmecc_nand_init_params()
984 * Calculate HW ECC
990 * ecc_code: buffer for ECC
997 /* get the first 2 ECC bytes */ in atmel_nand_calculate()
1003 /* get the last 2 ECC bytes */ in atmel_nand_calculate()
1013 * HW ECC read page function
1023 int eccsize = chip->ecc.size; in atmel_nand_read_page()
1024 int eccbytes = chip->ecc.bytes; in atmel_nand_read_page()
1025 uint32_t *eccpos = chip->ecc.layout->eccpos; in atmel_nand_read_page()
1034 /* move to ECC position if needed */ in atmel_nand_read_page()
1037 * because the ECC controller waits for in atmel_nand_read_page()
1046 /* the ECC controller needs to read the ECC just after the data */ in atmel_nand_read_page()
1051 stat = chip->ecc.correct(mtd, p, oob, NULL); in atmel_nand_read_page()
1068 * HW ECC Correction
1074 * read_ecc: ECC from the chip (unused)
1119 * the bit error is on the ECC itself. in atmel_nand_correct()
1121 dev_warn(host->dev, "atmel_nand : one bit error on ECC code." in atmel_nand_correct()
1143 * Enable HW ECC : unused on most chips
1151 nand->ecc.mode = NAND_ECC_HW; in atmel_hwecc_nand_init_param()
1152 nand->ecc.calculate = atmel_nand_calculate; in atmel_hwecc_nand_init_param()
1153 nand->ecc.correct = atmel_nand_correct; in atmel_hwecc_nand_init_param()
1154 nand->ecc.hwctl = atmel_nand_hwctl; in atmel_hwecc_nand_init_param()
1155 nand->ecc.read_page = atmel_nand_read_page; in atmel_hwecc_nand_init_param()
1156 nand->ecc.bytes = 4; in atmel_hwecc_nand_init_param()
1157 nand->ecc.strength = 4; in atmel_hwecc_nand_init_param()
1159 if (nand->ecc.mode == NAND_ECC_HW) { in atmel_hwecc_nand_init_param()
1160 /* ECC is calculated for the whole page (1 step) */ in atmel_hwecc_nand_init_param()
1161 nand->ecc.size = mtd->writesize; in atmel_hwecc_nand_init_param()
1163 /* set ECC page size and oob layout */ in atmel_hwecc_nand_init_param()
1166 nand->ecc.layout = &atmel_oobinfo_small; in atmel_hwecc_nand_init_param()
1171 nand->ecc.layout = &atmel_oobinfo_large; in atmel_hwecc_nand_init_param()
1176 nand->ecc.layout = &atmel_oobinfo_large; in atmel_hwecc_nand_init_param()
1181 nand->ecc.layout = &atmel_oobinfo_large; in atmel_hwecc_nand_init_param()
1186 /* page size not handled by HW ECC */ in atmel_hwecc_nand_init_param()
1187 /* switching back to soft ECC */ in atmel_hwecc_nand_init_param()
1188 nand->ecc.mode = NAND_ECC_SOFT; in atmel_hwecc_nand_init_param()
1189 nand->ecc.calculate = NULL; in atmel_hwecc_nand_init_param()
1190 nand->ecc.correct = NULL; in atmel_hwecc_nand_init_param()
1191 nand->ecc.hwctl = NULL; in atmel_hwecc_nand_init_param()
1192 nand->ecc.read_page = NULL; in atmel_hwecc_nand_init_param()
1193 nand->ecc.postpad = 0; in atmel_hwecc_nand_init_param()
1194 nand->ecc.prepad = 0; in atmel_hwecc_nand_init_param()
1195 nand->ecc.bytes = 0; in atmel_hwecc_nand_init_param()
1320 if (this->ecc.mode != NAND_ECC_SOFT) in nand_read_page()
1321 this->ecc.hwctl(mtd, NAND_ECC_READ); in nand_read_page()
1323 this->ecc.calculate(mtd, p, &ecc_calc[i]); in nand_read_page()
1334 this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); in nand_read_page()
1394 nand->ecc.mode = NAND_ECC_SOFT; in board_nand_init()
1431 if (nand_chip.ecc.mode == NAND_ECC_SOFT) { in nand_init()
1432 nand_chip.ecc.calculate = nand_calculate_ecc; in nand_init()
1433 nand_chip.ecc.correct = nand_correct_data; in nand_init()
1466 nand->ecc.mode = NAND_ECC_SOFT_BCH; in atmel_nand_chip_init()
1468 nand->ecc.mode = NAND_ECC_SOFT; in atmel_nand_chip_init()