aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/doc2001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices/doc2001.c')
-rw-r--r--drivers/mtd/devices/doc2001.c179
1 files changed, 71 insertions, 108 deletions
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);
38static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, 38static 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);
40static 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);
43static 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);
46static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, 40static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
47 struct mtd_oob_ops *ops); 41 struct mtd_oob_ops *ops);
48static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, 42static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
@@ -397,17 +391,9 @@ EXPORT_SYMBOL_GPL(DoCMil_init);
397static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, 391static 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
404static 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,
524static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, 502static 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
531static 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.*/