aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:25:53 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-23 17:25:53 -0400
commit7abd3ef9875eb2afcdcd4f450680298a2983a55e (patch)
tree64c19d2e5ecca182938acfcb8a172efb7d907d85 /drivers/mtd/nand/nand_base.c
parent3821720d51b5f304d2c33021a82c8da70f6d6ac9 (diff)
[MTD] Refactor NAND hwcontrol to cmd_ctrl
The hwcontrol function enforced a step by step state machine for any kind of hardware chip access. Let the hardware driver know which control bits are set and inform it about a change of the control lines. Let the hardware driver write out the command and address bytes directly. This gives a peformance advantage for address bus controlled chips and simplifies the quirks in the hardware drivers. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c115
1 files changed, 54 insertions, 61 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index aa2e14538bf4..f6997fb77b91 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -276,10 +276,10 @@ static void nand_select_chip(struct mtd_info *mtd, int chip)
276 struct nand_chip *this = mtd->priv; 276 struct nand_chip *this = mtd->priv;
277 switch (chip) { 277 switch (chip) {
278 case -1: 278 case -1:
279 this->hwcontrol(mtd, NAND_CTL_CLRNCE); 279 this->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
280 break; 280 break;
281 case 0: 281 case 0:
282 this->hwcontrol(mtd, NAND_CTL_SETNCE); 282 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
283 break; 283 break;
284 284
285 default: 285 default:
@@ -548,13 +548,12 @@ static void nand_wait_ready(struct mtd_info *mtd)
548 * Send command to NAND device. This function is used for small page 548 * Send command to NAND device. This function is used for small page
549 * devices (256/512 Bytes per page) 549 * devices (256/512 Bytes per page)
550 */ 550 */
551static void nand_command(struct mtd_info *mtd, unsigned command, int column, 551static void nand_command(struct mtd_info *mtd, unsigned int command,
552 int page_addr) 552 int column, int page_addr)
553{ 553{
554 register struct nand_chip *this = mtd->priv; 554 register struct nand_chip *this = mtd->priv;
555 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
555 556
556 /* Begin command latch cycle */
557 this->hwcontrol(mtd, NAND_CTL_SETCLE);
558 /* 557 /*
559 * Write out the command to the device. 558 * Write out the command to the device.
560 */ 559 */
@@ -572,33 +571,32 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
572 column -= 256; 571 column -= 256;
573 readcmd = NAND_CMD_READ1; 572 readcmd = NAND_CMD_READ1;
574 } 573 }
575 this->write_byte(mtd, readcmd); 574 this->cmd_ctrl(mtd, readcmd, ctrl);
575 ctrl &= ~NAND_CTRL_CHANGE;
576 } 576 }
577 this->write_byte(mtd, command); 577 this->cmd_ctrl(mtd, command, ctrl);
578 578
579 /* Set ALE and clear CLE to start address cycle */ 579 /*
580 this->hwcontrol(mtd, NAND_CTL_CLRCLE); 580 * Address cycle, when necessary
581 581 */
582 if (column != -1 || page_addr != -1) { 582 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
583 this->hwcontrol(mtd, NAND_CTL_SETALE); 583 /* Serially input address */
584 584 if (column != -1) {
585 /* Serially input address */ 585 /* Adjust columns for 16 bit buswidth */
586 if (column != -1) { 586 if (this->options & NAND_BUSWIDTH_16)
587 /* Adjust columns for 16 bit buswidth */ 587 column >>= 1;
588 if (this->options & NAND_BUSWIDTH_16) 588 this->cmd_ctrl(mtd, column, ctrl);
589 column >>= 1; 589 ctrl &= ~NAND_CTRL_CHANGE;
590 this->write_byte(mtd, column); 590 }
591 } 591 if (page_addr != -1) {
592 if (page_addr != -1) { 592 this->cmd_ctrl(mtd, page_addr, ctrl);
593 this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); 593 ctrl &= ~NAND_CTRL_CHANGE;
594 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); 594 this->cmd_ctrl(mtd, page_addr >> 8, ctrl);
595 /* One more address cycle for devices > 32MiB */ 595 /* One more address cycle for devices > 32MiB */
596 if (this->chipsize > (32 << 20)) 596 if (this->chipsize > (32 << 20))
597 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0x0f)); 597 this->cmd_ctrl(mtd, page_addr >> 16, ctrl);
598 }
599 /* Latch in address */
600 this->hwcontrol(mtd, NAND_CTL_CLRALE);
601 } 598 }
599 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
602 600
603 /* 601 /*
604 * program and erase have their own busy handlers 602 * program and erase have their own busy handlers
@@ -611,15 +609,16 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
611 case NAND_CMD_ERASE2: 609 case NAND_CMD_ERASE2:
612 case NAND_CMD_SEQIN: 610 case NAND_CMD_SEQIN:
613 case NAND_CMD_STATUS: 611 case NAND_CMD_STATUS:
612 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
614 return; 613 return;
615 614
616 case NAND_CMD_RESET: 615 case NAND_CMD_RESET:
617 if (this->dev_ready) 616 if (this->dev_ready)
618 break; 617 break;
619 udelay(this->chip_delay); 618 udelay(this->chip_delay);
620 this->hwcontrol(mtd, NAND_CTL_SETCLE); 619 this->cmd_ctrl(mtd, NAND_CMD_STATUS,
621 this->write_byte(mtd, NAND_CMD_STATUS); 620 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
622 this->hwcontrol(mtd, NAND_CTL_CLRCLE); 621 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
623 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; 622 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
624 return; 623 return;
625 624
@@ -648,12 +647,13 @@ static void nand_command(struct mtd_info *mtd, unsigned command, int column,
648 * @column: the column address for this command, -1 if none 647 * @column: the column address for this command, -1 if none
649 * @page_addr: the page address for this command, -1 if none 648 * @page_addr: the page address for this command, -1 if none
650 * 649 *
651 * Send command to NAND device. This is the version for the new large page devices 650 * Send command to NAND device. This is the version for the new large page
652 * We dont have the separate regions as we have in the small page devices. 651 * devices We dont have the separate regions as we have in the small page
653 * We must emulate NAND_CMD_READOOB to keep the code compatible. 652 * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
654 * 653 *
655 */ 654 */
656static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column, int page_addr) 655static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
656 int column, int page_addr)
657{ 657{
658 register struct nand_chip *this = mtd->priv; 658 register struct nand_chip *this = mtd->priv;
659 659
@@ -663,34 +663,33 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
663 command = NAND_CMD_READ0; 663 command = NAND_CMD_READ0;
664 } 664 }
665 665
666 /* Begin command latch cycle */ 666 /* Command latch cycle */
667 this->hwcontrol(mtd, NAND_CTL_SETCLE); 667 this->cmd_ctrl(mtd, command & 0xff,
668 /* Write out the command to the device. */ 668 NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
669 this->write_byte(mtd, (command & 0xff));
670 /* End command latch cycle */
671 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
672 669
673 if (column != -1 || page_addr != -1) { 670 if (column != -1 || page_addr != -1) {
674 this->hwcontrol(mtd, NAND_CTL_SETALE); 671 int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
675 672
676 /* Serially input address */ 673 /* Serially input address */
677 if (column != -1) { 674 if (column != -1) {
678 /* Adjust columns for 16 bit buswidth */ 675 /* Adjust columns for 16 bit buswidth */
679 if (this->options & NAND_BUSWIDTH_16) 676 if (this->options & NAND_BUSWIDTH_16)
680 column >>= 1; 677 column >>= 1;
681 this->write_byte(mtd, column & 0xff); 678 this->cmd_ctrl(mtd, column, ctrl);
682 this->write_byte(mtd, column >> 8); 679 ctrl &= ~NAND_CTRL_CHANGE;
680 this->cmd_ctrl(mtd, column >> 8, ctrl);
683 } 681 }
684 if (page_addr != -1) { 682 if (page_addr != -1) {
685 this->write_byte(mtd, (uint8_t)(page_addr & 0xff)); 683 this->cmd_ctrl(mtd, page_addr, ctrl);
686 this->write_byte(mtd, (uint8_t)((page_addr >> 8) & 0xff)); 684 this->cmd_ctrl(mtd, page_addr >> 8,
685 NAND_NCE | NAND_ALE);
687 /* One more address cycle for devices > 128MiB */ 686 /* One more address cycle for devices > 128MiB */
688 if (this->chipsize > (128 << 20)) 687 if (this->chipsize > (128 << 20))
689 this->write_byte(mtd, (uint8_t)((page_addr >> 16) & 0xff)); 688 this->cmd_ctrl(mtd, page_addr >> 16,
689 NAND_NCE | NAND_ALE);
690 } 690 }
691 /* Latch in address */
692 this->hwcontrol(mtd, NAND_CTL_CLRALE);
693 } 691 }
692 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
694 693
695 /* 694 /*
696 * program and erase have their own busy handlers 695 * program and erase have their own busy handlers
@@ -722,20 +721,14 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned command, int column,
722 if (this->dev_ready) 721 if (this->dev_ready)
723 break; 722 break;
724 udelay(this->chip_delay); 723 udelay(this->chip_delay);
725 this->hwcontrol(mtd, NAND_CTL_SETCLE); 724 this->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE | NAND_CLE);
726 this->write_byte(mtd, NAND_CMD_STATUS); 725 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
727 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
728 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ; 726 while (!(this->read_byte(mtd) & NAND_STATUS_READY)) ;
729 return; 727 return;
730 728
731 case NAND_CMD_READ0: 729 case NAND_CMD_READ0:
732 /* Begin command latch cycle */ 730 this->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_NCE | NAND_CLE);
733 this->hwcontrol(mtd, NAND_CTL_SETCLE); 731 this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE);
734 /* Write out the start read command */
735 this->write_byte(mtd, NAND_CMD_READSTART);
736 /* End command latch cycle */
737 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
738 /* Fall through into ready check */
739 732
740 /* This applies to read commands */ 733 /* This applies to read commands */
741 default: 734 default: