mtd: nand: Wait for PAGEPROG to finish in drivers setting NAND_ECC_CUSTOM_PAGE_ACCESS
[platform/kernel/u-boot.git] / drivers / mtd / nand / nand_base.c
index b025001..16d4554 100644 (file)
@@ -651,6 +651,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_ERASE2:
        case NAND_CMD_SEQIN:
        case NAND_CMD_STATUS:
+       case NAND_CMD_READID:
+       case NAND_CMD_SET_FEATURES:
                return;
 
        case NAND_CMD_RESET:
@@ -748,6 +750,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_SEQIN:
        case NAND_CMD_RNDIN:
        case NAND_CMD_STATUS:
+       case NAND_CMD_READID:
+       case NAND_CMD_SET_FEATURES:
                return;
 
        case NAND_CMD_RESET:
@@ -897,7 +901,180 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
        return status;
 }
 
-#define BITS_PER_BYTE 8
+/**
+ * nand_reset_data_interface - Reset data interface and timings
+ * @chip: The NAND chip
+ *
+ * Reset the Data interface and timings to ONFI mode 0.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_reset_data_interface(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       const struct nand_data_interface *conf;
+       int ret;
+
+       if (!chip->setup_data_interface)
+               return 0;
+
+       /*
+        * The ONFI specification says:
+        * "
+        * To transition from NV-DDR or NV-DDR2 to the SDR data
+        * interface, the host shall use the Reset (FFh) command
+        * using SDR timing mode 0. A device in any timing mode is
+        * required to recognize Reset (FFh) command issued in SDR
+        * timing mode 0.
+        * "
+        *
+        * Configure the data interface in SDR mode and set the
+        * timings to timing mode 0.
+        */
+
+       conf = nand_get_default_data_interface();
+       ret = chip->setup_data_interface(mtd, conf, false);
+       if (ret)
+               pr_err("Failed to configure data interface to SDR timing mode 0\n");
+
+       return ret;
+}
+
+/**
+ * nand_setup_data_interface - Setup the best data interface and timings
+ * @chip: The NAND chip
+ *
+ * Find and configure the best data interface and NAND timings supported by
+ * the chip and the driver.
+ * First tries to retrieve supported timing modes from ONFI information,
+ * and if the NAND chip does not support ONFI, relies on the
+ * ->onfi_timing_mode_default specified in the nand_ids table.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_setup_data_interface(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int ret;
+
+       if (!chip->setup_data_interface || !chip->data_interface)
+               return 0;
+
+       /*
+        * Ensure the timing mode has been changed on the chip side
+        * before changing timings on the controller side.
+        */
+       if (chip->onfi_version) {
+               u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
+                       chip->onfi_timing_mode_default,
+               };
+
+               ret = chip->onfi_set_features(mtd, chip,
+                               ONFI_FEATURE_ADDR_TIMING_MODE,
+                               tmode_param);
+               if (ret)
+                       goto err;
+       }
+
+       ret = chip->setup_data_interface(mtd, chip->data_interface, false);
+err:
+       return ret;
+}
+
+/**
+ * nand_init_data_interface - find the best data interface and timings
+ * @chip: The NAND chip
+ *
+ * Find the best data interface and NAND timings supported by the chip
+ * and the driver.
+ * First tries to retrieve supported timing modes from ONFI information,
+ * and if the NAND chip does not support ONFI, relies on the
+ * ->onfi_timing_mode_default specified in the nand_ids table. After this
+ * function nand_chip->data_interface is initialized with the best timing mode
+ * available.
+ *
+ * Returns 0 for success or negative error code otherwise.
+ */
+static int nand_init_data_interface(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int modes, mode, ret;
+
+       if (!chip->setup_data_interface)
+               return 0;
+
+       /*
+        * First try to identify the best timings from ONFI parameters and
+        * if the NAND does not support ONFI, fallback to the default ONFI
+        * timing mode.
+        */
+       modes = onfi_get_async_timing_mode(chip);
+       if (modes == ONFI_TIMING_MODE_UNKNOWN) {
+               if (!chip->onfi_timing_mode_default)
+                       return 0;
+
+               modes = GENMASK(chip->onfi_timing_mode_default, 0);
+       }
+
+       chip->data_interface = kzalloc(sizeof(*chip->data_interface),
+                                      GFP_KERNEL);
+       if (!chip->data_interface)
+               return -ENOMEM;
+
+       for (mode = fls(modes) - 1; mode >= 0; mode--) {
+               ret = onfi_init_data_interface(chip, chip->data_interface,
+                                              NAND_SDR_IFACE, mode);
+               if (ret)
+                       continue;
+
+               ret = chip->setup_data_interface(mtd, chip->data_interface,
+                                                true);
+               if (!ret) {
+                       chip->onfi_timing_mode_default = mode;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static void __maybe_unused nand_release_data_interface(struct nand_chip *chip)
+{
+       kfree(chip->data_interface);
+}
+
+/**
+ * nand_reset - Reset and initialize a NAND device
+ * @chip: The NAND chip
+ * @chipnr: Internal die id
+ *
+ * Returns 0 for success or negative error code otherwise
+ */
+int nand_reset(struct nand_chip *chip, int chipnr)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int ret;
+
+       ret = nand_reset_data_interface(chip);
+       if (ret)
+               return ret;
+
+       /*
+        * The CS line has to be released before we can apply the new NAND
+        * interface settings, hence this weird ->select_chip() dance.
+        */
+       chip->select_chip(mtd, chipnr);
+       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       chip->select_chip(mtd, -1);
+
+       chip->select_chip(mtd, chipnr);
+       ret = nand_setup_data_interface(chip);
+       chip->select_chip(mtd, -1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
 
 /**
  * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
@@ -1555,7 +1732,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                                 __func__, buf);
 
 read_retry:
-                       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+                       if (nand_standard_page_accessors(&chip->ecc))
+                               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
                        /*
                         * Now read the page into the buffer.  Absent an error,
@@ -2231,12 +2409,11 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
  * @buf: the data to write
  * @oob_required: must write chip->oob_poi to OOB
  * @page: page number to write
- * @cached: cached programming
  * @raw: use _raw version of write_page
  */
 static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                uint32_t offset, int data_len, const uint8_t *buf,
-               int oob_required, int page, int cached, int raw)
+               int oob_required, int page, int raw)
 {
        int status, subpage;
 
@@ -2246,7 +2423,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        else
                subpage = 0;
 
-       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+       if (nand_standard_page_accessors(&chip->ecc))
+               chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
        if (unlikely(raw))
                status = chip->ecc.write_page_raw(mtd, chip, buf,
@@ -2261,29 +2439,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        if (status < 0)
                return status;
 
-       /*
-        * Cached progamming disabled for now. Not sure if it's worth the
-        * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
-        */
-       cached = 0;
-
-       if (!cached || !NAND_HAS_CACHEPROG(chip)) {
-
+       if (nand_standard_page_accessors(&chip->ecc)) {
                chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-               status = chip->waitfunc(mtd, chip);
-               /*
-                * See if operation failed and additional status checks are
-                * available.
-                */
-               if ((status & NAND_STATUS_FAIL) && (chip->errstat))
-                       status = chip->errstat(mtd, chip, FL_WRITING, status,
-                                              page);
 
+               status = chip->waitfunc(mtd, chip);
                if (status & NAND_STATUS_FAIL)
                        return -EIO;
-       } else {
-               chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
-               status = chip->waitfunc(mtd, chip);
        }
 
        return 0;
@@ -2358,7 +2519,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops)
 {
-       int chipnr, realpage, page, blockmask, column;
+       int chipnr, realpage, page, column;
        struct nand_chip *chip = mtd_to_nand(mtd);
        uint32_t writelen = ops->len;
 
@@ -2394,7 +2555,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
        realpage = (int)(to >> chip->page_shift);
        page = realpage & chip->pagemask;
-       blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 
        /* Invalidate the page cache, when we write to the cached page */
        if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&
@@ -2409,7 +2569,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
        while (1) {
                int bytes = mtd->writesize;
-               int cached = writelen > bytes && page != blockmask;
                uint8_t *wbuf = buf;
                int use_bufpoi;
                int part_pagewr = (column || writelen < mtd->writesize);
@@ -2424,7 +2583,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                if (use_bufpoi) {
                        pr_debug("%s: using write bounce buffer for buf@%p\n",
                                         __func__, buf);
-                       cached = 0;
                        if (part_pagewr)
                                bytes = min_t(int, bytes - column, writelen);
                        chip->pagebuf = -1;
@@ -2442,7 +2600,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                        memset(chip->oob_poi, 0xff, mtd->oobsize);
                }
                ret = chip->write_page(mtd, chip, column, bytes, wbuf,
-                                       oob_required, page, cached,
+                                       oob_required, page,
                                        (ops->mode == MTD_OPS_RAW));
                if (ret)
                        break;
@@ -2578,10 +2736,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
        }
 
        chipnr = (int)(to >> chip->chip_shift);
-       chip->select_chip(mtd, chipnr);
-
-       /* Shift to get page */
-       page = (int)(to >> chip->page_shift);
 
        /*
         * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
@@ -2589,7 +2743,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
         * if we don't do this. I have no clue why, but I seem to have 'fixed'
         * it in the doc2000 driver in August 1999.  dwmw2.
         */
-       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       nand_reset(chip, chipnr);
+
+       chip->select_chip(mtd, chipnr);
+
+       /* Shift to get page */
+       page = (int)(to >> chip->page_shift);
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
@@ -2759,14 +2918,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
                status = chip->erase(mtd, page & chip->pagemask);
 
-               /*
-                * See if operation failed and additional status checks are
-                * available
-                */
-               if ((status & NAND_STATUS_FAIL) && (chip->errstat))
-                       status = chip->errstat(mtd, chip, FL_ERASING,
-                                              status, page);
-
                /* See if block erase succeeded */
                if (status & NAND_STATUS_FAIL) {
                        pr_debug("%s: failed erase, page 0x%08x\n",
@@ -3603,14 +3754,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        int i, maf_idx;
        u8 id_data[8];
 
-       /* Select the device */
-       chip->select_chip(mtd, 0);
-
        /*
         * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
         * after power-up.
         */
-       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       nand_reset(chip, 0);
+
+       /* Select the device */
+       chip->select_chip(mtd, 0);
 
        /* Send the command for reading device ID */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
@@ -3815,6 +3966,9 @@ static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node)
        if (ecc_step > 0)
                chip->ecc.size = ecc_step;
 
+       if (fdt_getprop(blob, node, "nand-ecc-maximize", NULL))
+               chip->ecc.options |= NAND_ECC_MAXIMIZE;
+
        return 0;
 }
 #else
@@ -3862,13 +4016,31 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                return PTR_ERR(type);
        }
 
+       /* Initialize the ->data_interface field. */
+       ret = nand_init_data_interface(chip);
+       if (ret)
+               return ret;
+
+       /*
+        * Setup the data interface correctly on the chip and controller side.
+        * This explicit call to nand_setup_data_interface() is only required
+        * for the first die, because nand_reset() has been called before
+        * ->data_interface and ->default_onfi_timing_mode were set.
+        * For the other dies, nand_reset() will automatically switch to the
+        * best mode for us.
+        */
+       ret = nand_setup_data_interface(chip);
+       if (ret)
+               return ret;
+
        chip->select_chip(mtd, -1);
 
        /* Check for a chip array */
        for (i = 1; i < maxchips; i++) {
-               chip->select_chip(mtd, i);
                /* See comment in nand_get_flash_type for reset */
-               chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+               nand_reset(chip, i);
+
+               chip->select_chip(mtd, i);
                /* Send the command for reading device ID */
                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
                /* Read manufacturer and device IDs */
@@ -3927,6 +4099,26 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
        return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds;
 }
 
+static bool invalid_ecc_page_accessors(struct nand_chip *chip)
+{
+       struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+       if (nand_standard_page_accessors(ecc))
+               return false;
+
+       /*
+        * NAND_ECC_CUSTOM_PAGE_ACCESS flag is set, make sure the NAND
+        * controller driver implements all the page accessors because
+        * default helpers are not suitable when the core does not
+        * send the READ0/PAGEPROG commands.
+        */
+       return (!ecc->read_page || !ecc->write_page ||
+               !ecc->read_page_raw || !ecc->write_page_raw ||
+               (NAND_HAS_SUBPAGE_READ(chip) && !ecc->read_subpage) ||
+               (NAND_HAS_SUBPAGE_WRITE(chip) && !ecc->write_subpage &&
+                ecc->hwctl && ecc->calculate));
+}
+
 /**
  * nand_scan_tail - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
@@ -3946,6 +4138,11 @@ int nand_scan_tail(struct mtd_info *mtd)
        BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
                        !(chip->bbt_options & NAND_BBT_USE_FLASH));
 
+       if (invalid_ecc_page_accessors(chip)) {
+               pr_err("Invalid ECC page accessors setup\n");
+               return -EINVAL;
+       }
+
        if (!(chip->options & NAND_OWN_BUFFERS)) {
                nbuf = kzalloc(sizeof(struct nand_buffers), GFP_KERNEL);
                chip->buffers = nbuf;