diff options
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 179 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001.c | 179 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001plus.c | 164 |
3 files changed, 207 insertions, 315 deletions
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index c54e40464d82..603a7951ac9b 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); |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 0cf022a69e65..0e2a9326f717 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
37 | size_t *retlen, u_char *buf); | 37 | size_t *retlen, u_char *buf); |
38 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | 38 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, |
39 | size_t *retlen, const u_char *buf); | 39 | size_t *retlen, const u_char *buf); |
40 | static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | ||
41 | size_t *retlen, u_char *buf, u_char *eccbuf, | ||
42 | struct nand_oobinfo *oobsel); | ||
43 | static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | ||
44 | size_t *retlen, const u_char *buf, u_char *eccbuf, | ||
45 | struct nand_oobinfo *oobsel); | ||
46 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | 40 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, |
47 | struct mtd_oob_ops *ops); | 41 | struct mtd_oob_ops *ops); |
48 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | 42 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, |
@@ -397,17 +391,9 @@ EXPORT_SYMBOL_GPL(DoCMil_init); | |||
397 | static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, | 391 | static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, |
398 | size_t *retlen, u_char *buf) | 392 | size_t *retlen, u_char *buf) |
399 | { | 393 | { |
400 | /* Just a special case of doc_read_ecc */ | ||
401 | return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); | ||
402 | } | ||
403 | |||
404 | static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | ||
405 | size_t *retlen, u_char *buf, u_char *eccbuf, | ||
406 | struct nand_oobinfo *oobsel) | ||
407 | { | ||
408 | int i, ret; | 394 | int i, ret; |
409 | volatile char dummy; | 395 | volatile char dummy; |
410 | unsigned char syndrome[6]; | 396 | unsigned char syndrome[6], eccbuf[6]; |
411 | struct DiskOnChip *this = mtd->priv; | 397 | struct DiskOnChip *this = mtd->priv; |
412 | void __iomem *docptr = this->virtadr; | 398 | void __iomem *docptr = this->virtadr; |
413 | struct Nand *mychip = &this->chips[from >> (this->chipshift)]; | 399 | struct Nand *mychip = &this->chips[from >> (this->chipshift)]; |
@@ -437,15 +423,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
437 | DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); | 423 | DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); |
438 | DoC_WaitReady(docptr); | 424 | DoC_WaitReady(docptr); |
439 | 425 | ||
440 | if (eccbuf) { | 426 | /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ |
441 | /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ | 427 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); |
442 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); | 428 | WriteDOC (DOC_ECC_EN, docptr, ECCConf); |
443 | WriteDOC (DOC_ECC_EN, docptr, ECCConf); | ||
444 | } else { | ||
445 | /* disable the ECC engine */ | ||
446 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); | ||
447 | WriteDOC (DOC_ECC_DIS, docptr, ECCConf); | ||
448 | } | ||
449 | 429 | ||
450 | /* Read the data via the internal pipeline through CDSN IO register, | 430 | /* Read the data via the internal pipeline through CDSN IO register, |
451 | see Pipelined Read Operations 11.3 */ | 431 | see Pipelined Read Operations 11.3 */ |
@@ -465,58 +445,56 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
465 | *retlen = len; | 445 | *retlen = len; |
466 | ret = 0; | 446 | ret = 0; |
467 | 447 | ||
468 | if (eccbuf) { | 448 | /* Read the ECC data from Spare Data Area, |
469 | /* Read the ECC data from Spare Data Area, | 449 | see Reed-Solomon EDC/ECC 11.1 */ |
470 | see Reed-Solomon EDC/ECC 11.1 */ | 450 | dummy = ReadDOC(docptr, ReadPipeInit); |
471 | dummy = ReadDOC(docptr, ReadPipeInit); | ||
472 | #ifndef USE_MEMCPY | 451 | #ifndef USE_MEMCPY |
473 | for (i = 0; i < 5; i++) { | 452 | for (i = 0; i < 5; i++) { |
474 | /* N.B. you have to increase the source address in this way or the | 453 | /* N.B. you have to increase the source address in this way or the |
475 | ECC logic will not work properly */ | 454 | ECC logic will not work properly */ |
476 | eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); | 455 | eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); |
477 | } | 456 | } |
478 | #else | 457 | #else |
479 | memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); | 458 | memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); |
480 | #endif | 459 | #endif |
481 | eccbuf[5] = ReadDOC(docptr, LastDataRead); | 460 | eccbuf[5] = ReadDOC(docptr, LastDataRead); |
482 | 461 | ||
483 | /* Flush the pipeline */ | 462 | /* Flush the pipeline */ |
484 | dummy = ReadDOC(docptr, ECCConf); | 463 | dummy = ReadDOC(docptr, ECCConf); |
485 | dummy = ReadDOC(docptr, ECCConf); | 464 | dummy = ReadDOC(docptr, ECCConf); |
486 | 465 | ||
487 | /* Check the ECC Status */ | 466 | /* Check the ECC Status */ |
488 | if (ReadDOC(docptr, ECCConf) & 0x80) { | 467 | if (ReadDOC(docptr, ECCConf) & 0x80) { |
489 | int nb_errors; | 468 | int nb_errors; |
490 | /* There was an ECC error */ | 469 | /* There was an ECC error */ |
491 | #ifdef ECC_DEBUG | 470 | #ifdef ECC_DEBUG |
492 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); | 471 | printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); |
493 | #endif | 472 | #endif |
494 | /* Read the ECC syndrom through the DiskOnChip ECC logic. | 473 | /* Read the ECC syndrom through the DiskOnChip ECC logic. |
495 | These syndrome will be all ZERO when there is no error */ | 474 | These syndrome will be all ZERO when there is no error */ |
496 | for (i = 0; i < 6; i++) { | 475 | for (i = 0; i < 6; i++) { |
497 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); | 476 | syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); |
498 | } | 477 | } |
499 | nb_errors = doc_decode_ecc(buf, syndrome); | 478 | nb_errors = doc_decode_ecc(buf, syndrome); |
500 | #ifdef ECC_DEBUG | 479 | #ifdef ECC_DEBUG |
501 | printk("ECC Errors corrected: %x\n", nb_errors); | 480 | printk("ECC Errors corrected: %x\n", nb_errors); |
502 | #endif | 481 | #endif |
503 | if (nb_errors < 0) { | 482 | if (nb_errors < 0) { |
504 | /* We return error, but have actually done the read. Not that | 483 | /* We return error, but have actually done the read. Not that |
505 | this can be told to user-space, via sys_read(), but at least | 484 | this can be told to user-space, via sys_read(), but at least |
506 | MTD-aware stuff can know about it by checking *retlen */ | 485 | MTD-aware stuff can know about it by checking *retlen */ |
507 | ret = -EIO; | 486 | ret = -EIO; |
508 | } | ||
509 | } | 487 | } |
488 | } | ||
510 | 489 | ||
511 | #ifdef PSYCHO_DEBUG | 490 | #ifdef PSYCHO_DEBUG |
512 | printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", | 491 | printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", |
513 | (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], | 492 | (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], |
514 | eccbuf[4], eccbuf[5]); | 493 | eccbuf[4], eccbuf[5]); |
515 | #endif | 494 | #endif |
516 | 495 | ||
517 | /* disable the ECC engine */ | 496 | /* disable the ECC engine */ |
518 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); | 497 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); |
519 | } | ||
520 | 498 | ||
521 | return ret; | 499 | return ret; |
522 | } | 500 | } |
@@ -524,15 +502,8 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | |||
524 | static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, | 502 | static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, |
525 | size_t *retlen, const u_char *buf) | 503 | size_t *retlen, const u_char *buf) |
526 | { | 504 | { |
527 | char eccbuf[6]; | ||
528 | return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL); | ||
529 | } | ||
530 | |||
531 | static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | ||
532 | size_t *retlen, const u_char *buf, u_char *eccbuf, | ||
533 | struct nand_oobinfo *oobsel) | ||
534 | { | ||
535 | int i,ret = 0; | 505 | int i,ret = 0; |
506 | char eccbuf[6]; | ||
536 | volatile char dummy; | 507 | volatile char dummy; |
537 | struct DiskOnChip *this = mtd->priv; | 508 | struct DiskOnChip *this = mtd->priv; |
538 | void __iomem *docptr = this->virtadr; | 509 | void __iomem *docptr = this->virtadr; |
@@ -573,15 +544,9 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
573 | DoC_Address(docptr, 3, to, 0x00, 0x00); | 544 | DoC_Address(docptr, 3, to, 0x00, 0x00); |
574 | DoC_WaitReady(docptr); | 545 | DoC_WaitReady(docptr); |
575 | 546 | ||
576 | if (eccbuf) { | 547 | /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ |
577 | /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ | 548 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); |
578 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); | 549 | WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); |
579 | WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); | ||
580 | } else { | ||
581 | /* disable the ECC engine */ | ||
582 | WriteDOC (DOC_ECC_RESET, docptr, ECCConf); | ||
583 | WriteDOC (DOC_ECC_DIS, docptr, ECCConf); | ||
584 | } | ||
585 | 550 | ||
586 | /* Write the data via the internal pipeline through CDSN IO register, | 551 | /* Write the data via the internal pipeline through CDSN IO register, |
587 | see Pipelined Write Operations 11.2 */ | 552 | see Pipelined Write Operations 11.2 */ |
@@ -596,46 +561,44 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | |||
596 | #endif | 561 | #endif |
597 | WriteDOC(0x00, docptr, WritePipeTerm); | 562 | WriteDOC(0x00, docptr, WritePipeTerm); |
598 | 563 | ||
599 | if (eccbuf) { | 564 | /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic |
600 | /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic | 565 | see Reed-Solomon EDC/ECC 11.1 */ |
601 | see Reed-Solomon EDC/ECC 11.1 */ | 566 | WriteDOC(0, docptr, NOP); |
602 | WriteDOC(0, docptr, NOP); | 567 | WriteDOC(0, docptr, NOP); |
603 | WriteDOC(0, docptr, NOP); | 568 | WriteDOC(0, docptr, NOP); |
604 | WriteDOC(0, docptr, NOP); | ||
605 | 569 | ||
606 | /* Read the ECC data through the DiskOnChip ECC logic */ | 570 | /* Read the ECC data through the DiskOnChip ECC logic */ |
607 | for (i = 0; i < 6; i++) { | 571 | for (i = 0; i < 6; i++) { |
608 | eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); | 572 | eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); |
609 | } | 573 | } |
610 | 574 | ||
611 | /* ignore the ECC engine */ | 575 | /* ignore the ECC engine */ |
612 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); | 576 | WriteDOC(DOC_ECC_DIS, docptr , ECCConf); |
613 | 577 | ||
614 | #ifndef USE_MEMCPY | 578 | #ifndef USE_MEMCPY |
615 | /* Write the ECC data to flash */ | 579 | /* Write the ECC data to flash */ |
616 | for (i = 0; i < 6; i++) { | 580 | for (i = 0; i < 6; i++) { |
617 | /* N.B. you have to increase the source address in this way or the | 581 | /* N.B. you have to increase the source address in this way or the |
618 | ECC logic will not work properly */ | 582 | ECC logic will not work properly */ |
619 | WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); | 583 | WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); |
620 | } | 584 | } |
621 | #else | 585 | #else |
622 | memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); | 586 | memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); |
623 | #endif | 587 | #endif |
624 | 588 | ||
625 | /* write the block status BLOCK_USED (0x5555) at the end of ECC data | 589 | /* write the block status BLOCK_USED (0x5555) at the end of ECC data |
626 | FIXME: this is only a hack for programming the IPL area for LinuxBIOS | 590 | FIXME: this is only a hack for programming the IPL area for LinuxBIOS |
627 | and should be replace with proper codes in user space utilities */ | 591 | and should be replace with proper codes in user space utilities */ |
628 | WriteDOC(0x55, docptr, Mil_CDSN_IO); | 592 | WriteDOC(0x55, docptr, Mil_CDSN_IO); |
629 | WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); | 593 | WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); |
630 | 594 | ||
631 | WriteDOC(0x00, docptr, WritePipeTerm); | 595 | WriteDOC(0x00, docptr, WritePipeTerm); |
632 | 596 | ||
633 | #ifdef PSYCHO_DEBUG | 597 | #ifdef PSYCHO_DEBUG |
634 | printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", | 598 | printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", |
635 | (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], | 599 | (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], |
636 | eccbuf[4], eccbuf[5]); | 600 | eccbuf[4], eccbuf[5]); |
637 | #endif | 601 | #endif |
638 | } | ||
639 | 602 | ||
640 | /* Commit the Page Program command and wait for ready | 603 | /* Commit the Page Program command and wait for ready |
641 | see Software Requirement 11.4 item 1.*/ | 604 | see Software Requirement 11.4 item 1.*/ |
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); |
42 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | 42 | static 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); |
44 | static 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); | ||
47 | static 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); | ||
50 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, | 44 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, |
51 | struct mtd_oob_ops *ops); | 45 | struct mtd_oob_ops *ops); |
52 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, | 46 | static 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) | |||
595 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | 589 | static 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 | |||
602 | static 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, | |||
735 | static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, | 708 | static 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 | |||
742 | static 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); |