diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 99 |
1 files changed, 95 insertions, 4 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0c3afccde8a2..d902370df3e0 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -748,6 +748,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
748 | * @mtd: mtd info structure | 748 | * @mtd: mtd info structure |
749 | * @chip: nand chip info structure | 749 | * @chip: nand chip info structure |
750 | * @buf: buffer to store read data | 750 | * @buf: buffer to store read data |
751 | * | ||
752 | * Not for syndrome calculating ecc controllers, which use a special oob layout | ||
751 | */ | 753 | */ |
752 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 754 | static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
753 | uint8_t *buf) | 755 | uint8_t *buf) |
@@ -758,6 +760,47 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
758 | } | 760 | } |
759 | 761 | ||
760 | /** | 762 | /** |
763 | * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc | ||
764 | * @mtd: mtd info structure | ||
765 | * @chip: nand chip info structure | ||
766 | * @buf: buffer to store read data | ||
767 | * | ||
768 | * We need a special oob layout and handling even when OOB isn't used. | ||
769 | */ | ||
770 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
771 | uint8_t *buf) | ||
772 | { | ||
773 | int eccsize = chip->ecc.size; | ||
774 | int eccbytes = chip->ecc.bytes; | ||
775 | uint8_t *oob = chip->oob_poi; | ||
776 | int steps, size; | ||
777 | |||
778 | for (steps = chip->ecc.steps; steps > 0; steps--) { | ||
779 | chip->read_buf(mtd, buf, eccsize); | ||
780 | buf += eccsize; | ||
781 | |||
782 | if (chip->ecc.prepad) { | ||
783 | chip->read_buf(mtd, oob, chip->ecc.prepad); | ||
784 | oob += chip->ecc.prepad; | ||
785 | } | ||
786 | |||
787 | chip->read_buf(mtd, oob, eccbytes); | ||
788 | oob += eccbytes; | ||
789 | |||
790 | if (chip->ecc.postpad) { | ||
791 | chip->read_buf(mtd, oob, chip->ecc.postpad); | ||
792 | oob += chip->ecc.postpad; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | size = mtd->oobsize - (oob - chip->oob_poi); | ||
797 | if (size) | ||
798 | chip->read_buf(mtd, oob, size); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | /** | ||
761 | * nand_read_page_swecc - [REPLACABLE] software ecc based page read function | 804 | * nand_read_page_swecc - [REPLACABLE] software ecc based page read function |
762 | * @mtd: mtd info structure | 805 | * @mtd: mtd info structure |
763 | * @chip: nand chip info structure | 806 | * @chip: nand chip info structure |
@@ -1482,6 +1525,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1482 | * @mtd: mtd info structure | 1525 | * @mtd: mtd info structure |
1483 | * @chip: nand chip info structure | 1526 | * @chip: nand chip info structure |
1484 | * @buf: data buffer | 1527 | * @buf: data buffer |
1528 | * | ||
1529 | * Not for syndrome calculating ecc controllers, which use a special oob layout | ||
1485 | */ | 1530 | */ |
1486 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | 1531 | static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
1487 | const uint8_t *buf) | 1532 | const uint8_t *buf) |
@@ -1491,6 +1536,44 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1491 | } | 1536 | } |
1492 | 1537 | ||
1493 | /** | 1538 | /** |
1539 | * nand_write_page_raw_syndrome - [Intern] raw page write function | ||
1540 | * @mtd: mtd info structure | ||
1541 | * @chip: nand chip info structure | ||
1542 | * @buf: data buffer | ||
1543 | * | ||
1544 | * We need a special oob layout and handling even when ECC isn't checked. | ||
1545 | */ | ||
1546 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | ||
1547 | const uint8_t *buf) | ||
1548 | { | ||
1549 | int eccsize = chip->ecc.size; | ||
1550 | int eccbytes = chip->ecc.bytes; | ||
1551 | uint8_t *oob = chip->oob_poi; | ||
1552 | int steps, size; | ||
1553 | |||
1554 | for (steps = chip->ecc.steps; steps > 0; steps--) { | ||
1555 | chip->write_buf(mtd, buf, eccsize); | ||
1556 | buf += eccsize; | ||
1557 | |||
1558 | if (chip->ecc.prepad) { | ||
1559 | chip->write_buf(mtd, oob, chip->ecc.prepad); | ||
1560 | oob += chip->ecc.prepad; | ||
1561 | } | ||
1562 | |||
1563 | chip->read_buf(mtd, oob, eccbytes); | ||
1564 | oob += eccbytes; | ||
1565 | |||
1566 | if (chip->ecc.postpad) { | ||
1567 | chip->write_buf(mtd, oob, chip->ecc.postpad); | ||
1568 | oob += chip->ecc.postpad; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | size = mtd->oobsize - (oob - chip->oob_poi); | ||
1573 | if (size) | ||
1574 | chip->write_buf(mtd, oob, size); | ||
1575 | } | ||
1576 | /** | ||
1494 | * nand_write_page_swecc - [REPLACABLE] software ecc based page write function | 1577 | * nand_write_page_swecc - [REPLACABLE] software ecc based page write function |
1495 | * @mtd: mtd info structure | 1578 | * @mtd: mtd info structure |
1496 | * @chip: nand chip info structure | 1579 | * @chip: nand chip info structure |
@@ -2569,10 +2652,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2569 | * check ECC mode, default to software if 3byte/512byte hardware ECC is | 2652 | * check ECC mode, default to software if 3byte/512byte hardware ECC is |
2570 | * selected and we have 256 byte pagesize fallback to software ECC | 2653 | * selected and we have 256 byte pagesize fallback to software ECC |
2571 | */ | 2654 | */ |
2572 | if (!chip->ecc.read_page_raw) | ||
2573 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2574 | if (!chip->ecc.write_page_raw) | ||
2575 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2576 | 2655 | ||
2577 | switch (chip->ecc.mode) { | 2656 | switch (chip->ecc.mode) { |
2578 | case NAND_ECC_HW: | 2657 | case NAND_ECC_HW: |
@@ -2581,6 +2660,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2581 | chip->ecc.read_page = nand_read_page_hwecc; | 2660 | chip->ecc.read_page = nand_read_page_hwecc; |
2582 | if (!chip->ecc.write_page) | 2661 | if (!chip->ecc.write_page) |
2583 | chip->ecc.write_page = nand_write_page_hwecc; | 2662 | chip->ecc.write_page = nand_write_page_hwecc; |
2663 | if (!chip->ecc.read_page_raw) | ||
2664 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2665 | if (!chip->ecc.write_page_raw) | ||
2666 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2584 | if (!chip->ecc.read_oob) | 2667 | if (!chip->ecc.read_oob) |
2585 | chip->ecc.read_oob = nand_read_oob_std; | 2668 | chip->ecc.read_oob = nand_read_oob_std; |
2586 | if (!chip->ecc.write_oob) | 2669 | if (!chip->ecc.write_oob) |
@@ -2602,6 +2685,10 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2602 | chip->ecc.read_page = nand_read_page_syndrome; | 2685 | chip->ecc.read_page = nand_read_page_syndrome; |
2603 | if (!chip->ecc.write_page) | 2686 | if (!chip->ecc.write_page) |
2604 | chip->ecc.write_page = nand_write_page_syndrome; | 2687 | chip->ecc.write_page = nand_write_page_syndrome; |
2688 | if (!chip->ecc.read_page_raw) | ||
2689 | chip->ecc.read_page_raw = nand_read_page_raw_syndrome; | ||
2690 | if (!chip->ecc.write_page_raw) | ||
2691 | chip->ecc.write_page_raw = nand_write_page_raw_syndrome; | ||
2605 | if (!chip->ecc.read_oob) | 2692 | if (!chip->ecc.read_oob) |
2606 | chip->ecc.read_oob = nand_read_oob_syndrome; | 2693 | chip->ecc.read_oob = nand_read_oob_syndrome; |
2607 | if (!chip->ecc.write_oob) | 2694 | if (!chip->ecc.write_oob) |
@@ -2620,6 +2707,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2620 | chip->ecc.read_page = nand_read_page_swecc; | 2707 | chip->ecc.read_page = nand_read_page_swecc; |
2621 | chip->ecc.read_subpage = nand_read_subpage; | 2708 | chip->ecc.read_subpage = nand_read_subpage; |
2622 | chip->ecc.write_page = nand_write_page_swecc; | 2709 | chip->ecc.write_page = nand_write_page_swecc; |
2710 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2711 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2623 | chip->ecc.read_oob = nand_read_oob_std; | 2712 | chip->ecc.read_oob = nand_read_oob_std; |
2624 | chip->ecc.write_oob = nand_write_oob_std; | 2713 | chip->ecc.write_oob = nand_write_oob_std; |
2625 | chip->ecc.size = 256; | 2714 | chip->ecc.size = 256; |
@@ -2632,6 +2721,8 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
2632 | chip->ecc.read_page = nand_read_page_raw; | 2721 | chip->ecc.read_page = nand_read_page_raw; |
2633 | chip->ecc.write_page = nand_write_page_raw; | 2722 | chip->ecc.write_page = nand_write_page_raw; |
2634 | chip->ecc.read_oob = nand_read_oob_std; | 2723 | chip->ecc.read_oob = nand_read_oob_std; |
2724 | chip->ecc.read_page_raw = nand_read_page_raw; | ||
2725 | chip->ecc.write_page_raw = nand_write_page_raw; | ||
2635 | chip->ecc.write_oob = nand_write_oob_std; | 2726 | chip->ecc.write_oob = nand_write_oob_std; |
2636 | chip->ecc.size = mtd->writesize; | 2727 | chip->ecc.size = mtd->writesize; |
2637 | chip->ecc.bytes = 0; | 2728 | chip->ecc.bytes = 0; |