diff options
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.patch | 1586 |
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); - |