diff options
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 480 |
1 files changed, 121 insertions, 359 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 778535006c83..649c238837bb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -139,23 +139,12 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len); | |||
139 | 139 | ||
140 | static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, | 140 | static 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); |
142 | static 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); | ||
145 | static int nand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, | 142 | static 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); |
147 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | 144 | static 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); |
149 | static 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); | ||
152 | static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, | 146 | static 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); |
154 | static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, | ||
155 | unsigned long count, loff_t to, size_t *retlen); | ||
156 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | ||
157 | unsigned long count, loff_t to, size_t *retlen, | ||
158 | uint8_t *eccbuf, struct nand_oobinfo *oobsel); | ||
159 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); | 148 | static int nand_erase(struct mtd_info *mtd, struct erase_info *instr); |
160 | static void nand_sync(struct mtd_info *mtd); | 149 | static void nand_sync(struct mtd_info *mtd); |
161 | 150 | ||
@@ -175,6 +164,12 @@ static int nand_verify_pages(struct mtd_info *mtd, struct nand_chip *this, | |||
175 | static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, | 164 | static int nand_get_device(struct nand_chip *this, struct mtd_info *mtd, |
176 | int new_state); | 165 | int new_state); |
177 | 166 | ||
167 | /* | ||
168 | * For devices which display every fart in the system on a seperate LED. Is | ||
169 | * compiled away when LED support is disabled. | ||
170 | */ | ||
171 | DEFINE_LED_TRIGGER(nand_led_trigger); | ||
172 | |||
178 | /** | 173 | /** |
179 | * nand_release_device - [GENERIC] release chip | 174 | * nand_release_device - [GENERIC] release chip |
180 | * @mtd: MTD device structure | 175 | * @mtd: MTD device structure |
@@ -209,19 +204,6 @@ static uint8_t nand_read_byte(struct mtd_info *mtd) | |||
209 | } | 204 | } |
210 | 205 | ||
211 | /** | 206 | /** |
212 | * nand_write_byte - [DEFAULT] write one byte to the chip | ||
213 | * @mtd: MTD device structure | ||
214 | * @byte: pointer to data byte to write | ||
215 | * | ||
216 | * Default write function for 8it buswith | ||
217 | */ | ||
218 | static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) | ||
219 | { | ||
220 | struct nand_chip *this = mtd->priv; | ||
221 | writeb(byte, this->IO_ADDR_W); | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip | 207 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip |
226 | * @mtd: MTD device structure | 208 | * @mtd: MTD device structure |
227 | * | 209 | * |
@@ -235,20 +217,6 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd) | |||
235 | } | 217 | } |
236 | 218 | ||
237 | /** | 219 | /** |
238 | * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip | ||
239 | * @mtd: MTD device structure | ||
240 | * @byte: pointer to data byte to write | ||
241 | * | ||
242 | * Default write function for 16bit buswith with | ||
243 | * endianess conversion | ||
244 | */ | ||
245 | static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) | ||
246 | { | ||
247 | struct nand_chip *this = mtd->priv; | ||
248 | writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * nand_read_word - [DEFAULT] read one word from the chip | 220 | * nand_read_word - [DEFAULT] read one word from the chip |
253 | * @mtd: MTD device structure | 221 | * @mtd: MTD device structure |
254 | * | 222 | * |
@@ -262,20 +230,6 @@ static u16 nand_read_word(struct mtd_info *mtd) | |||
262 | } | 230 | } |
263 | 231 | ||
264 | /** | 232 | /** |
265 | * nand_write_word - [DEFAULT] write one word to the chip | ||
266 | * @mtd: MTD device structure | ||
267 | * @word: data word to write | ||
268 | * | ||
269 | * Default write function for 16bit buswith without | ||
270 | * endianess conversion | ||
271 | */ | ||
272 | static void nand_write_word(struct mtd_info *mtd, u16 word) | ||
273 | { | ||
274 | struct nand_chip *this = mtd->priv; | ||
275 | writew(word, this->IO_ADDR_W); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * nand_select_chip - [DEFAULT] control CE line | 233 | * nand_select_chip - [DEFAULT] control CE line |
280 | * @mtd: MTD device structure | 234 | * @mtd: MTD device structure |
281 | * @chip: chipnumber to select, -1 for deselect | 235 | * @chip: chipnumber to select, -1 for deselect |
@@ -287,10 +241,10 @@ static void nand_select_chip(struct mtd_info *mtd, int chip) | |||
287 | struct nand_chip *this = mtd->priv; | 241 | struct nand_chip *this = mtd->priv; |
288 | switch (chip) { | 242 | switch (chip) { |
289 | case -1: | 243 | case -1: |
290 | this->hwcontrol(mtd, NAND_CTL_CLRNCE); | 244 | this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); |
291 | break; | 245 | break; |
292 | case 0: | 246 | case 0: |
293 | this->hwcontrol(mtd, NAND_CTL_SETNCE); | 247 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
294 | break; | 248 | break; |
295 | 249 | ||
296 | default: | 250 | default: |
@@ -528,8 +482,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, | |||
528 | return nand_isbad_bbt(mtd, ofs, allowbbt); | 482 | return nand_isbad_bbt(mtd, ofs, allowbbt); |
529 | } | 483 | } |
530 | 484 | ||
531 | DEFINE_LED_TRIGGER(nand_led_trigger); | ||
532 | |||
533 | /* | 485 | /* |
534 | * Wait for the ready pin, after a command | 486 | * Wait for the ready pin, after a command |
535 | * The timeout is catched later. | 487 | * The timeout is catched later. |
@@ -559,13 +511,12 @@ static void nand_wait_ready(struct mtd_info *mtd) | |||
559 | * Send command to NAND device. This function is used for small page | 511 | * Send command to NAND device. This function is used for small page |
560 | * devices (256/512 Bytes per page) | 512 | * devices (256/512 Bytes per page) |
561 | */ | 513 | */ |
562 | static void nand_command(struct mtd_info *mtd, unsigned command, int column, | 514 | static void nand_command(struct mtd_info *mtd, unsigned int command, |
563 | int page_addr) | 515 | int column, int page_addr) |
564 | { | 516 | { |
565 | register struct nand_chip *this = mtd->priv; | 517 | register struct nand_chip *this = mtd->priv; |
518 | int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; | ||
566 | 519 | ||
567 | /* Begin command latch cycle */ | ||
568 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
569 | /* | 520 | /* |
570 | * Write out the command to the device. | 521 | * Write out the command to the device. |
571 | */ | 522 | */ |
@@ -583,33 +534,32 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column, | |||
583 | column -= 256; | 534 | column -= 256; |
584 | readcmd = NAND_CMD_READ1; | 535 | readcmd = NAND_CMD_READ1; |
585 | } | 536 | } |
586 | this->write_byte(mtd, readcmd); | 537 | this->cmd_ctrl(mtd, readcmd, ctrl); |
538 | ctrl &= ~NAND_CTRL_CHANGE; | ||
587 | } | 539 | } |
588 | this->write_byte(mtd, command); | 540 | this->cmd_ctrl(mtd, command, ctrl); |
589 | |||
590 | /* Set ALE and clear CLE to start address cycle */ | ||
591 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
592 | |||
593 | if (column != -1 || page_addr != -1) { | ||
594 | this->hwcontrol(mtd, NAND_CTL_SETALE); | ||
595 | 541 | ||
596 | /* Serially input address */ | 542 | /* |
597 | if (column != -1) { | 543 | * Address cycle, when necessary |
598 | /* Adjust columns for 16 bit buswidth */ | 544 | */ |
599 | if (this->options & NAND_BUSWIDTH_16) | 545 | ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; |
600 | column >>= 1; | 546 | /* Serially input address */ |
601 | this->write_byte(mtd, column); | 547 | if (column != -1) { |
602 | } | 548 | /* Adjust columns for 16 bit buswidth */ |
603 | if (page_addr != -1) { | 549 | if (this->options & NAND_BUSWIDTH_16) |
604 | this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); | 550 | column >>= 1; |
605 | this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); | 551 | this->cmd_ctrl(mtd, column, ctrl); |
606 | /* One more address cycle for devices > 32MiB */ | 552 | ctrl &= ~NAND_CTRL_CHANGE; |
607 | if (this->chipsize > (32 << 20)) | 553 | } |
608 | this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f)); | 554 | if (page_addr != -1) { |
609 | } | 555 | this->cmd_ctrl(mtd, page_addr, ctrl); |
610 | /* Latch in address */ | 556 | ctrl &= ~NAND_CTRL_CHANGE; |
611 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | 557 | this->cmd_ctrl(mtd, page_addr >> 8, ctrl); |
558 | /* One more address cycle for devices > 32MiB */ | ||
559 | if (this->chipsize > (32 << 20)) | ||
560 | this->cmd_ctrl(mtd, page_addr >> 16, ctrl); | ||
612 | } | 561 | } |
562 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | ||
613 | 563 | ||
614 | /* | 564 | /* |
615 | * program and erase have their own busy handlers | 565 | * program and erase have their own busy handlers |
@@ -622,15 +572,16 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column, | |||
622 | case NAND_CMD_ERASE2: | 572 | case NAND_CMD_ERASE2: |
623 | case NAND_CMD_SEQIN: | 573 | case NAND_CMD_SEQIN: |
624 | case NAND_CMD_STATUS: | 574 | case NAND_CMD_STATUS: |
575 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE); | ||
625 | return; | 576 | return; |
626 | 577 | ||
627 | case NAND_CMD_RESET: | 578 | case NAND_CMD_RESET: |
628 | if (this->dev_ready) | 579 | if (this->dev_ready) |
629 | break; | 580 | break; |
630 | udelay(this->chip_delay); | 581 | udelay(this->chip_delay); |
631 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 582 | this->cmd_ctrl(mtd, NAND_CMD_STATUS, |
632 | this->write_byte(mtd, NAND_CMD_STATUS); | 583 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); |
633 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | 584 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE); |
634 | while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; | 585 | while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; |
635 | return; | 586 | return; |
636 | 587 | ||
@@ -659,12 +610,13 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column, | |||
659 | * @column: the column address for this command, -1 if none | 610 | * @column: the column address for this command, -1 if none |
660 | * @page_addr: the page address for this command, -1 if none | 611 | * @page_addr: the page address for this command, -1 if none |
661 | * | 612 | * |
662 | * Send command to NAND device. This is the version for the new large page devices | 613 | * Send command to NAND device. This is the version for the new large page |
663 | * We dont have the separate regions as we have in the small page devices. | 614 | * devices We dont have the separate regions as we have in the small page |
664 | * We must emulate NAND_CMD_READOOB to keep the code compatible. | 615 | * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. |
665 | * | 616 | * |
666 | */ | 617 | */ |
667 | static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr) | 618 | static void nand_command_lp(struct mtd_info *mtd, unsigned int command, |
619 | int column, int page_addr) | ||
668 | { | 620 | { |
669 | register struct nand_chip *this = mtd->priv; | 621 | register struct nand_chip *this = mtd->priv; |
670 | 622 | ||
@@ -674,34 +626,33 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, | |||
674 | command = NAND_CMD_READ0; | 626 | command = NAND_CMD_READ0; |
675 | } | 627 | } |
676 | 628 | ||
677 | /* Begin command latch cycle */ | 629 | /* Command latch cycle */ |
678 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 630 | this->cmd_ctrl(mtd, command & 0xff, |
679 | /* Write out the command to the device. */ | 631 | NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); |
680 | this->write_byte(mtd, (command & 0xff)); | ||
681 | /* End command latch cycle */ | ||
682 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
683 | 632 | ||
684 | if (column != -1 || page_addr != -1) { | 633 | if (column != -1 || page_addr != -1) { |
685 | this->hwcontrol(mtd, NAND_CTL_SETALE); | 634 | int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; |
686 | 635 | ||
687 | /* Serially input address */ | 636 | /* Serially input address */ |
688 | if (column != -1) { | 637 | if (column != -1) { |
689 | /* Adjust columns for 16 bit buswidth */ | 638 | /* Adjust columns for 16 bit buswidth */ |
690 | if (this->options & NAND_BUSWIDTH_16) | 639 | if (this->options & NAND_BUSWIDTH_16) |
691 | column >>= 1; | 640 | column >>= 1; |
692 | this->write_byte(mtd, column & 0xff); | 641 | this->cmd_ctrl(mtd, column, ctrl); |
693 | this->write_byte(mtd, column >> 8); | 642 | ctrl &= ~NAND_CTRL_CHANGE; |
643 | this->cmd_ctrl(mtd, column >> 8, ctrl); | ||
694 | } | 644 | } |
695 | if (page_addr != -1) { | 645 | if (page_addr != -1) { |
696 | this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); | 646 | this->cmd_ctrl(mtd, page_addr, ctrl); |
697 | this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); | 647 | this->cmd_ctrl(mtd, page_addr >> 8, |
648 | NAND_NCE | NAND_ALE); | ||
698 | /* One more address cycle for devices > 128MiB */ | 649 | /* One more address cycle for devices > 128MiB */ |
699 | if (this->chipsize > (128 << 20)) | 650 | if (this->chipsize > (128 << 20)) |
700 | this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff)); | 651 | this->cmd_ctrl(mtd, page_addr >> 16, |
652 | NAND_NCE | NAND_ALE); | ||
701 | } | 653 | } |
702 | /* Latch in address */ | ||
703 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | ||
704 | } | 654 | } |
655 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | ||
705 | 656 | ||
706 | /* | 657 | /* |
707 | * program and erase have their own busy handlers | 658 | * program and erase have their own busy handlers |
@@ -733,20 +684,14 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, | |||
733 | if (this->dev_ready) | 684 | if (this->dev_ready) |
734 | break; | 685 | break; |
735 | udelay(this->chip_delay); | 686 | udelay(this->chip_delay); |
736 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 687 | this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE); |
737 | this->write_byte(mtd, NAND_CMD_STATUS); | 688 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE); |
738 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
739 | while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; | 689 | while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; |
740 | return; | 690 | return; |
741 | 691 | ||
742 | case NAND_CMD_READ0: | 692 | case NAND_CMD_READ0: |
743 | /* Begin command latch cycle */ | 693 | this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE); |
744 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | 694 | this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE); |
745 | /* Write out the start read command */ | ||
746 | this->write_byte(mtd, NAND_CMD_READSTART); | ||
747 | /* End command latch cycle */ | ||
748 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
749 | /* Fall through into ready check */ | ||
750 | 695 | ||
751 | /* This applies to read commands */ | 696 | /* This applies to read commands */ |
752 | default: | 697 | default: |
@@ -1085,27 +1030,6 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retl | |||
1085 | } | 1030 | } |
1086 | 1031 | ||
1087 | /** | 1032 | /** |
1088 | * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc | ||
1089 | * @mtd: MTD device structure | ||
1090 | * @from: offset to read from | ||
1091 | * @len: number of bytes to read | ||
1092 | * @retlen: pointer to variable to store the number of read bytes | ||
1093 | * @buf: the databuffer to put data | ||
1094 | * @oob_buf: filesystem supplied oob data buffer | ||
1095 | * @oobsel: oob selection structure | ||
1096 | * | ||
1097 | * This function simply calls nand_do_read_ecc with flags = 0xff | ||
1098 | */ | ||
1099 | static int nand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | ||
1100 | size_t *retlen, uint8_t *buf, uint8_t *oob_buf, struct nand_oobinfo *oobsel) | ||
1101 | { | ||
1102 | /* use userspace supplied oobinfo, if zero */ | ||
1103 | if (oobsel == NULL) | ||
1104 | oobsel = &mtd->oobinfo; | ||
1105 | return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff); | ||
1106 | } | ||
1107 | |||
1108 | /** | ||
1109 | * nand_do_read_ecc - [MTD Interface] Read data with ECC | 1033 | * nand_do_read_ecc - [MTD Interface] Read data with ECC |
1110 | * @mtd: MTD device structure | 1034 | * @mtd: MTD device structure |
1111 | * @from: offset to read from | 1035 | * @from: offset to read from |
@@ -1529,6 +1453,56 @@ int nand_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, s | |||
1529 | } | 1453 | } |
1530 | 1454 | ||
1531 | /** | 1455 | /** |
1456 | * nand_write_raw - [GENERIC] Write raw data including oob | ||
1457 | * @mtd: MTD device structure | ||
1458 | * @buf: source buffer | ||
1459 | * @to: offset to write to | ||
1460 | * @len: number of bytes to write | ||
1461 | * @buf: source buffer | ||
1462 | * @oob: oob buffer | ||
1463 | * | ||
1464 | * Write raw data including oob | ||
1465 | */ | ||
1466 | int nand_write_raw(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | ||
1467 | uint8_t *buf, uint8_t *oob) | ||
1468 | { | ||
1469 | struct nand_chip *this = mtd->priv; | ||
1470 | int page = (int)(to >> this->page_shift); | ||
1471 | int chip = (int)(to >> this->chip_shift); | ||
1472 | int ret; | ||
1473 | |||
1474 | *retlen = 0; | ||
1475 | |||
1476 | /* Do not allow writes past end of device */ | ||
1477 | if ((to + len) > mtd->size) { | ||
1478 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt write " | ||
1479 | "beyond end of device\n"); | ||
1480 | return -EINVAL; | ||
1481 | } | ||
1482 | |||
1483 | /* Grab the lock and see if the device is available */ | ||
1484 | nand_get_device(this, mtd, FL_WRITING); | ||
1485 | |||
1486 | this->select_chip(mtd, chip); | ||
1487 | this->data_poi = buf; | ||
1488 | |||
1489 | while (len != *retlen) { | ||
1490 | ret = nand_write_page(mtd, this, page, oob, &mtd->oobinfo, 0); | ||
1491 | if (ret) | ||
1492 | return ret; | ||
1493 | page++; | ||
1494 | *retlen += mtd->writesize; | ||
1495 | this->data_poi += mtd->writesize; | ||
1496 | oob += mtd->oobsize; | ||
1497 | } | ||
1498 | |||
1499 | /* Deselect and wake up anyone waiting on the device */ | ||
1500 | nand_release_device(mtd); | ||
1501 | return 0; | ||
1502 | } | ||
1503 | EXPORT_SYMBOL_GPL(nand_write_raw); | ||
1504 | |||
1505 | /** | ||
1532 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer | 1506 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer |
1533 | * @mtd: MTD device structure | 1507 | * @mtd: MTD device structure |
1534 | * @fsbuf: buffer given by fs driver | 1508 | * @fsbuf: buffer given by fs driver |
@@ -1590,57 +1564,39 @@ static uint8_t *nand_prepare_oobbuf(struct mtd_info *mtd, uint8_t *fsbuf, struct | |||
1590 | #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 | 1564 | #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 |
1591 | 1565 | ||
1592 | /** | 1566 | /** |
1593 | * nand_write - [MTD Interface] compability function for nand_write_ecc | 1567 | * nand_write - [MTD Interface] NAND write with ECC |
1594 | * @mtd: MTD device structure | 1568 | * @mtd: MTD device structure |
1595 | * @to: offset to write to | 1569 | * @to: offset to write to |
1596 | * @len: number of bytes to write | 1570 | * @len: number of bytes to write |
1597 | * @retlen: pointer to variable to store the number of written bytes | 1571 | * @retlen: pointer to variable to store the number of written bytes |
1598 | * @buf: the data to write | 1572 | * @buf: the data to write |
1599 | * | 1573 | * |
1600 | * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL | ||
1601 | * | ||
1602 | */ | ||
1603 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) | ||
1604 | { | ||
1605 | return (nand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL)); | ||
1606 | } | ||
1607 | |||
1608 | /** | ||
1609 | * nand_write_ecc - [MTD Interface] NAND write with ECC | ||
1610 | * @mtd: MTD device structure | ||
1611 | * @to: offset to write to | ||
1612 | * @len: number of bytes to write | ||
1613 | * @retlen: pointer to variable to store the number of written bytes | ||
1614 | * @buf: the data to write | ||
1615 | * @eccbuf: filesystem supplied oob data buffer | ||
1616 | * @oobsel: oob selection structure | ||
1617 | * | ||
1618 | * NAND write with ECC | 1574 | * NAND write with ECC |
1619 | */ | 1575 | */ |
1620 | static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | 1576 | static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, |
1621 | size_t *retlen, const uint8_t *buf, uint8_t *eccbuf, | 1577 | size_t *retlen, const uint8_t *buf) |
1622 | struct nand_oobinfo *oobsel) | ||
1623 | { | 1578 | { |
1624 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; | 1579 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; |
1625 | int autoplace = 0, numpages, totalpages; | 1580 | int autoplace = 0, numpages, totalpages; |
1626 | struct nand_chip *this = mtd->priv; | 1581 | struct nand_chip *this = mtd->priv; |
1627 | uint8_t *oobbuf, *bufstart; | 1582 | uint8_t *oobbuf, *bufstart, *eccbuf = NULL; |
1628 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | 1583 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); |
1584 | struct nand_oobinfo *oobsel = &mtd->oobinfo; | ||
1629 | 1585 | ||
1630 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); | 1586 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write: to = 0x%08x, len = %i\n", (unsigned int)to, (int)len); |
1631 | 1587 | ||
1632 | /* Initialize retlen, in case of early exit */ | 1588 | /* Initialize retlen, in case of early exit */ |
1633 | *retlen = 0; | 1589 | *retlen = 0; |
1634 | 1590 | ||
1635 | /* Do not allow write past end of device */ | 1591 | /* Do not allow write past end of device */ |
1636 | if ((to + len) > mtd->size) { | 1592 | if ((to + len) > mtd->size) { |
1637 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); | 1593 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: Attempt to write past end of page\n"); |
1638 | return -EINVAL; | 1594 | return -EINVAL; |
1639 | } | 1595 | } |
1640 | 1596 | ||
1641 | /* reject writes, which are not page aligned */ | 1597 | /* reject writes, which are not page aligned */ |
1642 | if (NOTALIGNED(to) || NOTALIGNED(len)) { | 1598 | if (NOTALIGNED(to) || NOTALIGNED(len)) { |
1643 | printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | 1599 | printk(KERN_NOTICE "nand_write: Attempt to write not page aligned data\n"); |
1644 | return -EINVAL; | 1600 | return -EINVAL; |
1645 | } | 1601 | } |
1646 | 1602 | ||
@@ -1656,10 +1612,6 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1656 | if (nand_check_wp(mtd)) | 1612 | if (nand_check_wp(mtd)) |
1657 | goto out; | 1613 | goto out; |
1658 | 1614 | ||
1659 | /* if oobsel is NULL, use chip defaults */ | ||
1660 | if (oobsel == NULL) | ||
1661 | oobsel = &mtd->oobinfo; | ||
1662 | |||
1663 | /* Autoplace of oob data ? Use the default placement scheme */ | 1615 | /* Autoplace of oob data ? Use the default placement scheme */ |
1664 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | 1616 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { |
1665 | oobsel = this->autooob; | 1617 | oobsel = this->autooob; |
@@ -1694,7 +1646,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1694 | */ | 1646 | */ |
1695 | ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); | 1647 | ret = nand_write_page(mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); |
1696 | if (ret) { | 1648 | if (ret) { |
1697 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); | 1649 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: write_page failed %d\n", ret); |
1698 | goto out; | 1650 | goto out; |
1699 | } | 1651 | } |
1700 | /* Next oob page */ | 1652 | /* Next oob page */ |
@@ -1717,7 +1669,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1717 | ret = nand_verify_pages(mtd, this, startpage, page - startpage, | 1669 | ret = nand_verify_pages(mtd, this, startpage, page - startpage, |
1718 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | 1670 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); |
1719 | if (ret) { | 1671 | if (ret) { |
1720 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | 1672 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret); |
1721 | goto out; | 1673 | goto out; |
1722 | } | 1674 | } |
1723 | *retlen = written; | 1675 | *retlen = written; |
@@ -1746,7 +1698,7 @@ static int nand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
1746 | if (!ret) | 1698 | if (!ret) |
1747 | *retlen = written; | 1699 | *retlen = written; |
1748 | else | 1700 | else |
1749 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | 1701 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write: verify_pages failed %d\n", ret); |
1750 | 1702 | ||
1751 | out: | 1703 | out: |
1752 | /* Deselect and wake up anyone waiting on the device */ | 1704 | /* Deselect and wake up anyone waiting on the device */ |
@@ -1857,187 +1809,6 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, size_t *r | |||
1857 | } | 1809 | } |
1858 | 1810 | ||
1859 | /** | 1811 | /** |
1860 | * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc | ||
1861 | * @mtd: MTD device structure | ||
1862 | * @vecs: the iovectors to write | ||
1863 | * @count: number of vectors | ||
1864 | * @to: offset to write to | ||
1865 | * @retlen: pointer to variable to store the number of written bytes | ||
1866 | * | ||
1867 | * NAND write with kvec. This just calls the ecc function | ||
1868 | */ | ||
1869 | static int nand_writev(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | ||
1870 | loff_t to, size_t *retlen) | ||
1871 | { | ||
1872 | return (nand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL)); | ||
1873 | } | ||
1874 | |||
1875 | /** | ||
1876 | * nand_writev_ecc - [MTD Interface] write with iovec with ecc | ||
1877 | * @mtd: MTD device structure | ||
1878 | * @vecs: the iovectors to write | ||
1879 | * @count: number of vectors | ||
1880 | * @to: offset to write to | ||
1881 | * @retlen: pointer to variable to store the number of written bytes | ||
1882 | * @eccbuf: filesystem supplied oob data buffer | ||
1883 | * @oobsel: oob selection structure | ||
1884 | * | ||
1885 | * NAND write with iovec with ecc | ||
1886 | */ | ||
1887 | static int nand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | ||
1888 | loff_t to, size_t *retlen, uint8_t *eccbuf, struct nand_oobinfo *oobsel) | ||
1889 | { | ||
1890 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; | ||
1891 | int oob, numpages, autoplace = 0, startpage; | ||
1892 | struct nand_chip *this = mtd->priv; | ||
1893 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | ||
1894 | uint8_t *oobbuf, *bufstart; | ||
1895 | |||
1896 | /* Preset written len for early exit */ | ||
1897 | *retlen = 0; | ||
1898 | |||
1899 | /* Calculate total length of data */ | ||
1900 | total_len = 0; | ||
1901 | for (i = 0; i < count; i++) | ||
1902 | total_len += (int)vecs[i].iov_len; | ||
1903 | |||
1904 | DEBUG(MTD_DEBUG_LEVEL3, "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int)to, (unsigned int)total_len, count); | ||
1905 | |||
1906 | /* Do not allow write past end of page */ | ||
1907 | if ((to + total_len) > mtd->size) { | ||
1908 | DEBUG(MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n"); | ||
1909 | return -EINVAL; | ||
1910 | } | ||
1911 | |||
1912 | /* reject writes, which are not page aligned */ | ||
1913 | if (NOTALIGNED(to) || NOTALIGNED(total_len)) { | ||
1914 | printk(KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | ||
1915 | return -EINVAL; | ||
1916 | } | ||
1917 | |||
1918 | /* Grab the lock and see if the device is available */ | ||
1919 | nand_get_device(this, mtd, FL_WRITING); | ||
1920 | |||
1921 | /* Get the current chip-nr */ | ||
1922 | chipnr = (int)(to >> this->chip_shift); | ||
1923 | /* Select the NAND device */ | ||
1924 | this->select_chip(mtd, chipnr); | ||
1925 | |||
1926 | /* Check, if it is write protected */ | ||
1927 | if (nand_check_wp(mtd)) | ||
1928 | goto out; | ||
1929 | |||
1930 | /* if oobsel is NULL, use chip defaults */ | ||
1931 | if (oobsel == NULL) | ||
1932 | oobsel = &mtd->oobinfo; | ||
1933 | |||
1934 | /* Autoplace of oob data ? Use the default placement scheme */ | ||
1935 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | ||
1936 | oobsel = this->autooob; | ||
1937 | autoplace = 1; | ||
1938 | } | ||
1939 | if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) | ||
1940 | autoplace = 1; | ||
1941 | |||
1942 | /* Setup start page */ | ||
1943 | page = (int)(to >> this->page_shift); | ||
1944 | /* Invalidate the page cache, if we write to the cached page */ | ||
1945 | if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) | ||
1946 | this->pagebuf = -1; | ||
1947 | |||
1948 | startpage = page & this->pagemask; | ||
1949 | |||
1950 | /* Loop until all kvec' data has been written */ | ||
1951 | len = 0; | ||
1952 | while (count) { | ||
1953 | /* If the given tuple is >= pagesize then | ||
1954 | * write it out from the iov | ||
1955 | */ | ||
1956 | if ((vecs->iov_len - len) >= mtd->writesize) { | ||
1957 | /* Calc number of pages we can write | ||
1958 | * out of this iov in one go */ | ||
1959 | numpages = (vecs->iov_len - len) >> this->page_shift; | ||
1960 | /* Do not cross block boundaries */ | ||
1961 | numpages = min(ppblock - (startpage & (ppblock - 1)), numpages); | ||
1962 | oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages); | ||
1963 | bufstart = (uint8_t *) vecs->iov_base; | ||
1964 | bufstart += len; | ||
1965 | this->data_poi = bufstart; | ||
1966 | oob = 0; | ||
1967 | for (i = 1; i <= numpages; i++) { | ||
1968 | /* Write one page. If this is the last page to write | ||
1969 | * then use the real pageprogram command, else select | ||
1970 | * cached programming if supported by the chip. | ||
1971 | */ | ||
1972 | ret = nand_write_page(mtd, this, page & this->pagemask, | ||
1973 | &oobbuf[oob], oobsel, i != numpages); | ||
1974 | if (ret) | ||
1975 | goto out; | ||
1976 | this->data_poi += mtd->writesize; | ||
1977 | len += mtd->writesize; | ||
1978 | oob += mtd->oobsize; | ||
1979 | page++; | ||
1980 | } | ||
1981 | /* Check, if we have to switch to the next tuple */ | ||
1982 | if (len >= (int)vecs->iov_len) { | ||
1983 | vecs++; | ||
1984 | len = 0; | ||
1985 | count--; | ||
1986 | } | ||
1987 | } else { | ||
1988 | /* We must use the internal buffer, read data out of each | ||
1989 | * tuple until we have a full page to write | ||
1990 | */ | ||
1991 | int cnt = 0; | ||
1992 | while (cnt < mtd->writesize) { | ||
1993 | if (vecs->iov_base != NULL && vecs->iov_len) | ||
1994 | this->data_buf[cnt++] = ((uint8_t *) vecs->iov_base)[len++]; | ||
1995 | /* Check, if we have to switch to the next tuple */ | ||
1996 | if (len >= (int)vecs->iov_len) { | ||
1997 | vecs++; | ||
1998 | len = 0; | ||
1999 | count--; | ||
2000 | } | ||
2001 | } | ||
2002 | this->pagebuf = page; | ||
2003 | this->data_poi = this->data_buf; | ||
2004 | bufstart = this->data_poi; | ||
2005 | numpages = 1; | ||
2006 | oobbuf = nand_prepare_oobbuf(mtd, NULL, oobsel, autoplace, numpages); | ||
2007 | ret = nand_write_page(mtd, this, page & this->pagemask, oobbuf, oobsel, 0); | ||
2008 | if (ret) | ||
2009 | goto out; | ||
2010 | page++; | ||
2011 | } | ||
2012 | |||
2013 | this->data_poi = bufstart; | ||
2014 | ret = nand_verify_pages(mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); | ||
2015 | if (ret) | ||
2016 | goto out; | ||
2017 | |||
2018 | written += mtd->writesize * numpages; | ||
2019 | /* All done ? */ | ||
2020 | if (!count) | ||
2021 | break; | ||
2022 | |||
2023 | startpage = page & this->pagemask; | ||
2024 | /* Check, if we cross a chip boundary */ | ||
2025 | if (!startpage) { | ||
2026 | chipnr++; | ||
2027 | this->select_chip(mtd, -1); | ||
2028 | this->select_chip(mtd, chipnr); | ||
2029 | } | ||
2030 | } | ||
2031 | ret = 0; | ||
2032 | out: | ||
2033 | /* Deselect and wake up anyone waiting on the device */ | ||
2034 | nand_release_device(mtd); | ||
2035 | |||
2036 | *retlen = written; | ||
2037 | return ret; | ||
2038 | } | ||
2039 | |||
2040 | /** | ||
2041 | * single_erease_cmd - [GENERIC] NAND standard block erase command function | 1812 | * single_erease_cmd - [GENERIC] NAND standard block erase command function |
2042 | * @mtd: MTD device structure | 1813 | * @mtd: MTD device structure |
2043 | * @page: the page address of the block which will be erased | 1814 | * @page: the page address of the block which will be erased |
@@ -2392,12 +2163,8 @@ static void nand_set_defaults(struct nand_chip *this, int busw) | |||
2392 | 2163 | ||
2393 | if (!this->select_chip) | 2164 | if (!this->select_chip) |
2394 | this->select_chip = nand_select_chip; | 2165 | this->select_chip = nand_select_chip; |
2395 | if (!this->write_byte) | ||
2396 | this->write_byte = busw ? nand_write_byte16 : nand_write_byte; | ||
2397 | if (!this->read_byte) | 2166 | if (!this->read_byte) |
2398 | this->read_byte = busw ? nand_read_byte16 : nand_read_byte; | 2167 | this->read_byte = busw ? nand_read_byte16 : nand_read_byte; |
2399 | if (!this->write_word) | ||
2400 | this->write_word = nand_write_word; | ||
2401 | if (!this->read_word) | 2168 | if (!this->read_word) |
2402 | this->read_word = nand_read_word; | 2169 | this->read_word = nand_read_word; |
2403 | if (!this->block_bad) | 2170 | if (!this->block_bad) |
@@ -2713,13 +2480,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
2713 | mtd->unpoint = NULL; | 2480 | mtd->unpoint = NULL; |
2714 | mtd->read = nand_read; | 2481 | mtd->read = nand_read; |
2715 | mtd->write = nand_write; | 2482 | mtd->write = nand_write; |
2716 | mtd->read_ecc = nand_read_ecc; | ||
2717 | mtd->write_ecc = nand_write_ecc; | ||
2718 | mtd->read_oob = nand_read_oob; | 2483 | mtd->read_oob = nand_read_oob; |
2719 | mtd->write_oob = nand_write_oob; | 2484 | mtd->write_oob = nand_write_oob; |
2720 | mtd->readv = NULL; | ||
2721 | mtd->writev = nand_writev; | ||
2722 | mtd->writev_ecc = nand_writev_ecc; | ||
2723 | mtd->sync = nand_sync; | 2485 | mtd->sync = nand_sync; |
2724 | mtd->lock = NULL; | 2486 | mtd->lock = NULL; |
2725 | mtd->unlock = NULL; | 2487 | mtd->unlock = NULL; |