mtd: rawnand: Give the possibility to verify a read operation is supported
authorMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 7 May 2020 10:52:36 +0000 (12:52 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Mon, 11 May 2020 07:51:42 +0000 (09:51 +0200)
This can be used to discriminate between two path in the parameter
page detection: use data_in cycles (like before) if supported, use the
CHANGE READ COLUMN command otherwise.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Link: https://lore.kernel.org/linux-mtd/20200507105241.14299-9-miquel.raynal@bootlin.com
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/marvell_nand.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_jedec.c
drivers/mtd/nand/raw/nand_legacy.c
drivers/mtd/nand/raw/nand_micron.c
drivers/mtd/nand/raw/nand_onfi.c
include/linux/mtd/rawnand.h

index 31dc9fd..2a9222e 100644 (file)
@@ -694,7 +694,7 @@ static int fsmc_read_page_hwecc(struct nand_chip *chip, u8 *buf,
        for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
                nand_read_page_op(chip, page, s * eccsize, NULL, 0);
                chip->ecc.hwctl(chip, NAND_ECC_READ);
-               ret = nand_read_data_op(chip, p, eccsize, false);
+               ret = nand_read_data_op(chip, p, eccsize, false, false);
                if (ret)
                        return ret;
 
index 88269c4..a79ce4b 100644 (file)
@@ -1224,12 +1224,12 @@ static int marvell_nfc_hw_ecc_bch_read_page_raw(struct nand_chip *chip, u8 *buf,
 
                /* Read spare bytes */
                nand_read_data_op(chip, oob + (lt->spare_bytes * chunk),
-                                 spare_len, false);
+                                 spare_len, false, false);
 
                /* Read ECC bytes */
                nand_read_data_op(chip, oob + ecc_offset +
                                  (ALIGN(lt->ecc_bytes, 32) * chunk),
-                                 ecc_len, false);
+                                 ecc_len, false, false);
        }
 
        return 0;
index c440f11..8df8648 100644 (file)
@@ -740,7 +740,8 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
         */
        timeout_ms = jiffies + msecs_to_jiffies(timeout_ms) + 1;
        do {
-               ret = nand_read_data_op(chip, &status, sizeof(status), true);
+               ret = nand_read_data_op(chip, &status, sizeof(status), true,
+                                       false);
                if (ret)
                        break;
 
@@ -820,7 +821,7 @@ void panic_nand_wait(struct nand_chip *chip, unsigned long timeo)
                        u8 status;
 
                        ret = nand_read_data_op(chip, &status, sizeof(status),
-                                               true);
+                                               true, false);
                        if (ret)
                                return;
 
@@ -1918,6 +1919,8 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
  * @buf: buffer used to store the data
  * @len: length of the buffer
  * @force_8bit: force 8-bit bus access
+ * @check_only: do not actually run the command, only checks if the
+ *              controller driver supports it
  *
  * This function does a raw data read on the bus. Usually used after launching
  * another NAND operation like nand_read_page_op().
@@ -1926,7 +1929,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
  * Returns 0 on success, a negative error code otherwise.
  */
 int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
-                     bool force_8bit)
+                     bool force_8bit, bool check_only)
 {
        if (!len || !buf)
                return -EINVAL;
@@ -1939,9 +1942,15 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
 
                instrs[0].ctx.data.force_8bit = force_8bit;
 
+               if (check_only)
+                       return nand_check_op(chip, &op);
+
                return nand_exec_op(chip, &op);
        }
 
+       if (check_only)
+               return 0;
+
        if (force_8bit) {
                u8 *p = buf;
                unsigned int i;
@@ -2670,7 +2679,7 @@ int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required,
 
        if (oob_required) {
                ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
-                                       false);
+                                       false, false);
                if (ret)
                        return ret;
        }
@@ -2702,7 +2711,7 @@ static int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf,
                return ret;
 
        for (steps = chip->ecc.steps; steps > 0; steps--) {
-               ret = nand_read_data_op(chip, buf, eccsize, false);
+               ret = nand_read_data_op(chip, buf, eccsize, false, false);
                if (ret)
                        return ret;
 
@@ -2710,14 +2719,14 @@ static int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf,
 
                if (chip->ecc.prepad) {
                        ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
-                                               false);
+                                               false, false);
                        if (ret)
                                return ret;
 
                        oob += chip->ecc.prepad;
                }
 
-               ret = nand_read_data_op(chip, oob, eccbytes, false);
+               ret = nand_read_data_op(chip, oob, eccbytes, false, false);
                if (ret)
                        return ret;
 
@@ -2725,7 +2734,7 @@ static int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf,
 
                if (chip->ecc.postpad) {
                        ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
-                                               false);
+                                               false, false);
                        if (ret)
                                return ret;
 
@@ -2735,7 +2744,7 @@ static int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf,
 
        size = mtd->oobsize - (oob - chip->oob_poi);
        if (size) {
-               ret = nand_read_data_op(chip, oob, size, false);
+               ret = nand_read_data_op(chip, oob, size, false, false);
                if (ret)
                        return ret;
        }
@@ -2928,14 +2937,15 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
                chip->ecc.hwctl(chip, NAND_ECC_READ);
 
-               ret = nand_read_data_op(chip, p, eccsize, false);
+               ret = nand_read_data_op(chip, p, eccsize, false, false);
                if (ret)
                        return ret;
 
                chip->ecc.calculate(chip, p, &ecc_calc[i]);
        }
 
-       ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false);
+       ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false,
+                               false);
        if (ret)
                return ret;
 
@@ -3014,7 +3024,7 @@ static int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
 
                chip->ecc.hwctl(chip, NAND_ECC_READ);
 
-               ret = nand_read_data_op(chip, p, eccsize, false);
+               ret = nand_read_data_op(chip, p, eccsize, false, false);
                if (ret)
                        return ret;
 
@@ -3071,13 +3081,13 @@ static int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf,
 
                chip->ecc.hwctl(chip, NAND_ECC_READ);
 
-               ret = nand_read_data_op(chip, p, eccsize, false);
+               ret = nand_read_data_op(chip, p, eccsize, false, false);
                if (ret)
                        return ret;
 
                if (chip->ecc.prepad) {
                        ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
-                                               false);
+                                               false, false);
                        if (ret)
                                return ret;
 
@@ -3086,7 +3096,7 @@ static int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf,
 
                chip->ecc.hwctl(chip, NAND_ECC_READSYN);
 
-               ret = nand_read_data_op(chip, oob, eccbytes, false);
+               ret = nand_read_data_op(chip, oob, eccbytes, false, false);
                if (ret)
                        return ret;
 
@@ -3096,7 +3106,7 @@ static int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf,
 
                if (chip->ecc.postpad) {
                        ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
-                                               false);
+                                               false, false);
                        if (ret)
                                return ret;
 
@@ -3124,7 +3134,7 @@ static int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf,
        /* Calculate remaining oob bytes */
        i = mtd->oobsize - (oob - chip->oob_poi);
        if (i) {
-               ret = nand_read_data_op(chip, oob, i, false);
+               ret = nand_read_data_op(chip, oob, i, false, false);
                if (ret)
                        return ret;
        }
@@ -3426,7 +3436,7 @@ static int nand_read_oob_syndrome(struct nand_chip *chip, int page)
                        sndrnd = 1;
                toread = min_t(int, length, chunk);
 
-               ret = nand_read_data_op(chip, bufpoi, toread, false);
+               ret = nand_read_data_op(chip, bufpoi, toread, false, false);
                if (ret)
                        return ret;
 
@@ -3434,7 +3444,7 @@ static int nand_read_oob_syndrome(struct nand_chip *chip, int page)
                length -= toread;
        }
        if (length > 0) {
-               ret = nand_read_data_op(chip, bufpoi, length, false);
+               ret = nand_read_data_op(chip, bufpoi, length, false, false);
                if (ret)
                        return ret;
        }
index 15937e0..63069f1 100644 (file)
@@ -51,7 +51,7 @@ int nand_jedec_detect(struct nand_chip *chip)
        }
 
        for (i = 0; i < JEDEC_PARAM_PAGES; i++) {
-               ret = nand_read_data_op(chip, p, sizeof(*p), true);
+               ret = nand_read_data_op(chip, p, sizeof(*p), true, false);
                if (ret) {
                        ret = 0;
                        goto free_jedec_param_page;
index f91e92e..d64791c 100644 (file)
@@ -225,7 +225,8 @@ static void nand_wait_status_ready(struct nand_chip *chip, unsigned long timeo)
        do {
                u8 status;
 
-               ret = nand_read_data_op(chip, &status, sizeof(status), true);
+               ret = nand_read_data_op(chip, &status, sizeof(status), true,
+                                       false);
                if (ret)
                        return;
 
@@ -552,7 +553,8 @@ static int nand_wait(struct nand_chip *chip)
                                        break;
                        } else {
                                ret = nand_read_data_op(chip, &status,
-                                                       sizeof(status), true);
+                                                       sizeof(status), true,
+                                                       false);
                                if (ret)
                                        return ret;
 
@@ -563,7 +565,7 @@ static int nand_wait(struct nand_chip *chip)
                } while (time_before(jiffies, timeo));
        }
 
-       ret = nand_read_data_op(chip, &status, sizeof(status), true);
+       ret = nand_read_data_op(chip, &status, sizeof(status), true, false);
        if (ret)
                return ret;
 
index 5665403..3a37d48 100644 (file)
@@ -212,7 +212,7 @@ static int micron_nand_on_die_ecc_status_4(struct nand_chip *chip, u8 status,
         */
        if (!oob_required) {
                ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
-                                       false);
+                                       false, false);
                if (ret)
                        return ret;
        }
@@ -304,10 +304,10 @@ micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf,
        if (ret)
                goto out;
 
-       ret = nand_read_data_op(chip, buf, mtd->writesize, false);
+       ret = nand_read_data_op(chip, buf, mtd->writesize, false, false);
        if (!ret && oob_required)
                ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
-                                       false);
+                                       false, false);
 
        if (chip->ecc.strength == 4)
                max_bitflips = micron_nand_on_die_ecc_status_4(chip, status,
index ee0f2c2..e6ffbe8 100644 (file)
@@ -167,7 +167,8 @@ int nand_onfi_detect(struct nand_chip *chip)
        }
 
        for (i = 0; i < ONFI_PARAM_PAGES; i++) {
-               ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf), true);
+               ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf), true,
+                                       false);
                if (ret) {
                        ret = 0;
                        goto free_onfi_param_page;
index d1f5c52..70380c9 100644 (file)
@@ -1363,7 +1363,7 @@ int nand_change_write_column_op(struct nand_chip *chip,
                                unsigned int offset_in_page, const void *buf,
                                unsigned int len, bool force_8bit);
 int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
-                     bool force_8bit);
+                     bool force_8bit, bool check_only);
 int nand_write_data_op(struct nand_chip *chip, const void *buf,
                       unsigned int len, bool force_8bit);