aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch')
-rw-r--r--target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch1586
1 files changed, 0 insertions, 1586 deletions
diff --git a/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch b/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch
deleted file mode 100644
index 03dcb07554..0000000000
--- a/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch
+++ /dev/null
@@ -1,1586 +0,0 @@
-commit 97d90da8a886949f09bb4754843fb0b504956ad2
-Author: Boris Brezillon <boris.brezillon@free-electrons.com>
-Date: Thu Nov 30 18:01:29 2017 +0100
-
- mtd: nand: provide several helpers to do common NAND operations
-
- This is part of the process of removing direct calls to ->cmdfunc()
- outside of the core in order to introduce a better interface to execute
- NAND operations.
-
- Here we provide several helpers and make use of them to remove all
- direct calls to ->cmdfunc(). This way, we can easily modify those
- helpers to make use of the new ->exec_op() interface when available.
-
- Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
- [miquel.raynal@free-electrons.com: rebased and fixed some conflicts]
- Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
- Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
-
---- a/drivers/mtd/nand/nand_base.c
-+++ b/drivers/mtd/nand/nand_base.c
-@@ -561,14 +561,19 @@ static int nand_block_markbad_lowlevel(s
- static int nand_check_wp(struct mtd_info *mtd)
- {
- struct nand_chip *chip = mtd_to_nand(mtd);
-+ u8 status;
-+ int ret;
-
- /* Broken xD cards report WP despite being writable */
- if (chip->options & NAND_BROKEN_XD)
- return 0;
-
- /* Check the WP bit */
-- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-- return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
-+ ret = nand_status_op(chip, &status);
-+ if (ret)
-+ return ret;
-+
-+ return status & NAND_STATUS_WP ? 0 : 1;
- }
-
- /**
-@@ -667,10 +672,17 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
- static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
- {
- register struct nand_chip *chip = mtd_to_nand(mtd);
-+ int ret;
-
- timeo = jiffies + msecs_to_jiffies(timeo);
- do {
-- if ((chip->read_byte(mtd) & NAND_STATUS_READY))
-+ u8 status;
-+
-+ ret = nand_read_data_op(chip, &status, sizeof(status), true);
-+ if (ret)
-+ return;
-+
-+ if (status & NAND_STATUS_READY)
- break;
- touch_softlockup_watchdog();
- } while (time_before(jiffies, timeo));
-@@ -1021,7 +1033,15 @@ static void panic_nand_wait(struct mtd_i
- if (chip->dev_ready(mtd))
- break;
- } else {
-- if (chip->read_byte(mtd) & NAND_STATUS_READY)
-+ int ret;
-+ u8 status;
-+
-+ ret = nand_read_data_op(chip, &status, sizeof(status),
-+ true);
-+ if (ret)
-+ return;
-+
-+ if (status & NAND_STATUS_READY)
- break;
- }
- mdelay(1);
-@@ -1038,8 +1058,9 @@ static void panic_nand_wait(struct mtd_i
- static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
- {
-
-- int status;
- unsigned long timeo = 400;
-+ u8 status;
-+ int ret;
-
- /*
- * Apply this short delay always to ensure that we do wait tWB in any
-@@ -1047,7 +1068,9 @@ static int nand_wait(struct mtd_info *mt
- */
- ndelay(100);
-
-- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-+ ret = nand_status_op(chip, NULL);
-+ if (ret)
-+ return ret;
-
- if (in_interrupt() || oops_in_progress)
- panic_nand_wait(mtd, chip, timeo);
-@@ -1058,14 +1081,22 @@ static int nand_wait(struct mtd_info *mt
- if (chip->dev_ready(mtd))
- break;
- } else {
-- if (chip->read_byte(mtd) & NAND_STATUS_READY)
-+ ret = nand_read_data_op(chip, &status,
-+ sizeof(status), true);
-+ if (ret)
-+ return ret;
-+
-+ if (status & NAND_STATUS_READY)
- break;
- }
- cond_resched();
- } while (time_before(jiffies, timeo));
- }
-
-- status = (int)chip->read_byte(mtd);
-+ ret = nand_read_data_op(chip, &status, sizeof(status), true);
-+ if (ret)
-+ return ret;
-+
- /* This can happen if in case of timeout or buggy dev_ready */
- WARN_ON(!(status & NAND_STATUS_READY));
- return status;
-@@ -1220,6 +1251,516 @@ static void nand_release_data_interface(
- }
-
- /**
-+ * nand_read_page_op - Do a READ PAGE operation
-+ * @chip: The NAND chip
-+ * @page: page to read
-+ * @offset_in_page: offset within the page
-+ * @buf: buffer used to store the data
-+ * @len: length of the buffer
-+ *
-+ * This function issues a READ PAGE operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_read_page_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, void *buf, unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_READ0, offset_in_page, page);
-+ if (len)
-+ chip->read_buf(mtd, buf, len);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_read_page_op);
-+
-+/**
-+ * nand_read_param_page_op - Do a READ PARAMETER PAGE operation
-+ * @chip: The NAND chip
-+ * @page: parameter page to read
-+ * @buf: buffer used to store the data
-+ * @len: length of the buffer
-+ *
-+ * This function issues a READ PARAMETER PAGE operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf,
-+ unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ unsigned int i;
-+ u8 *p = buf;
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_PARAM, page, -1);
-+ for (i = 0; i < len; i++)
-+ p[i] = chip->read_byte(mtd);
-+
-+ return 0;
-+}
-+
-+/**
-+ * nand_change_read_column_op - Do a CHANGE READ COLUMN operation
-+ * @chip: The NAND chip
-+ * @offset_in_page: offset within the page
-+ * @buf: buffer used to store the data
-+ * @len: length of the buffer
-+ * @force_8bit: force 8-bit bus access
-+ *
-+ * This function issues a CHANGE READ COLUMN operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_change_read_column_op(struct nand_chip *chip,
-+ unsigned int offset_in_page, void *buf,
-+ unsigned int len, bool force_8bit)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset_in_page, -1);
-+ if (len)
-+ chip->read_buf(mtd, buf, len);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_change_read_column_op);
-+
-+/**
-+ * nand_read_oob_op - Do a READ OOB operation
-+ * @chip: The NAND chip
-+ * @page: page to read
-+ * @offset_in_oob: offset within the OOB area
-+ * @buf: buffer used to store the data
-+ * @len: length of the buffer
-+ *
-+ * This function issues a READ OOB operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_oob, void *buf, unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_oob + len > mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_READOOB, offset_in_oob, page);
-+ if (len)
-+ chip->read_buf(mtd, buf, len);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_read_oob_op);
-+
-+/**
-+ * nand_prog_page_begin_op - starts a PROG PAGE operation
-+ * @chip: The NAND chip
-+ * @page: page to write
-+ * @offset_in_page: offset within the page
-+ * @buf: buffer containing the data to write to the page
-+ * @len: length of the buffer
-+ *
-+ * This function issues the first half of a PROG PAGE operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, const void *buf,
-+ unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page);
-+
-+ if (buf)
-+ chip->write_buf(mtd, buf, len);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_prog_page_begin_op);
-+
-+/**
-+ * nand_prog_page_end_op - ends a PROG PAGE operation
-+ * @chip: The NAND chip
-+ *
-+ * This function issues the second half of a PROG PAGE operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_prog_page_end_op(struct nand_chip *chip)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ int status;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-+
-+ status = chip->waitfunc(mtd, chip);
-+ if (status & NAND_STATUS_FAIL)
-+ return -EIO;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_prog_page_end_op);
-+
-+/**
-+ * nand_prog_page_op - Do a full PROG PAGE operation
-+ * @chip: The NAND chip
-+ * @page: page to write
-+ * @offset_in_page: offset within the page
-+ * @buf: buffer containing the data to write to the page
-+ * @len: length of the buffer
-+ *
-+ * This function issues a full PROG PAGE operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, const void *buf,
-+ unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ int status;
-+
-+ if (!len || !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page);
-+ chip->write_buf(mtd, buf, len);
-+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-+
-+ status = chip->waitfunc(mtd, chip);
-+ if (status & NAND_STATUS_FAIL)
-+ return -EIO;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_prog_page_op);
-+
-+/**
-+ * nand_change_write_column_op - Do a CHANGE WRITE COLUMN operation
-+ * @chip: The NAND chip
-+ * @offset_in_page: offset within the page
-+ * @buf: buffer containing the data to send to the NAND
-+ * @len: length of the buffer
-+ * @force_8bit: force 8-bit bus access
-+ *
-+ * This function issues a CHANGE WRITE COLUMN operation.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_change_write_column_op(struct nand_chip *chip,
-+ unsigned int offset_in_page,
-+ const void *buf, unsigned int len,
-+ bool force_8bit)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ if (offset_in_page + len > mtd->writesize + mtd->oobsize)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset_in_page, -1);
-+ if (len)
-+ chip->write_buf(mtd, buf, len);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_change_write_column_op);
-+
-+/**
-+ * nand_readid_op - Do a READID operation
-+ * @chip: The NAND chip
-+ * @addr: address cycle to pass after the READID command
-+ * @buf: buffer used to store the ID
-+ * @len: length of the buffer
-+ *
-+ * This function sends a READID command and reads back the ID returned by the
-+ * NAND.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
-+ unsigned int len)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ unsigned int i;
-+ u8 *id = buf;
-+
-+ if (len && !buf)
-+ return -EINVAL;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_READID, addr, -1);
-+
-+ for (i = 0; i < len; i++)
-+ id[i] = chip->read_byte(mtd);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_readid_op);
-+
-+/**
-+ * nand_status_op - Do a STATUS operation
-+ * @chip: The NAND chip
-+ * @status: out variable to store the NAND status
-+ *
-+ * This function sends a STATUS command and reads back the status returned by
-+ * the NAND.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_status_op(struct nand_chip *chip, u8 *status)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-+ if (status)
-+ *status = chip->read_byte(mtd);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_status_op);
-+
-+/**
-+ * nand_exit_status_op - Exit a STATUS operation
-+ * @chip: The NAND chip
-+ *
-+ * This function sends a READ0 command to cancel the effect of the STATUS
-+ * command to avoid reading only the status until a new read command is sent.
-+ *
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_exit_status_op(struct nand_chip *chip)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_exit_status_op);
-+
-+/**
-+ * nand_erase_op - Do an erase operation
-+ * @chip: The NAND chip
-+ * @eraseblock: block to erase
-+ *
-+ * This function sends an ERASE command and waits for the NAND to be ready
-+ * before returning.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ unsigned int page = eraseblock <<
-+ (chip->phys_erase_shift - chip->page_shift);
-+ int status;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
-+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-+
-+ status = chip->waitfunc(mtd, chip);
-+ if (status < 0)
-+ return status;
-+
-+ if (status & NAND_STATUS_FAIL)
-+ return -EIO;
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_erase_op);
-+
-+/**
-+ * nand_set_features_op - Do a SET FEATURES operation
-+ * @chip: The NAND chip
-+ * @feature: feature id
-+ * @data: 4 bytes of data
-+ *
-+ * This function sends a SET FEATURES command and waits for the NAND to be
-+ * ready before returning.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+static int nand_set_features_op(struct nand_chip *chip, u8 feature,
-+ const void *data)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ const u8 *params = data;
-+ int i, status;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1);
-+ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
-+ chip->write_byte(mtd, params[i]);
-+
-+ status = chip->waitfunc(mtd, chip);
-+ if (status & NAND_STATUS_FAIL)
-+ return -EIO;
-+
-+ return 0;
-+}
-+
-+/**
-+ * nand_get_features_op - Do a GET FEATURES operation
-+ * @chip: The NAND chip
-+ * @feature: feature id
-+ * @data: 4 bytes of data
-+ *
-+ * This function sends a GET FEATURES command and waits for the NAND to be
-+ * ready before returning.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+static int nand_get_features_op(struct nand_chip *chip, u8 feature,
-+ void *data)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+ u8 *params = data;
-+ int i;
-+
-+ chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1);
-+ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
-+ params[i] = chip->read_byte(mtd);
-+
-+ return 0;
-+}
-+
-+/**
-+ * nand_reset_op - Do a reset operation
-+ * @chip: The NAND chip
-+ *
-+ * This function sends a RESET command and waits for the NAND to be ready
-+ * before returning.
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_reset_op(struct nand_chip *chip)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_reset_op);
-+
-+/**
-+ * nand_read_data_op - Read data from the NAND
-+ * @chip: The NAND chip
-+ * @buf: buffer used to store the data
-+ * @len: length of the buffer
-+ * @force_8bit: force 8-bit bus access
-+ *
-+ * This function does a raw data read on the bus. Usually used after launching
-+ * another NAND operation like nand_read_page_op().
-+ * This function does not select/unselect the CS line.
-+ *
-+ * 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)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (!len || !buf)
-+ return -EINVAL;
-+
-+ if (force_8bit) {
-+ u8 *p = buf;
-+ unsigned int i;
-+
-+ for (i = 0; i < len; i++)
-+ p[i] = chip->read_byte(mtd);
-+ } else {
-+ chip->read_buf(mtd, buf, len);
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_read_data_op);
-+
-+/**
-+ * nand_write_data_op - Write data from the NAND
-+ * @chip: The NAND chip
-+ * @buf: buffer containing the data to send on the bus
-+ * @len: length of the buffer
-+ * @force_8bit: force 8-bit bus access
-+ *
-+ * This function does a raw data write on the bus. Usually used after launching
-+ * another NAND operation like nand_write_page_begin_op().
-+ * This function does not select/unselect the CS line.
-+ *
-+ * Returns 0 on success, a negative error code otherwise.
-+ */
-+int nand_write_data_op(struct nand_chip *chip, const void *buf,
-+ unsigned int len, bool force_8bit)
-+{
-+ struct mtd_info *mtd = nand_to_mtd(chip);
-+
-+ if (!len || !buf)
-+ return -EINVAL;
-+
-+ if (force_8bit) {
-+ const u8 *p = buf;
-+ unsigned int i;
-+
-+ for (i = 0; i < len; i++)
-+ chip->write_byte(mtd, p[i]);
-+ } else {
-+ chip->write_buf(mtd, buf, len);
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(nand_write_data_op);
-+
-+/**
- * nand_reset - Reset and initialize a NAND device
- * @chip: The NAND chip
- * @chipnr: Internal die id
-@@ -1240,8 +1781,10 @@ int nand_reset(struct nand_chip *chip, i
- * interface settings, hence this weird ->select_chip() dance.
- */
- chip->select_chip(mtd, chipnr);
-- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+ ret = nand_reset_op(chip);
- chip->select_chip(mtd, -1);
-+ if (ret)
-+ return ret;
-
- chip->select_chip(mtd, chipnr);
- ret = nand_setup_data_interface(chip, chipnr);
-@@ -1397,9 +1940,19 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chun
- int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
- {
-- chip->read_buf(mtd, buf, mtd->writesize);
-- if (oob_required)
-- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-+ int ret;
-+
-+ ret = nand_read_data_op(chip, buf, mtd->writesize, false);
-+ if (ret)
-+ return ret;
-+
-+ if (oob_required) {
-+ ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
-+ false);
-+ if (ret)
-+ return ret;
-+ }
-+
- return 0;
- }
- EXPORT_SYMBOL(nand_read_page_raw);
-@@ -1421,29 +1974,46 @@ static int nand_read_page_raw_syndrome(s
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- uint8_t *oob = chip->oob_poi;
-- int steps, size;
-+ int steps, size, ret;
-
- for (steps = chip->ecc.steps; steps > 0; steps--) {
-- chip->read_buf(mtd, buf, eccsize);
-+ ret = nand_read_data_op(chip, buf, eccsize, false);
-+ if (ret)
-+ return ret;
-+
- buf += eccsize;
-
- if (chip->ecc.prepad) {
-- chip->read_buf(mtd, oob, chip->ecc.prepad);
-+ ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.prepad;
- }
-
-- chip->read_buf(mtd, oob, eccbytes);
-+ ret = nand_read_data_op(chip, oob, eccbytes, false);
-+ if (ret)
-+ return ret;
-+
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
-- chip->read_buf(mtd, oob, chip->ecc.postpad);
-+ ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
-- if (size)
-- chip->read_buf(mtd, oob, size);
-+ if (size) {
-+ ret = nand_read_data_op(chip, oob, size, false);
-+ if (ret)
-+ return ret;
-+ }
-
- return 0;
- }
-@@ -1532,7 +2102,9 @@ static int nand_read_subpage(struct mtd_
- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
-
- p = bufpoi + data_col_addr;
-- chip->read_buf(mtd, p, datafrag_len);
-+ ret = nand_read_data_op(chip, p, datafrag_len, false);
-+ if (ret)
-+ return ret;
-
- /* Calculate ECC */
- for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
-@@ -1550,8 +2122,11 @@ static int nand_read_subpage(struct mtd_
- gaps = 1;
-
- if (gaps) {
-- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
-- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-+ ret = nand_change_read_column_op(chip, mtd->writesize,
-+ chip->oob_poi, mtd->oobsize,
-+ false);
-+ if (ret)
-+ return ret;
- } else {
- /*
- * Send the command to read the particular ECC bytes take care
-@@ -1565,9 +2140,12 @@ static int nand_read_subpage(struct mtd_
- (busw - 1))
- aligned_len++;
-
-- chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
-- mtd->writesize + aligned_pos, -1);
-- chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
-+ ret = nand_change_read_column_op(chip,
-+ mtd->writesize + aligned_pos,
-+ &chip->oob_poi[aligned_pos],
-+ aligned_len, false);
-+ if (ret)
-+ return ret;
- }
-
- ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode,
-@@ -1624,10 +2202,17 @@ static int nand_read_page_hwecc(struct m
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
-- chip->read_buf(mtd, p, eccsize);
-+
-+ ret = nand_read_data_op(chip, p, eccsize, false);
-+ if (ret)
-+ return ret;
-+
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- }
-- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-+
-+ ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false);
-+ if (ret)
-+ return ret;
-
- ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
- chip->ecc.total);
-@@ -1686,9 +2271,13 @@ static int nand_read_page_hwecc_oob_firs
- unsigned int max_bitflips = 0;
-
- /* Read the OOB area first */
-- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
-- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-- chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
-+ ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
-+ if (ret)
-+ return ret;
-+
-+ ret = nand_read_page_op(chip, page, 0, NULL, 0);
-+ if (ret)
-+ return ret;
-
- ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
- chip->ecc.total);
-@@ -1699,7 +2288,11 @@ static int nand_read_page_hwecc_oob_firs
- int stat;
-
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
-- chip->read_buf(mtd, p, eccsize);
-+
-+ ret = nand_read_data_op(chip, p, eccsize, false);
-+ if (ret)
-+ return ret;
-+
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
-
- stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
-@@ -1736,7 +2329,7 @@ static int nand_read_page_hwecc_oob_firs
- static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
- {
-- int i, eccsize = chip->ecc.size;
-+ int ret, i, eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- int eccsteps = chip->ecc.steps;
- int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
-@@ -1748,21 +2341,36 @@ static int nand_read_page_syndrome(struc
- int stat;
-
- chip->ecc.hwctl(mtd, NAND_ECC_READ);
-- chip->read_buf(mtd, p, eccsize);
-+
-+ ret = nand_read_data_op(chip, p, eccsize, false);
-+ if (ret)
-+ return ret;
-
- if (chip->ecc.prepad) {
-- chip->read_buf(mtd, oob, chip->ecc.prepad);
-+ ret = nand_read_data_op(chip, oob, chip->ecc.prepad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.prepad;
- }
-
- chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
-- chip->read_buf(mtd, oob, eccbytes);
-+
-+ ret = nand_read_data_op(chip, oob, eccbytes, false);
-+ if (ret)
-+ return ret;
-+
- stat = chip->ecc.correct(mtd, p, oob, NULL);
-
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
-- chip->read_buf(mtd, oob, chip->ecc.postpad);
-+ ret = nand_read_data_op(chip, oob, chip->ecc.postpad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.postpad;
- }
-
-@@ -1786,8 +2394,11 @@ static int nand_read_page_syndrome(struc
-
- /* Calculate remaining oob bytes */
- i = mtd->oobsize - (oob - chip->oob_poi);
-- if (i)
-- chip->read_buf(mtd, oob, i);
-+ if (i) {
-+ ret = nand_read_data_op(chip, oob, i, false);
-+ if (ret)
-+ return ret;
-+ }
-
- return max_bitflips;
- }
-@@ -1908,8 +2519,11 @@ static int nand_do_read_ops(struct mtd_i
- __func__, buf);
-
- read_retry:
-- if (nand_standard_page_accessors(&chip->ecc))
-- chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
-+ if (nand_standard_page_accessors(&chip->ecc)) {
-+ ret = nand_read_page_op(chip, page, 0, NULL, 0);
-+ if (ret)
-+ break;
-+ }
-
- /*
- * Now read the page into the buffer. Absent an error,
-@@ -2068,9 +2682,7 @@ static int nand_read(struct mtd_info *mt
- */
- int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page)
- {
-- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
-- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-- return 0;
-+ return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
- }
- EXPORT_SYMBOL(nand_read_oob_std);
-
-@@ -2088,25 +2700,43 @@ int nand_read_oob_syndrome(struct mtd_in
- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsize = chip->ecc.size;
- uint8_t *bufpoi = chip->oob_poi;
-- int i, toread, sndrnd = 0, pos;
-+ int i, toread, sndrnd = 0, pos, ret;
-+
-+ ret = nand_read_page_op(chip, page, chip->ecc.size, NULL, 0);
-+ if (ret)
-+ return ret;
-
-- chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
- for (i = 0; i < chip->ecc.steps; i++) {
- if (sndrnd) {
-+ int ret;
-+
- pos = eccsize + i * (eccsize + chunk);
- if (mtd->writesize > 512)
-- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
-+ ret = nand_change_read_column_op(chip, pos,
-+ NULL, 0,
-+ false);
- else
-- chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
-+ ret = nand_read_page_op(chip, page, pos, NULL,
-+ 0);
-+
-+ if (ret)
-+ return ret;
- } else
- sndrnd = 1;
- toread = min_t(int, length, chunk);
-- chip->read_buf(mtd, bufpoi, toread);
-+
-+ ret = nand_read_data_op(chip, bufpoi, toread, false);
-+ if (ret)
-+ return ret;
-+
- bufpoi += toread;
- length -= toread;
- }
-- if (length > 0)
-- chip->read_buf(mtd, bufpoi, length);
-+ if (length > 0) {
-+ ret = nand_read_data_op(chip, bufpoi, length, false);
-+ if (ret)
-+ return ret;
-+ }
-
- return 0;
- }
-@@ -2120,18 +2750,8 @@ EXPORT_SYMBOL(nand_read_oob_syndrome);
- */
- int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page)
- {
-- int status = 0;
-- const uint8_t *buf = chip->oob_poi;
-- int length = mtd->oobsize;
--
-- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
-- chip->write_buf(mtd, buf, length);
-- /* Send command to program the OOB data */
-- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
--
-- status = chip->waitfunc(mtd, chip);
--
-- return status & NAND_STATUS_FAIL ? -EIO : 0;
-+ return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi,
-+ mtd->oobsize);
- }
- EXPORT_SYMBOL(nand_write_oob_std);
-
-@@ -2147,7 +2767,7 @@ int nand_write_oob_syndrome(struct mtd_i
- {
- int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
- int eccsize = chip->ecc.size, length = mtd->oobsize;
-- int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
-+ int ret, i, len, pos, sndcmd = 0, steps = chip->ecc.steps;
- const uint8_t *bufpoi = chip->oob_poi;
-
- /*
-@@ -2161,7 +2781,10 @@ int nand_write_oob_syndrome(struct mtd_i
- } else
- pos = eccsize;
-
-- chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
-+ ret = nand_prog_page_begin_op(chip, page, pos, NULL, 0);
-+ if (ret)
-+ return ret;
-+
- for (i = 0; i < steps; i++) {
- if (sndcmd) {
- if (mtd->writesize <= 512) {
-@@ -2170,28 +2793,40 @@ int nand_write_oob_syndrome(struct mtd_i
- len = eccsize;
- while (len > 0) {
- int num = min_t(int, len, 4);
-- chip->write_buf(mtd, (uint8_t *)&fill,
-- num);
-+
-+ ret = nand_write_data_op(chip, &fill,
-+ num, false);
-+ if (ret)
-+ return ret;
-+
- len -= num;
- }
- } else {
- pos = eccsize + i * (eccsize + chunk);
-- chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
-+ ret = nand_change_write_column_op(chip, pos,
-+ NULL, 0,
-+ false);
-+ if (ret)
-+ return ret;
- }
- } else
- sndcmd = 1;
- len = min_t(int, length, chunk);
-- chip->write_buf(mtd, bufpoi, len);
-+
-+ ret = nand_write_data_op(chip, bufpoi, len, false);
-+ if (ret)
-+ return ret;
-+
- bufpoi += len;
- length -= len;
- }
-- if (length > 0)
-- chip->write_buf(mtd, bufpoi, length);
--
-- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-- status = chip->waitfunc(mtd, chip);
-+ if (length > 0) {
-+ ret = nand_write_data_op(chip, bufpoi, length, false);
-+ if (ret)
-+ return ret;
-+ }
-
-- return status & NAND_STATUS_FAIL ? -EIO : 0;
-+ return nand_prog_page_end_op(chip);
- }
- EXPORT_SYMBOL(nand_write_oob_syndrome);
-
-@@ -2346,9 +2981,18 @@ static int nand_read_oob(struct mtd_info
- int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page)
- {
-- chip->write_buf(mtd, buf, mtd->writesize);
-- if (oob_required)
-- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+ int ret;
-+
-+ ret = nand_write_data_op(chip, buf, mtd->writesize, false);
-+ if (ret)
-+ return ret;
-+
-+ if (oob_required) {
-+ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize,
-+ false);
-+ if (ret)
-+ return ret;
-+ }
-
- return 0;
- }
-@@ -2372,29 +3016,46 @@ static int nand_write_page_raw_syndrome(
- int eccsize = chip->ecc.size;
- int eccbytes = chip->ecc.bytes;
- uint8_t *oob = chip->oob_poi;
-- int steps, size;
-+ int steps, size, ret;
-
- for (steps = chip->ecc.steps; steps > 0; steps--) {
-- chip->write_buf(mtd, buf, eccsize);
-+ ret = nand_write_data_op(chip, buf, eccsize, false);
-+ if (ret)
-+ return ret;
-+
- buf += eccsize;
-
- if (chip->ecc.prepad) {
-- chip->write_buf(mtd, oob, chip->ecc.prepad);
-+ ret = nand_write_data_op(chip, oob, chip->ecc.prepad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.prepad;
- }
-
-- chip->write_buf(mtd, oob, eccbytes);
-+ ret = nand_write_data_op(chip, oob, eccbytes, false);
-+ if (ret)
-+ return ret;
-+
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
-- chip->write_buf(mtd, oob, chip->ecc.postpad);
-+ ret = nand_write_data_op(chip, oob, chip->ecc.postpad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.postpad;
- }
- }
-
- size = mtd->oobsize - (oob - chip->oob_poi);
-- if (size)
-- chip->write_buf(mtd, oob, size);
-+ if (size) {
-+ ret = nand_write_data_op(chip, oob, size, false);
-+ if (ret)
-+ return ret;
-+ }
-
- return 0;
- }
-@@ -2448,7 +3109,11 @@ static int nand_write_page_hwecc(struct
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-- chip->write_buf(mtd, p, eccsize);
-+
-+ ret = nand_write_data_op(chip, p, eccsize, false);
-+ if (ret)
-+ return ret;
-+
- chip->ecc.calculate(mtd, p, &ecc_calc[i]);
- }
-
-@@ -2457,7 +3122,9 @@ static int nand_write_page_hwecc(struct
- if (ret)
- return ret;
-
-- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false);
-+ if (ret)
-+ return ret;
-
- return 0;
- }
-@@ -2493,7 +3160,9 @@ static int nand_write_subpage_hwecc(stru
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-
- /* write data (untouched subpages already masked by 0xFF) */
-- chip->write_buf(mtd, buf, ecc_size);
-+ ret = nand_write_data_op(chip, buf, ecc_size, false);
-+ if (ret)
-+ return ret;
-
- /* mask ECC of un-touched subpages by padding 0xFF */
- if ((step < start_step) || (step > end_step))
-@@ -2520,7 +3189,9 @@ static int nand_write_subpage_hwecc(stru
- return ret;
-
- /* write OOB buffer to NAND device */
-- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-+ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false);
-+ if (ret)
-+ return ret;
-
- return 0;
- }
-@@ -2547,31 +3218,49 @@ static int nand_write_page_syndrome(stru
- int eccsteps = chip->ecc.steps;
- const uint8_t *p = buf;
- uint8_t *oob = chip->oob_poi;
-+ int ret;
-
- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
--
- chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-- chip->write_buf(mtd, p, eccsize);
-+
-+ ret = nand_write_data_op(chip, p, eccsize, false);
-+ if (ret)
-+ return ret;
-
- if (chip->ecc.prepad) {
-- chip->write_buf(mtd, oob, chip->ecc.prepad);
-+ ret = nand_write_data_op(chip, oob, chip->ecc.prepad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.prepad;
- }
-
- chip->ecc.calculate(mtd, p, oob);
-- chip->write_buf(mtd, oob, eccbytes);
-+
-+ ret = nand_write_data_op(chip, oob, eccbytes, false);
-+ if (ret)
-+ return ret;
-+
- oob += eccbytes;
-
- if (chip->ecc.postpad) {
-- chip->write_buf(mtd, oob, chip->ecc.postpad);
-+ ret = nand_write_data_op(chip, oob, chip->ecc.postpad,
-+ false);
-+ if (ret)
-+ return ret;
-+
- oob += chip->ecc.postpad;
- }
- }
-
- /* Calculate remaining oob bytes */
- i = mtd->oobsize - (oob - chip->oob_poi);
-- if (i)
-- chip->write_buf(mtd, oob, i);
-+ if (i) {
-+ ret = nand_write_data_op(chip, oob, i, false);
-+ if (ret)
-+ return ret;
-+ }
-
- return 0;
- }
-@@ -2599,8 +3288,11 @@ static int nand_write_page(struct mtd_in
- else
- subpage = 0;
-
-- if (nand_standard_page_accessors(&chip->ecc))
-- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-+ if (nand_standard_page_accessors(&chip->ecc)) {
-+ status = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
-+ if (status)
-+ return status;
-+ }
-
- if (unlikely(raw))
- status = chip->ecc.write_page_raw(mtd, chip, buf,
-@@ -2615,13 +3307,8 @@ static int nand_write_page(struct mtd_in
- if (status < 0)
- return status;
-
-- if (nand_standard_page_accessors(&chip->ecc)) {
-- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
--
-- status = chip->waitfunc(mtd, chip);
-- if (status & NAND_STATUS_FAIL)
-- return -EIO;
-- }
-+ if (nand_standard_page_accessors(&chip->ecc))
-+ return nand_prog_page_end_op(chip);
-
- return 0;
- }
-@@ -2994,17 +3681,12 @@ out:
- static int single_erase(struct mtd_info *mtd, int page)
- {
- struct nand_chip *chip = mtd_to_nand(mtd);
-- int status;
-+ unsigned int eraseblock;
-
- /* Send commands to erase a block */
-- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
-- chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
--
-- status = chip->waitfunc(mtd, chip);
-- if (status < 0)
-- return status;
-+ eraseblock = page >> (chip->phys_erase_shift - chip->page_shift);
-
-- return status & NAND_STATUS_FAIL ? -EIO : 0;
-+ return nand_erase_op(chip, eraseblock);
- }
-
- /**
-@@ -3231,22 +3913,12 @@ static int nand_max_bad_blocks(struct mt
- static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
- int addr, uint8_t *subfeature_param)
- {
-- int status;
-- int i;
--
- if (!chip->onfi_version ||
- !(le16_to_cpu(chip->onfi_params.opt_cmd)
- & ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
-
-- chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
-- for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
-- chip->write_byte(mtd, subfeature_param[i]);
--
-- status = chip->waitfunc(mtd, chip);
-- if (status & NAND_STATUS_FAIL)
-- return -EIO;
-- return 0;
-+ return nand_set_features_op(chip, addr, subfeature_param);
- }
-
- /**
-@@ -3259,17 +3931,12 @@ static int nand_onfi_set_features(struct
- static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
- int addr, uint8_t *subfeature_param)
- {
-- int i;
--
- if (!chip->onfi_version ||
- !(le16_to_cpu(chip->onfi_params.opt_cmd)
- & ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
-
-- chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
-- for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
-- *subfeature_param++ = chip->read_byte(mtd);
-- return 0;
-+ return nand_get_features_op(chip, addr, subfeature_param);
- }
-
- /**
-@@ -3412,12 +4079,11 @@ static u16 onfi_crc16(u16 crc, u8 const
- static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
- struct nand_onfi_params *p)
- {
-- struct mtd_info *mtd = nand_to_mtd(chip);
- struct onfi_ext_param_page *ep;
- struct onfi_ext_section *s;
- struct onfi_ext_ecc_info *ecc;
- uint8_t *cursor;
-- int ret = -EINVAL;
-+ int ret;
- int len;
- int i;
-
-@@ -3427,14 +4093,18 @@ static int nand_flash_detect_ext_param_p
- return -ENOMEM;
-
- /* Send our own NAND_CMD_PARAM. */
-- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
-+ ret = nand_read_param_page_op(chip, 0, NULL, 0);
-+ if (ret)
-+ goto ext_out;
-
- /* Use the Change Read Column command to skip the ONFI param pages. */
-- chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
-- sizeof(*p) * p->num_of_param_pages , -1);
-+ ret = nand_change_read_column_op(chip,
-+ sizeof(*p) * p->num_of_param_pages,
-+ ep, len, true);
-+ if (ret)
-+ goto ext_out;
-
-- /* Read out the Extended Parameter Page. */
-- chip->read_buf(mtd, (uint8_t *)ep, len);
-+ ret = -EINVAL;
- if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2)
- != le16_to_cpu(ep->crc))) {
- pr_debug("fail in the CRC.\n");
-@@ -3487,19 +4157,23 @@ static int nand_flash_detect_onfi(struct
- {
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_onfi_params *p = &chip->onfi_params;
-- int i, j;
-- int val;
-+ char id[4];
-+ int i, ret, val;
-
- /* Try ONFI for unknown chip or LP */
-- chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
-- if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
-- chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
-+ ret = nand_readid_op(chip, 0x20, id, sizeof(id));
-+ if (ret || strncmp(id, "ONFI", 4))
-+ return 0;
-+
-+ ret = nand_read_param_page_op(chip, 0, NULL, 0);
-+ if (ret)
- return 0;
-
-- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
- for (i = 0; i < 3; i++) {
-- for (j = 0; j < sizeof(*p); j++)
-- ((uint8_t *)p)[j] = chip->read_byte(mtd);
-+ ret = nand_read_data_op(chip, p, sizeof(*p), true);
-+ if (ret)
-+ return 0;
-+
- if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
- le16_to_cpu(p->crc)) {
- break;
-@@ -3590,20 +4264,22 @@ static int nand_flash_detect_jedec(struc
- struct mtd_info *mtd = nand_to_mtd(chip);
- struct nand_jedec_params *p = &chip->jedec_params;
- struct jedec_ecc_info *ecc;
-- int val;
-- int i, j;
-+ char id[5];
-+ int i, val, ret;
-
- /* Try JEDEC for unknown chip or LP */
-- chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
-- if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' ||
-- chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' ||
-- chip->read_byte(mtd) != 'C')
-+ ret = nand_readid_op(chip, 0x40, id, sizeof(id));
-+ if (ret || strncmp(id, "JEDEC", sizeof(id)))
-+ return 0;
-+
-+ ret = nand_read_param_page_op(chip, 0x40, NULL, 0);
-+ if (ret)
- return 0;
-
-- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1);
- for (i = 0; i < 3; i++) {
-- for (j = 0; j < sizeof(*p); j++)
-- ((uint8_t *)p)[j] = chip->read_byte(mtd);
-+ ret = nand_read_data_op(chip, p, sizeof(*p), true);
-+ if (ret)
-+ return 0;
-
- if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) ==
- le16_to_cpu(p->crc))
-@@ -3882,8 +4558,7 @@ static int nand_detect(struct nand_chip
- {
- const struct nand_manufacturer *manufacturer;
- struct mtd_info *mtd = nand_to_mtd(chip);
-- int busw;
-- int i;
-+ int busw, ret;
- u8 *id_data = chip->id.data;
- u8 maf_id, dev_id;
-
-@@ -3891,17 +4566,21 @@ static int nand_detect(struct nand_chip
- * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
- * after power-up.
- */
-- nand_reset(chip, 0);
-+ ret = nand_reset(chip, 0);
-+ if (ret)
-+ return ret;
-
- /* Select the device */
- chip->select_chip(mtd, 0);
-
- /* Send the command for reading device ID */
-- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
-+ ret = nand_readid_op(chip, 0, id_data, 2);
-+ if (ret)
-+ return ret;
-
- /* Read manufacturer and device IDs */
-- maf_id = chip->read_byte(mtd);
-- dev_id = chip->read_byte(mtd);
-+ maf_id = id_data[0];
-+ dev_id = id_data[1];
-
- /*
- * Try again to make sure, as some systems the bus-hold or other
-@@ -3910,11 +4589,10 @@ static int nand_detect(struct nand_chip
- * not match, ignore the device completely.
- */
-
-- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
--
- /* Read entire ID string */
-- for (i = 0; i < ARRAY_SIZE(chip->id.data); i++)
-- id_data[i] = chip->read_byte(mtd);
-+ ret = nand_readid_op(chip, 0, id_data, sizeof(chip->id.data));
-+ if (ret)
-+ return ret;
-
- if (id_data[0] != maf_id || id_data[1] != dev_id) {
- pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
-@@ -4238,15 +4916,16 @@ int nand_scan_ident(struct mtd_info *mtd
-
- /* Check for a chip array */
- for (i = 1; i < maxchips; i++) {
-+ u8 id[2];
-+
- /* See comment in nand_get_flash_type for reset */
- nand_reset(chip, i);
-
- chip->select_chip(mtd, i);
- /* Send the command for reading device ID */
-- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
-+ nand_readid_op(chip, 0, id, sizeof(id));
- /* Read manufacturer and device IDs */
-- if (nand_maf_id != chip->read_byte(mtd) ||
-- nand_dev_id != chip->read_byte(mtd)) {
-+ if (nand_maf_id != id[0] || nand_dev_id != id[1]) {
- chip->select_chip(mtd, -1);
- break;
- }
---- a/drivers/mtd/nand/qcom_nandc.c
-+++ b/drivers/mtd/nand/qcom_nandc.c
-@@ -1990,7 +1990,7 @@ static int qcom_nandc_write_oob(struct m
- struct nand_ecc_ctrl *ecc = &chip->ecc;
- u8 *oob = chip->oob_poi;
- int data_size, oob_size;
-- int ret, status = 0;
-+ int ret;
-
- host->use_ecc = true;
-
-@@ -2027,11 +2027,7 @@ static int qcom_nandc_write_oob(struct m
- return -EIO;
- }
-
-- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
--
-- status = chip->waitfunc(mtd, chip);
--
-- return status & NAND_STATUS_FAIL ? -EIO : 0;
-+ return nand_prog_page_end_op(chip);
- }
-
- static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
-@@ -2081,7 +2077,7 @@ static int qcom_nandc_block_markbad(stru
- struct qcom_nand_host *host = to_qcom_nand_host(chip);
- struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
-- int page, ret, status = 0;
-+ int page, ret;
-
- clear_read_regs(nandc);
- clear_bam_transaction(nandc);
-@@ -2114,11 +2110,7 @@ static int qcom_nandc_block_markbad(stru
- return -EIO;
- }
-
-- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
--
-- status = chip->waitfunc(mtd, chip);
--
-- return status & NAND_STATUS_FAIL ? -EIO : 0;
-+ return nand_prog_page_end_op(chip);
- }
-
- /*
---- a/include/linux/mtd/rawnand.h
-+++ b/include/linux/mtd/rawnand.h
-@@ -1313,6 +1313,35 @@ int nand_write_page_raw(struct mtd_info
- /* Reset and initialize a NAND device */
- int nand_reset(struct nand_chip *chip, int chipnr);
-
-+/* NAND operation helpers */
-+int nand_reset_op(struct nand_chip *chip);
-+int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
-+ unsigned int len);
-+int nand_status_op(struct nand_chip *chip, u8 *status);
-+int nand_exit_status_op(struct nand_chip *chip);
-+int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock);
-+int nand_read_page_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, void *buf, unsigned int len);
-+int nand_change_read_column_op(struct nand_chip *chip,
-+ unsigned int offset_in_page, void *buf,
-+ unsigned int len, bool force_8bit);
-+int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, void *buf, unsigned int len);
-+int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, const void *buf,
-+ unsigned int len);
-+int nand_prog_page_end_op(struct nand_chip *chip);
-+int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
-+ unsigned int offset_in_page, const void *buf,
-+ unsigned int len);
-+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);
-+int nand_write_data_op(struct nand_chip *chip, const void *buf,
-+ unsigned int len, bool force_8bit);
-+
- /* Free resources held by the NAND device */
- void nand_cleanup(struct nand_chip *chip);
-