aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_bbt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/nand_bbt.c')
-rw-r--r--drivers/mtd/nand/nand_bbt.c104
1 files changed, 62 insertions, 42 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index fbccb2a25186..ecaaca18d1e0 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -156,7 +156,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
156 156
157 while (totlen) { 157 while (totlen) {
158 len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); 158 len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
159 res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob); 159 res = mtd->read(mtd, from, len, &retlen, buf);
160 if (res < 0) { 160 if (res < 0) {
161 if (retlen != len) { 161 if (retlen != len) {
162 printk(KERN_INFO "nand_bbt: Error reading bad block table\n"); 162 printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
@@ -471,17 +471,17 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
471 * 471 *
472*/ 472*/
473static int write_bbt(struct mtd_info *mtd, uint8_t *buf, 473static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
474 struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) 474 struct nand_bbt_descr *td, struct nand_bbt_descr *md,
475 int chipsel)
475{ 476{
476 struct nand_chip *this = mtd->priv; 477 struct nand_chip *this = mtd->priv;
477 struct nand_oobinfo oobinfo;
478 struct erase_info einfo; 478 struct erase_info einfo;
479 int i, j, res, chip = 0; 479 int i, j, res, chip = 0;
480 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; 480 int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
481 int nrchips, bbtoffs, pageoffs; 481 int nrchips, bbtoffs, pageoffs, ooboffs;
482 uint8_t msk[4]; 482 uint8_t msk[4];
483 uint8_t rcode = td->reserved_block_code; 483 uint8_t rcode = td->reserved_block_code;
484 size_t retlen, len = 0; 484 size_t retlen, len = 0, ooblen;
485 loff_t to; 485 loff_t to;
486 486
487 if (!rcode) 487 if (!rcode)
@@ -526,12 +526,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
526 for (i = 0; i < td->maxblocks; i++) { 526 for (i = 0; i < td->maxblocks; i++) {
527 int block = startblock + dir * i; 527 int block = startblock + dir * i;
528 /* Check, if the block is bad */ 528 /* Check, if the block is bad */
529 switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) { 529 switch ((this->bbt[block >> 2] >>
530 (2 * (block & 0x03))) & 0x03) {
530 case 0x01: 531 case 0x01:
531 case 0x03: 532 case 0x03:
532 continue; 533 continue;
533 } 534 }
534 page = block << (this->bbt_erase_shift - this->page_shift); 535 page = block <<
536 (this->bbt_erase_shift - this->page_shift);
535 /* Check, if the block is used by the mirror table */ 537 /* Check, if the block is used by the mirror table */
536 if (!md || md->pages[chip] != page) 538 if (!md || md->pages[chip] != page)
537 goto write; 539 goto write;
@@ -542,11 +544,20 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
542 544
543 /* Set up shift count and masks for the flash table */ 545 /* Set up shift count and masks for the flash table */
544 bits = td->options & NAND_BBT_NRBITS_MSK; 546 bits = td->options & NAND_BBT_NRBITS_MSK;
547 msk[2] = ~rcode;
545 switch (bits) { 548 switch (bits) {
546 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break; 549 case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
547 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break; 550 msk[3] = 0x01;
548 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break; 551 break;
549 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; 552 case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
553 msk[3] = 0x03;
554 break;
555 case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
556 msk[3] = 0x0f;
557 break;
558 case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
559 msk[3] = 0xff;
560 break;
550 default: return -EINVAL; 561 default: return -EINVAL;
551 } 562 }
552 563
@@ -554,49 +565,55 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
554 565
555 to = ((loff_t) page) << this->page_shift; 566 to = ((loff_t) page) << this->page_shift;
556 567
557 memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
558 oobinfo.useecc = MTD_NANDECC_PLACEONLY;
559
560 /* Must we save the block contents ? */ 568 /* Must we save the block contents ? */
561 if (td->options & NAND_BBT_SAVECONTENT) { 569 if (td->options & NAND_BBT_SAVECONTENT) {
562 /* Make it block aligned */ 570 /* Make it block aligned */
563 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); 571 to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
564 len = 1 << this->bbt_erase_shift; 572 len = 1 << this->bbt_erase_shift;
565 res = mtd->read_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo); 573 res = mtd->read(mtd, to, len, &retlen, buf);
566 if (res < 0) { 574 if (res < 0) {
567 if (retlen != len) { 575 if (retlen != len) {
568 printk(KERN_INFO 576 printk(KERN_INFO "nand_bbt: Error "
569 "nand_bbt: Error reading block for writing the bad block table\n"); 577 "reading block for writing "
578 "the bad block table\n");
570 return res; 579 return res;
571 } 580 }
572 printk(KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n"); 581 printk(KERN_WARNING "nand_bbt: ECC error "
582 "while reading block for writing "
583 "bad block table\n");
573 } 584 }
585 /* Read oob data */
586 ooblen = (len >> this->page_shift) * mtd->oobsize;
587 res = mtd->read_oob(mtd, to + mtd->writesize, ooblen,
588 &retlen, &buf[len]);
589 if (res < 0 || retlen != ooblen)
590 goto outerr;
591
574 /* Calc the byte offset in the buffer */ 592 /* Calc the byte offset in the buffer */
575 pageoffs = page - (int)(to >> this->page_shift); 593 pageoffs = page - (int)(to >> this->page_shift);
576 offs = pageoffs << this->page_shift; 594 offs = pageoffs << this->page_shift;
577 /* Preset the bbt area with 0xff */ 595 /* Preset the bbt area with 0xff */
578 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); 596 memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
579 /* Preset the bbt's oob area with 0xff */ 597 ooboffs = len + (pageoffs * mtd->oobsize);
580 memset(&buf[len + pageoffs * mtd->oobsize], 0xff, 598
581 ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
582 if (td->options & NAND_BBT_VERSION) {
583 buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
584 }
585 } else { 599 } else {
586 /* Calc length */ 600 /* Calc length */
587 len = (size_t) (numblocks >> sft); 601 len = (size_t) (numblocks >> sft);
588 /* Make it page aligned ! */ 602 /* Make it page aligned ! */
589 len = (len + (mtd->writesize - 1)) & ~(mtd->writesize - 1); 603 len = (len + (mtd->writesize - 1)) &
604 ~(mtd->writesize - 1);
590 /* Preset the buffer with 0xff */ 605 /* Preset the buffer with 0xff */
591 memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize); 606 memset(buf, 0xff, len +
607 (len >> this->page_shift)* mtd->oobsize);
592 offs = 0; 608 offs = 0;
609 ooboffs = len;
593 /* Pattern is located in oob area of first page */ 610 /* Pattern is located in oob area of first page */
594 memcpy(&buf[len + td->offs], td->pattern, td->len); 611 memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
595 if (td->options & NAND_BBT_VERSION) {
596 buf[len + td->veroffs] = td->version[chip];
597 }
598 } 612 }
599 613
614 if (td->options & NAND_BBT_VERSION)
615 buf[ooboffs + td->veroffs] = td->version[chip];
616
600 /* walk through the memory table */ 617 /* walk through the memory table */
601 for (i = 0; i < numblocks;) { 618 for (i = 0; i < numblocks;) {
602 uint8_t dat; 619 uint8_t dat;
@@ -604,7 +621,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
604 for (j = 0; j < 4; j++, i++) { 621 for (j = 0; j < 4; j++, i++) {
605 int sftcnt = (i << (3 - sft)) & sftmsk; 622 int sftcnt = (i << (3 - sft)) & sftmsk;
606 /* Do not store the reserved bbt blocks ! */ 623 /* Do not store the reserved bbt blocks ! */
607 buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); 624 buf[offs + (i >> sft)] &=
625 ~(msk[dat & 0x03] << sftcnt);
608 dat >>= 2; 626 dat >>= 2;
609 } 627 }
610 } 628 }
@@ -614,23 +632,25 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
614 einfo.addr = (unsigned long)to; 632 einfo.addr = (unsigned long)to;
615 einfo.len = 1 << this->bbt_erase_shift; 633 einfo.len = 1 << this->bbt_erase_shift;
616 res = nand_erase_nand(mtd, &einfo, 1); 634 res = nand_erase_nand(mtd, &einfo, 1);
617 if (res < 0) { 635 if (res < 0)
618 printk(KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); 636 goto outerr;
619 return res;
620 }
621 637
622 res = mtd->write_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo); 638 res = nand_write_raw(mtd, to, len, &retlen, buf, &buf[len]);
623 if (res < 0) { 639 if (res < 0)
624 printk(KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); 640 goto outerr;
625 return res; 641
626 } 642 printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
627 printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", 643 "0x%02X\n", (unsigned int)to, td->version[chip]);
628 (unsigned int)to, td->version[chip]);
629 644
630 /* Mark it as used */ 645 /* Mark it as used */
631 td->pages[chip] = page; 646 td->pages[chip] = page;
632 } 647 }
633 return 0; 648 return 0;
649
650 outerr:
651 printk(KERN_WARNING
652 "nand_bbt: Error while writing bad block table %d\n", res);
653 return res;
634} 654}
635 655
636/** 656/**