Commit 956e944c authored by David Woodhouse's avatar David Woodhouse

[MTD NAND] Allow override of page read and write functions.

- allow high-level nand_write_page() function to be overridden
- likewise low-level write_page_raw() and read_page_raw() functions
- Clean up the abuse of chip->ecc.{write,read}_page() with MTD_OOB_RAW
Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 4bf63fcb
...@@ -990,6 +990,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, ...@@ -990,6 +990,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
} }
/* Now read the page into the buffer */ /* Now read the page into the buffer */
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi); ret = chip->ecc.read_page(mtd, chip, bufpoi);
if (ret < 0) if (ret < 0)
break; break;
...@@ -1323,8 +1326,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -1323,8 +1326,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
static int nand_read_oob(struct mtd_info *mtd, loff_t from, static int nand_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf) = NULL;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP; int ret = -ENOTSUPP;
...@@ -1342,12 +1343,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -1342,12 +1343,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
switch(ops->mode) { switch(ops->mode) {
case MTD_OOB_PLACE: case MTD_OOB_PLACE:
case MTD_OOB_AUTO: case MTD_OOB_AUTO:
break;
case MTD_OOB_RAW: case MTD_OOB_RAW:
/* Replace the read_page algorithm temporary */
read_page = chip->ecc.read_page;
chip->ecc.read_page = nand_read_page_raw;
break; break;
default: default:
...@@ -1359,8 +1355,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -1359,8 +1355,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
else else
ret = nand_do_read_ops(mtd, from, ops); ret = nand_do_read_ops(mtd, from, ops);
if (unlikely(ops->mode == MTD_OOB_RAW))
chip->ecc.read_page = read_page;
out: out:
nand_release_device(mtd); nand_release_device(mtd);
return ret; return ret;
...@@ -1479,7 +1473,7 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -1479,7 +1473,7 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
} }
/** /**
* nand_write_page - [INTERNAL] write one page * nand_write_page - [REPLACEABLE] write one page
* @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
...@@ -1487,12 +1481,15 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -1487,12 +1481,15 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
* @cached: cached programming * @cached: cached programming
*/ */
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) const uint8_t *buf, 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))
chip->ecc.write_page_raw(mtd, chip, buf);
else
chip->ecc.write_page(mtd, chip, buf); chip->ecc.write_page(mtd, chip, buf);
/* /*
...@@ -1636,7 +1633,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -1636,7 +1633,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (unlikely(oob)) if (unlikely(oob))
oob = nand_fill_oob(chip, oob, ops); oob = nand_fill_oob(chip, oob, ops);
ret = nand_write_page(mtd, chip, buf, page, cached); ret = chip->write_page(mtd, chip, buf, page, cached,
(ops->mode == MTD_OOB_RAW));
if (ret) if (ret)
break; break;
...@@ -1769,8 +1767,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -1769,8 +1767,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
static int nand_write_oob(struct mtd_info *mtd, loff_t to, static int nand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf) = NULL;
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
int ret = -ENOTSUPP; int ret = -ENOTSUPP;
...@@ -1788,12 +1784,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -1788,12 +1784,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
switch(ops->mode) { switch(ops->mode) {
case MTD_OOB_PLACE: case MTD_OOB_PLACE:
case MTD_OOB_AUTO: case MTD_OOB_AUTO:
break;
case MTD_OOB_RAW: case MTD_OOB_RAW:
/* Replace the write_page algorithm temporary */
write_page = chip->ecc.write_page;
chip->ecc.write_page = nand_write_page_raw;
break; break;
default: default:
...@@ -1805,8 +1796,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -1805,8 +1796,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
else else
ret = nand_do_write_ops(mtd, to, ops); ret = nand_do_write_ops(mtd, to, ops);
if (unlikely(ops->mode == MTD_OOB_RAW))
chip->ecc.write_page = write_page;
out: out:
nand_release_device(mtd); nand_release_device(mtd);
return ret; return ret;
...@@ -2383,10 +2372,18 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -2383,10 +2372,18 @@ int nand_scan_tail(struct mtd_info *mtd)
} }
} }
if (!chip->write_page)
chip->write_page = nand_write_page;
/* /*
* check ECC mode, default to software if 3byte/512byte hardware ECC is * check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC * selected and we have 256 byte pagesize fallback to software ECC
*/ */
if (!chip->ecc.read_page_raw)
chip->ecc.read_page_raw = nand_read_page_raw;
if (!chip->ecc.write_page_raw)
chip->ecc.write_page_raw = nand_write_page_raw;
switch (chip->ecc.mode) { switch (chip->ecc.mode) {
case NAND_ECC_HW: case NAND_ECC_HW:
/* Use standard hwecc read page function ? */ /* Use standard hwecc read page function ? */
...@@ -2444,6 +2441,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -2444,6 +2441,7 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.size = mtd->writesize; chip->ecc.size = mtd->writesize;
chip->ecc.bytes = 0; chip->ecc.bytes = 0;
break; break;
default: default:
printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
chip->ecc.mode); chip->ecc.mode);
......
...@@ -235,6 +235,8 @@ struct nand_hw_control { ...@@ -235,6 +235,8 @@ struct nand_hw_control {
* be provided if an hardware ECC is available * be provided if an hardware ECC is available
* @calculate: function for ecc calculation or readback from ecc hardware * @calculate: function for ecc calculation or readback from ecc hardware
* @correct: function for ecc correction, matching to ecc generator (sw/hw) * @correct: function for ecc correction, matching to ecc generator (sw/hw)
* @read_page_raw: function to read a raw page without ECC
* @write_page_raw: function to write a raw page without ECC
* @read_page: function to read a page according to the ecc generator requirements * @read_page: function to read a page according to the ecc generator requirements
* @write_page: function to write a page according to the ecc generator requirements * @write_page: function to write a page according to the ecc generator requirements
* @read_oob: function to read chip OOB data * @read_oob: function to read chip OOB data
...@@ -256,6 +258,12 @@ struct nand_ecc_ctrl { ...@@ -256,6 +258,12 @@ struct nand_ecc_ctrl {
int (*correct)(struct mtd_info *mtd, uint8_t *dat, int (*correct)(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *read_ecc,
uint8_t *calc_ecc); uint8_t *calc_ecc);
int (*read_page_raw)(struct mtd_info *mtd,
struct nand_chip *chip,
uint8_t *buf);
void (*write_page_raw)(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf);
int (*read_page)(struct mtd_info *mtd, int (*read_page)(struct mtd_info *mtd,
struct nand_chip *chip, struct nand_chip *chip,
uint8_t *buf); uint8_t *buf);
...@@ -344,6 +352,7 @@ struct nand_buffers { ...@@ -344,6 +352,7 @@ struct nand_buffers {
* @priv: [OPTIONAL] pointer to private chip date * @priv: [OPTIONAL] pointer to private chip date
* @errstat: [OPTIONAL] hardware specific function to perform additional error status checks * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks
* (determine if errors are correctable) * (determine if errors are correctable)
* @write_page [REPLACEABLE] High-level page write function
*/ */
struct nand_chip { struct nand_chip {
...@@ -366,6 +375,8 @@ struct nand_chip { ...@@ -366,6 +375,8 @@ struct nand_chip {
void (*erase_cmd)(struct mtd_info *mtd, int page); void (*erase_cmd)(struct mtd_info *mtd, int page);
int (*scan_bbt)(struct mtd_info *mtd); int (*scan_bbt)(struct mtd_info *mtd);
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, 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