summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2017-11-30 12:01:30 -0500
committerBoris Brezillon <boris.brezillon@free-electrons.com>2017-12-14 07:34:17 -0500
commit25f815f66a141436df8a4c45e5d2765272aea2ac (patch)
treec218dcaa4440f1cfbc62efbf67a1d80b72c5a4e1
parent97d90da8a886949f09bb4754843fb0b504956ad2 (diff)
mtd: nand: force drivers to explicitly send READ/PROG commands
The core currently send the READ0 and SEQIN+PAGEPROG commands in nand_do_read/write_ops(). This is inconsistent with ->read/write_oob[_raw]() hooks behavior which are expected to send these commands. There's already a flag (NAND_ECC_CUSTOM_PAGE_ACCESS) to inform the core that a specific controller wants to send the READ/SEQIN+PAGEPROG commands on its own, but it's an opt-in flag, and existing drivers are unlikely to be updated to pass it. Moreover, some controllers cannot dissociate the READ/PAGEPROG commands from the associated data transfer and ECC engine activation, and developers have to hack things in their ->cmdfunc() implementation to handle such complex cases, or have to accept the perf penalty of sending twice the same command. To address this problem we are planning on adding a new interface which is passed all information about a NAND operation (including the amount of data to transfer) and replacing all calls to ->cmdfunc() to calls to this new ->exec_op() hook. But, in order to do that, we need to have all ->cmdfunc() calls placed near their associated ->read/write_buf/byte() calls. Modify the core and relevant drivers to make NAND_ECC_CUSTOM_PAGE_ACCESS the default case, and remove this flag. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> [miquel.raynal@free-electrons.com: tested, fixed and rebased on nand/next] Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com> Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
-rw-r--r--drivers/mtd/nand/atmel/nand-controller.c7
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c6
-rw-r--r--drivers/mtd/nand/brcmnand/brcmnand.c13
-rw-r--r--drivers/mtd/nand/cafe_nand.c6
-rw-r--r--drivers/mtd/nand/denali.c1
-rw-r--r--drivers/mtd/nand/docg4.c12
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c10
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c6
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c31
-rw-r--r--drivers/mtd/nand/hisi504_nand.c6
-rw-r--r--drivers/mtd/nand/lpc32xx_mlc.c5
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c11
-rw-r--r--drivers/mtd/nand/mtk_nand.c22
-rw-r--r--drivers/mtd/nand/nand_base.c87
-rw-r--r--drivers/mtd/nand/nand_micron.c56
-rw-r--r--drivers/mtd/nand/omap2.c10
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c6
-rw-r--r--drivers/mtd/nand/qcom_nandc.c11
-rw-r--r--drivers/mtd/nand/sh_flctl.c6
-rw-r--r--drivers/mtd/nand/sunxi_nand.c34
-rw-r--r--drivers/mtd/nand/tango_nand.c1
-rw-r--r--drivers/mtd/nand/vf610_nfc.c6
-rw-r--r--drivers/staging/mt29f_spinand/mt29f_spinand.c5
-rw-r--r--include/linux/mtd/rawnand.h11
24 files changed, 171 insertions, 198 deletions
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
index e81fdd2d47b1..b2f00b398490 100644
--- a/drivers/mtd/nand/atmel/nand-controller.c
+++ b/drivers/mtd/nand/atmel/nand-controller.c
@@ -841,6 +841,8 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
841 struct atmel_nand *nand = to_atmel_nand(chip); 841 struct atmel_nand *nand = to_atmel_nand(chip);
842 int ret; 842 int ret;
843 843
844 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
845
844 ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw); 846 ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
845 if (ret) 847 if (ret)
846 return ret; 848 return ret;
@@ -857,7 +859,7 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
857 859
858 atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); 860 atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
859 861
860 return 0; 862 return nand_prog_page_end_op(chip);
861} 863}
862 864
863static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, 865static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
@@ -881,6 +883,8 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
881 struct mtd_info *mtd = nand_to_mtd(chip); 883 struct mtd_info *mtd = nand_to_mtd(chip);
882 int ret; 884 int ret;
883 885
886 nand_read_page_op(chip, page, 0, NULL, 0);
887
884 ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw); 888 ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
885 if (ret) 889 if (ret)
886 return ret; 890 return ret;
@@ -1178,7 +1182,6 @@ static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
1178 chip->ecc.write_page = atmel_hsmc_nand_pmecc_write_page; 1182 chip->ecc.write_page = atmel_hsmc_nand_pmecc_write_page;
1179 chip->ecc.read_page_raw = atmel_hsmc_nand_pmecc_read_page_raw; 1183 chip->ecc.read_page_raw = atmel_hsmc_nand_pmecc_read_page_raw;
1180 chip->ecc.write_page_raw = atmel_hsmc_nand_pmecc_write_page_raw; 1184 chip->ecc.write_page_raw = atmel_hsmc_nand_pmecc_write_page_raw;
1181 chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS;
1182 1185
1183 return 0; 1186 return 0;
1184} 1187}
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 5655dca6ce43..87bbd177b3e5 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -572,6 +572,8 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
572static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 572static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
573 uint8_t *buf, int oob_required, int page) 573 uint8_t *buf, int oob_required, int page)
574{ 574{
575 nand_read_page_op(chip, page, 0, NULL, 0);
576
575 bf5xx_nand_read_buf(mtd, buf, mtd->writesize); 577 bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
576 bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); 578 bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
577 579
@@ -582,10 +584,10 @@ static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
582 struct nand_chip *chip, const uint8_t *buf, int oob_required, 584 struct nand_chip *chip, const uint8_t *buf, int oob_required,
583 int page) 585 int page)
584{ 586{
585 bf5xx_nand_write_buf(mtd, buf, mtd->writesize); 587 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
586 bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); 588 bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
587 589
588 return 0; 590 return nand_prog_page_end_op(chip);
589} 591}
590 592
591/* 593/*
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 3f441096a14c..e6879d4d53ca 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -1689,7 +1689,6 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
1689 sas = mtd->oobsize / chip->ecc.steps; 1689 sas = mtd->oobsize / chip->ecc.steps;
1690 1690
1691 /* read without ecc for verification */ 1691 /* read without ecc for verification */
1692 nand_read_page_op(chip, page, 0, NULL, 0);
1693 ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page); 1692 ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page);
1694 if (ret) 1693 if (ret)
1695 return ret; 1694 return ret;
@@ -1793,6 +1792,8 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
1793 struct brcmnand_host *host = nand_get_controller_data(chip); 1792 struct brcmnand_host *host = nand_get_controller_data(chip);
1794 u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; 1793 u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
1795 1794
1795 nand_read_page_op(chip, page, 0, NULL, 0);
1796
1796 return brcmnand_read(mtd, chip, host->last_addr, 1797 return brcmnand_read(mtd, chip, host->last_addr,
1797 mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); 1798 mtd->writesize >> FC_SHIFT, (u32 *)buf, oob);
1798} 1799}
@@ -1804,6 +1805,8 @@ static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1804 u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; 1805 u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL;
1805 int ret; 1806 int ret;
1806 1807
1808 nand_read_page_op(chip, page, 0, NULL, 0);
1809
1807 brcmnand_set_ecc_enabled(host, 0); 1810 brcmnand_set_ecc_enabled(host, 0);
1808 ret = brcmnand_read(mtd, chip, host->last_addr, 1811 ret = brcmnand_read(mtd, chip, host->last_addr,
1809 mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); 1812 mtd->writesize >> FC_SHIFT, (u32 *)buf, oob);
@@ -1909,8 +1912,10 @@ static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1909 struct brcmnand_host *host = nand_get_controller_data(chip); 1912 struct brcmnand_host *host = nand_get_controller_data(chip);
1910 void *oob = oob_required ? chip->oob_poi : NULL; 1913 void *oob = oob_required ? chip->oob_poi : NULL;
1911 1914
1915 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1912 brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); 1916 brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob);
1913 return 0; 1917
1918 return nand_prog_page_end_op(chip);
1914} 1919}
1915 1920
1916static int brcmnand_write_page_raw(struct mtd_info *mtd, 1921static int brcmnand_write_page_raw(struct mtd_info *mtd,
@@ -1920,10 +1925,12 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd,
1920 struct brcmnand_host *host = nand_get_controller_data(chip); 1925 struct brcmnand_host *host = nand_get_controller_data(chip);
1921 void *oob = oob_required ? chip->oob_poi : NULL; 1926 void *oob = oob_required ? chip->oob_poi : NULL;
1922 1927
1928 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1923 brcmnand_set_ecc_enabled(host, 0); 1929 brcmnand_set_ecc_enabled(host, 0);
1924 brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); 1930 brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob);
1925 brcmnand_set_ecc_enabled(host, 1); 1931 brcmnand_set_ecc_enabled(host, 1);
1926 return 0; 1932
1933 return nand_prog_page_end_op(chip);
1927} 1934}
1928 1935
1929static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, 1936static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 95c2cfa68b66..de36762e3058 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -383,7 +383,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
383 cafe_readl(cafe, NAND_ECC_RESULT), 383 cafe_readl(cafe, NAND_ECC_RESULT),
384 cafe_readl(cafe, NAND_ECC_SYN01)); 384 cafe_readl(cafe, NAND_ECC_SYN01));
385 385
386 chip->read_buf(mtd, buf, mtd->writesize); 386 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
387 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 387 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
388 388
389 if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { 389 if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
@@ -541,13 +541,13 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
541{ 541{
542 struct cafe_priv *cafe = nand_get_controller_data(chip); 542 struct cafe_priv *cafe = nand_get_controller_data(chip);
543 543
544 chip->write_buf(mtd, buf, mtd->writesize); 544 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
545 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 545 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
546 546
547 /* Set up ECC autogeneration */ 547 /* Set up ECC autogeneration */
548 cafe->ctl2 |= (1<<30); 548 cafe->ctl2 |= (1<<30);
549 549
550 return 0; 550 return nand_prog_page_end_op(chip);
551} 551}
552 552
553static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs) 553static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index d5c80d617854..47a253737bb2 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1358,7 +1358,6 @@ int denali_init(struct denali_nand_info *denali)
1358 chip->read_buf = denali_read_buf; 1358 chip->read_buf = denali_read_buf;
1359 chip->write_buf = denali_write_buf; 1359 chip->write_buf = denali_write_buf;
1360 } 1360 }
1361 chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS;
1362 chip->ecc.read_page = denali_read_page; 1361 chip->ecc.read_page = denali_read_page;
1363 chip->ecc.read_page_raw = denali_read_page_raw; 1362 chip->ecc.read_page_raw = denali_read_page_raw;
1364 chip->ecc.write_page = denali_write_page; 1363 chip->ecc.write_page = denali_write_page;
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 5a27f56dafdc..72f1327c4430 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -785,6 +785,8 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
785 785
786 dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); 786 dev_dbg(doc->dev, "%s: page %08x\n", __func__, page);
787 787
788 nand_read_page_op(nand, page, 0, NULL, 0);
789
788 writew(DOC_ECCCONF0_READ_MODE | 790 writew(DOC_ECCCONF0_READ_MODE |
789 DOC_ECCCONF0_ECC_ENABLE | 791 DOC_ECCCONF0_ECC_ENABLE |
790 DOC_ECCCONF0_UNKNOWN | 792 DOC_ECCCONF0_UNKNOWN |
@@ -948,7 +950,7 @@ static int docg4_erase_block(struct mtd_info *mtd, int page)
948} 950}
949 951
950static int write_page(struct mtd_info *mtd, struct nand_chip *nand, 952static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
951 const uint8_t *buf, bool use_ecc) 953 const uint8_t *buf, int page, bool use_ecc)
952{ 954{
953 struct docg4_priv *doc = nand_get_controller_data(nand); 955 struct docg4_priv *doc = nand_get_controller_data(nand);
954 void __iomem *docptr = doc->virtadr; 956 void __iomem *docptr = doc->virtadr;
@@ -956,6 +958,8 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
956 958
957 dev_dbg(doc->dev, "%s...\n", __func__); 959 dev_dbg(doc->dev, "%s...\n", __func__);
958 960
961 nand_prog_page_begin_op(nand, page, 0, NULL, 0);
962
959 writew(DOC_ECCCONF0_ECC_ENABLE | 963 writew(DOC_ECCCONF0_ECC_ENABLE |
960 DOC_ECCCONF0_UNKNOWN | 964 DOC_ECCCONF0_UNKNOWN |
961 DOCG4_BCH_SIZE, 965 DOCG4_BCH_SIZE,
@@ -1000,19 +1004,19 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
1000 writew(0, docptr + DOC_DATAEND); 1004 writew(0, docptr + DOC_DATAEND);
1001 write_nop(docptr); 1005 write_nop(docptr);
1002 1006
1003 return 0; 1007 return nand_prog_page_end_op(nand);
1004} 1008}
1005 1009
1006static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, 1010static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
1007 const uint8_t *buf, int oob_required, int page) 1011 const uint8_t *buf, int oob_required, int page)
1008{ 1012{
1009 return write_page(mtd, nand, buf, false); 1013 return write_page(mtd, nand, buf, page, false);
1010} 1014}
1011 1015
1012static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, 1016static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
1013 const uint8_t *buf, int oob_required, int page) 1017 const uint8_t *buf, int oob_required, int page)
1014{ 1018{
1015 return write_page(mtd, nand, buf, true); 1019 return write_page(mtd, nand, buf, page, true);
1016} 1020}
1017 1021
1018static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand, 1022static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 17db2f90aa2c..8b6dcd739ecb 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -713,7 +713,7 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
713 struct fsl_lbc_ctrl *ctrl = priv->ctrl; 713 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
714 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 714 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
715 715
716 fsl_elbc_read_buf(mtd, buf, mtd->writesize); 716 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
717 if (oob_required) 717 if (oob_required)
718 fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); 718 fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
719 719
@@ -729,10 +729,10 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
729static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 729static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
730 const uint8_t *buf, int oob_required, int page) 730 const uint8_t *buf, int oob_required, int page)
731{ 731{
732 fsl_elbc_write_buf(mtd, buf, mtd->writesize); 732 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
733 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 733 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
734 734
735 return 0; 735 return nand_prog_page_end_op(chip);
736} 736}
737 737
738/* ECC will be calculated automatically, and errors will be detected in 738/* ECC will be calculated automatically, and errors will be detected in
@@ -742,10 +742,10 @@ static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
742 uint32_t offset, uint32_t data_len, 742 uint32_t offset, uint32_t data_len,
743 const uint8_t *buf, int oob_required, int page) 743 const uint8_t *buf, int oob_required, int page)
744{ 744{
745 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
745 fsl_elbc_write_buf(mtd, buf, mtd->writesize); 746 fsl_elbc_write_buf(mtd, buf, mtd->writesize);
746 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 747 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
747 748 return nand_prog_page_end_op(chip);
748 return 0;
749} 749}
750 750
751static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) 751static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index bbdd68a54d68..4872a7ba6503 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -688,7 +688,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
688 struct fsl_ifc_ctrl *ctrl = priv->ctrl; 688 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
689 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; 689 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
690 690
691 fsl_ifc_read_buf(mtd, buf, mtd->writesize); 691 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
692 if (oob_required) 692 if (oob_required)
693 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); 693 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
694 694
@@ -711,10 +711,10 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
711static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 711static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
712 const uint8_t *buf, int oob_required, int page) 712 const uint8_t *buf, int oob_required, int page)
713{ 713{
714 fsl_ifc_write_buf(mtd, buf, mtd->writesize); 714 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
715 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 715 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
716 716
717 return 0; 717 return nand_prog_page_end_op(chip);
718} 718}
719 719
720static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) 720static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 63a425ced4cd..3c3f3f58fdcb 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -1043,6 +1043,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
1043 unsigned int max_bitflips = 0; 1043 unsigned int max_bitflips = 0;
1044 int ret; 1044 int ret;
1045 1045
1046 nand_read_page_op(chip, page, 0, NULL, 0);
1047
1046 dev_dbg(this->dev, "page number is : %d\n", page); 1048 dev_dbg(this->dev, "page number is : %d\n", page);
1047 ret = read_page_prepare(this, buf, nfc_geo->payload_size, 1049 ret = read_page_prepare(this, buf, nfc_geo->payload_size,
1048 this->payload_virt, this->payload_phys, 1050 this->payload_virt, this->payload_phys,
@@ -1220,12 +1222,12 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
1220 meta = geo->metadata_size; 1222 meta = geo->metadata_size;
1221 if (first) { 1223 if (first) {
1222 col = meta + (size + ecc_parity_size) * first; 1224 col = meta + (size + ecc_parity_size) * first;
1223 nand_change_read_column_op(chip, col, NULL, 0, false);
1224
1225 meta = 0; 1225 meta = 0;
1226 buf = buf + first * size; 1226 buf = buf + first * size;
1227 } 1227 }
1228 1228
1229 nand_read_page_op(chip, page, col, NULL, 0);
1230
1229 /* Save the old environment */ 1231 /* Save the old environment */
1230 r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0); 1232 r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0);
1231 r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1); 1233 r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1);
@@ -1277,6 +1279,9 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1277 int ret; 1279 int ret;
1278 1280
1279 dev_dbg(this->dev, "ecc write page.\n"); 1281 dev_dbg(this->dev, "ecc write page.\n");
1282
1283 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1284
1280 if (this->swap_block_mark) { 1285 if (this->swap_block_mark) {
1281 /* 1286 /*
1282 * If control arrives here, we're doing block mark swapping. 1287 * If control arrives here, we're doing block mark swapping.
@@ -1338,7 +1343,10 @@ exit_auxiliary:
1338 payload_virt, payload_phys); 1343 payload_virt, payload_phys);
1339 } 1344 }
1340 1345
1341 return 0; 1346 if (ret)
1347 return ret;
1348
1349 return nand_prog_page_end_op(chip);
1342} 1350}
1343 1351
1344/* 1352/*
@@ -1472,8 +1480,8 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
1472 uint8_t *oob = chip->oob_poi; 1480 uint8_t *oob = chip->oob_poi;
1473 int step; 1481 int step;
1474 1482
1475 chip->read_buf(mtd, tmp_buf, 1483 nand_read_page_op(chip, page, 0, tmp_buf,
1476 mtd->writesize + mtd->oobsize); 1484 mtd->writesize + mtd->oobsize);
1477 1485
1478 /* 1486 /*
1479 * If required, swap the bad block marker and the data stored in the 1487 * If required, swap the bad block marker and the data stored in the
@@ -1609,24 +1617,19 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
1609 if (this->swap_block_mark) 1617 if (this->swap_block_mark)
1610 swap(tmp_buf[0], tmp_buf[mtd->writesize]); 1618 swap(tmp_buf[0], tmp_buf[mtd->writesize]);
1611 1619
1612 chip->write_buf(mtd, tmp_buf, mtd->writesize + mtd->oobsize); 1620 return nand_prog_page_op(chip, page, 0, tmp_buf,
1613 1621 mtd->writesize + mtd->oobsize);
1614 return 0;
1615} 1622}
1616 1623
1617static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, 1624static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
1618 int page) 1625 int page)
1619{ 1626{
1620 nand_read_page_op(chip, page, 0, NULL, 0);
1621
1622 return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page); 1627 return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page);
1623} 1628}
1624 1629
1625static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, 1630static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
1626 int page) 1631 int page)
1627{ 1632{
1628 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1629
1630 return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page); 1633 return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page);
1631} 1634}
1632 1635
@@ -1798,9 +1801,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
1798 /* Write the first page of the current stride. */ 1801 /* Write the first page of the current stride. */
1799 dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); 1802 dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
1800 1803
1801 nand_prog_page_begin_op(chip, page, 0, NULL, 0); 1804 status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
1802 chip->ecc.write_page_raw(mtd, chip, buffer, 0, page);
1803 status = nand_prog_page_end_op(chip);
1804 if (status) 1805 if (status)
1805 dev_err(dev, "[%s] Write failed.\n", __func__); 1806 dev_err(dev, "[%s] Write failed.\n", __func__);
1806 } 1807 }
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c
index 184d765c8bbe..cb862793ab6d 100644
--- a/drivers/mtd/nand/hisi504_nand.c
+++ b/drivers/mtd/nand/hisi504_nand.c
@@ -544,7 +544,7 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd,
544 int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc; 544 int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc;
545 int stat_1, stat_2; 545 int stat_1, stat_2;
546 546
547 chip->read_buf(mtd, buf, mtd->writesize); 547 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
548 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 548 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
549 549
550 /* errors which can not be corrected by ECC */ 550 /* errors which can not be corrected by ECC */
@@ -589,11 +589,11 @@ static int hisi_nand_write_page_hwecc(struct mtd_info *mtd,
589 struct nand_chip *chip, const uint8_t *buf, int oob_required, 589 struct nand_chip *chip, const uint8_t *buf, int oob_required,
590 int page) 590 int page)
591{ 591{
592 chip->write_buf(mtd, buf, mtd->writesize); 592 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
593 if (oob_required) 593 if (oob_required)
594 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 594 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
595 595
596 return 0; 596 return nand_prog_page_end_op(chip);
597} 597}
598 598
599static void hisi_nfc_host_init(struct hinfc_host *host) 599static void hisi_nfc_host_init(struct hinfc_host *host)
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 31cb3b2967b9..e357948a7505 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -522,6 +522,8 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
522 memcpy(dma_buf, buf, mtd->writesize); 522 memcpy(dma_buf, buf, mtd->writesize);
523 } 523 }
524 524
525 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
526
525 for (i = 0; i < host->mlcsubpages; i++) { 527 for (i = 0; i < host->mlcsubpages; i++) {
526 /* Start Encode */ 528 /* Start Encode */
527 writeb(0x00, MLC_ECC_ENC_REG(host->io_base)); 529 writeb(0x00, MLC_ECC_ENC_REG(host->io_base));
@@ -550,7 +552,8 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
550 /* Wait for Controller Ready */ 552 /* Wait for Controller Ready */
551 lpc32xx_waitfunc_controller(mtd, chip); 553 lpc32xx_waitfunc_controller(mtd, chip);
552 } 554 }
553 return 0; 555
556 return nand_prog_page_end_op(chip);
554} 557}
555 558
556static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip, 559static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index 2b96c281b1a2..5f7cc6da0a7f 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -686,6 +686,8 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
686 uint8_t *pb; 686 uint8_t *pb;
687 int error; 687 int error;
688 688
689 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
690
689 /* Write data, calculate ECC on outbound data */ 691 /* Write data, calculate ECC on outbound data */
690 error = lpc32xx_xfer(mtd, (uint8_t *)buf, chip->ecc.steps, 0); 692 error = lpc32xx_xfer(mtd, (uint8_t *)buf, chip->ecc.steps, 0);
691 if (error) 693 if (error)
@@ -704,7 +706,8 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd,
704 706
705 /* Write ECC data to device */ 707 /* Write ECC data to device */
706 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 708 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
707 return 0; 709
710 return nand_prog_page_end_op(chip);
708} 711}
709 712
710/* 713/*
@@ -717,9 +720,11 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
717 int oob_required, int page) 720 int oob_required, int page)
718{ 721{
719 /* Raw writes can just use the FIFO interface */ 722 /* Raw writes can just use the FIFO interface */
720 chip->write_buf(mtd, buf, chip->ecc.size * chip->ecc.steps); 723 nand_prog_page_begin_op(chip, page, 0, buf,
724 chip->ecc.size * chip->ecc.steps);
721 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 725 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
722 return 0; 726
727 return nand_prog_page_end_op(chip);
723} 728}
724 729
725static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host) 730static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host)
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index 9c4adaf9331b..5d76be451596 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -761,6 +761,8 @@ static int mtk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
761 u32 reg; 761 u32 reg;
762 int ret; 762 int ret;
763 763
764 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
765
764 if (!raw) { 766 if (!raw) {
765 /* OOB => FDM: from register, ECC: from HW */ 767 /* OOB => FDM: from register, ECC: from HW */
766 reg = nfi_readw(nfc, NFI_CNFG) | CNFG_AUTO_FMT_EN; 768 reg = nfi_readw(nfc, NFI_CNFG) | CNFG_AUTO_FMT_EN;
@@ -794,7 +796,10 @@ static int mtk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
794 if (!raw) 796 if (!raw)
795 mtk_ecc_disable(nfc->ecc); 797 mtk_ecc_disable(nfc->ecc);
796 798
797 return ret; 799 if (ret)
800 return ret;
801
802 return nand_prog_page_end_op(chip);
798} 803}
799 804
800static int mtk_nfc_write_page_hwecc(struct mtd_info *mtd, 805static int mtk_nfc_write_page_hwecc(struct mtd_info *mtd,
@@ -832,15 +837,7 @@ static int mtk_nfc_write_subpage_hwecc(struct mtd_info *mtd,
832static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, 837static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
833 int page) 838 int page)
834{ 839{
835 int ret; 840 return mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page);
836
837 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
838
839 ret = mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page);
840 if (ret < 0)
841 return -EIO;
842
843 return nand_prog_page_end_op(chip);
844} 841}
845 842
846static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors) 843static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
@@ -889,8 +886,7 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
889 len = sectors * chip->ecc.size + (raw ? sectors * spare : 0); 886 len = sectors * chip->ecc.size + (raw ? sectors * spare : 0);
890 buf = bufpoi + start * chip->ecc.size; 887 buf = bufpoi + start * chip->ecc.size;
891 888
892 if (column != 0) 889 nand_read_page_op(chip, page, column, NULL, 0);
893 nand_change_read_column_op(chip, column, NULL, 0, false);
894 890
895 addr = dma_map_single(nfc->dev, buf, len, DMA_FROM_DEVICE); 891 addr = dma_map_single(nfc->dev, buf, len, DMA_FROM_DEVICE);
896 rc = dma_mapping_error(nfc->dev, addr); 892 rc = dma_mapping_error(nfc->dev, addr);
@@ -1013,8 +1009,6 @@ static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1013static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, 1009static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
1014 int page) 1010 int page)
1015{ 1011{
1016 nand_read_page_op(chip, page, 0, NULL, 0);
1017
1018 return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page); 1012 return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page);
1019} 1013}
1020 1014
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 539132ef0095..e3bf33bc1fb6 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1940,7 +1940,7 @@ int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
1940{ 1940{
1941 int ret; 1941 int ret;
1942 1942
1943 ret = nand_read_data_op(chip, buf, mtd->writesize, false); 1943 ret = nand_read_page_op(chip, page, 0, buf, mtd->writesize);
1944 if (ret) 1944 if (ret)
1945 return ret; 1945 return ret;
1946 1946
@@ -1974,6 +1974,10 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
1974 uint8_t *oob = chip->oob_poi; 1974 uint8_t *oob = chip->oob_poi;
1975 int steps, size, ret; 1975 int steps, size, ret;
1976 1976
1977 ret = nand_read_page_op(chip, page, 0, NULL, 0);
1978 if (ret)
1979 return ret;
1980
1977 for (steps = chip->ecc.steps; steps > 0; steps--) { 1981 for (steps = chip->ecc.steps; steps > 0; steps--) {
1978 ret = nand_read_data_op(chip, buf, eccsize, false); 1982 ret = nand_read_data_op(chip, buf, eccsize, false);
1979 if (ret) 1983 if (ret)
@@ -2096,11 +2100,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
2096 2100
2097 data_col_addr = start_step * chip->ecc.size; 2101 data_col_addr = start_step * chip->ecc.size;
2098 /* If we read not a page aligned data */ 2102 /* If we read not a page aligned data */
2099 if (data_col_addr != 0)
2100 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
2101
2102 p = bufpoi + data_col_addr; 2103 p = bufpoi + data_col_addr;
2103 ret = nand_read_data_op(chip, p, datafrag_len, false); 2104 ret = nand_read_page_op(chip, page, data_col_addr, p, datafrag_len);
2104 if (ret) 2105 if (ret)
2105 return ret; 2106 return ret;
2106 2107
@@ -2198,6 +2199,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
2198 uint8_t *ecc_code = chip->buffers->ecccode; 2199 uint8_t *ecc_code = chip->buffers->ecccode;
2199 unsigned int max_bitflips = 0; 2200 unsigned int max_bitflips = 0;
2200 2201
2202 ret = nand_read_page_op(chip, page, 0, NULL, 0);
2203 if (ret)
2204 return ret;
2205
2201 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 2206 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
2202 chip->ecc.hwctl(mtd, NAND_ECC_READ); 2207 chip->ecc.hwctl(mtd, NAND_ECC_READ);
2203 2208
@@ -2335,6 +2340,10 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
2335 uint8_t *oob = chip->oob_poi; 2340 uint8_t *oob = chip->oob_poi;
2336 unsigned int max_bitflips = 0; 2341 unsigned int max_bitflips = 0;
2337 2342
2343 ret = nand_read_page_op(chip, page, 0, NULL, 0);
2344 if (ret)
2345 return ret;
2346
2338 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 2347 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
2339 int stat; 2348 int stat;
2340 2349
@@ -2517,12 +2526,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
2517 __func__, buf); 2526 __func__, buf);
2518 2527
2519read_retry: 2528read_retry:
2520 if (nand_standard_page_accessors(&chip->ecc)) {
2521 ret = nand_read_page_op(chip, page, 0, NULL, 0);
2522 if (ret)
2523 break;
2524 }
2525
2526 /* 2529 /*
2527 * Now read the page into the buffer. Absent an error, 2530 * Now read the page into the buffer. Absent an error,
2528 * the read methods return max bitflips per ecc step. 2531 * the read methods return max bitflips per ecc step.
@@ -2978,7 +2981,7 @@ int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
2978{ 2981{
2979 int ret; 2982 int ret;
2980 2983
2981 ret = nand_write_data_op(chip, buf, mtd->writesize, false); 2984 ret = nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
2982 if (ret) 2985 if (ret)
2983 return ret; 2986 return ret;
2984 2987
@@ -2989,7 +2992,7 @@ int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
2989 return ret; 2992 return ret;
2990 } 2993 }
2991 2994
2992 return 0; 2995 return nand_prog_page_end_op(chip);
2993} 2996}
2994EXPORT_SYMBOL(nand_write_page_raw); 2997EXPORT_SYMBOL(nand_write_page_raw);
2995 2998
@@ -3013,6 +3016,10 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
3013 uint8_t *oob = chip->oob_poi; 3016 uint8_t *oob = chip->oob_poi;
3014 int steps, size, ret; 3017 int steps, size, ret;
3015 3018
3019 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
3020 if (ret)
3021 return ret;
3022
3016 for (steps = chip->ecc.steps; steps > 0; steps--) { 3023 for (steps = chip->ecc.steps; steps > 0; steps--) {
3017 ret = nand_write_data_op(chip, buf, eccsize, false); 3024 ret = nand_write_data_op(chip, buf, eccsize, false);
3018 if (ret) 3025 if (ret)
@@ -3052,7 +3059,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
3052 return ret; 3059 return ret;
3053 } 3060 }
3054 3061
3055 return 0; 3062 return nand_prog_page_end_op(chip);
3056} 3063}
3057/** 3064/**
3058 * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function 3065 * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
@@ -3102,6 +3109,10 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
3102 uint8_t *ecc_calc = chip->buffers->ecccalc; 3109 uint8_t *ecc_calc = chip->buffers->ecccalc;
3103 const uint8_t *p = buf; 3110 const uint8_t *p = buf;
3104 3111
3112 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
3113 if (ret)
3114 return ret;
3115
3105 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 3116 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
3106 chip->ecc.hwctl(mtd, NAND_ECC_WRITE); 3117 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
3107 3118
@@ -3121,7 +3132,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
3121 if (ret) 3132 if (ret)
3122 return ret; 3133 return ret;
3123 3134
3124 return 0; 3135 return nand_prog_page_end_op(chip);
3125} 3136}
3126 3137
3127 3138
@@ -3150,6 +3161,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
3150 int oob_bytes = mtd->oobsize / ecc_steps; 3161 int oob_bytes = mtd->oobsize / ecc_steps;
3151 int step, ret; 3162 int step, ret;
3152 3163
3164 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
3165 if (ret)
3166 return ret;
3167
3153 for (step = 0; step < ecc_steps; step++) { 3168 for (step = 0; step < ecc_steps; step++) {
3154 /* configure controller for WRITE access */ 3169 /* configure controller for WRITE access */
3155 chip->ecc.hwctl(mtd, NAND_ECC_WRITE); 3170 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
@@ -3188,7 +3203,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
3188 if (ret) 3203 if (ret)
3189 return ret; 3204 return ret;
3190 3205
3191 return 0; 3206 return nand_prog_page_end_op(chip);
3192} 3207}
3193 3208
3194 3209
@@ -3215,6 +3230,10 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
3215 uint8_t *oob = chip->oob_poi; 3230 uint8_t *oob = chip->oob_poi;
3216 int ret; 3231 int ret;
3217 3232
3233 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
3234 if (ret)
3235 return ret;
3236
3218 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { 3237 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
3219 chip->ecc.hwctl(mtd, NAND_ECC_WRITE); 3238 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
3220 3239
@@ -3257,7 +3276,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
3257 return ret; 3276 return ret;
3258 } 3277 }
3259 3278
3260 return 0; 3279 return nand_prog_page_end_op(chip);
3261} 3280}
3262 3281
3263/** 3282/**
@@ -3283,12 +3302,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
3283 else 3302 else
3284 subpage = 0; 3303 subpage = 0;
3285 3304
3286 if (nand_standard_page_accessors(&chip->ecc)) {
3287 status = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
3288 if (status)
3289 return status;
3290 }
3291
3292 if (unlikely(raw)) 3305 if (unlikely(raw))
3293 status = chip->ecc.write_page_raw(mtd, chip, buf, 3306 status = chip->ecc.write_page_raw(mtd, chip, buf,
3294 oob_required, page); 3307 oob_required, page);
@@ -3302,9 +3315,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
3302 if (status < 0) 3315 if (status < 0)
3303 return status; 3316 return status;
3304 3317
3305 if (nand_standard_page_accessors(&chip->ecc))
3306 return nand_prog_page_end_op(chip);
3307
3308 return 0; 3318 return 0;
3309} 3319}
3310 3320
@@ -5290,26 +5300,6 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
5290 return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; 5300 return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds;
5291} 5301}
5292 5302
5293static bool invalid_ecc_page_accessors(struct nand_chip *chip)
5294{
5295 struct nand_ecc_ctrl *ecc = &chip->ecc;
5296
5297 if (nand_standard_page_accessors(ecc))
5298 return false;
5299
5300 /*
5301 * NAND_ECC_CUSTOM_PAGE_ACCESS flag is set, make sure the NAND
5302 * controller driver implements all the page accessors because
5303 * default helpers are not suitable when the core does not
5304 * send the READ0/PAGEPROG commands.
5305 */
5306 return (!ecc->read_page || !ecc->write_page ||
5307 !ecc->read_page_raw || !ecc->write_page_raw ||
5308 (NAND_HAS_SUBPAGE_READ(chip) && !ecc->read_subpage) ||
5309 (NAND_HAS_SUBPAGE_WRITE(chip) && !ecc->write_subpage &&
5310 ecc->hwctl && ecc->calculate));
5311}
5312
5313/** 5303/**
5314 * nand_scan_tail - [NAND Interface] Scan for the NAND device 5304 * nand_scan_tail - [NAND Interface] Scan for the NAND device
5315 * @mtd: MTD device structure 5305 * @mtd: MTD device structure
@@ -5331,11 +5321,6 @@ int nand_scan_tail(struct mtd_info *mtd)
5331 return -EINVAL; 5321 return -EINVAL;
5332 } 5322 }
5333 5323
5334 if (invalid_ecc_page_accessors(chip)) {
5335 pr_err("Invalid ECC page accessors setup\n");
5336 return -EINVAL;
5337 }
5338
5339 if (!(chip->options & NAND_OWN_BUFFERS)) { 5324 if (!(chip->options & NAND_OWN_BUFFERS)) {
5340 nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL); 5325 nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
5341 if (!nbuf) 5326 if (!nbuf)
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/nand_micron.c
index bf2dc23e1c32..02e109ae73f1 100644
--- a/drivers/mtd/nand/nand_micron.c
+++ b/drivers/mtd/nand/nand_micron.c
@@ -149,7 +149,10 @@ micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
149 else if (status & NAND_STATUS_WRITE_RECOMMENDED) 149 else if (status & NAND_STATUS_WRITE_RECOMMENDED)
150 max_bitflips = chip->ecc.strength; 150 max_bitflips = chip->ecc.strength;
151 151
152 ret = nand_read_page_raw(mtd, chip, buf, oob_required, page); 152 ret = nand_read_data_op(chip, buf, mtd->writesize, false);
153 if (!ret && oob_required)
154 ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize,
155 false);
153 156
154out: 157out:
155 micron_nand_on_die_ecc_setup(chip, false); 158 micron_nand_on_die_ecc_setup(chip, false);
@@ -168,56 +171,12 @@ micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
168 if (ret) 171 if (ret)
169 return ret; 172 return ret;
170 173
171 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
172 if (ret)
173 goto out;
174
175 ret = nand_write_page_raw(mtd, chip, buf, oob_required, page); 174 ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
176 if (ret)
177 return ret;
178
179 ret = nand_prog_page_end_op(chip);
180
181out:
182 micron_nand_on_die_ecc_setup(chip, false); 175 micron_nand_on_die_ecc_setup(chip, false);
183 176
184 return ret; 177 return ret;
185} 178}
186 179
187static int
188micron_nand_read_page_raw_on_die_ecc(struct mtd_info *mtd,
189 struct nand_chip *chip,
190 uint8_t *buf, int oob_required,
191 int page)
192{
193 int ret;
194
195 ret = nand_read_page_op(chip, page, 0, NULL, 0);
196 if (ret)
197 return ret;
198
199 return nand_read_page_raw(mtd, chip, buf, oob_required, page);
200}
201
202static int
203micron_nand_write_page_raw_on_die_ecc(struct mtd_info *mtd,
204 struct nand_chip *chip,
205 const uint8_t *buf, int oob_required,
206 int page)
207{
208 int ret;
209
210 ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
211 if (ret)
212 return ret;
213
214 ret = nand_write_page_raw(mtd, chip, buf, oob_required, page);
215 if (ret)
216 return ret;
217
218 return nand_prog_page_end_op(chip);
219}
220
221enum { 180enum {
222 /* The NAND flash doesn't support on-die ECC */ 181 /* The NAND flash doesn't support on-die ECC */
223 MICRON_ON_DIE_UNSUPPORTED, 182 MICRON_ON_DIE_UNSUPPORTED,
@@ -310,17 +269,14 @@ static int micron_nand_init(struct nand_chip *chip)
310 return -EINVAL; 269 return -EINVAL;
311 } 270 }
312 271
313 chip->ecc.options = NAND_ECC_CUSTOM_PAGE_ACCESS;
314 chip->ecc.bytes = 8; 272 chip->ecc.bytes = 8;
315 chip->ecc.size = 512; 273 chip->ecc.size = 512;
316 chip->ecc.strength = 4; 274 chip->ecc.strength = 4;
317 chip->ecc.algo = NAND_ECC_BCH; 275 chip->ecc.algo = NAND_ECC_BCH;
318 chip->ecc.read_page = micron_nand_read_page_on_die_ecc; 276 chip->ecc.read_page = micron_nand_read_page_on_die_ecc;
319 chip->ecc.write_page = micron_nand_write_page_on_die_ecc; 277 chip->ecc.write_page = micron_nand_write_page_on_die_ecc;
320 chip->ecc.read_page_raw = 278 chip->ecc.read_page_raw = nand_read_page_raw;
321 micron_nand_read_page_raw_on_die_ecc; 279 chip->ecc.write_page_raw = nand_write_page_raw;
322 chip->ecc.write_page_raw =
323 micron_nand_write_page_raw_on_die_ecc;
324 280
325 mtd_set_ooblayout(mtd, &micron_nand_on_die_ooblayout_ops); 281 mtd_set_ooblayout(mtd, &micron_nand_on_die_ooblayout_ops);
326 } 282 }
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 6e1b209cd5a7..5cb4db6f88e3 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1532,6 +1532,8 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
1532 int ret; 1532 int ret;
1533 uint8_t *ecc_calc = chip->buffers->ecccalc; 1533 uint8_t *ecc_calc = chip->buffers->ecccalc;
1534 1534
1535 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1536
1535 /* Enable GPMC ecc engine */ 1537 /* Enable GPMC ecc engine */
1536 chip->ecc.hwctl(mtd, NAND_ECC_WRITE); 1538 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
1537 1539
@@ -1548,7 +1550,8 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
1548 1550
1549 /* Write ecc vector to OOB area */ 1551 /* Write ecc vector to OOB area */
1550 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 1552 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1551 return 0; 1553
1554 return nand_prog_page_end_op(chip);
1552} 1555}
1553 1556
1554/** 1557/**
@@ -1582,6 +1585,7 @@ static int omap_write_subpage_bch(struct mtd_info *mtd,
1582 * ECC is calculated for all subpages but we choose 1585 * ECC is calculated for all subpages but we choose
1583 * only what we want. 1586 * only what we want.
1584 */ 1587 */
1588 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1585 1589
1586 /* Enable GPMC ECC engine */ 1590 /* Enable GPMC ECC engine */
1587 chip->ecc.hwctl(mtd, NAND_ECC_WRITE); 1591 chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
@@ -1614,7 +1618,7 @@ static int omap_write_subpage_bch(struct mtd_info *mtd,
1614 /* write OOB buffer to NAND device */ 1618 /* write OOB buffer to NAND device */
1615 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 1619 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1616 1620
1617 return 0; 1621 return nand_prog_page_end_op(chip);
1618} 1622}
1619 1623
1620/** 1624/**
@@ -1640,6 +1644,8 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
1640 int stat, ret; 1644 int stat, ret;
1641 unsigned int max_bitflips = 0; 1645 unsigned int max_bitflips = 0;
1642 1646
1647 nand_read_page_op(chip, page, 0, NULL, 0);
1648
1643 /* Enable GPMC ecc engine */ 1649 /* Enable GPMC ecc engine */
1644 chip->ecc.hwctl(mtd, NAND_ECC_READ); 1650 chip->ecc.hwctl(mtd, NAND_ECC_READ);
1645 1651
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 28bcdf64c1fc..021374fe59dc 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1348,10 +1348,10 @@ static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
1348 struct nand_chip *chip, const uint8_t *buf, int oob_required, 1348 struct nand_chip *chip, const uint8_t *buf, int oob_required,
1349 int page) 1349 int page)
1350{ 1350{
1351 chip->write_buf(mtd, buf, mtd->writesize); 1351 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
1352 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 1352 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
1353 1353
1354 return 0; 1354 return nand_prog_page_end_op(chip);
1355} 1355}
1356 1356
1357static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, 1357static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
@@ -1361,7 +1361,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
1361 struct pxa3xx_nand_host *host = nand_get_controller_data(chip); 1361 struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
1362 struct pxa3xx_nand_info *info = host->info_data; 1362 struct pxa3xx_nand_info *info = host->info_data;
1363 1363
1364 chip->read_buf(mtd, buf, mtd->writesize); 1364 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
1365 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 1365 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
1366 1366
1367 if (info->retcode == ERR_CORERR && info->use_ecc) { 1367 if (info->retcode == ERR_CORERR && info->use_ecc) {
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index e34313ecd903..245d0f39e0aa 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -1725,6 +1725,7 @@ static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
1725 u8 *data_buf, *oob_buf = NULL; 1725 u8 *data_buf, *oob_buf = NULL;
1726 int ret; 1726 int ret;
1727 1727
1728 nand_read_page_op(chip, page, 0, NULL, 0);
1728 data_buf = buf; 1729 data_buf = buf;
1729 oob_buf = oob_required ? chip->oob_poi : NULL; 1730 oob_buf = oob_required ? chip->oob_poi : NULL;
1730 1731
@@ -1750,6 +1751,7 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd,
1750 int i, ret; 1751 int i, ret;
1751 int read_loc; 1752 int read_loc;
1752 1753
1754 nand_read_page_op(chip, page, 0, NULL, 0);
1753 data_buf = buf; 1755 data_buf = buf;
1754 oob_buf = chip->oob_poi; 1756 oob_buf = chip->oob_poi;
1755 1757
@@ -1850,6 +1852,8 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1850 u8 *data_buf, *oob_buf; 1852 u8 *data_buf, *oob_buf;
1851 int i, ret; 1853 int i, ret;
1852 1854
1855 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1856
1853 clear_read_regs(nandc); 1857 clear_read_regs(nandc);
1854 clear_bam_transaction(nandc); 1858 clear_bam_transaction(nandc);
1855 1859
@@ -1902,6 +1906,9 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
1902 1906
1903 free_descs(nandc); 1907 free_descs(nandc);
1904 1908
1909 if (!ret)
1910 ret = nand_prog_page_end_op(chip);
1911
1905 return ret; 1912 return ret;
1906} 1913}
1907 1914
@@ -1916,6 +1923,7 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
1916 u8 *data_buf, *oob_buf; 1923 u8 *data_buf, *oob_buf;
1917 int i, ret; 1924 int i, ret;
1918 1925
1926 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1919 clear_read_regs(nandc); 1927 clear_read_regs(nandc);
1920 clear_bam_transaction(nandc); 1928 clear_bam_transaction(nandc);
1921 1929
@@ -1970,6 +1978,9 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd,
1970 1978
1971 free_descs(nandc); 1979 free_descs(nandc);
1972 1980
1981 if (!ret)
1982 ret = nand_prog_page_end_op(chip);
1983
1973 return ret; 1984 return ret;
1974} 1985}
1975 1986
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 3c5008a4f5f3..c4e7755448e6 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -614,7 +614,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
614static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 614static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
615 uint8_t *buf, int oob_required, int page) 615 uint8_t *buf, int oob_required, int page)
616{ 616{
617 chip->read_buf(mtd, buf, mtd->writesize); 617 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
618 if (oob_required) 618 if (oob_required)
619 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 619 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
620 return 0; 620 return 0;
@@ -624,9 +624,9 @@ static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
624 const uint8_t *buf, int oob_required, 624 const uint8_t *buf, int oob_required,
625 int page) 625 int page)
626{ 626{
627 chip->write_buf(mtd, buf, mtd->writesize); 627 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
628 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 628 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
629 return 0; 629 return nand_prog_page_end_op(chip);
630} 630}
631 631
632static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) 632static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index da5cc36f4c30..5c176dee821e 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1245,6 +1245,8 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
1245 int ret, i, cur_off = 0; 1245 int ret, i, cur_off = 0;
1246 bool raw_mode = false; 1246 bool raw_mode = false;
1247 1247
1248 nand_read_page_op(chip, page, 0, NULL, 0);
1249
1248 sunxi_nfc_hw_ecc_enable(mtd); 1250 sunxi_nfc_hw_ecc_enable(mtd);
1249 1251
1250 for (i = 0; i < ecc->steps; i++) { 1252 for (i = 0; i < ecc->steps; i++) {
@@ -1278,14 +1280,14 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd,
1278{ 1280{
1279 int ret; 1281 int ret;
1280 1282
1283 nand_read_page_op(chip, page, 0, NULL, 0);
1284
1281 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page, 1285 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page,
1282 chip->ecc.steps); 1286 chip->ecc.steps);
1283 if (ret >= 0) 1287 if (ret >= 0)
1284 return ret; 1288 return ret;
1285 1289
1286 /* Fallback to PIO mode */ 1290 /* Fallback to PIO mode */
1287 nand_change_read_column_op(chip, 0, NULL, 0, false);
1288
1289 return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page); 1291 return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page);
1290} 1292}
1291 1293
@@ -1298,6 +1300,8 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
1298 int ret, i, cur_off = 0; 1300 int ret, i, cur_off = 0;
1299 unsigned int max_bitflips = 0; 1301 unsigned int max_bitflips = 0;
1300 1302
1303 nand_read_page_op(chip, page, 0, NULL, 0);
1304
1301 sunxi_nfc_hw_ecc_enable(mtd); 1305 sunxi_nfc_hw_ecc_enable(mtd);
1302 1306
1303 for (i = data_offs / ecc->size; 1307 for (i = data_offs / ecc->size;
@@ -1329,13 +1333,13 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd,
1329 int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size); 1333 int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size);
1330 int ret; 1334 int ret;
1331 1335
1336 nand_read_page_op(chip, page, 0, NULL, 0);
1337
1332 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks); 1338 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks);
1333 if (ret >= 0) 1339 if (ret >= 0)
1334 return ret; 1340 return ret;
1335 1341
1336 /* Fallback to PIO mode */ 1342 /* Fallback to PIO mode */
1337 nand_change_read_column_op(chip, 0, NULL, 0, false);
1338
1339 return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen, 1343 return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen,
1340 buf, page); 1344 buf, page);
1341} 1345}
@@ -1348,6 +1352,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1348 struct nand_ecc_ctrl *ecc = &chip->ecc; 1352 struct nand_ecc_ctrl *ecc = &chip->ecc;
1349 int ret, i, cur_off = 0; 1353 int ret, i, cur_off = 0;
1350 1354
1355 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1356
1351 sunxi_nfc_hw_ecc_enable(mtd); 1357 sunxi_nfc_hw_ecc_enable(mtd);
1352 1358
1353 for (i = 0; i < ecc->steps; i++) { 1359 for (i = 0; i < ecc->steps; i++) {
@@ -1369,7 +1375,7 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1369 1375
1370 sunxi_nfc_hw_ecc_disable(mtd); 1376 sunxi_nfc_hw_ecc_disable(mtd);
1371 1377
1372 return 0; 1378 return nand_prog_page_end_op(chip);
1373} 1379}
1374 1380
1375static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd, 1381static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
@@ -1381,6 +1387,8 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
1381 struct nand_ecc_ctrl *ecc = &chip->ecc; 1387 struct nand_ecc_ctrl *ecc = &chip->ecc;
1382 int ret, i, cur_off = 0; 1388 int ret, i, cur_off = 0;
1383 1389
1390 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1391
1384 sunxi_nfc_hw_ecc_enable(mtd); 1392 sunxi_nfc_hw_ecc_enable(mtd);
1385 1393
1386 for (i = data_offs / ecc->size; 1394 for (i = data_offs / ecc->size;
@@ -1399,7 +1407,7 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
1399 1407
1400 sunxi_nfc_hw_ecc_disable(mtd); 1408 sunxi_nfc_hw_ecc_disable(mtd);
1401 1409
1402 return 0; 1410 return nand_prog_page_end_op(chip);
1403} 1411}
1404 1412
1405static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, 1413static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
@@ -1429,6 +1437,8 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
1429 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page); 1437 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page);
1430 } 1438 }
1431 1439
1440 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1441
1432 sunxi_nfc_hw_ecc_enable(mtd); 1442 sunxi_nfc_hw_ecc_enable(mtd);
1433 sunxi_nfc_randomizer_config(mtd, page, false); 1443 sunxi_nfc_randomizer_config(mtd, page, false);
1434 sunxi_nfc_randomizer_enable(mtd); 1444 sunxi_nfc_randomizer_enable(mtd);
@@ -1459,7 +1469,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
1459 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi, 1469 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1460 NULL, page); 1470 NULL, page);
1461 1471
1462 return 0; 1472 return nand_prog_page_end_op(chip);
1463 1473
1464pio_fallback: 1474pio_fallback:
1465 return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page); 1475 return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page);
@@ -1475,6 +1485,8 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
1475 int ret, i, cur_off = 0; 1485 int ret, i, cur_off = 0;
1476 bool raw_mode = false; 1486 bool raw_mode = false;
1477 1487
1488 nand_read_page_op(chip, page, 0, NULL, 0);
1489
1478 sunxi_nfc_hw_ecc_enable(mtd); 1490 sunxi_nfc_hw_ecc_enable(mtd);
1479 1491
1480 for (i = 0; i < ecc->steps; i++) { 1492 for (i = 0; i < ecc->steps; i++) {
@@ -1511,6 +1523,8 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1511 struct nand_ecc_ctrl *ecc = &chip->ecc; 1523 struct nand_ecc_ctrl *ecc = &chip->ecc;
1512 int ret, i, cur_off = 0; 1524 int ret, i, cur_off = 0;
1513 1525
1526 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1527
1514 sunxi_nfc_hw_ecc_enable(mtd); 1528 sunxi_nfc_hw_ecc_enable(mtd);
1515 1529
1516 for (i = 0; i < ecc->steps; i++) { 1530 for (i = 0; i < ecc->steps; i++) {
@@ -1532,15 +1546,13 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1532 1546
1533 sunxi_nfc_hw_ecc_disable(mtd); 1547 sunxi_nfc_hw_ecc_disable(mtd);
1534 1548
1535 return 0; 1549 return nand_prog_page_end_op(chip);
1536} 1550}
1537 1551
1538static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd, 1552static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
1539 struct nand_chip *chip, 1553 struct nand_chip *chip,
1540 int page) 1554 int page)
1541{ 1555{
1542 nand_read_page_op(chip, page, 0, NULL, 0);
1543
1544 chip->pagebuf = -1; 1556 chip->pagebuf = -1;
1545 1557
1546 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page); 1558 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page);
@@ -1552,8 +1564,6 @@ static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
1552{ 1564{
1553 int ret; 1565 int ret;
1554 1566
1555 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1556
1557 chip->pagebuf = -1; 1567 chip->pagebuf = -1;
1558 1568
1559 memset(chip->buffers->databuf, 0xff, mtd->writesize); 1569 memset(chip->buffers->databuf, 0xff, mtd->writesize);
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c
index 97a300b46b1d..c5bee00b7f5e 100644
--- a/drivers/mtd/nand/tango_nand.c
+++ b/drivers/mtd/nand/tango_nand.c
@@ -580,7 +580,6 @@ static int chip_init(struct device *dev, struct device_node *np)
580 ecc->write_page = tango_write_page; 580 ecc->write_page = tango_write_page;
581 ecc->read_oob = tango_read_oob; 581 ecc->read_oob = tango_read_oob;
582 ecc->write_oob = tango_write_oob; 582 ecc->write_oob = tango_write_oob;
583 ecc->options = NAND_ECC_CUSTOM_PAGE_ACCESS;
584 583
585 err = nand_scan_tail(mtd); 584 err = nand_scan_tail(mtd);
586 if (err) 585 if (err)
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 8037d4b48a05..80d31a58e558 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -560,7 +560,7 @@ static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
560 int eccsize = chip->ecc.size; 560 int eccsize = chip->ecc.size;
561 int stat; 561 int stat;
562 562
563 vf610_nfc_read_buf(mtd, buf, eccsize); 563 nand_read_page_op(chip, page, 0, buf, eccsize);
564 if (oob_required) 564 if (oob_required)
565 vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize); 565 vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
566 566
@@ -580,7 +580,7 @@ static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
580{ 580{
581 struct vf610_nfc *nfc = mtd_to_nfc(mtd); 581 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
582 582
583 vf610_nfc_write_buf(mtd, buf, mtd->writesize); 583 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
584 if (oob_required) 584 if (oob_required)
585 vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 585 vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
586 586
@@ -588,7 +588,7 @@ static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
588 nfc->use_hw_ecc = true; 588 nfc->use_hw_ecc = true;
589 nfc->write_sz = mtd->writesize + mtd->oobsize; 589 nfc->write_sz = mtd->writesize + mtd->oobsize;
590 590
591 return 0; 591 return nand_prog_page_end_op(chip);
592} 592}
593 593
594static const struct of_device_id vf610_nfc_dt_ids[] = { 594static const struct of_device_id vf610_nfc_dt_ids[] = {
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index 87595c594b12..264ad362d858 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -637,8 +637,7 @@ static int spinand_write_page_hwecc(struct mtd_info *mtd,
637 int eccsteps = chip->ecc.steps; 637 int eccsteps = chip->ecc.steps;
638 638
639 enable_hw_ecc = 1; 639 enable_hw_ecc = 1;
640 chip->write_buf(mtd, p, eccsize * eccsteps); 640 return nand_prog_page_op(chip, page, 0, p, eccsize * eccsteps);
641 return 0;
642} 641}
643 642
644static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 643static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
@@ -653,7 +652,7 @@ static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
653 652
654 enable_read_hw_ecc = 1; 653 enable_read_hw_ecc = 1;
655 654
656 chip->read_buf(mtd, p, eccsize * eccsteps); 655 nand_read_page_op(chip, page, 0, p, eccsize * eccsteps);
657 if (oob_required) 656 if (oob_required)
658 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); 657 chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
659 658
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index fd99d5137d71..e6810f0b8f9e 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -133,12 +133,6 @@ enum nand_ecc_algo {
133 */ 133 */
134#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0) 134#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0)
135#define NAND_ECC_MAXIMIZE BIT(1) 135#define NAND_ECC_MAXIMIZE BIT(1)
136/*
137 * If your controller already sends the required NAND commands when
138 * reading or writing a page, then the framework is not supposed to
139 * send READ0 and SEQIN/PAGEPROG respectively.
140 */
141#define NAND_ECC_CUSTOM_PAGE_ACCESS BIT(2)
142 136
143/* Bit mask for flags passed to do_nand_read_ecc */ 137/* Bit mask for flags passed to do_nand_read_ecc */
144#define NAND_GET_DEVICE 0x80 138#define NAND_GET_DEVICE 0x80
@@ -602,11 +596,6 @@ struct nand_ecc_ctrl {
602 int page); 596 int page);
603}; 597};
604 598
605static inline int nand_standard_page_accessors(struct nand_ecc_ctrl *ecc)
606{
607 return !(ecc->options & NAND_ECC_CUSTOM_PAGE_ACCESS);
608}
609
610/** 599/**
611 * struct nand_buffers - buffer structure for read/write 600 * struct nand_buffers - buffer structure for read/write
612 * @ecccalc: buffer pointer for calculated ECC, size is oobsize. 601 * @ecccalc: buffer pointer for calculated ECC, size is oobsize.