diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2017-11-30 12:01:30 -0500 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2017-12-14 07:34:17 -0500 |
commit | 25f815f66a141436df8a4c45e5d2765272aea2ac (patch) | |
tree | c218dcaa4440f1cfbc62efbf67a1d80b72c5a4e1 | |
parent | 97d90da8a886949f09bb4754843fb0b504956ad2 (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>
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 | ||
863 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | 865 | static 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, | |||
572 | static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 572 | static 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 | ||
1916 | static int brcmnand_write_page_raw(struct mtd_info *mtd, | 1921 | static 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 | ||
1929 | static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | 1936 | static 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 | ||
553 | static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs) | 553 | static 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 | ||
950 | static int write_page(struct mtd_info *mtd, struct nand_chip *nand, | 952 | static 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 | ||
1006 | static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, | 1010 | static 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 | ||
1012 | static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, | 1016 | static 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 | ||
1018 | static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand, | 1022 | static 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, | |||
729 | static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 729 | static 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 | ||
751 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 751 | static 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, | |||
711 | static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 711 | static 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 | ||
720 | static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) | 720 | static 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 | ||
1617 | static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1624 | static 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 | ||
1625 | static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1630 | static 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 | ||
599 | static void hisi_nfc_host_init(struct hinfc_host *host) | 599 | static 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 | ||
556 | static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | 559 | static 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 | ||
725 | static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host) | 730 | static 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 | ||
800 | static int mtk_nfc_write_page_hwecc(struct mtd_info *mtd, | 805 | static 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, | |||
832 | static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 837 | static 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 | ||
846 | static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors) | 843 | static 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, | |||
1013 | static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, | 1009 | static 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 | ||
2519 | read_retry: | 2528 | read_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 | } |
2994 | EXPORT_SYMBOL(nand_write_page_raw); | 2997 | EXPORT_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 | ||
5293 | static 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 | ||
154 | out: | 157 | out: |
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 | |||
181 | out: | ||
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 | ||
187 | static int | ||
188 | micron_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 | |||
202 | static int | ||
203 | micron_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 | |||
221 | enum { | 180 | enum { |
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, µn_nand_on_die_ooblayout_ops); | 281 | mtd_set_ooblayout(mtd, µn_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 | ||
1357 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | 1357 | static 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 | |||
614 | static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 614 | static 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 | ||
632 | static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr) | 632 | static 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 | ||
1375 | static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd, | 1381 | static 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 | ||
1405 | static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, | 1413 | static 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 | ||
1464 | pio_fallback: | 1474 | pio_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 | ||
1538 | static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd, | 1552 | static 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 | ||
594 | static const struct of_device_id vf610_nfc_dt_ids[] = { | 594 | static 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 | ||
644 | static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | 643 | static 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 | ||
605 | static 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. |