Commit 1fbb938d authored by Brian Norris's avatar Brian Norris Committed by David Woodhouse

mtd: nand: add 'oob_required' argument to NAND {read,write}_page interfaces

New NAND controllers can perform read/write via HW engines which don't expose
OOB data in their DMA mode. To reflect this, we should rework the nand_chip /
nand_ecc_ctrl interfaces that assume that drivers will always read/write OOB
data in the nand_chip.oob_poi buffer. A better interface includes a boolean
argument that explicitly tells the callee when OOB data is requested by the
calling layer (for reading/writing to/from nand_chip.oob_poi).

This patch adds the 'oob_required' parameter to each relevant {read,write}_page
interface; all 'oob_required' parameters are left unused for now. The next
patch will set the parameter properly in the nand_base.c callers, and follow-up
patches will make use of 'oob_required' in some of the callee functions.

Note that currently, there is no harm in ignoring the 'oob_required' parameter
and *always* utilizing nand_chip.oob_poi, but there can be
performance/complexity/design benefits from avoiding filling oob_poi in the
common case. I will try to implement this for some drivers which can be ported
easily.

Note: I couldn't compile-test all of these easily, as some had ARCH
dependencies.

[dwmw2: Merge later 1/0 vs. true/false cleanup]
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
Reviewed-by: default avatarShmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: default avatarJiandong Zheng <jdzheng@broadcom.com>
Acked-by: default avatarMike Dunn <mikedunn@newsguy.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent b4f7aa84
...@@ -324,9 +324,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd, ...@@ -324,9 +324,10 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
* mtd: mtd info structure * mtd: mtd info structure
* chip: nand chip info structure * chip: nand chip info structure
* buf: buffer to store read data * buf: buffer to store read data
* oob_required: caller expects OOB data read to chip->oob_poi
*/ */
static int atmel_nand_read_page(struct mtd_info *mtd, static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
int eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
......
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
/* ---- Private Function Prototypes -------------------------------------- */ /* ---- Private Function Prototypes -------------------------------------- */
static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int page); struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf); struct nand_chip *chip, const uint8_t *buf, int oob_required);
/* ---- Private Variables ------------------------------------------------ */ /* ---- Private Variables ------------------------------------------------ */
...@@ -103,11 +103,12 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = { ...@@ -103,11 +103,12 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = {
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
* *
***************************************************************************/ ***************************************************************************/
static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t * buf, struct nand_chip *chip, uint8_t * buf,
int page) int oob_required, int page)
{ {
int sectorIdx = 0; int sectorIdx = 0;
int eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
...@@ -190,10 +191,11 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, ...@@ -190,10 +191,11 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
* *
***************************************************************************/ ***************************************************************************/
static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf) struct nand_chip *chip, const uint8_t *buf, int oob_required)
{ {
int sectorIdx = 0; int sectorIdx = 0;
int eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
......
...@@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, ...@@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
* for MLC parts which may have permanently stuck bits. * for MLC parts which may have permanently stuck bits.
*/ */
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0); int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0);
if (ret < 0) if (ret < 0)
return -EFAULT; return -EFAULT;
else { else {
......
...@@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, ...@@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
} }
static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
bf5xx_nand_read_buf(mtd, buf, mtd->writesize); bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip ...@@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip
} }
static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
bf5xx_nand_write_buf(mtd, buf, mtd->writesize); bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
......
...@@ -375,12 +375,13 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -375,12 +375,13 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
* *
* The hw generator calculates the error syndrome automatically. Therefor * The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling. * we need a special oob layout and handling.
*/ */
static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
struct cafe_priv *cafe = mtd->priv; struct cafe_priv *cafe = mtd->priv;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
...@@ -520,7 +521,8 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { ...@@ -520,7 +521,8 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf) struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{ {
struct cafe_priv *cafe = mtd->priv; struct cafe_priv *cafe = mtd->priv;
...@@ -532,16 +534,17 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, ...@@ -532,16 +534,17 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd,
} }
static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw) const uint8_t *buf, int oob_required, int page,
int cached, int raw)
{ {
int status; int status;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw)) if (unlikely(raw))
chip->ecc.write_page_raw(mtd, chip, buf); chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
else else
chip->ecc.write_page(mtd, chip, buf); chip->ecc.write_page(mtd, chip, buf, oob_required);
/* /*
* Cached progamming disabled for now, Not sure if its worth the * Cached progamming disabled for now, Not sure if its worth the
......
...@@ -1087,7 +1087,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1087,7 +1087,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
* by write_page above. * by write_page above.
* */ * */
static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
/* for regular page writes, we let HW handle all the ECC /* for regular page writes, we let HW handle all the ECC
* data written to the device. */ * data written to the device. */
...@@ -1099,7 +1099,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1099,7 +1099,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* write_page() function above. * write_page() function above.
*/ */
static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
/* for raw page writes, we want to disable ECC and simply write /* for raw page writes, we want to disable ECC and simply write
whatever data is in the buffer. */ whatever data is in the buffer. */
...@@ -1122,7 +1122,7 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1122,7 +1122,7 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
} }
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
unsigned int max_bitflips; unsigned int max_bitflips;
struct denali_nand_info *denali = mtd_to_denali(mtd); struct denali_nand_info *denali = mtd_to_denali(mtd);
...@@ -1175,7 +1175,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1175,7 +1175,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
} }
static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
struct denali_nand_info *denali = mtd_to_denali(mtd); struct denali_nand_info *denali = mtd_to_denali(mtd);
......
...@@ -787,13 +787,13 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, ...@@ -787,13 +787,13 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
return read_page(mtd, nand, buf, page, false); return read_page(mtd, nand, buf, page, false);
} }
static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
return read_page(mtd, nand, buf, page, true); return read_page(mtd, nand, buf, page, true);
} }
...@@ -953,13 +953,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand, ...@@ -953,13 +953,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand,
} }
static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
return write_page(mtd, nand, buf, false); return write_page(mtd, nand, buf, false);
} }
static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
return write_page(mtd, nand, buf, true); return write_page(mtd, nand, buf, true);
} }
...@@ -1003,7 +1003,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) ...@@ -1003,7 +1003,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
return -ENOMEM; return -ENOMEM;
read_page_prologue(mtd, g4_addr); read_page_prologue(mtd, g4_addr);
status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE); status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
if (status) if (status)
goto exit; goto exit;
...@@ -1080,7 +1080,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) ...@@ -1080,7 +1080,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* write first page of block */ /* write first page of block */
write_page_prologue(mtd, g4_addr); write_page_prologue(mtd, g4_addr);
docg4_write_page(mtd, nand, buf); docg4_write_page(mtd, nand, buf, 1);
ret = pageprog(mtd); ret = pageprog(mtd);
if (!ret) if (!ret)
mtd->ecc_stats.badblocks++; mtd->ecc_stats.badblocks++;
......
...@@ -746,10 +746,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) ...@@ -746,10 +746,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
return 0; return 0;
} }
static int fsl_elbc_read_page(struct mtd_info *mtd, static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
uint8_t *buf,
int page)
{ {
struct fsl_elbc_mtd *priv = chip->priv; struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_lbc_ctrl *ctrl = priv->ctrl;
...@@ -767,9 +765,8 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, ...@@ -767,9 +765,8 @@ static int fsl_elbc_read_page(struct mtd_info *mtd,
/* ECC will be calculated automatically, and errors will be detected in /* ECC will be calculated automatically, and errors will be detected in
* waitfunc. * waitfunc.
*/ */
static void fsl_elbc_write_page(struct mtd_info *mtd, static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, const uint8_t *buf, int oob_required)
const uint8_t *buf)
{ {
fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
......
...@@ -698,9 +698,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) ...@@ -698,9 +698,8 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
return nand_fsr | NAND_STATUS_WP; return nand_fsr | NAND_STATUS_WP;
} }
static int fsl_ifc_read_page(struct mtd_info *mtd, static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
uint8_t *buf, int page)
{ {
struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_mtd *priv = chip->priv;
struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_ctrl *ctrl = priv->ctrl;
...@@ -721,9 +720,8 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, ...@@ -721,9 +720,8 @@ static int fsl_ifc_read_page(struct mtd_info *mtd,
/* ECC will be calculated automatically, and errors will be detected in /* ECC will be calculated automatically, and errors will be detected in
* waitfunc. * waitfunc.
*/ */
static void fsl_ifc_write_page(struct mtd_info *mtd, static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, const uint8_t *buf, int oob_required)
const uint8_t *buf)
{ {
fsl_ifc_write_buf(mtd, buf, mtd->writesize); fsl_ifc_write_buf(mtd, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
......
...@@ -692,6 +692,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, ...@@ -692,6 +692,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller expects OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* This routine is needed for fsmc version 8 as reading from NAND chip has to be * This routine is needed for fsmc version 8 as reading from NAND chip has to be
...@@ -701,7 +702,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, ...@@ -701,7 +702,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
* max of 8 bits) * max of 8 bits)
*/ */
static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data *host = container_of(mtd,
struct fsmc_nand_data, mtd); struct fsmc_nand_data, mtd);
......
...@@ -842,7 +842,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this, ...@@ -842,7 +842,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
} }
static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
struct gpmi_nand_data *this = chip->priv; struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry; struct bch_geometry *nfc_geo = &this->bch_geometry;
...@@ -928,8 +928,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -928,8 +928,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
return ret; return ret;
} }
static void gpmi_ecc_write_page(struct mtd_info *mtd, static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
struct nand_chip *chip, const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
struct gpmi_nand_data *this = chip->priv; struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry; struct bch_geometry *nfc_geo = &this->bch_geometry;
...@@ -1309,7 +1309,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) ...@@ -1309,7 +1309,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Write the first page of the current stride. */ /* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
chip->ecc.write_page_raw(mtd, chip, buffer); chip->ecc.write_page_raw(mtd, chip, buffer, 0);
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
/* Wait for the write to finish. */ /* Wait for the write to finish. */
......
...@@ -1066,12 +1066,13 @@ EXPORT_SYMBOL(nand_lock); ...@@ -1066,12 +1066,13 @@ EXPORT_SYMBOL(nand_lock);
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* Not for syndrome calculating ECC controllers, which use a special oob layout. * Not for syndrome calculating ECC controllers, which use a special oob layout.
*/ */
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -1083,13 +1084,14 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1083,13 +1084,14 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* We need a special oob layout and handling even when OOB isn't used. * We need a special oob layout and handling even when OOB isn't used.
*/ */
static int nand_read_page_raw_syndrome(struct mtd_info *mtd, static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, struct nand_chip *chip, uint8_t *buf,
uint8_t *buf, int page) int oob_required, int page)
{ {
int eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1126,10 +1128,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, ...@@ -1126,10 +1128,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
*/ */
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1140,7 +1143,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1140,7 +1143,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t *eccpos = chip->ecc.layout->eccpos; uint32_t *eccpos = chip->ecc.layout->eccpos;
unsigned int max_bitflips = 0; unsigned int max_bitflips = 0;
chip->ecc.read_page_raw(mtd, chip, buf, page); chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]); chip->ecc.calculate(mtd, p, &ecc_calc[i]);
...@@ -1263,12 +1266,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1263,12 +1266,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* Not for syndrome calculating ECC controllers which need a special oob layout. * Not for syndrome calculating ECC controllers which need a special oob layout.
*/ */
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1311,6 +1315,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1311,6 +1315,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* Hardware ECC for large page chips, require OOB to be read first. For this * Hardware ECC for large page chips, require OOB to be read first. For this
...@@ -1320,7 +1325,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1320,7 +1325,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* the data area, by overwriting the NAND manufacturer bad block markings. * the data area, by overwriting the NAND manufacturer bad block markings.
*/ */
static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int page) struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1362,13 +1367,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, ...@@ -1362,13 +1367,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: buffer to store read data * @buf: buffer to store read data
* @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read * @page: page number to read
* *
* The hw generator calculates the error syndrome automatically. Therefore we * The hw generator calculates the error syndrome automatically. Therefore we
* need a special oob layout and handling. * need a special oob layout and handling.
*/ */
static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1514,14 +1520,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, ...@@ -1514,14 +1520,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
* the read methods return max bitflips per ecc step. * the read methods return max bitflips per ecc step.
*/ */
if (unlikely(ops->mode == MTD_OPS_RAW)) if (unlikely(ops->mode == MTD_OPS_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
bufpoi, page); 1, page);
else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
ret = chip->ecc.read_subpage(mtd, chip, ret = chip->ecc.read_subpage(mtd, chip,
col, bytes, bufpoi); col, bytes, bufpoi);
else else
ret = chip->ecc.read_page(mtd, chip, bufpoi, ret = chip->ecc.read_page(mtd, chip, bufpoi,
page); 1, page);
if (ret < 0) { if (ret < 0) {
if (!aligned) if (!aligned)
/* Invalidate page cache */ /* Invalidate page cache */
...@@ -1913,11 +1919,12 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -1913,11 +1919,12 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
* *
* Not for syndrome calculating ECC controllers, which use a special oob layout. * Not for syndrome calculating ECC controllers, which use a special oob layout.
*/ */
static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
...@@ -1928,12 +1935,13 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1928,12 +1935,13 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
* *
* We need a special oob layout and handling even when ECC isn't checked. * We need a special oob layout and handling even when ECC isn't checked.
*/ */
static void nand_write_page_raw_syndrome(struct mtd_info *mtd, static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
int eccsize = chip->ecc.size; int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1967,9 +1975,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, ...@@ -1967,9 +1975,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
*/ */
static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -1985,7 +1994,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1985,7 +1994,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0; i < chip->ecc.total; i++) for (i = 0; i < chip->ecc.total; i++)
chip->oob_poi[eccpos[i]] = ecc_calc[i]; chip->oob_poi[eccpos[i]] = ecc_calc[i];
chip->ecc.write_page_raw(mtd, chip, buf); chip->ecc.write_page_raw(mtd, chip, buf, 1);
} }
/** /**
...@@ -1993,9 +2002,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -1993,9 +2002,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
*/ */
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -2021,12 +2031,14 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2021,12 +2031,14 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure * @mtd: mtd info structure
* @chip: nand chip info structure * @chip: nand chip info structure
* @buf: data buffer * @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
* *
* The hw generator calculates the error syndrome automatically. Therefore we * The hw generator calculates the error syndrome automatically. Therefore we
* need a special oob layout and handling. * need a special oob layout and handling.
*/ */
static void nand_write_page_syndrome(struct mtd_info *mtd, static void nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf) struct nand_chip *chip,
const uint8_t *buf, int oob_required)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -2065,21 +2077,23 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -2065,21 +2077,23 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
* @mtd: MTD device structure * @mtd: MTD device structure
* @chip: NAND chip descriptor * @chip: NAND chip descriptor
* @buf: the data to write * @buf: the data to write
* @oob_required: must write chip->oob_poi to OOB
* @page: page number to write * @page: page number to write
* @cached: cached programming * @cached: cached programming
* @raw: use _raw version of write_page * @raw: use _raw version of write_page
*/ */
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw) const uint8_t *buf, int oob_required, int page,
int cached, int raw)
{ {
int status; int status;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw)) if (unlikely(raw))
chip->ecc.write_page_raw(mtd, chip, buf); chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
else else
chip->ecc.write_page(mtd, chip, buf); chip->ecc.write_page(mtd, chip, buf, oob_required);
/* /*
* Cached progamming disabled for now. Not sure if it's worth the * Cached progamming disabled for now. Not sure if it's worth the
...@@ -2261,7 +2275,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2261,7 +2275,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
memset(chip->oob_poi, 0xff, mtd->oobsize); memset(chip->oob_poi, 0xff, mtd->oobsize);
} }
ret = chip->write_page(mtd, chip, wbuf, page, cached, ret = chip->write_page(mtd, chip, wbuf, 1, page, cached,
(ops->mode == MTD_OPS_RAW)); (ops->mode == MTD_OPS_RAW));
if (ret) if (ret)
break; break;
......
...@@ -682,14 +682,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, ...@@ -682,14 +682,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
} }
static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf) struct nand_chip *chip, const uint8_t *buf, int oob_required)
{ {
chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
} }
static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int page) struct nand_chip *chip, uint8_t *buf, int oob_required,
int page)
{ {
struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_host *host = mtd->priv;
struct pxa3xx_nand_info *info = host->info_data; struct pxa3xx_nand_info *info = host->info_data;
......
...@@ -344,7 +344,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va ...@@ -344,7 +344,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va
} }
static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page) uint8_t *buf, int oob_required, int page)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
...@@ -366,7 +366,7 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -366,7 +366,7 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
} }
static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) const uint8_t *buf, int oob_required)
{ {
int i, eccsize = chip->ecc.size; int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes; int eccbytes = chip->ecc.bytes;
......
...@@ -360,15 +360,15 @@ struct nand_ecc_ctrl { ...@@ -360,15 +360,15 @@ struct nand_ecc_ctrl {
int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
uint8_t *calc_ecc); uint8_t *calc_ecc);
int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page); uint8_t *buf, int oob_required, int page);
void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf); const uint8_t *buf, int oob_required);
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page); uint8_t *buf, int oob_required, int page);
int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offs, uint32_t len, uint8_t *buf); uint32_t offs, uint32_t len, uint8_t *buf);
void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf); const uint8_t *buf, int oob_required);
int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
int page); int page);
int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
...@@ -504,7 +504,8 @@ struct nand_chip { ...@@ -504,7 +504,8 @@ struct nand_chip {
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
int status, int page); int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw); const uint8_t *buf, int oob_required, int page,
int cached, int raw);
int chip_delay; int chip_delay;
unsigned int options; unsigned int options;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment