diff options
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 44 | ||||
-rw-r--r-- | include/linux/mtd/nand.h | 11 |
2 files changed, 32 insertions, 23 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e1e81a9543e8..baece61169f4 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -990,7 +990,10 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
990 | } | 990 | } |
991 | 991 | ||
992 | /* Now read the page into the buffer */ | 992 | /* Now read the page into the buffer */ |
993 | ret = chip->ecc.read_page(mtd, chip, bufpoi); | 993 | if (unlikely(ops->mode == MTD_OOB_RAW)) |
994 | ret = chip->ecc.read_page_raw(mtd, chip, bufpoi); | ||
995 | else | ||
996 | ret = chip->ecc.read_page(mtd, chip, bufpoi); | ||
994 | if (ret < 0) | 997 | if (ret < 0) |
995 | break; | 998 | break; |
996 | 999 | ||
@@ -1323,8 +1326,6 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1323 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, | 1326 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, |
1324 | struct mtd_oob_ops *ops) | 1327 | struct mtd_oob_ops *ops) |
1325 | { | 1328 | { |
1326 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, | ||
1327 | uint8_t *buf) = NULL; | ||
1328 | struct nand_chip *chip = mtd->priv; | 1329 | struct nand_chip *chip = mtd->priv; |
1329 | int ret = -ENOTSUPP; | 1330 | int ret = -ENOTSUPP; |
1330 | 1331 | ||
@@ -1342,12 +1343,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1342 | switch(ops->mode) { | 1343 | switch(ops->mode) { |
1343 | case MTD_OOB_PLACE: | 1344 | case MTD_OOB_PLACE: |
1344 | case MTD_OOB_AUTO: | 1345 | case MTD_OOB_AUTO: |
1345 | break; | ||
1346 | |||
1347 | case MTD_OOB_RAW: | 1346 | case MTD_OOB_RAW: |
1348 | /* Replace the read_page algorithm temporary */ | ||
1349 | read_page = chip->ecc.read_page; | ||
1350 | chip->ecc.read_page = nand_read_page_raw; | ||
1351 | break; | 1347 | break; |
1352 | 1348 | ||
1353 | default: | 1349 | default: |
@@ -1359,8 +1355,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1359 | else | 1355 | else |
1360 | ret = nand_do_read_ops(mtd, from, ops); | 1356 | ret = nand_do_read_ops(mtd, from, ops); |
1361 | 1357 | ||
1362 | if (unlikely(ops->mode == MTD_OOB_RAW)) | ||
1363 | chip->ecc.read_page = read_page; | ||
1364 | out: | 1358 | out: |
1365 | nand_release_device(mtd); | 1359 | nand_release_device(mtd); |
1366 | return ret; | 1360 | return ret; |
@@ -1479,7 +1473,7 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, | |||
1479 | } | 1473 | } |
1480 | 1474 | ||
1481 | /** | 1475 | /** |
1482 | * nand_write_page - [INTERNAL] write one page | 1476 | * nand_write_page - [REPLACEABLE] write one page |
1483 | * @mtd: MTD device structure | 1477 | * @mtd: MTD device structure |
1484 | * @chip: NAND chip descriptor | 1478 | * @chip: NAND chip descriptor |
1485 | * @buf: the data to write | 1479 | * @buf: the data to write |
@@ -1487,13 +1481,16 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, | |||
1487 | * @cached: cached programming | 1481 | * @cached: cached programming |
1488 | */ | 1482 | */ |
1489 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | 1483 | static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
1490 | const uint8_t *buf, int page, int cached) | 1484 | const uint8_t *buf, int page, int cached, int raw) |
1491 | { | 1485 | { |
1492 | int status; | 1486 | int status; |
1493 | 1487 | ||
1494 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | 1488 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); |
1495 | 1489 | ||
1496 | chip->ecc.write_page(mtd, chip, buf); | 1490 | if (unlikely(raw)) |
1491 | chip->ecc.write_page_raw(mtd, chip, buf); | ||
1492 | else | ||
1493 | chip->ecc.write_page(mtd, chip, buf); | ||
1497 | 1494 | ||
1498 | /* | 1495 | /* |
1499 | * Cached progamming disabled for now, Not sure if its worth the | 1496 | * 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, | |||
1636 | if (unlikely(oob)) | 1633 | if (unlikely(oob)) |
1637 | oob = nand_fill_oob(chip, oob, ops); | 1634 | oob = nand_fill_oob(chip, oob, ops); |
1638 | 1635 | ||
1639 | ret = nand_write_page(mtd, chip, buf, page, cached); | 1636 | ret = chip->write_page(mtd, chip, buf, page, cached, |
1637 | (ops->mode == MTD_OOB_RAW)); | ||
1640 | if (ret) | 1638 | if (ret) |
1641 | break; | 1639 | break; |
1642 | 1640 | ||
@@ -1769,8 +1767,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
1769 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, | 1767 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, |
1770 | struct mtd_oob_ops *ops) | 1768 | struct mtd_oob_ops *ops) |
1771 | { | 1769 | { |
1772 | void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | ||
1773 | const uint8_t *buf) = NULL; | ||
1774 | struct nand_chip *chip = mtd->priv; | 1770 | struct nand_chip *chip = mtd->priv; |
1775 | int ret = -ENOTSUPP; | 1771 | int ret = -ENOTSUPP; |
1776 | 1772 | ||
@@ -1788,12 +1784,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
1788 | switch(ops->mode) { | 1784 | switch(ops->mode) { |
1789 | case MTD_OOB_PLACE: | 1785 | case MTD_OOB_PLACE: |
1790 | case MTD_OOB_AUTO: | 1786 | case MTD_OOB_AUTO: |
1791 | break; | ||
1792 | |||
1793 | case MTD_OOB_RAW: | 1787 | case MTD_OOB_RAW: |
1794 | /* Replace the write_page algorithm temporary */ | ||
1795 | write_page = chip->ecc.write_page; | ||
1796 | chip->ecc.write_page = nand_write_page_raw; | ||
1797 | break; | 1788 | break; |
1798 | 1789 | ||
1799 | default: | 1790 | default: |
@@ -1805,8 +1796,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
1805 | else | 1796 | else |
1806 | ret = nand_do_write_ops(mtd, to, ops); | 1797 | ret = nand_do_write_ops(mtd, to, ops); |
1807 | 1798 | ||
1808 | if (unlikely(ops->mode == MTD_OOB_RAW)) | ||
1809 | chip->ecc.write_page = write_page; | ||
1810 | out: | 1799 | out: |
1811 | nand_release_device(mtd); | 1800 | nand_release_device(mtd); |
1812 | return ret; | 1801 | return ret; |
@@ -2383,10 +2372,18 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2383 | } | 2372 | } |
2384 | } | 2373 | } |
2385 | 2374 | ||
2375 | if (!chip->write_page) | ||
2376 | chip->write_page = nand_write_page; | ||
2377 | |||
2386 | /* | 2378 | /* |
2387 | * check ECC mode, default to software if 3byte/512byte hardware ECC is | 2379 | * check ECC mode, default to software if 3byte/512byte hardware ECC is |
2388 | * selected and we have 256 byte pagesize fallback to software ECC | 2380 | * selected and we have 256 byte pagesize fallback to software ECC |
2389 | */ | 2381 | */ |
2382 | if (!chip->ecc.read_page_raw) | ||
2383 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2384 | if (!chip->ecc.write_page_raw) | ||
2385 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2386 | |||
2390 | switch (chip->ecc.mode) { | 2387 | switch (chip->ecc.mode) { |
2391 | case NAND_ECC_HW: | 2388 | case NAND_ECC_HW: |
2392 | /* Use standard hwecc read page function ? */ | 2389 | /* Use standard hwecc read page function ? */ |
@@ -2444,6 +2441,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2444 | chip->ecc.size = mtd->writesize; | 2441 | chip->ecc.size = mtd->writesize; |
2445 | chip->ecc.bytes = 0; | 2442 | chip->ecc.bytes = 0; |
2446 | break; | 2443 | break; |
2444 | |||
2447 | default: | 2445 | default: |
2448 | printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", | 2446 | printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", |
2449 | chip->ecc.mode); | 2447 | chip->ecc.mode); |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index cd4fe9ae8622..2bcbcc896835 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -235,6 +235,8 @@ struct nand_hw_control { | |||
235 | * be provided if an hardware ECC is available | 235 | * be provided if an hardware ECC is available |
236 | * @calculate: function for ecc calculation or readback from ecc hardware | 236 | * @calculate: function for ecc calculation or readback from ecc hardware |
237 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) | 237 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) |
238 | * @read_page_raw: function to read a raw page without ECC | ||
239 | * @write_page_raw: function to write a raw page without ECC | ||
238 | * @read_page: function to read a page according to the ecc generator requirements | 240 | * @read_page: function to read a page according to the ecc generator requirements |
239 | * @write_page: function to write a page according to the ecc generator requirements | 241 | * @write_page: function to write a page according to the ecc generator requirements |
240 | * @read_oob: function to read chip OOB data | 242 | * @read_oob: function to read chip OOB data |
@@ -256,6 +258,12 @@ struct nand_ecc_ctrl { | |||
256 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, | 258 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, |
257 | uint8_t *read_ecc, | 259 | uint8_t *read_ecc, |
258 | uint8_t *calc_ecc); | 260 | uint8_t *calc_ecc); |
261 | int (*read_page_raw)(struct mtd_info *mtd, | ||
262 | struct nand_chip *chip, | ||
263 | uint8_t *buf); | ||
264 | void (*write_page_raw)(struct mtd_info *mtd, | ||
265 | struct nand_chip *chip, | ||
266 | const uint8_t *buf); | ||
259 | int (*read_page)(struct mtd_info *mtd, | 267 | int (*read_page)(struct mtd_info *mtd, |
260 | struct nand_chip *chip, | 268 | struct nand_chip *chip, |
261 | uint8_t *buf); | 269 | uint8_t *buf); |
@@ -344,6 +352,7 @@ struct nand_buffers { | |||
344 | * @priv: [OPTIONAL] pointer to private chip date | 352 | * @priv: [OPTIONAL] pointer to private chip date |
345 | * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks | 353 | * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks |
346 | * (determine if errors are correctable) | 354 | * (determine if errors are correctable) |
355 | * @write_page [REPLACEABLE] High-level page write function | ||
347 | */ | 356 | */ |
348 | 357 | ||
349 | struct nand_chip { | 358 | struct nand_chip { |
@@ -366,6 +375,8 @@ struct nand_chip { | |||
366 | void (*erase_cmd)(struct mtd_info *mtd, int page); | 375 | void (*erase_cmd)(struct mtd_info *mtd, int page); |
367 | int (*scan_bbt)(struct mtd_info *mtd); | 376 | int (*scan_bbt)(struct mtd_info *mtd); |
368 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); | 377 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); |
378 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | ||
379 | const uint8_t *buf, int page, int cached, int raw); | ||
369 | 380 | ||
370 | int chip_delay; | 381 | int chip_delay; |
371 | unsigned int options; | 382 | unsigned int options; |