Lines Matching +full:ecc +full:- +full:size

1 // SPDX-License-Identifier: GPL-2.0-only
10 #include <linux/dma-mapping.h>
18 #include <linux/mtd/nand-ecc-sw-bch.h>
21 #include <linux/omap-dma.h>
29 #include <linux/omap-gpmc.h>
30 #include <linux/platform_data/mtd-nand-omap2.h>
32 #define DRIVER_NAME "omap2-nand"
122 /* GPMC ecc engine settings for read */
129 /* GPMC ecc engine settings for write */
170 /* fields specific for BCHx_HW ECC scheme */
198 * omap_prefetch_enable - configures and starts prefetch transfer
212 return -1; in omap_prefetch_enable()
214 if (readl(info->reg.gpmc_prefetch_control)) in omap_prefetch_enable()
215 return -EBUSY; in omap_prefetch_enable()
218 writel(u32_count, info->reg.gpmc_prefetch_config2); in omap_prefetch_enable()
226 writel(val, info->reg.gpmc_prefetch_config1); in omap_prefetch_enable()
229 writel(0x1, info->reg.gpmc_prefetch_control); in omap_prefetch_enable()
235 * omap_prefetch_reset - disables and stops the prefetch engine
242 config1 = readl(info->reg.gpmc_prefetch_config1); in omap_prefetch_reset()
244 return -EINVAL; in omap_prefetch_reset()
247 writel(0x0, info->reg.gpmc_prefetch_control); in omap_prefetch_reset()
250 writel(0x0, info->reg.gpmc_prefetch_config1); in omap_prefetch_reset()
256 * omap_nand_data_in_pref - NAND data in using prefetch engine
272 /* read 32-bit words using prefetch and remaining bytes normally */ in omap_nand_data_in_pref()
275 pref_len = len - (len & 3); in omap_nand_data_in_pref()
276 ret = omap_prefetch_enable(info->gpmc_cs, in omap_nand_data_in_pref()
283 r_count = readl(info->reg.gpmc_prefetch_status); in omap_nand_data_in_pref()
286 ioread32_rep(info->fifo, p, r_count); in omap_nand_data_in_pref()
288 pref_len -= r_count << 2; in omap_nand_data_in_pref()
291 omap_prefetch_reset(info->gpmc_cs, info); in omap_nand_data_in_pref()
299 * omap_nand_data_out_pref - NAND data out using Write Posting engine
319 writeb(*(u8 *)buf, info->fifo); in omap_nand_data_out_pref()
321 len--; in omap_nand_data_out_pref()
325 ret = omap_prefetch_enable(info->gpmc_cs, in omap_nand_data_out_pref()
332 w_count = readl(info->reg.gpmc_prefetch_status); in omap_nand_data_out_pref()
335 for (i = 0; (i < w_count) && len; i++, len -= 2) in omap_nand_data_out_pref()
336 iowrite16(*p++, info->fifo); in omap_nand_data_out_pref()
338 /* wait for data to flushed-out before reset the prefetch */ in omap_nand_data_out_pref()
344 val = readl(info->reg.gpmc_prefetch_status); in omap_nand_data_out_pref()
349 omap_prefetch_reset(info->gpmc_cs, info); in omap_nand_data_out_pref()
387 n = dma_map_sg(info->dma->device->dev, &sg, 1, dir); in omap_nand_dma_transfer()
389 dev_err(&info->pdev->dev, in omap_nand_dma_transfer()
394 tx = dmaengine_prep_slave_sg(info->dma, &sg, n, in omap_nand_dma_transfer()
400 tx->callback = omap_nand_dma_callback; in omap_nand_dma_transfer()
401 tx->callback_param = &info->comp; in omap_nand_dma_transfer()
404 init_completion(&info->comp); in omap_nand_dma_transfer()
407 dma_async_issue_pending(info->dma); in omap_nand_dma_transfer()
410 ret = omap_prefetch_enable(info->gpmc_cs, in omap_nand_dma_transfer()
416 wait_for_completion(&info->comp); in omap_nand_dma_transfer()
422 val = readl(info->reg.gpmc_prefetch_status); in omap_nand_dma_transfer()
427 omap_prefetch_reset(info->gpmc_cs, info); in omap_nand_dma_transfer()
429 dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); in omap_nand_dma_transfer()
433 dma_unmap_sg(info->dma->device->dev, &sg, 1, dir); in omap_nand_dma_transfer()
442 * omap_nand_data_in_dma_pref - NAND data in using DMA and Prefetch
454 if (len <= mtd->oobsize) in omap_nand_data_in_dma_pref()
462 * omap_nand_data_out_dma_pref - NAND data out using DMA and write posting
475 if (len <= mtd->oobsize) in omap_nand_data_out_dma_pref()
483 * omap_nand_irq - GPMC irq handler
492 bytes = readl(info->reg.gpmc_prefetch_status); in omap_nand_irq()
495 if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ in omap_nand_irq()
496 if (this_irq == info->gpmc_irq_count) in omap_nand_irq()
499 if (info->buf_len && (info->buf_len < bytes)) in omap_nand_irq()
500 bytes = info->buf_len; in omap_nand_irq()
501 else if (!info->buf_len) in omap_nand_irq()
503 iowrite32_rep(info->fifo, (u32 *)info->buf, in omap_nand_irq()
505 info->buf = info->buf + bytes; in omap_nand_irq()
506 info->buf_len -= bytes; in omap_nand_irq()
509 ioread32_rep(info->fifo, (u32 *)info->buf, in omap_nand_irq()
511 info->buf = info->buf + bytes; in omap_nand_irq()
513 if (this_irq == info->gpmc_irq_count) in omap_nand_irq()
520 complete(&info->comp); in omap_nand_irq()
522 disable_irq_nosync(info->gpmc_irq_fifo); in omap_nand_irq()
523 disable_irq_nosync(info->gpmc_irq_count); in omap_nand_irq()
529 * omap_nand_data_in_irq_pref - NAND data in using Prefetch and IRQ
535 struct mtd_info *mtd = nand_to_mtd(&info->nand); in omap_nand_data_in_irq_pref()
538 if (len <= mtd->oobsize || force_8bit) { in omap_nand_data_in_irq_pref()
543 info->iomode = OMAP_NAND_IO_READ; in omap_nand_data_in_irq_pref()
544 info->buf = buf; in omap_nand_data_in_irq_pref()
545 init_completion(&info->comp); in omap_nand_data_in_irq_pref()
548 ret = omap_prefetch_enable(info->gpmc_cs, in omap_nand_data_in_irq_pref()
556 info->buf_len = len; in omap_nand_data_in_irq_pref()
558 enable_irq(info->gpmc_irq_count); in omap_nand_data_in_irq_pref()
559 enable_irq(info->gpmc_irq_fifo); in omap_nand_data_in_irq_pref()
562 wait_for_completion(&info->comp); in omap_nand_data_in_irq_pref()
565 omap_prefetch_reset(info->gpmc_cs, info); in omap_nand_data_in_irq_pref()
570 * omap_nand_data_out_irq_pref - NAND out using write posting and IRQ
577 struct mtd_info *mtd = nand_to_mtd(&info->nand); in omap_nand_data_out_irq_pref()
582 if (len <= mtd->oobsize || force_8bit) { in omap_nand_data_out_irq_pref()
587 info->iomode = OMAP_NAND_IO_WRITE; in omap_nand_data_out_irq_pref()
588 info->buf = (u_char *) buf; in omap_nand_data_out_irq_pref()
589 init_completion(&info->comp); in omap_nand_data_out_irq_pref()
591 /* configure and start prefetch transfer : size=24 */ in omap_nand_data_out_irq_pref()
592 ret = omap_prefetch_enable(info->gpmc_cs, in omap_nand_data_out_irq_pref()
600 info->buf_len = len; in omap_nand_data_out_irq_pref()
602 enable_irq(info->gpmc_irq_count); in omap_nand_data_out_irq_pref()
603 enable_irq(info->gpmc_irq_fifo); in omap_nand_data_out_irq_pref()
606 wait_for_completion(&info->comp); in omap_nand_data_out_irq_pref()
608 /* wait for data to flushed-out before reset the prefetch */ in omap_nand_data_out_irq_pref()
612 val = readl(info->reg.gpmc_prefetch_status); in omap_nand_data_out_irq_pref()
618 omap_prefetch_reset(info->gpmc_cs, info); in omap_nand_data_out_irq_pref()
623 * gen_true_ecc - This function will generate true ECC value
624 * @ecc_buf: buffer to store ecc code
626 * This generated true ECC value can be used when correcting
643 * omap_compare_ecc - Detect (2 bits) and correct (1 bit) error in data
644 * @ecc_data1: ecc code from nand spare area
645 * @ecc_data2: ecc code from hardware register obtained from hardware ecc
648 * This function compares two ECC's and indicates if there is an error.
651 * was corrected, %1 is returned. Otherwise, %-1 is returned.
724 * ECC values are equal in omap_compare_ecc()
730 pr_debug("ECC UNCORRECTED_ERROR 1\n"); in omap_compare_ecc()
731 return -EBADMSG; in omap_compare_ecc()
734 /* UN-Correctable error */ in omap_compare_ecc()
735 pr_debug("ECC UNCORRECTED_ERROR B\n"); in omap_compare_ecc()
736 return -EBADMSG; in omap_compare_ecc()
752 pr_debug("Correcting single bit ECC error at offset: " in omap_compare_ecc()
766 return -EBADMSG; in omap_compare_ecc()
771 * omap_correct_data - Compares the ECC read with HW generated ECC
774 * @read_ecc: ecc read from nand flash
775 * @calc_ecc: ecc read from HW ECC registers
777 * Compares the ecc read from nand spare area with ECC registers values
778 * and if ECC's mismatched, it will call 'omap_compare_ecc' for error
781 * corrected errors is returned. If uncorrectable errors exist, %-1 is
792 if (info->nand.ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST && in omap_correct_data()
793 info->nand.ecc.size == 2048) in omap_correct_data()
814 * omap_calculate_ecc - Generate non-inverted ECC bytes.
816 * @dat: The pointer to data on which ecc is computed
819 * Using noninverted ECC can be considered ugly since writing a blank
820 * page ie. padding will clear the ECC bytes. This is no problem as long
822 * an erased page will produce an ECC mismatch between generated and read
823 * ECC bytes that has to be dealt with separately.
831 val = readl(info->reg.gpmc_ecc_config); in omap_calculate_ecc()
832 if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs) in omap_calculate_ecc()
833 return -EINVAL; in omap_calculate_ecc()
835 /* read ecc result */ in omap_calculate_ecc()
836 val = readl(info->reg.gpmc_ecc1_result); in omap_calculate_ecc()
846 * omap_enable_hwecc - This function enables the hardware ecc functionality
853 unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; in omap_enable_hwecc()
856 /* clear ecc and enable bits */ in omap_enable_hwecc()
858 writel(val, info->reg.gpmc_ecc_control); in omap_enable_hwecc()
860 /* program ecc and result sizes */ in omap_enable_hwecc()
861 val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) | in omap_enable_hwecc()
863 writel(val, info->reg.gpmc_ecc_size_config); in omap_enable_hwecc()
868 writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); in omap_enable_hwecc()
871 writel(ECCCLEAR, info->reg.gpmc_ecc_control); in omap_enable_hwecc()
874 dev_info(&info->pdev->dev, in omap_enable_hwecc()
879 /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ in omap_enable_hwecc()
880 val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); in omap_enable_hwecc()
881 writel(val, info->reg.gpmc_ecc_config); in omap_enable_hwecc()
885 * omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation
889 * When using BCH with SW correction (i.e. no ELM), sector size is set
901 enum omap_ecc ecc_opt = info->ecc_opt; in omap_enable_hwecc_bch()
905 /* GPMC configurations for calculating ECC */ in omap_enable_hwecc_bch()
916 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
936 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
949 nsectors = chip->ecc.steps; in omap_enable_hwecc_bch()
952 ecc_size0 = 52; /* ECC bits in nibbles per sector */ in omap_enable_hwecc_bch()
953 ecc_size1 = 0; /* non-ECC bits in nibbles per sector */ in omap_enable_hwecc_bch()
964 writel(ECC1, info->reg.gpmc_ecc_control); in omap_enable_hwecc_bch()
966 /* Configure ecc size for BCH */ in omap_enable_hwecc_bch()
968 writel(val, info->reg.gpmc_ecc_size_config); in omap_enable_hwecc_bch()
970 dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; in omap_enable_hwecc_bch()
977 (((nsectors-1) & 0x7) << 4) | /* number of sectors */ in omap_enable_hwecc_bch()
978 (info->gpmc_cs << 1) | /* ECC CS */ in omap_enable_hwecc_bch()
979 (0x1)); /* enable ECC */ in omap_enable_hwecc_bch()
981 writel(val, info->reg.gpmc_ecc_config); in omap_enable_hwecc_bch()
983 /* Clear ecc and enable bits */ in omap_enable_hwecc_bch()
984 writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); in omap_enable_hwecc_bch()
992 * _omap_calculate_ecc_bch - Generate ECC bytes for one sector
994 * @dat: The pointer to data on which ecc is computed
998 * Support calculating of BCH4/8/16 ECC vectors for one sector
1005 int eccbytes = info->nand.ecc.bytes; in _omap_calculate_ecc_bch()
1006 struct gpmc_nand_regs *gpmc_regs = &info->reg; in _omap_calculate_ecc_bch()
1013 switch (info->ecc_opt) { in _omap_calculate_ecc_bch()
1016 bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); in _omap_calculate_ecc_bch()
1017 bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); in _omap_calculate_ecc_bch()
1018 bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); in _omap_calculate_ecc_bch()
1019 bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); in _omap_calculate_ecc_bch()
1036 bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); in _omap_calculate_ecc_bch()
1037 bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); in _omap_calculate_ecc_bch()
1048 val = readl(gpmc_regs->gpmc_bch_result6[i]); in _omap_calculate_ecc_bch()
1051 val = readl(gpmc_regs->gpmc_bch_result5[i]); in _omap_calculate_ecc_bch()
1056 val = readl(gpmc_regs->gpmc_bch_result4[i]); in _omap_calculate_ecc_bch()
1061 val = readl(gpmc_regs->gpmc_bch_result3[i]); in _omap_calculate_ecc_bch()
1066 val = readl(gpmc_regs->gpmc_bch_result2[i]); in _omap_calculate_ecc_bch()
1071 val = readl(gpmc_regs->gpmc_bch_result1[i]); in _omap_calculate_ecc_bch()
1076 val = readl(gpmc_regs->gpmc_bch_result0[i]); in _omap_calculate_ecc_bch()
1083 return -EINVAL; in _omap_calculate_ecc_bch()
1086 /* ECC scheme specific syndrome customizations */ in _omap_calculate_ecc_bch()
1087 switch (info->ecc_opt) { in _omap_calculate_ecc_bch()
1090 * ECC of blank pages results in 0x0 on reading back in _omap_calculate_ecc_bch()
1096 /* Set 8th ECC byte as 0x0 for ROM compatibility */ in _omap_calculate_ecc_bch()
1097 ecc_calc[eccbytes - 1] = 0x0; in _omap_calculate_ecc_bch()
1101 * ECC of blank pages results in 0x0 on reading back in _omap_calculate_ecc_bch()
1107 /* Set 14th ECC byte as 0x0 for ROM compatibility */ in _omap_calculate_ecc_bch()
1108 ecc_calc[eccbytes - 1] = 0x0; in _omap_calculate_ecc_bch()
1113 return -EINVAL; in _omap_calculate_ecc_bch()
1120 * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction
1122 * @dat: The pointer to data on which ecc is computed
1123 * @ecc_calc: Buffer storing the calculated ECC bytes
1125 * Support calculating of BCH4/8/16 ECC vectors for one sector. This is used
1126 * when SW based correction is required as ECC is required for one sector
1136 * omap_calculate_ecc_bch_multi - Generate ECC for multiple sectors
1138 * @dat: The pointer to data on which ecc is computed
1139 * @ecc_calc: Buffer storing the calculated ECC bytes
1141 * Support calculating of BCH4/8/16 ecc vectors for the entire page in one go.
1147 int eccbytes = info->nand.ecc.bytes; in omap_calculate_ecc_bch_multi()
1151 nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; in omap_calculate_ecc_bch_multi()
1164 * erased_sector_bitflips - count bit flips
1178 for (i = 0; i < info->nand.ecc.size; i++) { in erased_sector_bitflips()
1180 if (flip_bits > info->nand.ecc.strength) in erased_sector_bitflips()
1184 for (i = 0; i < info->nand.ecc.bytes - 1; i++) { in erased_sector_bitflips()
1186 if (flip_bits > info->nand.ecc.strength) in erased_sector_bitflips()
1195 memset(data, 0xFF, info->nand.ecc.size); in erased_sector_bitflips()
1196 memset(oob, 0xFF, info->nand.ecc.bytes); in erased_sector_bitflips()
1203 * omap_elm_correct_data - corrects page data area in case error reported
1206 * @read_ecc: ecc read from nand flash
1207 * @calc_ecc: ecc read from HW ECC registers
1209 * Calculated ecc vector reported as zero in case of non-error pages.
1210 * In case of non-zero ecc vector, first filter out erased-pages, and
1211 * then process data via ELM to detect bit-flips.
1217 struct nand_ecc_ctrl *ecc = &info->nand.ecc; in omap_elm_correct_data() local
1218 int eccsteps = info->nsteps_per_eccpg; in omap_elm_correct_data()
1231 switch (info->ecc_opt) { in omap_elm_correct_data()
1233 /* omit 7th ECC byte reserved for ROM code compatibility */ in omap_elm_correct_data()
1234 actual_eccbytes = ecc->bytes - 1; in omap_elm_correct_data()
1238 /* omit 14th ECC byte reserved for ROM code compatibility */ in omap_elm_correct_data()
1239 actual_eccbytes = ecc->bytes - 1; in omap_elm_correct_data()
1243 actual_eccbytes = ecc->bytes; in omap_elm_correct_data()
1247 dev_err(&info->pdev->dev, "invalid driver configuration\n"); in omap_elm_correct_data()
1248 return -EINVAL; in omap_elm_correct_data()
1259 * In case of error, non zero ecc reported. in omap_elm_correct_data()
1263 eccflag = 1; /* non zero ecc, error present */ in omap_elm_correct_data()
1272 * calc_ecc[] matches pattern for ECC(all 0xff) in omap_elm_correct_data()
1273 * so this is definitely an erased-page in omap_elm_correct_data()
1276 buf = &data[info->nand.ecc.size * i]; in omap_elm_correct_data()
1278 * count number of 0-bits in read_buf. in omap_elm_correct_data()
1286 * number of 0-bits within ECC limits in omap_elm_correct_data()
1287 * So this may be an erased-page in omap_elm_correct_data()
1292 * Too many 0-bits. It may be a in omap_elm_correct_data()
1293 * - programmed-page, OR in omap_elm_correct_data()
1294 * - erased-page with many bit-flips in omap_elm_correct_data()
1303 /* Update the ecc vector */ in omap_elm_correct_data()
1304 calc_ecc += ecc->bytes; in omap_elm_correct_data()
1305 read_ecc += ecc->bytes; in omap_elm_correct_data()
1313 elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); in omap_elm_correct_data()
1318 dev_err(&info->pdev->dev, in omap_elm_correct_data()
1319 "uncorrectable bit-flips found\n"); in omap_elm_correct_data()
1320 err = -EBADMSG; in omap_elm_correct_data()
1323 switch (info->ecc_opt) { in omap_elm_correct_data()
1334 return -EINVAL; in omap_elm_correct_data()
1336 error_max = (ecc->size + actual_eccbytes) * 8; in omap_elm_correct_data()
1341 byte_pos = (error_max - pos - 1) / 8; in omap_elm_correct_data()
1350 (byte_pos - 512), in omap_elm_correct_data()
1351 spare_ecc[byte_pos - 512]); in omap_elm_correct_data()
1352 spare_ecc[byte_pos - 512] ^= in omap_elm_correct_data()
1356 dev_err(&info->pdev->dev, in omap_elm_correct_data()
1357 "invalid bit-flip @ %d:%d\n", in omap_elm_correct_data()
1359 err = -EBADMSG; in omap_elm_correct_data()
1367 /* Update page data with sector size */ in omap_elm_correct_data()
1368 data += ecc->size; in omap_elm_correct_data()
1369 spare_ecc += ecc->bytes; in omap_elm_correct_data()
1376 * omap_write_page_bch - BCH ecc based write page function for entire page
1379 * @oob_required: must write chip->oob_poi to OOB
1389 uint8_t *ecc_calc = chip->ecc.calc_buf; in omap_write_page_bch()
1397 for (eccpg = 0; eccpg < info->neccpg; eccpg++) { in omap_write_page_bch()
1398 /* Enable GPMC ecc engine */ in omap_write_page_bch()
1399 chip->ecc.hwctl(chip, NAND_ECC_WRITE); in omap_write_page_bch()
1402 info->data_out(chip, buf + (eccpg * info->eccpg_size), in omap_write_page_bch()
1403 info->eccpg_size, false); in omap_write_page_bch()
1405 /* Update ecc vector from GPMC result registers */ in omap_write_page_bch()
1407 buf + (eccpg * info->eccpg_size), in omap_write_page_bch()
1413 chip->oob_poi, in omap_write_page_bch()
1414 eccpg * info->eccpg_bytes, in omap_write_page_bch()
1415 info->eccpg_bytes); in omap_write_page_bch()
1420 /* Write ecc vector to OOB area */ in omap_write_page_bch()
1421 info->data_out(chip, chip->oob_poi, mtd->oobsize, false); in omap_write_page_bch()
1427 * omap_write_subpage_bch - BCH hardware ECC based subpage write
1432 * @oob_required: must write chip->oob_poi to OOB
1443 u8 *ecc_calc = chip->ecc.calc_buf; in omap_write_subpage_bch()
1444 int ecc_size = chip->ecc.size; in omap_write_subpage_bch()
1445 int ecc_bytes = chip->ecc.bytes; in omap_write_subpage_bch()
1447 u32 end_step = (offset + data_len - 1) / ecc_size; in omap_write_subpage_bch()
1453 * as ECC is calculated by hardware. in omap_write_subpage_bch()
1454 * ECC is calculated for all subpages but we choose in omap_write_subpage_bch()
1461 for (eccpg = 0; eccpg < info->neccpg; eccpg++) { in omap_write_subpage_bch()
1462 /* Enable GPMC ECC engine */ in omap_write_subpage_bch()
1463 chip->ecc.hwctl(chip, NAND_ECC_WRITE); in omap_write_subpage_bch()
1466 info->data_out(chip, buf + (eccpg * info->eccpg_size), in omap_write_subpage_bch()
1467 info->eccpg_size, false); in omap_write_subpage_bch()
1469 for (step = 0; step < info->nsteps_per_eccpg; step++) { in omap_write_subpage_bch()
1470 unsigned int base_step = eccpg * info->nsteps_per_eccpg; in omap_write_subpage_bch()
1471 const u8 *bufoffs = buf + (eccpg * info->eccpg_size); in omap_write_subpage_bch()
1473 /* Mask ECC of un-touched subpages with 0xFFs */ in omap_write_subpage_bch()
1489 * Copy the calculated ECC for the whole page including the in omap_write_subpage_bch()
1492 ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, in omap_write_subpage_bch()
1493 eccpg * info->eccpg_bytes, in omap_write_subpage_bch()
1494 info->eccpg_bytes); in omap_write_subpage_bch()
1500 info->data_out(chip, chip->oob_poi, mtd->oobsize, false); in omap_write_subpage_bch()
1506 * omap_read_page_bch - BCH ecc based page read function for entire page
1509 * @oob_required: caller requires OOB data read to chip->oob_poi
1512 * For BCH ecc scheme, GPMC used for syndrome calculation and ELM module
1516 * ecc engine enabled. ecc vector updated after read of OOB data.
1517 * For non error pages ecc vector reported as zero.
1524 uint8_t *ecc_calc = chip->ecc.calc_buf; in omap_read_page_bch()
1525 uint8_t *ecc_code = chip->ecc.code_buf; in omap_read_page_bch()
1533 for (eccpg = 0; eccpg < info->neccpg; eccpg++) { in omap_read_page_bch()
1534 /* Enable GPMC ecc engine */ in omap_read_page_bch()
1535 chip->ecc.hwctl(chip, NAND_ECC_READ); in omap_read_page_bch()
1538 ret = nand_change_read_column_op(chip, eccpg * info->eccpg_size, in omap_read_page_bch()
1539 buf + (eccpg * info->eccpg_size), in omap_read_page_bch()
1540 info->eccpg_size, false); in omap_read_page_bch()
1546 mtd->writesize + BBM_LEN + in omap_read_page_bch()
1547 (eccpg * info->eccpg_bytes), in omap_read_page_bch()
1548 chip->oob_poi + BBM_LEN + in omap_read_page_bch()
1549 (eccpg * info->eccpg_bytes), in omap_read_page_bch()
1550 info->eccpg_bytes, false); in omap_read_page_bch()
1554 /* Calculate ecc bytes */ in omap_read_page_bch()
1556 buf + (eccpg * info->eccpg_size), in omap_read_page_bch()
1562 chip->oob_poi, in omap_read_page_bch()
1563 eccpg * info->eccpg_bytes, in omap_read_page_bch()
1564 info->eccpg_bytes); in omap_read_page_bch()
1568 stat = chip->ecc.correct(chip, in omap_read_page_bch()
1569 buf + (eccpg * info->eccpg_size), in omap_read_page_bch()
1572 mtd->ecc_stats.failed++; in omap_read_page_bch()
1574 mtd->ecc_stats.corrected += stat; in omap_read_page_bch()
1583 * is_elm_present - checks for presence of ELM module by scanning DT nodes
1592 /* check whether elm-id is passed via DT */ in is_elm_present()
1594 dev_err(&info->pdev->dev, "ELM devicetree node not found\n"); in is_elm_present()
1600 dev_err(&info->pdev->dev, "ELM device not found\n"); in is_elm_present()
1604 info->elm_dev = &pdev->dev; in is_elm_present()
1612 switch (info->ecc_opt) { in omap2_nand_ecc_check()
1634 dev_err(&info->pdev->dev, in omap2_nand_ecc_check()
1639 dev_err(&info->pdev->dev, in omap2_nand_ecc_check()
1643 if (ecc_needs_elm && !is_elm_present(info, info->elm_of_node)) { in omap2_nand_ecc_check()
1644 dev_err(&info->pdev->dev, "ELM not available\n"); in omap2_nand_ecc_check()
1652 [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
1654 [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma",
1655 [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq",
1660 struct device_node *child = dev->of_node; in omap_get_dt_info()
1667 return -EINVAL; in omap_get_dt_info()
1670 info->gpmc_cs = cs; in omap_get_dt_info()
1672 /* detect availability of ELM module. Won't be present pre-OMAP4 */ in omap_get_dt_info()
1673 info->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); in omap_get_dt_info()
1674 if (!info->elm_of_node) { in omap_get_dt_info()
1675 info->elm_of_node = of_parse_phandle(child, "elm_id", 0); in omap_get_dt_info()
1676 if (!info->elm_of_node) in omap_get_dt_info()
1677 dev_dbg(dev, "ti,elm-id not in DT\n"); in omap_get_dt_info()
1680 /* select ecc-scheme for NAND */ in omap_get_dt_info()
1681 if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { in omap_get_dt_info()
1682 dev_err(dev, "ti,nand-ecc-opt not found\n"); in omap_get_dt_info()
1683 return -EINVAL; in omap_get_dt_info()
1687 info->ecc_opt = OMAP_ECC_HAM1_CODE_SW; in omap_get_dt_info()
1689 !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) { in omap_get_dt_info()
1690 info->ecc_opt = OMAP_ECC_HAM1_CODE_HW; in omap_get_dt_info()
1692 if (info->elm_of_node) in omap_get_dt_info()
1693 info->ecc_opt = OMAP_ECC_BCH4_CODE_HW; in omap_get_dt_info()
1695 info->ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; in omap_get_dt_info()
1697 if (info->elm_of_node) in omap_get_dt_info()
1698 info->ecc_opt = OMAP_ECC_BCH8_CODE_HW; in omap_get_dt_info()
1700 info->ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; in omap_get_dt_info()
1702 info->ecc_opt = OMAP_ECC_BCH16_CODE_HW; in omap_get_dt_info()
1704 dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n"); in omap_get_dt_info()
1705 return -EINVAL; in omap_get_dt_info()
1709 if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) { in omap_get_dt_info()
1712 info->xfer_type = i; in omap_get_dt_info()
1717 dev_err(dev, "unrecognized value for ti,nand-xfer-type\n"); in omap_get_dt_info()
1718 return -EINVAL; in omap_get_dt_info()
1728 struct nand_chip *chip = &info->nand; in omap_ooblayout_ecc()
1731 if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && in omap_ooblayout_ecc()
1732 !(chip->options & NAND_BUSWIDTH_16)) in omap_ooblayout_ecc()
1736 return -ERANGE; in omap_ooblayout_ecc()
1738 oobregion->offset = off; in omap_ooblayout_ecc()
1739 oobregion->length = chip->ecc.total; in omap_ooblayout_ecc()
1748 struct nand_chip *chip = &info->nand; in omap_ooblayout_free()
1751 if (info->ecc_opt == OMAP_ECC_HAM1_CODE_HW && in omap_ooblayout_free()
1752 !(chip->options & NAND_BUSWIDTH_16)) in omap_ooblayout_free()
1756 return -ERANGE; in omap_ooblayout_free()
1758 off += chip->ecc.total; in omap_ooblayout_free()
1759 if (off >= mtd->oobsize) in omap_ooblayout_free()
1760 return -ERANGE; in omap_ooblayout_free()
1762 oobregion->offset = off; in omap_ooblayout_free()
1763 oobregion->length = mtd->oobsize - off; in omap_ooblayout_free()
1769 .ecc = omap_ooblayout_ecc,
1782 return -ERANGE; in omap_sw_ooblayout_ecc()
1786 * reserved after each ECC step. in omap_sw_ooblayout_ecc()
1788 oobregion->offset = off + (section * (ecc_bytes + 1)); in omap_sw_ooblayout_ecc()
1789 oobregion->length = ecc_bytes; in omap_sw_ooblayout_ecc()
1803 return -ERANGE; in omap_sw_ooblayout_free()
1807 * reserved after each ECC step. in omap_sw_ooblayout_free()
1810 if (off >= mtd->oobsize) in omap_sw_ooblayout_free()
1811 return -ERANGE; in omap_sw_ooblayout_free()
1813 oobregion->offset = off; in omap_sw_ooblayout_free()
1814 oobregion->length = mtd->oobsize - off; in omap_sw_ooblayout_free()
1820 .ecc = omap_sw_ooblayout_ecc,
1828 struct device *dev = &info->pdev->dev; in omap_nand_attach_chip()
1830 int elm_bch_strength = -1; in omap_nand_attach_chip()
1835 if (chip->bbt_options & NAND_BBT_USE_FLASH) in omap_nand_attach_chip()
1836 chip->bbt_options |= NAND_BBT_NO_OOB; in omap_nand_attach_chip()
1838 chip->options |= NAND_SKIP_BBTSCAN; in omap_nand_attach_chip()
1840 /* Re-populate low-level callbacks based on xfer modes */ in omap_nand_attach_chip()
1841 switch (info->xfer_type) { in omap_nand_attach_chip()
1843 info->data_in = omap_nand_data_in_pref; in omap_nand_attach_chip()
1844 info->data_out = omap_nand_data_out_pref; in omap_nand_attach_chip()
1854 info->dma = dma_request_chan(dev->parent, "rxtx"); in omap_nand_attach_chip()
1856 if (IS_ERR(info->dma)) { in omap_nand_attach_chip()
1858 return PTR_ERR(info->dma); in omap_nand_attach_chip()
1863 cfg.src_addr = info->phys_base; in omap_nand_attach_chip()
1864 cfg.dst_addr = info->phys_base; in omap_nand_attach_chip()
1869 err = dmaengine_slave_config(info->dma, &cfg); in omap_nand_attach_chip()
1877 info->data_in = omap_nand_data_in_dma_pref; in omap_nand_attach_chip()
1878 info->data_out = omap_nand_data_out_dma_pref; in omap_nand_attach_chip()
1883 info->gpmc_irq_fifo = platform_get_irq(info->pdev, 0); in omap_nand_attach_chip()
1884 if (info->gpmc_irq_fifo <= 0) in omap_nand_attach_chip()
1885 return -ENODEV; in omap_nand_attach_chip()
1886 err = devm_request_irq(dev, info->gpmc_irq_fifo, in omap_nand_attach_chip()
1888 "gpmc-nand-fifo", info); in omap_nand_attach_chip()
1891 info->gpmc_irq_fifo, err); in omap_nand_attach_chip()
1892 info->gpmc_irq_fifo = 0; in omap_nand_attach_chip()
1896 info->gpmc_irq_count = platform_get_irq(info->pdev, 1); in omap_nand_attach_chip()
1897 if (info->gpmc_irq_count <= 0) in omap_nand_attach_chip()
1898 return -ENODEV; in omap_nand_attach_chip()
1899 err = devm_request_irq(dev, info->gpmc_irq_count, in omap_nand_attach_chip()
1901 "gpmc-nand-count", info); in omap_nand_attach_chip()
1904 info->gpmc_irq_count, err); in omap_nand_attach_chip()
1905 info->gpmc_irq_count = 0; in omap_nand_attach_chip()
1909 info->data_in = omap_nand_data_in_irq_pref; in omap_nand_attach_chip()
1910 info->data_out = omap_nand_data_out_irq_pref; in omap_nand_attach_chip()
1914 dev_err(dev, "xfer_type %d not supported!\n", info->xfer_type); in omap_nand_attach_chip()
1915 return -EINVAL; in omap_nand_attach_chip()
1919 return -EINVAL; in omap_nand_attach_chip()
1925 if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) { in omap_nand_attach_chip()
1926 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; in omap_nand_attach_chip()
1927 chip->ecc.algo = NAND_ECC_ALGO_HAMMING; in omap_nand_attach_chip()
1931 /* Populate MTD interface based on ECC scheme */ in omap_nand_attach_chip()
1932 switch (info->ecc_opt) { in omap_nand_attach_chip()
1935 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
1936 chip->ecc.bytes = 3; in omap_nand_attach_chip()
1937 chip->ecc.size = 512; in omap_nand_attach_chip()
1938 chip->ecc.strength = 1; in omap_nand_attach_chip()
1939 chip->ecc.calculate = omap_calculate_ecc; in omap_nand_attach_chip()
1940 chip->ecc.hwctl = omap_enable_hwecc; in omap_nand_attach_chip()
1941 chip->ecc.correct = omap_correct_data; in omap_nand_attach_chip()
1943 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
1945 if (!(chip->options & NAND_BUSWIDTH_16)) in omap_nand_attach_chip()
1952 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
1953 chip->ecc.size = 512; in omap_nand_attach_chip()
1954 chip->ecc.bytes = 7; in omap_nand_attach_chip()
1955 chip->ecc.strength = 4; in omap_nand_attach_chip()
1956 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
1957 chip->ecc.correct = rawnand_sw_bch_correct; in omap_nand_attach_chip()
1958 chip->ecc.calculate = omap_calculate_ecc_bch_sw; in omap_nand_attach_chip()
1961 oobbytes_per_step = chip->ecc.bytes + 1; in omap_nand_attach_chip()
1971 pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
1972 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
1973 chip->ecc.size = 512; in omap_nand_attach_chip()
1974 /* 14th bit is kept reserved for ROM-code compatibility */ in omap_nand_attach_chip()
1975 chip->ecc.bytes = 7 + 1; in omap_nand_attach_chip()
1976 chip->ecc.strength = 4; in omap_nand_attach_chip()
1977 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
1978 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
1979 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
1980 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
1981 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
1983 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
1989 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
1990 chip->ecc.size = 512; in omap_nand_attach_chip()
1991 chip->ecc.bytes = 13; in omap_nand_attach_chip()
1992 chip->ecc.strength = 8; in omap_nand_attach_chip()
1993 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
1994 chip->ecc.correct = rawnand_sw_bch_correct; in omap_nand_attach_chip()
1995 chip->ecc.calculate = omap_calculate_ecc_bch_sw; in omap_nand_attach_chip()
1998 oobbytes_per_step = chip->ecc.bytes + 1; in omap_nand_attach_chip()
2008 pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
2009 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
2010 chip->ecc.size = 512; in omap_nand_attach_chip()
2011 /* 14th bit is kept reserved for ROM-code compatibility */ in omap_nand_attach_chip()
2012 chip->ecc.bytes = 13 + 1; in omap_nand_attach_chip()
2013 chip->ecc.strength = 8; in omap_nand_attach_chip()
2014 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2015 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
2016 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
2017 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
2018 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
2020 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2025 pr_info("Using OMAP_ECC_BCH16_CODE_HW ECC scheme\n"); in omap_nand_attach_chip()
2026 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in omap_nand_attach_chip()
2027 chip->ecc.size = 512; in omap_nand_attach_chip()
2028 chip->ecc.bytes = 26; in omap_nand_attach_chip()
2029 chip->ecc.strength = 16; in omap_nand_attach_chip()
2030 chip->ecc.hwctl = omap_enable_hwecc_bch; in omap_nand_attach_chip()
2031 chip->ecc.correct = omap_elm_correct_data; in omap_nand_attach_chip()
2032 chip->ecc.read_page = omap_read_page_bch; in omap_nand_attach_chip()
2033 chip->ecc.write_page = omap_write_page_bch; in omap_nand_attach_chip()
2034 chip->ecc.write_subpage = omap_write_subpage_bch; in omap_nand_attach_chip()
2036 oobbytes_per_step = chip->ecc.bytes; in omap_nand_attach_chip()
2040 dev_err(dev, "Invalid or unsupported ECC scheme\n"); in omap_nand_attach_chip()
2041 return -EINVAL; in omap_nand_attach_chip()
2045 chip->ecc.steps = mtd->writesize / chip->ecc.size; in omap_nand_attach_chip()
2046 info->neccpg = chip->ecc.steps / ERROR_VECTOR_MAX; in omap_nand_attach_chip()
2047 if (info->neccpg) { in omap_nand_attach_chip()
2048 info->nsteps_per_eccpg = ERROR_VECTOR_MAX; in omap_nand_attach_chip()
2050 info->neccpg = 1; in omap_nand_attach_chip()
2051 info->nsteps_per_eccpg = chip->ecc.steps; in omap_nand_attach_chip()
2053 info->eccpg_size = info->nsteps_per_eccpg * chip->ecc.size; in omap_nand_attach_chip()
2054 info->eccpg_bytes = info->nsteps_per_eccpg * chip->ecc.bytes; in omap_nand_attach_chip()
2056 err = elm_config(info->elm_dev, elm_bch_strength, in omap_nand_attach_chip()
2057 info->nsteps_per_eccpg, chip->ecc.size, in omap_nand_attach_chip()
2058 chip->ecc.bytes); in omap_nand_attach_chip()
2063 /* Check if NAND device's OOB is enough to store ECC signatures */ in omap_nand_attach_chip()
2065 (mtd->writesize / chip->ecc.size)); in omap_nand_attach_chip()
2066 if (mtd->oobsize < min_oobbytes) { in omap_nand_attach_chip()
2069 min_oobbytes, mtd->oobsize); in omap_nand_attach_chip()
2070 return -EINVAL; in omap_nand_attach_chip()
2083 ioread8_rep(info->fifo, buf, len); in omap_nand_data_in()
2085 ioread16_rep(info->fifo, buf, len >> 1); in omap_nand_data_in()
2087 ioread32_rep(info->fifo, buf, len >> 2); in omap_nand_data_in()
2098 iowrite8_rep(info->fifo, buf, len); in omap_nand_data_out()
2100 iowrite16_rep(info->fifo, buf, len >> 1); in omap_nand_data_out()
2102 iowrite32_rep(info->fifo, buf, len >> 2); in omap_nand_data_out()
2112 switch (instr->type) { in omap_nand_exec_instr()
2114 iowrite8(instr->ctx.cmd.opcode, in omap_nand_exec_instr()
2115 info->reg.gpmc_nand_command); in omap_nand_exec_instr()
2119 for (i = 0; i < instr->ctx.addr.naddrs; i++) { in omap_nand_exec_instr()
2120 iowrite8(instr->ctx.addr.addrs[i], in omap_nand_exec_instr()
2121 info->reg.gpmc_nand_address); in omap_nand_exec_instr()
2126 info->data_in(chip, instr->ctx.data.buf.in, in omap_nand_exec_instr()
2127 instr->ctx.data.len, in omap_nand_exec_instr()
2128 instr->ctx.data.force_8bit); in omap_nand_exec_instr()
2132 info->data_out(chip, instr->ctx.data.buf.out, in omap_nand_exec_instr()
2133 instr->ctx.data.len, in omap_nand_exec_instr()
2134 instr->ctx.data.force_8bit); in omap_nand_exec_instr()
2138 ret = info->ready_gpiod ? in omap_nand_exec_instr()
2139 nand_gpio_waitrdy(chip, info->ready_gpiod, instr->ctx.waitrdy.timeout_ms) : in omap_nand_exec_instr()
2140 nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); in omap_nand_exec_instr()
2146 if (instr->delay_ns) in omap_nand_exec_instr()
2147 ndelay(instr->delay_ns); in omap_nand_exec_instr()
2161 for (i = 0; i < op->ninstrs; i++) { in omap_nand_exec_op()
2164 ret = omap_nand_exec_instr(chip, &op->instrs[i]); in omap_nand_exec_op()
2177 /* Shared among all NAND instances to synchronize access to the ECC Engine */
2188 struct device *dev = &pdev->dev; in omap_nand_probe()
2191 info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), in omap_nand_probe()
2194 return -ENOMEM; in omap_nand_probe()
2196 info->pdev = pdev; in omap_nand_probe()
2202 info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); in omap_nand_probe()
2203 if (!info->ops) { in omap_nand_probe()
2204 dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); in omap_nand_probe()
2205 return -ENODEV; in omap_nand_probe()
2208 nand_chip = &info->nand; in omap_nand_probe()
2210 mtd->dev.parent = &pdev->dev; in omap_nand_probe()
2211 nand_set_flash_node(nand_chip, dev->of_node); in omap_nand_probe()
2213 if (!mtd->name) { in omap_nand_probe()
2214 mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, in omap_nand_probe()
2215 "omap2-nand.%d", info->gpmc_cs); in omap_nand_probe()
2216 if (!mtd->name) { in omap_nand_probe()
2217 dev_err(&pdev->dev, "Failed to set MTD name\n"); in omap_nand_probe()
2218 return -ENOMEM; in omap_nand_probe()
2226 info->fifo = vaddr; in omap_nand_probe()
2227 info->phys_base = res->start; in omap_nand_probe()
2235 nand_chip->controller = &omap_gpmc_controller; in omap_nand_probe()
2237 info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", in omap_nand_probe()
2239 if (IS_ERR(info->ready_gpiod)) { in omap_nand_probe()
2241 return PTR_ERR(info->ready_gpiod); in omap_nand_probe()
2244 if (info->flash_bbt) in omap_nand_probe()
2245 nand_chip->bbt_options |= NAND_BBT_USE_FLASH; in omap_nand_probe()
2248 info->data_in = omap_nand_data_in; in omap_nand_probe()
2249 info->data_out = omap_nand_data_out; in omap_nand_probe()
2267 if (!IS_ERR_OR_NULL(info->dma)) in omap_nand_probe()
2268 dma_release_channel(info->dma); in omap_nand_probe()
2283 if (info->dma) in omap_nand_remove()
2284 dma_release_channel(info->dma); in omap_nand_remove()
2289 /* omap_nand_ids defined in linux/platform_data/mtd-nand-omap2.h */