[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: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
@@ -990,7 +990,10 @@ 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 */
|
||||||
ret = chip->ecc.read_page(mtd, chip, bufpoi);
|
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);
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,13 +1481,16 @@ 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);
|
||||||
|
|
||||||
chip->ecc.write_page(mtd, chip, buf);
|
if (unlikely(raw))
|
||||||
|
chip->ecc.write_page_raw(mtd, chip, buf);
|
||||||
|
else
|
||||||
|
chip->ecc.write_page(mtd, chip, buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cached progamming disabled for now, Not sure if its worth the
|
* Cached progamming disabled for now, Not sure if its worth the
|
||||||
@@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
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 {
|
|||||||
* 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 {
|
|||||||
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 {
|
|||||||
* @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 {
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user