forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/mtd/nand/raw/nand_micron.c
....@@ -1,22 +1,14 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2017 Free Electrons
34 * Copyright (C) 2017 NextThing Co
45 *
56 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
167 */
178
18
-#include <linux/mtd/rawnand.h>
199 #include <linux/slab.h>
10
+
11
+#include "internals.h"
2012
2113 /*
2214 * Special Micron status bit 3 indicates that the block has been
....@@ -74,9 +66,8 @@
7466 struct micron_on_die_ecc ecc;
7567 };
7668
77
-static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
69
+static int micron_nand_setup_read_retry(struct nand_chip *chip, int retry_mode)
7870 {
79
- struct nand_chip *chip = mtd_to_nand(mtd);
8071 u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
8172
8273 return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
....@@ -93,7 +84,7 @@
9384 struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor;
9485
9586 chip->read_retries = micron->read_retry_options;
96
- chip->setup_read_retry = micron_nand_setup_read_retry;
87
+ chip->ops.setup_read_retry = micron_nand_setup_read_retry;
9788 }
9889
9990 if (p->supports_set_get_features) {
....@@ -201,6 +192,7 @@
201192 struct micron_nand *micron = nand_get_manufacturer_data(chip);
202193 struct mtd_info *mtd = nand_to_mtd(chip);
203194 unsigned int step, max_bitflips = 0;
195
+ bool use_datain = false;
204196 int ret;
205197
206198 if (!(status & NAND_ECC_STATUS_WRITE_RECOMMENDED)) {
....@@ -220,8 +212,27 @@
220212 * in non-raw mode, even if the user did not request those bytes.
221213 */
222214 if (!oob_required) {
223
- ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
224
- false);
215
+ /*
216
+ * We first check which operation is supported by the controller
217
+ * before running it. This trick makes it possible to support
218
+ * all controllers, even the most constraints, without almost
219
+ * any performance hit.
220
+ *
221
+ * TODO: could be enhanced to avoid repeating the same check
222
+ * over and over in the fast path.
223
+ */
224
+ if (!nand_has_exec_op(chip) ||
225
+ !nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false,
226
+ true))
227
+ use_datain = true;
228
+
229
+ if (use_datain)
230
+ ret = nand_read_data_op(chip, chip->oob_poi,
231
+ mtd->oobsize, false, false);
232
+ else
233
+ ret = nand_change_read_column_op(chip, mtd->writesize,
234
+ chip->oob_poi,
235
+ mtd->oobsize, false);
225236 if (ret)
226237 return ret;
227238 }
....@@ -290,10 +301,11 @@
290301 }
291302
292303 static int
293
-micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
294
- uint8_t *buf, int oob_required,
295
- int page)
304
+micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf,
305
+ int oob_required, int page)
296306 {
307
+ struct mtd_info *mtd = nand_to_mtd(chip);
308
+ bool use_datain = false;
297309 u8 status;
298310 int ret, max_bitflips = 0;
299311
....@@ -309,14 +321,36 @@
309321 if (ret)
310322 goto out;
311323
312
- ret = nand_exit_status_op(chip);
313
- if (ret)
314
- goto out;
324
+ /*
325
+ * We first check which operation is supported by the controller before
326
+ * running it. This trick makes it possible to support all controllers,
327
+ * even the most constraints, without almost any performance hit.
328
+ *
329
+ * TODO: could be enhanced to avoid repeating the same check over and
330
+ * over in the fast path.
331
+ */
332
+ if (!nand_has_exec_op(chip) ||
333
+ !nand_read_data_op(chip, buf, mtd->writesize, false, true))
334
+ use_datain = true;
315335
316
- ret = nand_read_data_op(chip, buf, mtd->writesize, false);
317
- if (!ret && oob_required)
318
- ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
336
+ if (use_datain) {
337
+ ret = nand_exit_status_op(chip);
338
+ if (ret)
339
+ goto out;
340
+
341
+ ret = nand_read_data_op(chip, buf, mtd->writesize, false,
319342 false);
343
+ if (!ret && oob_required)
344
+ ret = nand_read_data_op(chip, chip->oob_poi,
345
+ mtd->oobsize, false, false);
346
+ } else {
347
+ ret = nand_change_read_column_op(chip, 0, buf, mtd->writesize,
348
+ false);
349
+ if (!ret && oob_required)
350
+ ret = nand_change_read_column_op(chip, mtd->writesize,
351
+ chip->oob_poi,
352
+ mtd->oobsize, false);
353
+ }
320354
321355 if (chip->ecc.strength == 4)
322356 max_bitflips = micron_nand_on_die_ecc_status_4(chip, status,
....@@ -332,9 +366,8 @@
332366 }
333367
334368 static int
335
-micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
336
- const uint8_t *buf, int oob_required,
337
- int page)
369
+micron_nand_write_page_on_die_ecc(struct nand_chip *chip, const uint8_t *buf,
370
+ int oob_required, int page)
338371 {
339372 int ret;
340373
....@@ -342,7 +375,7 @@
342375 if (ret)
343376 return ret;
344377
345
- ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
378
+ ret = nand_write_page_raw(chip, buf, oob_required, page);
346379 micron_nand_on_die_ecc_setup(chip, false);
347380
348381 return ret;
....@@ -380,19 +413,21 @@
380413 */
381414 static int micron_supports_on_die_ecc(struct nand_chip *chip)
382415 {
416
+ const struct nand_ecc_props *requirements =
417
+ nanddev_get_ecc_requirements(&chip->base);
383418 u8 id[5];
384419 int ret;
385420
386421 if (!chip->parameters.onfi)
387422 return MICRON_ON_DIE_UNSUPPORTED;
388423
389
- if (chip->bits_per_cell != 1)
424
+ if (nanddev_bits_per_cell(&chip->base) != 1)
390425 return MICRON_ON_DIE_UNSUPPORTED;
391426
392427 /*
393428 * We only support on-die ECC of 4/512 or 8/512
394429 */
395
- if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8)
430
+ if (requirements->strength != 4 && requirements->strength != 8)
396431 return MICRON_ON_DIE_UNSUPPORTED;
397432
398433 /* 0x2 means on-die ECC is available. */
....@@ -433,7 +468,7 @@
433468 /*
434469 * We only support on-die ECC of 4/512 or 8/512
435470 */
436
- if (chip->ecc_strength_ds != 4 && chip->ecc_strength_ds != 8)
471
+ if (requirements->strength != 4 && requirements->strength != 8)
437472 return MICRON_ON_DIE_UNSUPPORTED;
438473
439474 return MICRON_ON_DIE_SUPPORTED;
....@@ -441,6 +476,9 @@
441476
442477 static int micron_nand_init(struct nand_chip *chip)
443478 {
479
+ struct nand_device *base = &chip->base;
480
+ const struct nand_ecc_props *requirements =
481
+ nanddev_get_ecc_requirements(base);
444482 struct mtd_info *mtd = nand_to_mtd(chip);
445483 struct micron_nand *micron;
446484 int ondie;
....@@ -456,19 +494,21 @@
456494 if (ret)
457495 goto err_free_manuf_data;
458496
497
+ chip->options |= NAND_BBM_FIRSTPAGE;
498
+
459499 if (mtd->writesize == 2048)
460
- chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
500
+ chip->options |= NAND_BBM_SECONDPAGE;
461501
462502 ondie = micron_supports_on_die_ecc(chip);
463503
464504 if (ondie == MICRON_ON_DIE_MANDATORY &&
465
- chip->ecc.mode != NAND_ECC_ON_DIE) {
505
+ chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_DIE) {
466506 pr_err("On-die ECC forcefully enabled, not supported\n");
467507 ret = -EINVAL;
468508 goto err_free_manuf_data;
469509 }
470510
471
- if (chip->ecc.mode == NAND_ECC_ON_DIE) {
511
+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_DIE) {
472512 if (ondie == MICRON_ON_DIE_UNSUPPORTED) {
473513 pr_err("On-die ECC selected but not supported\n");
474514 ret = -EINVAL;
....@@ -488,7 +528,7 @@
488528 * That's not needed for 8-bit ECC, because the status expose
489529 * a better approximation of the number of bitflips in a page.
490530 */
491
- if (chip->ecc_strength_ds == 4) {
531
+ if (requirements->strength == 4) {
492532 micron->ecc.rawbuf = kmalloc(mtd->writesize +
493533 mtd->oobsize,
494534 GFP_KERNEL);
....@@ -498,17 +538,17 @@
498538 }
499539 }
500540
501
- if (chip->ecc_strength_ds == 4)
541
+ if (requirements->strength == 4)
502542 mtd_set_ooblayout(mtd,
503543 &micron_nand_on_die_4_ooblayout_ops);
504544 else
505545 mtd_set_ooblayout(mtd,
506546 &micron_nand_on_die_8_ooblayout_ops);
507547
508
- chip->ecc.bytes = chip->ecc_strength_ds * 2;
548
+ chip->ecc.bytes = requirements->strength * 2;
509549 chip->ecc.size = 512;
510
- chip->ecc.strength = chip->ecc_strength_ds;
511
- chip->ecc.algo = NAND_ECC_BCH;
550
+ chip->ecc.strength = requirements->strength;
551
+ chip->ecc.algo = NAND_ECC_ALGO_BCH;
512552 chip->ecc.read_page = micron_nand_read_page_on_die_ecc;
513553 chip->ecc.write_page = micron_nand_write_page_on_die_ecc;
514554
....@@ -516,8 +556,10 @@
516556 chip->ecc.read_page_raw = nand_read_page_raw_notsupp;
517557 chip->ecc.write_page_raw = nand_write_page_raw_notsupp;
518558 } else {
519
- chip->ecc.read_page_raw = nand_read_page_raw;
520
- chip->ecc.write_page_raw = nand_write_page_raw;
559
+ if (!chip->ecc.read_page_raw)
560
+ chip->ecc.read_page_raw = nand_read_page_raw;
561
+ if (!chip->ecc.write_page_raw)
562
+ chip->ecc.write_page_raw = nand_write_page_raw;
521563 }
522564 }
523565