Lines Matching +full:on +full:- +full:chip

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
69 static int micron_nand_setup_read_retry(struct nand_chip *chip, int retry_mode) in micron_nand_setup_read_retry() argument
73 return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature); in micron_nand_setup_read_retry()
77 * Configure chip properties from Micron vendor-specific ONFI table
79 static int micron_nand_onfi_init(struct nand_chip *chip) in micron_nand_onfi_init() argument
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->ops.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()
135 struct nand_chip *chip = mtd_to_nand(mtd); in micron_nand_on_die_8_ooblayout_ecc() local
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()
150 struct nand_chip *chip = mtd_to_nand(mtd); in micron_nand_on_die_8_ooblayout_free() local
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()
166 static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable) in micron_nand_on_die_ecc_setup() argument
168 struct micron_nand *micron = nand_get_manufacturer_data(chip); in micron_nand_on_die_ecc_setup()
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()
181 ret = nand_set_features(chip, ONFI_FEATURE_ON_DIE_ECC, feature); in micron_nand_on_die_ecc_setup()
183 micron->ecc.enabled = enable; in micron_nand_on_die_ecc_setup()
188 static int micron_nand_on_die_ecc_status_4(struct nand_chip *chip, u8 status, in micron_nand_on_die_ecc_status_4() argument
192 struct micron_nand *micron = nand_get_manufacturer_data(chip); in micron_nand_on_die_ecc_status_4()
193 struct mtd_info *mtd = nand_to_mtd(chip); in micron_nand_on_die_ecc_status_4()
200 mtd->ecc_stats.failed++; in micron_nand_on_die_ecc_status_4()
212 * in non-raw mode, even if the user did not request those bytes. in micron_nand_on_die_ecc_status_4()
224 if (!nand_has_exec_op(chip) || in micron_nand_on_die_ecc_status_4()
225 !nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false, in micron_nand_on_die_ecc_status_4()
230 ret = nand_read_data_op(chip, chip->oob_poi, in micron_nand_on_die_ecc_status_4()
231 mtd->oobsize, false, false); in micron_nand_on_die_ecc_status_4()
233 ret = nand_change_read_column_op(chip, mtd->writesize, in micron_nand_on_die_ecc_status_4()
234 chip->oob_poi, in micron_nand_on_die_ecc_status_4()
235 mtd->oobsize, false); in micron_nand_on_die_ecc_status_4()
240 micron_nand_on_die_ecc_setup(chip, false); in micron_nand_on_die_ecc_status_4()
242 ret = nand_read_page_op(chip, page, 0, micron->ecc.rawbuf, in micron_nand_on_die_ecc_status_4()
243 mtd->writesize + mtd->oobsize); in micron_nand_on_die_ecc_status_4()
247 for (step = 0; step < chip->ecc.steps; step++) { in micron_nand_on_die_ecc_status_4()
251 offs = step * chip->ecc.size; in micron_nand_on_die_ecc_status_4()
252 rawbuf = micron->ecc.rawbuf + offs; in micron_nand_on_die_ecc_status_4()
255 for (i = 0; i < chip->ecc.size; i++) in micron_nand_on_die_ecc_status_4()
259 rawbuf = micron->ecc.rawbuf + mtd->writesize + offs; in micron_nand_on_die_ecc_status_4()
260 corrbuf = chip->oob_poi + offs; in micron_nand_on_die_ecc_status_4()
262 for (i = 0; i < chip->ecc.bytes + 4; i++) in micron_nand_on_die_ecc_status_4()
265 if (WARN_ON(nbitflips > chip->ecc.strength)) in micron_nand_on_die_ecc_status_4()
266 return -EINVAL; in micron_nand_on_die_ecc_status_4()
269 mtd->ecc_stats.corrected += nbitflips; in micron_nand_on_die_ecc_status_4()
275 static int micron_nand_on_die_ecc_status_8(struct nand_chip *chip, u8 status) in micron_nand_on_die_ecc_status_8() argument
277 struct mtd_info *mtd = nand_to_mtd(chip); in micron_nand_on_die_ecc_status_8()
281 * how many bit-flips were seen. in micron_nand_on_die_ecc_status_8()
285 mtd->ecc_stats.failed++; in micron_nand_on_die_ecc_status_8()
288 mtd->ecc_stats.corrected += 3; in micron_nand_on_die_ecc_status_8()
291 mtd->ecc_stats.corrected += 6; in micron_nand_on_die_ecc_status_8()
295 mtd->ecc_stats.corrected += 8; in micron_nand_on_die_ecc_status_8()
304 micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf, in micron_nand_read_page_on_die_ecc() argument
307 struct mtd_info *mtd = nand_to_mtd(chip); in micron_nand_read_page_on_die_ecc()
312 ret = micron_nand_on_die_ecc_setup(chip, true); in micron_nand_read_page_on_die_ecc()
316 ret = nand_read_page_op(chip, page, 0, NULL, 0); in micron_nand_read_page_on_die_ecc()
320 ret = nand_status_op(chip, &status); in micron_nand_read_page_on_die_ecc()
332 if (!nand_has_exec_op(chip) || in micron_nand_read_page_on_die_ecc()
333 !nand_read_data_op(chip, buf, mtd->writesize, false, true)) in micron_nand_read_page_on_die_ecc()
337 ret = nand_exit_status_op(chip); in micron_nand_read_page_on_die_ecc()
341 ret = nand_read_data_op(chip, buf, mtd->writesize, false, in micron_nand_read_page_on_die_ecc()
344 ret = nand_read_data_op(chip, chip->oob_poi, in micron_nand_read_page_on_die_ecc()
345 mtd->oobsize, false, false); in micron_nand_read_page_on_die_ecc()
347 ret = nand_change_read_column_op(chip, 0, buf, mtd->writesize, in micron_nand_read_page_on_die_ecc()
350 ret = nand_change_read_column_op(chip, mtd->writesize, in micron_nand_read_page_on_die_ecc()
351 chip->oob_poi, in micron_nand_read_page_on_die_ecc()
352 mtd->oobsize, false); in micron_nand_read_page_on_die_ecc()
355 if (chip->ecc.strength == 4) in micron_nand_read_page_on_die_ecc()
356 max_bitflips = micron_nand_on_die_ecc_status_4(chip, status, in micron_nand_read_page_on_die_ecc()
360 max_bitflips = micron_nand_on_die_ecc_status_8(chip, status); in micron_nand_read_page_on_die_ecc()
363 micron_nand_on_die_ecc_setup(chip, false); in micron_nand_read_page_on_die_ecc()
369 micron_nand_write_page_on_die_ecc(struct nand_chip *chip, const uint8_t *buf, in micron_nand_write_page_on_die_ecc() argument
374 ret = micron_nand_on_die_ecc_setup(chip, true); in micron_nand_write_page_on_die_ecc()
378 ret = nand_write_page_raw(chip, buf, oob_required, page); in micron_nand_write_page_on_die_ecc()
379 micron_nand_on_die_ecc_setup(chip, false); in micron_nand_write_page_on_die_ecc()
385 /* The NAND flash doesn't support on-die ECC */
389 * The NAND flash supports on-die ECC and it can be
395 * The NAND flash supports on-die ECC, and it cannot be
405 * Try to detect if the NAND support on-die ECC. To do this, we enable
408 * allow disabling the on-die ECC and we don't support such NANDs for
411 * This function also has the side effect of disabling on-die ECC if
414 static int micron_supports_on_die_ecc(struct nand_chip *chip) in micron_supports_on_die_ecc() argument
417 nanddev_get_ecc_requirements(&chip->base); in micron_supports_on_die_ecc()
421 if (!chip->parameters.onfi) in micron_supports_on_die_ecc()
424 if (nanddev_bits_per_cell(&chip->base) != 1) in micron_supports_on_die_ecc()
428 * We only support on-die ECC of 4/512 or 8/512 in micron_supports_on_die_ecc()
430 if (requirements->strength != 4 && requirements->strength != 8) in micron_supports_on_die_ecc()
433 /* 0x2 means on-die ECC is available. */ in micron_supports_on_die_ecc()
434 if (chip->id.len != 5 || in micron_supports_on_die_ecc()
435 (chip->id.data[4] & MICRON_ID_INTERNAL_ECC_MASK) != 0x2) in micron_supports_on_die_ecc()
446 ret = micron_nand_on_die_ecc_setup(chip, true); in micron_supports_on_die_ecc()
450 ret = nand_readid_op(chip, 0, id, sizeof(id)); in micron_supports_on_die_ecc()
454 ret = micron_nand_on_die_ecc_setup(chip, false); in micron_supports_on_die_ecc()
461 ret = nand_readid_op(chip, 0, id, sizeof(id)); in micron_supports_on_die_ecc()
469 * We only support on-die ECC of 4/512 or 8/512 in micron_supports_on_die_ecc()
471 if (requirements->strength != 4 && requirements->strength != 8) in micron_supports_on_die_ecc()
477 static int micron_nand_init(struct nand_chip *chip) in micron_nand_init() argument
479 struct nand_device *base = &chip->base; in micron_nand_init()
482 struct mtd_info *mtd = nand_to_mtd(chip); in micron_nand_init()
489 return -ENOMEM; in micron_nand_init()
491 nand_set_manufacturer_data(chip, micron); in micron_nand_init()
493 ret = micron_nand_onfi_init(chip); in micron_nand_init()
497 chip->options |= NAND_BBM_FIRSTPAGE; in micron_nand_init()
499 if (mtd->writesize == 2048) in micron_nand_init()
500 chip->options |= NAND_BBM_SECONDPAGE; in micron_nand_init()
502 ondie = micron_supports_on_die_ecc(chip); in micron_nand_init()
505 chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_DIE) { in micron_nand_init()
506 pr_err("On-die ECC forcefully enabled, not supported\n"); in micron_nand_init()
507 ret = -EINVAL; in micron_nand_init()
511 if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_DIE) { in micron_nand_init()
513 pr_err("On-die ECC selected but not supported\n"); in micron_nand_init()
514 ret = -EINVAL; in micron_nand_init()
519 micron->ecc.forced = true; in micron_nand_init()
520 micron->ecc.enabled = true; in micron_nand_init()
524 * In case of 4bit on-die ECC, we need a buffer to store a in micron_nand_init()
528 * That's not needed for 8-bit ECC, because the status expose in micron_nand_init()
531 if (requirements->strength == 4) { in micron_nand_init()
532 micron->ecc.rawbuf = kmalloc(mtd->writesize + in micron_nand_init()
533 mtd->oobsize, in micron_nand_init()
535 if (!micron->ecc.rawbuf) { in micron_nand_init()
536 ret = -ENOMEM; in micron_nand_init()
541 if (requirements->strength == 4) in micron_nand_init()
548 chip->ecc.bytes = requirements->strength * 2; in micron_nand_init()
549 chip->ecc.size = 512; in micron_nand_init()
550 chip->ecc.strength = requirements->strength; in micron_nand_init()
551 chip->ecc.algo = NAND_ECC_ALGO_BCH; in micron_nand_init()
552 chip->ecc.read_page = micron_nand_read_page_on_die_ecc; in micron_nand_init()
553 chip->ecc.write_page = micron_nand_write_page_on_die_ecc; in micron_nand_init()
556 chip->ecc.read_page_raw = nand_read_page_raw_notsupp; in micron_nand_init()
557 chip->ecc.write_page_raw = nand_write_page_raw_notsupp; in micron_nand_init()
559 if (!chip->ecc.read_page_raw) in micron_nand_init()
560 chip->ecc.read_page_raw = nand_read_page_raw; in micron_nand_init()
561 if (!chip->ecc.write_page_raw) in micron_nand_init()
562 chip->ecc.write_page_raw = nand_write_page_raw; in micron_nand_init()
569 kfree(micron->ecc.rawbuf); in micron_nand_init()
575 static void micron_nand_cleanup(struct nand_chip *chip) in micron_nand_cleanup() argument
577 struct micron_nand *micron = nand_get_manufacturer_data(chip); in micron_nand_cleanup()
579 kfree(micron->ecc.rawbuf); in micron_nand_cleanup()
583 static void micron_fixup_onfi_param_page(struct nand_chip *chip, in micron_fixup_onfi_param_page() argument
587 * MT29F1G08ABAFAWP-ITE:F and possibly others report 00 00 for the in micron_fixup_onfi_param_page()
591 if (le16_to_cpu(p->revision) == 0) in micron_fixup_onfi_param_page()
592 p->revision = cpu_to_le16(ONFI_VERSION_1_0); in micron_fixup_onfi_param_page()