aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/doc2001plus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices/doc2001plus.c')
-rw-r--r--drivers/mtd/devices/doc2001plus.c164
1 files changed, 63 insertions, 101 deletions
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 66cb1e50469a..92dbb47f2ac3 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
41 size_t *retlen, u_char *buf); 41 size_t *retlen, u_char *buf);
42static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, 42static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
43 size_t *retlen, const u_char *buf); 43 size_t *retlen, const u_char *buf);
44static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
45 size_t *retlen, u_char *buf, u_char *eccbuf,
46 struct nand_oobinfo *oobsel);
47static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
48 size_t *retlen, const u_char *buf, u_char *eccbuf,
49 struct nand_oobinfo *oobsel);
50static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, 44static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
51 struct mtd_oob_ops *ops); 45 struct mtd_oob_ops *ops);
52static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, 46static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
@@ -595,18 +589,10 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
595static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, 589static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
596 size_t *retlen, u_char *buf) 590 size_t *retlen, u_char *buf)
597{ 591{
598 /* Just a special case of doc_read_ecc */
599 return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
600}
601
602static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
603 size_t *retlen, u_char *buf, u_char *eccbuf,
604 struct nand_oobinfo *oobsel)
605{
606 int ret, i; 592 int ret, i;
607 volatile char dummy; 593 volatile char dummy;
608 loff_t fofs; 594 loff_t fofs;
609 unsigned char syndrome[6]; 595 unsigned char syndrome[6], eccbuf[6];
610 struct DiskOnChip *this = mtd->priv; 596 struct DiskOnChip *this = mtd->priv;
611 void __iomem * docptr = this->virtadr; 597 void __iomem * docptr = this->virtadr;
612 struct Nand *mychip = &this->chips[from >> (this->chipshift)]; 598 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
@@ -644,56 +630,51 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
644 WriteDOC(0, docptr, Mplus_FlashControl); 630 WriteDOC(0, docptr, Mplus_FlashControl);
645 DoC_WaitReady(docptr); 631 DoC_WaitReady(docptr);
646 632
647 if (eccbuf) { 633 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
648 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ 634 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
649 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); 635 WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
650 WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
651 } else {
652 /* disable the ECC engine */
653 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
654 }
655 636
656 /* Let the caller know we completed it */ 637 /* Let the caller know we completed it */
657 *retlen = len; 638 *retlen = len;
658 ret = 0; 639 ret = 0;
659 640
660 ReadDOC(docptr, Mplus_ReadPipeInit); 641 ReadDOC(docptr, Mplus_ReadPipeInit);
661 ReadDOC(docptr, Mplus_ReadPipeInit); 642 ReadDOC(docptr, Mplus_ReadPipeInit);
662 643
663 if (eccbuf) { 644 /* Read the data via the internal pipeline through CDSN IO
664 /* Read the data via the internal pipeline through CDSN IO 645 register, see Pipelined Read Operations 11.3 */
665 register, see Pipelined Read Operations 11.3 */ 646 MemReadDOC(docptr, buf, len);
666 MemReadDOC(docptr, buf, len);
667 647
668 /* Read the ECC data following raw data */ 648 /* Read the ECC data following raw data */
669 MemReadDOC(docptr, eccbuf, 4); 649 MemReadDOC(docptr, eccbuf, 4);
670 eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); 650 eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
671 eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); 651 eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
672 652
673 /* Flush the pipeline */ 653 /* Flush the pipeline */
674 dummy = ReadDOC(docptr, Mplus_ECCConf); 654 dummy = ReadDOC(docptr, Mplus_ECCConf);
675 dummy = ReadDOC(docptr, Mplus_ECCConf); 655 dummy = ReadDOC(docptr, Mplus_ECCConf);
676 656
677 /* Check the ECC Status */ 657 /* Check the ECC Status */
678 if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { 658 if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
679 int nb_errors; 659 int nb_errors;
680 /* There was an ECC error */ 660 /* There was an ECC error */
681#ifdef ECC_DEBUG 661#ifdef ECC_DEBUG
682 printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); 662 printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
683#endif 663#endif
684 /* Read the ECC syndrom through the DiskOnChip ECC logic. 664 /* Read the ECC syndrom through the DiskOnChip ECC logic.
685 These syndrome will be all ZERO when there is no error */ 665 These syndrome will be all ZERO when there is no error */
686 for (i = 0; i < 6; i++) 666 for (i = 0; i < 6; i++)
687 syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); 667 syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
688 668
689 nb_errors = doc_decode_ecc(buf, syndrome); 669 nb_errors = doc_decode_ecc(buf, syndrome);
690#ifdef ECC_DEBUG 670#ifdef ECC_DEBUG
691 printk("ECC Errors corrected: %x\n", nb_errors); 671 printk("ECC Errors corrected: %x\n", nb_errors);
692#endif 672#endif
693 if (nb_errors < 0) { 673 if (nb_errors < 0) {
694 /* We return error, but have actually done the read. Not that 674 /* We return error, but have actually done the
695 this can be told to user-space, via sys_read(), but at least 675 read. Not that this can be told to user-space, via
696 MTD-aware stuff can know about it by checking *retlen */ 676 sys_read(), but at least MTD-aware stuff can know
677 about it by checking *retlen */
697#ifdef ECC_DEBUG 678#ifdef ECC_DEBUG
698 printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n", 679 printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
699 __FILE__, __LINE__, (int)from); 680 __FILE__, __LINE__, (int)from);
@@ -707,24 +688,16 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
707 eccbuf[3], eccbuf[4], eccbuf[5]); 688 eccbuf[3], eccbuf[4], eccbuf[5]);
708#endif 689#endif
709 ret = -EIO; 690 ret = -EIO;
710 }
711 } 691 }
692 }
712 693
713#ifdef PSYCHO_DEBUG 694#ifdef PSYCHO_DEBUG
714 printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 695 printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
715 (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], 696 (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
716 eccbuf[4], eccbuf[5]); 697 eccbuf[4], eccbuf[5]);
717#endif 698#endif
718 699 /* disable the ECC engine */
719 /* disable the ECC engine */ 700 WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
720 WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
721 } else {
722 /* Read the data via the internal pipeline through CDSN IO
723 register, see Pipelined Read Operations 11.3 */
724 MemReadDOC(docptr, buf, len-2);
725 buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
726 buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
727 }
728 701
729 /* Disable flash internally */ 702 /* Disable flash internally */
730 WriteDOC(0, docptr, Mplus_FlashSelect); 703 WriteDOC(0, docptr, Mplus_FlashSelect);
@@ -735,17 +708,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
735static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, 708static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
736 size_t *retlen, const u_char *buf) 709 size_t *retlen, const u_char *buf)
737{ 710{
738 char eccbuf[6];
739 return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
740}
741
742static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
743 size_t *retlen, const u_char *buf, u_char *eccbuf,
744 struct nand_oobinfo *oobsel)
745{
746 int i, before, ret = 0; 711 int i, before, ret = 0;
747 loff_t fto; 712 loff_t fto;
748 volatile char dummy; 713 volatile char dummy;
714 char eccbuf[6];
749 struct DiskOnChip *this = mtd->priv; 715 struct DiskOnChip *this = mtd->priv;
750 void __iomem * docptr = this->virtadr; 716 void __iomem * docptr = this->virtadr;
751 struct Nand *mychip = &this->chips[to >> (this->chipshift)]; 717 struct Nand *mychip = &this->chips[to >> (this->chipshift)];
@@ -795,46 +761,42 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
795 /* Disable the ECC engine */ 761 /* Disable the ECC engine */
796 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); 762 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
797 763
798 if (eccbuf) { 764 if (before) {
799 if (before) { 765 /* Write the block status BLOCK_USED (0x5555) */
800 /* Write the block status BLOCK_USED (0x5555) */ 766 WriteDOC(0x55, docptr, Mil_CDSN_IO);
801 WriteDOC(0x55, docptr, Mil_CDSN_IO); 767 WriteDOC(0x55, docptr, Mil_CDSN_IO);
802 WriteDOC(0x55, docptr, Mil_CDSN_IO);
803 }
804
805 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
806 WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
807 } 768 }
808 769
770 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
771 WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
772
809 MemWriteDOC(docptr, (unsigned char *) buf, len); 773 MemWriteDOC(docptr, (unsigned char *) buf, len);
810 774
811 if (eccbuf) { 775 /* Write ECC data to flash, the ECC info is generated by
812 /* Write ECC data to flash, the ECC info is generated by 776 the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
813 the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ 777 DoC_Delay(docptr, 3);
814 DoC_Delay(docptr, 3);
815 778
816 /* Read the ECC data through the DiskOnChip ECC logic */ 779 /* Read the ECC data through the DiskOnChip ECC logic */
817 for (i = 0; i < 6; i++) 780 for (i = 0; i < 6; i++)
818 eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); 781 eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
819 782
820 /* disable the ECC engine */ 783 /* disable the ECC engine */
821 WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); 784 WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
822 785
823 /* Write the ECC data to flash */ 786 /* Write the ECC data to flash */
824 MemWriteDOC(docptr, eccbuf, 6); 787 MemWriteDOC(docptr, eccbuf, 6);
825 788
826 if (!before) { 789 if (!before) {
827 /* Write the block status BLOCK_USED (0x5555) */ 790 /* Write the block status BLOCK_USED (0x5555) */
828 WriteDOC(0x55, docptr, Mil_CDSN_IO+6); 791 WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
829 WriteDOC(0x55, docptr, Mil_CDSN_IO+7); 792 WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
830 } 793 }
831 794
832#ifdef PSYCHO_DEBUG 795#ifdef PSYCHO_DEBUG
833 printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 796 printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
834 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], 797 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
835 eccbuf[4], eccbuf[5]); 798 eccbuf[4], eccbuf[5]);
836#endif 799#endif
837 }
838 800
839 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 801 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
840 WriteDOC(0x00, docptr, Mplus_WritePipeTerm); 802 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);