diff options
author | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-06-28 04:11:33 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-06-28 04:11:33 -0400 |
commit | 7f8a894066b826a4baea49c2a3adbba0a56a192f (patch) | |
tree | 94833927f58f47a2b29b026ed1839b90a3ef29cf /drivers/mtd/devices/doc2000.c | |
parent | a39727f212426b9d5f9267b3318a2afaf9922d3b (diff) |
[MTD] DOC: Fixup read functions and do a little cleanup
The NAND rework resulted in non ECC based reads. Fix it up and
do a bit of cleanup while at it.
Pointed out by Adrian Bunk.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/devices/doc2000.c')
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 179 |
1 files changed, 73 insertions, 106 deletions
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index c54e40464d8..603a7951ac9 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -55,10 +55,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
55 | size_t *retlen, u_char *buf); | 55 | size_t *retlen, u_char *buf); |
56 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | 56 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, |
57 | size_t *retlen, const u_char *buf); | 57 | size_t *retlen, const u_char *buf); |
58 | static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | ||
59 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | ||
60 | static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | ||
61 | size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | ||
62 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | 58 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, |
63 | struct mtd_oob_ops *ops); | 59 | struct mtd_oob_ops *ops); |
64 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | 60 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, |
@@ -615,17 +611,10 @@ EXPORT_SYMBOL_GPL(DoC2k_init); | |||
615 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | 611 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, |
616 | size_t * retlen, u_char * buf) | 612 | size_t * retlen, u_char * buf) |
617 | { | 613 | { |
618 | /* Just a special case of doc_read_ecc */ | ||
619 | return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); | ||
620 | } | ||
621 | |||
622 | static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | ||
623 | size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) | ||
624 | { | ||
625 | struct DiskOnChip *this = mtd->priv; | 614 | struct DiskOnChip *this = mtd->priv; |
626 | void __iomem *docptr = this->virtadr; | 615 | void __iomem *docptr = this->virtadr; |
627 | struct Nand *mychip; | 616 | struct Nand *mychip; |
628 | unsigned char syndrome[6]; | 617 | unsigned char syndrome[6], eccbuf[6]; |
629 | volatile char dummy; | 618 | volatile char dummy; |
630 | int i, len256 = 0, ret=0; | 619 | int i, len256 = 0, ret=0; |
631 | size_t left = len; | 620 | size_t left = len; |
@@ -673,15 +662,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
673 | DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, | 662 | DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, |
674 | CDSN_CTRL_ECC_IO); | 663 | CDSN_CTRL_ECC_IO); |
675 | 664 | ||
676 | if (eccbuf) { | 665 | /* Prime the ECC engine */ |
677 | /* Prime the ECC engine */ | 666 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); |
678 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | 667 | WriteDOC(DOC_ECC_EN, docptr, ECCConf); |
679 | WriteDOC(DOC_ECC_EN, docptr, ECCConf); | ||
680 | } else { | ||
681 | /* disable the ECC engine */ | ||
682 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | ||
683 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | ||
684 | } | ||
685 | 668 | ||
686 | /* treat crossing 256-byte sector for 2M x 8bits devices */ | 669 | /* treat crossing 256-byte sector for 2M x 8bits devices */ |
687 | if (this->page256 && from + len > (from | 0xff) + 1) { | 670 | if (this->page256 && from + len > (from | 0xff) + 1) { |
@@ -698,58 +681,59 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
698 | /* Let the caller know we completed it */ | 681 | /* Let the caller know we completed it */ |
699 | *retlen += len; | 682 | *retlen += len; |
700 | 683 | ||
701 | if (eccbuf) { | 684 | /* Read the ECC data through the DiskOnChip ECC logic */ |
702 | /* Read the ECC data through the DiskOnChip ECC logic */ | 685 | /* Note: this will work even with 2M x 8bit devices as */ |
703 | /* Note: this will work even with 2M x 8bit devices as */ | 686 | /* they have 8 bytes of OOB per 256 page. mf. */ |
704 | /* they have 8 bytes of OOB per 256 page. mf. */ | 687 | DoC_ReadBuf(this, eccbuf, 6); |
705 | DoC_ReadBuf(this, eccbuf, 6); | ||
706 | |||
707 | /* Flush the pipeline */ | ||
708 | if (DoC_is_Millennium(this)) { | ||
709 | dummy = ReadDOC(docptr, ECCConf); | ||
710 | dummy = ReadDOC(docptr, ECCConf); | ||
711 | i = ReadDOC(docptr, ECCConf); | ||
712 | } else { | ||
713 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
714 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
715 | i = ReadDOC(docptr, 2k_ECCStatus); | ||
716 | } | ||
717 | 688 | ||
718 | /* Check the ECC Status */ | 689 | /* Flush the pipeline */ |
719 | if (i & 0x80) { | 690 | if (DoC_is_Millennium(this)) { |
720 | int nb_errors; | 691 | dummy = ReadDOC(docptr, ECCConf); |
721 | /* There was an ECC error */ | 692 | dummy = ReadDOC(docptr, ECCConf); |
693 | i = ReadDOC(docptr, ECCConf); | ||
694 | } else { | ||
695 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
696 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
697 | i = ReadDOC(docptr, 2k_ECCStatus); | ||
698 | } | ||
699 | |||
700 | /* Check the ECC Status */ | ||
701 | if (i & 0x80) { | ||
702 | int nb_errors; | ||
703 | /* There was an ECC error */ | ||
722 | #ifdef ECC_DEBUG | 704 | #ifdef ECC_DEBUG |
723 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); | 705 | printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); |
724 | #endif | 706 | #endif |
725 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 707 | /* Read the ECC syndrom through the DiskOnChip ECC |
726 | These syndrome will be all ZERO when there is no error */ | 708 | logic. These syndrome will be all ZERO when there |
727 | for (i = 0; i < 6; i++) { | 709 | is no error */ |
728 | syndrome[i] = | 710 | for (i = 0; i < 6; i++) { |
729 | ReadDOC(docptr, ECCSyndrome0 + i); | 711 | syndrome[i] = |
730 | } | 712 | ReadDOC(docptr, ECCSyndrome0 + i); |
731 | nb_errors = doc_decode_ecc(buf, syndrome); | 713 | } |
714 | nb_errors = doc_decode_ecc(buf, syndrome); | ||
732 | 715 | ||
733 | #ifdef ECC_DEBUG | 716 | #ifdef ECC_DEBUG |
734 | printk(KERN_ERR "Errors corrected: %x\n", nb_errors); | 717 | printk(KERN_ERR "Errors corrected: %x\n", nb_errors); |
735 | #endif | 718 | #endif |
736 | if (nb_errors < 0) { | 719 | if (nb_errors < 0) { |
737 | /* We return error, but have actually done the read. Not that | 720 | /* We return error, but have actually done the |
738 | this can be told to user-space, via sys_read(), but at least | 721 | read. Not that this can be told to |
739 | MTD-aware stuff can know about it by checking *retlen */ | 722 | user-space, via sys_read(), but at least |
740 | ret = -EIO; | 723 | MTD-aware stuff can know about it by |
741 | } | 724 | checking *retlen */ |
725 | ret = -EIO; | ||
742 | } | 726 | } |
727 | } | ||
743 | 728 | ||
744 | #ifdef PSYCHO_DEBUG | 729 | #ifdef PSYCHO_DEBUG |
745 | printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", | 730 | printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", |
746 | (long)from, eccbuf[0], eccbuf[1], eccbuf[2], | 731 | (long)from, eccbuf[0], eccbuf[1], eccbuf[2], |
747 | eccbuf[3], eccbuf[4], eccbuf[5]); | 732 | eccbuf[3], eccbuf[4], eccbuf[5]); |
748 | #endif | 733 | #endif |
749 | 734 | ||
750 | /* disable the ECC engine */ | 735 | /* disable the ECC engine */ |
751 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); | 736 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); |
752 | } | ||
753 | 737 | ||
754 | /* according to 11.4.1, we need to wait for the busy line | 738 | /* according to 11.4.1, we need to wait for the busy line |
755 | * drop if we read to the end of the page. */ | 739 | * drop if we read to the end of the page. */ |
@@ -771,17 +755,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
771 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | 755 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, |
772 | size_t * retlen, const u_char * buf) | 756 | size_t * retlen, const u_char * buf) |
773 | { | 757 | { |
774 | char eccbuf[6]; | ||
775 | return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL); | ||
776 | } | ||
777 | |||
778 | static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | ||
779 | size_t * retlen, const u_char * buf, | ||
780 | u_char * eccbuf, struct nand_oobinfo *oobsel) | ||
781 | { | ||
782 | struct DiskOnChip *this = mtd->priv; | 758 | struct DiskOnChip *this = mtd->priv; |
783 | int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ | 759 | int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ |
784 | void __iomem *docptr = this->virtadr; | 760 | void __iomem *docptr = this->virtadr; |
761 | unsigned char eccbuf[6]; | ||
785 | volatile char dummy; | 762 | volatile char dummy; |
786 | int len256 = 0; | 763 | int len256 = 0; |
787 | struct Nand *mychip; | 764 | struct Nand *mychip; |
@@ -835,15 +812,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
835 | DoC_Command(this, NAND_CMD_SEQIN, 0); | 812 | DoC_Command(this, NAND_CMD_SEQIN, 0); |
836 | DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); | 813 | DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); |
837 | 814 | ||
838 | if (eccbuf) { | 815 | /* Prime the ECC engine */ |
839 | /* Prime the ECC engine */ | 816 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); |
840 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | 817 | WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); |
841 | WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); | ||
842 | } else { | ||
843 | /* disable the ECC engine */ | ||
844 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | ||
845 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | ||
846 | } | ||
847 | 818 | ||
848 | /* treat crossing 256-byte sector for 2M x 8bits devices */ | 819 | /* treat crossing 256-byte sector for 2M x 8bits devices */ |
849 | if (this->page256 && to + len > (to | 0xff) + 1) { | 820 | if (this->page256 && to + len > (to | 0xff) + 1) { |
@@ -873,39 +844,35 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
873 | 844 | ||
874 | DoC_WriteBuf(this, &buf[len256], len - len256); | 845 | DoC_WriteBuf(this, &buf[len256], len - len256); |
875 | 846 | ||
876 | if (eccbuf) { | 847 | WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, CDSNControl); |
877 | WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, | ||
878 | CDSNControl); | ||
879 | |||
880 | if (DoC_is_Millennium(this)) { | ||
881 | WriteDOC(0, docptr, NOP); | ||
882 | WriteDOC(0, docptr, NOP); | ||
883 | WriteDOC(0, docptr, NOP); | ||
884 | } else { | ||
885 | WriteDOC_(0, docptr, this->ioreg); | ||
886 | WriteDOC_(0, docptr, this->ioreg); | ||
887 | WriteDOC_(0, docptr, this->ioreg); | ||
888 | } | ||
889 | 848 | ||
890 | WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, | 849 | if (DoC_is_Millennium(this)) { |
891 | CDSNControl); | 850 | WriteDOC(0, docptr, NOP); |
851 | WriteDOC(0, docptr, NOP); | ||
852 | WriteDOC(0, docptr, NOP); | ||
853 | } else { | ||
854 | WriteDOC_(0, docptr, this->ioreg); | ||
855 | WriteDOC_(0, docptr, this->ioreg); | ||
856 | WriteDOC_(0, docptr, this->ioreg); | ||
857 | } | ||
892 | 858 | ||
893 | /* Read the ECC data through the DiskOnChip ECC logic */ | 859 | WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, |
894 | for (di = 0; di < 6; di++) { | 860 | CDSNControl); |
895 | eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); | ||
896 | } | ||
897 | 861 | ||
898 | /* Reset the ECC engine */ | 862 | /* Read the ECC data through the DiskOnChip ECC logic */ |
899 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | 863 | for (di = 0; di < 6; di++) { |
864 | eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); | ||
865 | } | ||
866 | |||
867 | /* Reset the ECC engine */ | ||
868 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | ||
900 | 869 | ||
901 | #ifdef PSYCHO_DEBUG | 870 | #ifdef PSYCHO_DEBUG |
902 | printk | 871 | printk |
903 | ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", | 872 | ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", |
904 | (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], | 873 | (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], |
905 | eccbuf[4], eccbuf[5]); | 874 | eccbuf[4], eccbuf[5]); |
906 | #endif | 875 | #endif |
907 | } | ||
908 | |||
909 | DoC_Command(this, NAND_CMD_PAGEPROG, 0); | 876 | DoC_Command(this, NAND_CMD_PAGEPROG, 0); |
910 | 877 | ||
911 | DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); | 878 | DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); |