Lines Matching +full:nand +full:- +full:ecc +full:- +full:strength
1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
15 * corrected by on-die ECC and should be rewritten.
20 * On chips with 8-bit ECC and additional bit can be used to distinguish
24 * ----- ----- ----- -----------
27 * 0 1 0 4 - 6 errors corrected, recommend rewrite
29 * 1 0 0 1 - 3 errors corrected
31 * 1 1 0 7 - 8 errors corrected, recommend rewrite
66 struct micron_on_die_ecc ecc; member
77 * Configure chip properties from Micron vendor-specific ONFI table
81 struct nand_parameters *p = &chip->parameters; in micron_nand_onfi_init()
83 if (p->onfi) { in micron_nand_onfi_init()
84 struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor; in micron_nand_onfi_init()
86 chip->read_retries = micron->read_retry_options; in micron_nand_onfi_init()
87 chip->setup_read_retry = micron_nand_setup_read_retry; in micron_nand_onfi_init()
90 if (p->supports_set_get_features) { in micron_nand_onfi_init()
91 set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->set_feature_list); in micron_nand_onfi_init()
92 set_bit(ONFI_FEATURE_ON_DIE_ECC, p->set_feature_list); in micron_nand_onfi_init()
93 set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->get_feature_list); in micron_nand_onfi_init()
94 set_bit(ONFI_FEATURE_ON_DIE_ECC, p->get_feature_list); in micron_nand_onfi_init()
105 return -ERANGE; in micron_nand_on_die_4_ooblayout_ecc()
107 oobregion->offset = (section * 16) + 8; in micron_nand_on_die_4_ooblayout_ecc()
108 oobregion->length = 8; in micron_nand_on_die_4_ooblayout_ecc()
118 return -ERANGE; in micron_nand_on_die_4_ooblayout_free()
120 oobregion->offset = (section * 16) + 2; in micron_nand_on_die_4_ooblayout_free()
121 oobregion->length = 6; in micron_nand_on_die_4_ooblayout_free()
127 .ecc = micron_nand_on_die_4_ooblayout_ecc,
138 return -ERANGE; in micron_nand_on_die_8_ooblayout_ecc()
140 oobregion->offset = mtd->oobsize - chip->ecc.total; in micron_nand_on_die_8_ooblayout_ecc()
141 oobregion->length = chip->ecc.total; in micron_nand_on_die_8_ooblayout_ecc()
153 return -ERANGE; in micron_nand_on_die_8_ooblayout_free()
155 oobregion->offset = 2; in micron_nand_on_die_8_ooblayout_free()
156 oobregion->length = mtd->oobsize - chip->ecc.total - 2; in micron_nand_on_die_8_ooblayout_free()
162 .ecc = micron_nand_on_die_8_ooblayout_ecc,
172 if (micron->ecc.forced) in micron_nand_on_die_ecc_setup()
175 if (micron->ecc.enabled == enable) in micron_nand_on_die_ecc_setup()
183 micron->ecc.enabled = enable; in micron_nand_on_die_ecc_setup()
199 mtd->ecc_stats.failed++; in micron_nand_on_die_ecc_status_4()
205 * The internal ECC doesn't tell us the number of bitflips that have in micron_nand_on_die_ecc_status_4()
211 * in non-raw mode, even if the user did not request those bytes. in micron_nand_on_die_ecc_status_4()
214 ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, in micron_nand_on_die_ecc_status_4()
222 ret = nand_read_page_op(chip, page, 0, micron->ecc.rawbuf, in micron_nand_on_die_ecc_status_4()
223 mtd->writesize + mtd->oobsize); in micron_nand_on_die_ecc_status_4()
227 for (step = 0; step < chip->ecc.steps; step++) { in micron_nand_on_die_ecc_status_4()
231 offs = step * chip->ecc.size; in micron_nand_on_die_ecc_status_4()
232 rawbuf = micron->ecc.rawbuf + offs; in micron_nand_on_die_ecc_status_4()
235 for (i = 0; i < chip->ecc.size; i++) in micron_nand_on_die_ecc_status_4()
239 rawbuf = micron->ecc.rawbuf + mtd->writesize + offs; in micron_nand_on_die_ecc_status_4()
240 corrbuf = chip->oob_poi + offs; in micron_nand_on_die_ecc_status_4()
242 for (i = 0; i < chip->ecc.bytes + 4; i++) in micron_nand_on_die_ecc_status_4()
245 if (WARN_ON(nbitflips > chip->ecc.strength)) in micron_nand_on_die_ecc_status_4()
246 return -EINVAL; in micron_nand_on_die_ecc_status_4()
249 mtd->ecc_stats.corrected += nbitflips; in micron_nand_on_die_ecc_status_4()
261 * how many bit-flips were seen. in micron_nand_on_die_ecc_status_8()
265 mtd->ecc_stats.failed++; in micron_nand_on_die_ecc_status_8()
268 mtd->ecc_stats.corrected += 3; in micron_nand_on_die_ecc_status_8()
271 mtd->ecc_stats.corrected += 6; in micron_nand_on_die_ecc_status_8()
275 mtd->ecc_stats.corrected += 8; in micron_nand_on_die_ecc_status_8()
307 ret = nand_read_data_op(chip, buf, mtd->writesize, false); in micron_nand_read_page_on_die_ecc()
309 ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, in micron_nand_read_page_on_die_ecc()
312 if (chip->ecc.strength == 4) in micron_nand_read_page_on_die_ecc()
342 /* The NAND flash doesn't support on-die ECC */
346 * The NAND flash supports on-die ECC and it can be
352 * The NAND flash supports on-die ECC, and it cannot be
362 * Try to detect if the NAND support on-die ECC. To do this, we enable
365 * allow disabling the on-die ECC and we don't support such NANDs for
368 * This function also has the side effect of disabling on-die ECC if
376 if (!chip->parameters.onfi) in micron_supports_on_die_ecc()
379 if (nanddev_bits_per_cell(&chip->base) != 1) in micron_supports_on_die_ecc()
383 * We only support on-die ECC of 4/512 or 8/512 in micron_supports_on_die_ecc()
385 if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) in micron_supports_on_die_ecc()
388 /* 0x2 means on-die ECC is available. */ in micron_supports_on_die_ecc()
389 if (chip->id.len != 5 || in micron_supports_on_die_ecc()
390 (chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2) in micron_supports_on_die_ecc()
394 * It seems that there are devices which do not support ECC officially. in micron_supports_on_die_ecc()
396 * enabling the ECC feature but don't reflect that to the READ_ID table. in micron_supports_on_die_ecc()
397 * So we have to guarantee that we disable the ECC feature directly in micron_supports_on_die_ecc()
424 * We only support on-die ECC of 4/512 or 8/512 in micron_supports_on_die_ecc()
426 if (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8) in micron_supports_on_die_ecc()
441 return -ENOMEM; in micron_nand_init()
449 if (mtd->writesize == 2048) in micron_nand_init()
450 chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; in micron_nand_init()
455 chip->ecc.mode != NAND_ECC_ON_DIE) { in micron_nand_init()
456 pr_err("On-die ECC forcefully enabled, not supported\n"); in micron_nand_init()
457 ret = -EINVAL; in micron_nand_init()
461 if (chip->ecc.mode == NAND_ECC_ON_DIE) { in micron_nand_init()
463 pr_err("On-die ECC selected but not supported\n"); in micron_nand_init()
464 ret = -EINVAL; in micron_nand_init()
469 micron->ecc.forced = true; in micron_nand_init()
470 micron->ecc.enabled = true; in micron_nand_init()
474 * In case of 4bit on-die ECC, we need a buffer to store a in micron_nand_init()
476 * to the same page after ECC correction happened and extract in micron_nand_init()
478 * That's not needed for 8-bit ECC, because the status expose in micron_nand_init()
481 if (chip->base.eccreq.strength == 4) { in micron_nand_init()
482 micron->ecc.rawbuf = kmalloc(mtd->writesize + in micron_nand_init()
483 mtd->oobsize, in micron_nand_init()
485 if (!micron->ecc.rawbuf) { in micron_nand_init()
486 ret = -ENOMEM; in micron_nand_init()
491 if (chip->base.eccreq.strength == 4) in micron_nand_init()
498 chip->ecc.bytes = chip->base.eccreq.strength * 2; in micron_nand_init()
499 chip->ecc.size = 512; in micron_nand_init()
500 chip->ecc.strength = chip->base.eccreq.strength; in micron_nand_init()
501 chip->ecc.algo = NAND_ECC_BCH; in micron_nand_init()
502 chip->ecc.read_page = micron_nand_read_page_on_die_ecc; in micron_nand_init()
503 chip->ecc.write_page = micron_nand_write_page_on_die_ecc; in micron_nand_init()
506 chip->ecc.read_page_raw = nand_read_page_raw_notsupp; in micron_nand_init()
507 chip->ecc.write_page_raw = nand_write_page_raw_notsupp; in micron_nand_init()
509 chip->ecc.read_page_raw = nand_read_page_raw; in micron_nand_init()
510 chip->ecc.write_page_raw = nand_write_page_raw; in micron_nand_init()
517 kfree(micron->ecc.rawbuf); in micron_nand_init()
527 kfree(micron->ecc.rawbuf); in micron_nand_cleanup()
535 * MT29F1G08ABAFAWP-ITE:F and possibly others report 00 00 for the in micron_fixup_onfi_param_page()
539 if (le16_to_cpu(p->revision) == 0) in micron_fixup_onfi_param_page()
540 p->revision = cpu_to_le16(ONFI_VERSION_1_0); in micron_fixup_onfi_param_page()