Lines Matching full:ecc
122 /* GPMC ecc engine settings for read */
129 /* GPMC ecc engine settings for write */
170 /* fields specific for BCHx_HW ECC scheme */
718 * gen_true_ecc - This function will generate true ECC value
719 * @ecc_buf: buffer to store ecc code
721 * This generated true ECC value can be used when correcting
739 * @ecc_data1: ecc code from nand spare area
740 * @ecc_data2: ecc code from hardware register obtained from hardware ecc
743 * This function compares two ECC's and indicates if there is an error.
819 * ECC values are equal in omap_compare_ecc()
825 pr_debug("ECC UNCORRECTED_ERROR 1\n"); in omap_compare_ecc()
830 pr_debug("ECC UNCORRECTED_ERROR B\n"); in omap_compare_ecc()
847 pr_debug("Correcting single bit ECC error at offset: " in omap_compare_ecc()
866 * omap_correct_data - Compares the ECC read with HW generated ECC
869 * @read_ecc: ecc read from nand flash
870 * @calc_ecc: ecc read from HW ECC registers
872 * Compares the ecc read from nand spare area with ECC registers values
873 * and if ECC's mismatched, it will call 'omap_compare_ecc' for error
887 if ((info->nand.ecc.mode == NAND_ECC_HW) && in omap_correct_data()
888 (info->nand.ecc.size == 2048)) in omap_correct_data()
909 * omap_calcuate_ecc - Generate non-inverted ECC bytes.
911 * @dat: The pointer to data on which ecc is computed
914 * Using noninverted ECC can be considered ugly since writing a blank
915 * page ie. padding will clear the ECC bytes. This is no problem as long
917 * an erased page will produce an ECC mismatch between generated and read
918 * ECC bytes that has to be dealt with separately.
930 /* read ecc result */ in omap_calculate_ecc()
941 * omap_enable_hwecc - This function enables the hardware ecc functionality
951 /* clear ecc and enable bits */ in omap_enable_hwecc()
955 /* program ecc and result sizes */ in omap_enable_hwecc()
956 val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) | in omap_enable_hwecc()
974 /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ in omap_enable_hwecc()
1024 * omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation
1044 /* GPMC configurations for calculating ECC */ in omap_enable_hwecc_bch()
1055 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
1075 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
1088 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
1091 ecc_size0 = 52; /* ECC bits in nibbles per sector */ in omap_enable_hwecc_bch()
1092 ecc_size1 = 0; /* non-ECC bits in nibbles per sector */ in omap_enable_hwecc_bch()
1105 /* Configure ecc size for BCH */ in omap_enable_hwecc_bch()
1117 (info->gpmc_cs << 1) | /* ECC CS */ in omap_enable_hwecc_bch()
1118 (0x1)); /* enable ECC */ in omap_enable_hwecc_bch()
1122 /* Clear ecc and enable bits */ in omap_enable_hwecc_bch()
1131 * _omap_calculate_ecc_bch - Generate ECC bytes for one sector
1133 * @dat: The pointer to data on which ecc is computed
1137 * Support calculating of BCH4/8/16 ECC vectors for one sector
1144 int eccbytes = info->nand.ecc.bytes; in _omap_calculate_ecc_bch()
1225 /* ECC scheme specific syndrome customizations */ in _omap_calculate_ecc_bch()
1229 * ECC of blank pages results in 0x0 on reading back in _omap_calculate_ecc_bch()
1235 /* Set 8th ECC byte as 0x0 for ROM compatibility */ in _omap_calculate_ecc_bch()
1240 * ECC of blank pages results in 0x0 on reading back in _omap_calculate_ecc_bch()
1246 /* Set 14th ECC byte as 0x0 for ROM compatibility */ in _omap_calculate_ecc_bch()
1259 * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction
1261 * @dat: The pointer to data on which ecc is computed
1264 * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
1265 * when SW based correction is required as ECC is required for one sector
1275 * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
1277 * @dat: The pointer to data on which ecc is computed
1280 * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
1286 int eccbytes = info->nand.ecc.bytes; in omap_calculate_ecc_bch_multi()
1317 for (i = 0; i < info->nand.ecc.size; i++) { in erased_sector_bitflips()
1319 if (flip_bits > info->nand.ecc.strength) in erased_sector_bitflips()
1323 for (i = 0; i < info->nand.ecc.bytes - 1; i++) { in erased_sector_bitflips()
1325 if (flip_bits > info->nand.ecc.strength) in erased_sector_bitflips()
1334 memset(data, 0xFF, info->nand.ecc.size); in erased_sector_bitflips()
1335 memset(oob, 0xFF, info->nand.ecc.bytes); in erased_sector_bitflips()
1345 * @read_ecc: ecc read from nand flash
1346 * @calc_ecc: ecc read from HW ECC registers
1348 * Calculated ecc vector reported as zero in case of non-error pages.
1349 * In case of non-zero ecc vector, first filter out erased-pages, and
1356 struct nand_ecc_ctrl *ecc = &info->nand.ecc; in omap_elm_correct_data() local
1357 int eccsteps = info->nand.ecc.steps; in omap_elm_correct_data()
1372 /* omit 7th ECC byte reserved for ROM code compatibility */ in omap_elm_correct_data()
1373 actual_eccbytes = ecc->bytes - 1; in omap_elm_correct_data()
1377 /* omit 14th ECC byte reserved for ROM code compatibility */ in omap_elm_correct_data()
1378 actual_eccbytes = ecc->bytes - 1; in omap_elm_correct_data()
1382 actual_eccbytes = ecc->bytes; in omap_elm_correct_data()
1398 * In case of error, non zero ecc reported. in omap_elm_correct_data()
1402 eccflag = 1; /* non zero ecc, error present */ in omap_elm_correct_data()
1411 * calc_ecc[] matches pattern for ECC(all 0xff) in omap_elm_correct_data()
1415 buf = &data[info->nand.ecc.size * i]; in omap_elm_correct_data()
1425 * number of 0-bits within ECC limits in omap_elm_correct_data()
1442 /* Update the ecc vector */ in omap_elm_correct_data()
1443 calc_ecc += ecc->bytes; in omap_elm_correct_data()
1444 read_ecc += ecc->bytes; in omap_elm_correct_data()
1475 error_max = (ecc->size + actual_eccbytes) * 8; in omap_elm_correct_data()
1507 data += ecc->size; in omap_elm_correct_data()
1508 spare_ecc += ecc->bytes; in omap_elm_correct_data()
1515 * omap_write_page_bch - BCH ecc based write page function for entire page
1528 uint8_t *ecc_calc = chip->ecc.calc_buf; in omap_write_page_bch()
1532 /* Enable GPMC ecc engine */ in omap_write_page_bch()
1533 chip->ecc.hwctl(chip, NAND_ECC_WRITE); in omap_write_page_bch()
1538 /* Update ecc vector from GPMC result registers */ in omap_write_page_bch()
1542 chip->ecc.total); in omap_write_page_bch()
1546 /* Write ecc vector to OOB area */ in omap_write_page_bch()
1553 * omap_write_subpage_bch - BCH hardware ECC based subpage write
1568 u8 *ecc_calc = chip->ecc.calc_buf; in omap_write_subpage_bch()
1569 int ecc_size = chip->ecc.size; in omap_write_subpage_bch()
1570 int ecc_bytes = chip->ecc.bytes; in omap_write_subpage_bch()
1571 int ecc_steps = chip->ecc.steps; in omap_write_subpage_bch()
1578 * as ECC is calculated by hardware. in omap_write_subpage_bch()
1579 * ECC is calculated for all subpages but we choose in omap_write_subpage_bch()
1584 /* Enable GPMC ECC engine */ in omap_write_subpage_bch()
1585 chip->ecc.hwctl(chip, NAND_ECC_WRITE); in omap_write_subpage_bch()
1591 /* mask ECC of un-touched subpages by padding 0xFF */ in omap_write_subpage_bch()
1604 /* copy calculated ECC for whole page to chip->buffer->oob */ in omap_write_subpage_bch()
1606 ecc_calc = chip->ecc.calc_buf; in omap_write_subpage_bch()
1608 chip->ecc.total); in omap_write_subpage_bch()
1619 * omap_read_page_bch - BCH ecc based page read function for entire page
1625 * For BCH ecc scheme, GPMC used for syndrome calculation and ELM module
1629 * ecc engine enabled. ecc vector updated after read of OOB data.
1630 * For non error pages ecc vector reported as zero.
1636 uint8_t *ecc_calc = chip->ecc.calc_buf; in omap_read_page_bch()
1637 uint8_t *ecc_code = chip->ecc.code_buf; in omap_read_page_bch()
1643 /* Enable GPMC ecc engine */ in omap_read_page_bch()
1644 chip->ecc.hwctl(chip, NAND_ECC_READ); in omap_read_page_bch()
1653 chip->ecc.total, false); in omap_read_page_bch()
1655 /* Calculate ecc bytes */ in omap_read_page_bch()
1659 chip->ecc.total); in omap_read_page_bch()
1663 stat = chip->ecc.correct(chip, buf, ecc_code, ecc_calc); in omap_read_page_bch()
1772 /* select ecc-scheme for NAND */ in omap_get_dt_info()
1773 if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { in omap_get_dt_info()
1774 dev_err(dev, "ti,nand-ecc-opt not found\n"); in omap_get_dt_info()
1796 dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n"); in omap_get_dt_info()
1831 oobregion->length = chip->ecc.total; in omap_ooblayout_ecc()
1850 off += chip->ecc.total; in omap_ooblayout_free()
1861 .ecc = omap_ooblayout_ecc,
1871 if (section >= chip->ecc.steps) in omap_sw_ooblayout_ecc()
1876 * reserved after each ECC step. in omap_sw_ooblayout_ecc()
1878 oobregion->offset = off + (section * (chip->ecc.bytes + 1)); in omap_sw_ooblayout_ecc()
1879 oobregion->length = chip->ecc.bytes; in omap_sw_ooblayout_ecc()
1895 * reserved after each ECC step. in omap_sw_ooblayout_free()
1897 off += ((chip->ecc.bytes + 1) * chip->ecc.steps); in omap_sw_ooblayout_free()
1908 .ecc = omap_sw_ooblayout_ecc,
2017 chip->ecc.mode = NAND_ECC_SOFT; in omap_nand_attach_chip()
2018 chip->ecc.algo = NAND_ECC_HAMMING; in omap_nand_attach_chip()
2022 /* Populate MTD interface based on ECC scheme */ in omap_nand_attach_chip()
2026 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2027 chip->ecc.bytes = 3; in omap_nand_attach_chip()
2028 chip->ecc.size = 512; in omap_nand_attach_chip()
2029 chip->ecc.strength = 1; in omap_nand_attach_chip()
2030 chip->ecc.calculate = omap_calculate_ecc; in omap_nand_attach_chip()
2031 chip->ecc.hwctl = omap_enable_hwecc; in omap_nand_attach_chip()
2032 chip->ecc.correct = omap_correct_data; in omap_nand_attach_chip()
2034 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2043 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2044 chip->ecc.size = 512; in omap_nand_attach_chip()
2045 chip->ecc.bytes = 7; in omap_nand_attach_chip()
2046 chip->ecc.strength = 4; in omap_nand_attach_chip()
2047 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2048 chip->ecc.correct = nand_bch_correct_data; in omap_nand_attach_chip()
2049 chip->ecc.calculate = omap_calculate_ecc_bch_sw; in omap_nand_attach_chip()
2052 oobbytes_per_step = chip->ecc.bytes + 1; in omap_nand_attach_chip()
2054 chip->ecc.priv = nand_bch_init(mtd); in omap_nand_attach_chip()
2055 if (!chip->ecc.priv) { in omap_nand_attach_chip()
2062 pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
2063 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2064 chip->ecc.size = 512; in omap_nand_attach_chip()
2066 chip->ecc.bytes = 7 + 1; in omap_nand_attach_chip()
2067 chip->ecc.strength = 4; in omap_nand_attach_chip()
2068 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2069 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
2070 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
2071 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
2072 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
2074 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2077 mtd->writesize / chip->ecc.size, in omap_nand_attach_chip()
2078 chip->ecc.size, chip->ecc.bytes); in omap_nand_attach_chip()
2085 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2086 chip->ecc.size = 512; in omap_nand_attach_chip()
2087 chip->ecc.bytes = 13; in omap_nand_attach_chip()
2088 chip->ecc.strength = 8; in omap_nand_attach_chip()
2089 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2090 chip->ecc.correct = nand_bch_correct_data; in omap_nand_attach_chip()
2091 chip->ecc.calculate = omap_calculate_ecc_bch_sw; in omap_nand_attach_chip()
2094 oobbytes_per_step = chip->ecc.bytes + 1; in omap_nand_attach_chip()
2096 chip->ecc.priv = nand_bch_init(mtd); in omap_nand_attach_chip()
2097 if (!chip->ecc.priv) { in omap_nand_attach_chip()
2104 pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
2105 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2106 chip->ecc.size = 512; in omap_nand_attach_chip()
2108 chip->ecc.bytes = 13 + 1; in omap_nand_attach_chip()
2109 chip->ecc.strength = 8; in omap_nand_attach_chip()
2110 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2111 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
2112 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
2113 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
2114 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
2116 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2119 mtd->writesize / chip->ecc.size, in omap_nand_attach_chip()
2120 chip->ecc.size, chip->ecc.bytes); in omap_nand_attach_chip()
2127 pr_info("Using OMAP_ECC_BCH16_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
2128 chip->ecc.mode = NAND_ECC_HW; in omap_nand_attach_chip()
2129 chip->ecc.size = 512; in omap_nand_attach_chip()
2130 chip->ecc.bytes = 26; in omap_nand_attach_chip()
2131 chip->ecc.strength = 16; in omap_nand_attach_chip()
2132 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2133 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
2134 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
2135 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
2136 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
2138 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2141 mtd->writesize / chip->ecc.size, in omap_nand_attach_chip()
2142 chip->ecc.size, chip->ecc.bytes); in omap_nand_attach_chip()
2148 dev_err(dev, "Invalid or unsupported ECC scheme\n"); in omap_nand_attach_chip()
2152 /* Check if NAND device's OOB is enough to store ECC signatures */ in omap_nand_attach_chip()
2154 (mtd->writesize / chip->ecc.size)); in omap_nand_attach_chip()
2169 /* Shared among all NAND instances to synchronize access to the ECC Engine */
2202 nand_chip->ecc.priv = NULL; in omap_nand_probe()
2278 if (nand_chip->ecc.priv) { in omap_nand_probe()
2279 nand_bch_free(nand_chip->ecc.priv); in omap_nand_probe()
2280 nand_chip->ecc.priv = NULL; in omap_nand_probe()
2290 if (nand_chip->ecc.priv) { in omap_nand_remove()
2291 nand_bch_free(nand_chip->ecc.priv); in omap_nand_remove()
2292 nand_chip->ecc.priv = NULL; in omap_nand_remove()