aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/nand_base.c122
-rw-r--r--drivers/mtd/nand/nand_bbt.c104
2 files changed, 122 insertions, 104 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index da2f4d16e506..d796eb508b4f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -139,16 +139,10 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
139 139
140static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, 140static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
141 size_t *retlen, uint8_t *buf); 141 size_t *retlen, uint8_t *buf);
142static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
143 size_t *retlen, uint8_t *buf, uint8_t *eccbuf,
144 struct nand_oobinfo *oobsel);
145static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, 142static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
146 size_t *retlen, uint8_t *buf); 143 size_t *retlen, uint8_t *buf);
147static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, 144static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
148 size_t *retlen, const uint8_t *buf); 145 size_t *retlen, const uint8_t *buf);
149static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
150 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf,
151 struct nand_oobinfo *oobsel);
152static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, 146static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
153 size_t *retlen, const uint8_t *buf); 147 size_t *retlen, const uint8_t *buf);
154static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); 148static int nand_erase(struct mtd_info *mtd, struct erase_info *instr);
@@ -1080,27 +1074,6 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl
1080} 1074}
1081 1075
1082/** 1076/**
1083 * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
1084 * @mtd: MTD device structure
1085 * @from: offset to read from
1086 * @len: number of bytes to read
1087 * @retlen: pointer to variable to store the number of read bytes
1088 * @buf: the databuffer to put data
1089 * @oob_buf: filesystem supplied oob data buffer
1090 * @oobsel: oob selection structure
1091 *
1092 * This function simply calls nand_do_read_ecc with flags = 0xff
1093 */
1094static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
1095 size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel)
1096{
1097 /* use userspace supplied oobinfo, if zero */
1098 if (oobsel == NULL)
1099 oobsel = &mtd->oobinfo;
1100 return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
1101}
1102
1103/**
1104 * nand_do_read_ecc - [MTD Interface] Read data with ECC 1077 * nand_do_read_ecc - [MTD Interface] Read data with ECC
1105 * @mtd: MTD device structure 1078 * @mtd: MTD device structure
1106 * @from: offset to read from 1079 * @from: offset to read from
@@ -1524,6 +1497,55 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s
1524} 1497}
1525 1498
1526/** 1499/**
1500 * nand_write_raw - [GENERIC] Write raw data including oob
1501 * @mtd: MTD device structure
1502 * @buf: source buffer
1503 * @to: offset to write to
1504 * @len: number of bytes to write
1505 * @buf: source buffer
1506 * @oob: oob buffer
1507 *
1508 * Write raw data including oob
1509 */
1510int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1511 uint8_t *buf, uint8_t *oob)
1512{
1513 struct nand_chip *this = mtd->priv;
1514 int page = (int)(to >> this->page_shift);
1515 int chip = (int)(to >> this->chip_shift);
1516 int ret;
1517
1518 *retlen = 0;
1519
1520 /* Do not allow writes past end of device */
1521 if ((to + len) > mtd->size) {
1522 DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write "
1523 "beyond end of device\n");
1524 return -EINVAL;
1525 }
1526
1527 /* Grab the lock and see if the device is available */
1528 nand_get_device(this, mtd, FL_WRITING);
1529
1530 this->select_chip(mtd, chip);
1531 this->data_poi = buf;
1532
1533 while (len != *retlen) {
1534 ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0);
1535 if (ret)
1536 return ret;
1537 page++;
1538 *retlen += mtd->writesize;
1539 this->data_poi += mtd->writesize;
1540 oob += mtd->oobsize;
1541 }
1542
1543 /* Deselect and wake up anyone waiting on the device */
1544 nand_release_device(mtd);
1545 return 0;
1546}
1547
1548/**
1527 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer 1549 * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
1528 * @mtd: MTD device structure 1550 * @mtd: MTD device structure
1529 * @fsbuf: buffer given by fs driver 1551 * @fsbuf: buffer given by fs driver
@@ -1585,57 +1607,39 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct
1585#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 1607#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
1586 1608
1587/** 1609/**
1588 * nand_write - [MTD Interface] compability function for nand_write_ecc 1610 * nand_write - [MTD Interface] NAND write with ECC
1589 * @mtd: MTD device structure
1590 * @to: offset to write to
1591 * @len: number of bytes to write
1592 * @retlen: pointer to variable to store the number of written bytes
1593 * @buf: the data to write
1594 *
1595 * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
1596 *
1597*/
1598static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf)
1599{
1600 return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL));
1601}
1602
1603/**
1604 * nand_write_ecc - [MTD Interface] NAND write with ECC
1605 * @mtd: MTD device structure 1611 * @mtd: MTD device structure
1606 * @to: offset to write to 1612 * @to: offset to write to
1607 * @len: number of bytes to write 1613 * @len: number of bytes to write
1608 * @retlen: pointer to variable to store the number of written bytes 1614 * @retlen: pointer to variable to store the number of written bytes
1609 * @buf: the data to write 1615 * @buf: the data to write
1610 * @eccbuf: filesystem supplied oob data buffer
1611 * @oobsel: oob selection structure
1612 * 1616 *
1613 * NAND write with ECC 1617 * NAND write with ECC
1614 */ 1618 */
1615static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 1619static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
1616 size_t *retlen, const uint8_t *buf, uint8_t *eccbuf, 1620 size_t *retlen, const uint8_t *buf)
1617 struct nand_oobinfo *oobsel)
1618{ 1621{
1619 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; 1622 int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
1620 int autoplace = 0, numpages, totalpages; 1623 int autoplace = 0, numpages, totalpages;
1621 struct nand_chip *this = mtd->priv; 1624 struct nand_chip *this = mtd->priv;
1622 uint8_t *oobbuf, *bufstart; 1625 uint8_t *oobbuf, *bufstart, *eccbuf = NULL;
1623 int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); 1626 int ppblock = (1 << (this->phys_erase_shift - this->page_shift));
1627 struct nand_oobinfo *oobsel = &mtd->oobinfo;
1624 1628
1625 DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); 1629 DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len);
1626 1630
1627 /* Initialize retlen, in case of early exit */ 1631 /* Initialize retlen, in case of early exit */
1628 *retlen = 0; 1632 *retlen = 0;
1629 1633
1630 /* Do not allow write past end of device */ 1634 /* Do not allow write past end of device */
1631 if ((to + len) > mtd->size) { 1635 if ((to + len) > mtd->size) {
1632 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); 1636 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n");
1633 return -EINVAL; 1637 return -EINVAL;
1634 } 1638 }
1635 1639
1636 /* reject writes, which are not page aligned */ 1640 /* reject writes, which are not page aligned */
1637 if (NOTALIGNED(to) || NOTALIGNED(len)) { 1641 if (NOTALIGNED(to) || NOTALIGNED(len)) {
1638 printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); 1642 printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n");
1639 return -EINVAL; 1643 return -EINVAL;
1640 } 1644 }
1641 1645
@@ -1651,10 +1655,6 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1651 if (nand_check_wp(mtd)) 1655 if (nand_check_wp(mtd))
1652 goto out; 1656 goto out;
1653 1657
1654 /* if oobsel is NULL, use chip defaults */
1655 if (oobsel == NULL)
1656 oobsel = &mtd->oobinfo;
1657
1658 /* Autoplace of oob data ? Use the default placement scheme */ 1658 /* Autoplace of oob data ? Use the default placement scheme */
1659 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { 1659 if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
1660 oobsel = this->autooob; 1660 oobsel = this->autooob;
@@ -1689,7 +1689,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1689 */ 1689 */
1690 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); 1690 ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
1691 if (ret) { 1691 if (ret) {
1692 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); 1692 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret);
1693 goto out; 1693 goto out;
1694 } 1694 }
1695 /* Next oob page */ 1695 /* Next oob page */
@@ -1712,7 +1712,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1712 ret = nand_verify_pages(mtd, this, startpage, page - startpage, 1712 ret = nand_verify_pages(mtd, this, startpage, page - startpage,
1713 oobbuf, oobsel, chipnr, (eccbuf != NULL)); 1713 oobbuf, oobsel, chipnr, (eccbuf != NULL));
1714 if (ret) { 1714 if (ret) {
1715 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); 1715 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
1716 goto out; 1716 goto out;
1717 } 1717 }
1718 *retlen = written; 1718 *retlen = written;
@@ -1741,7 +1741,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
1741 if (!ret) 1741 if (!ret)
1742 *retlen = written; 1742 *retlen = written;
1743 else 1743 else
1744 DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); 1744 DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret);
1745 1745
1746 out: 1746 out:
1747 /* Deselect and wake up anyone waiting on the device */ 1747 /* Deselect and wake up anyone waiting on the device */
@@ -2527,8 +2527,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
2527 mtd->unpoint = NULL; 2527 mtd->unpoint = NULL;
2528 mtd->read = nand_read; 2528 mtd->read = nand_read;
2529 mtd->write = nand_write; 2529 mtd->write = nand_write;
2530 mtd->read_ecc = nand_read_ecc;
2531 mtd->write_ecc = nand_write_ecc;
2532 mtd->read_oob = nand_read_oob; 2530 mtd->read_oob = nand_read_oob;
2533 mtd->write_oob = nand_write_oob; 2531 mtd->write_oob = nand_write_oob;
2534 mtd->sync = nand_sync; 2532 mtd->sync = nand_sync;
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/**