aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-08-06 09:53:06 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-08-06 11:36:59 -0400
commit5f97304ef12b79f1a466971eefdf93ea3b2d341f (patch)
treeba279472202f9a0520dc61aadea7a1e9c4f0d876 /drivers
parentc29c607afa2e94a43f249f19a2d3097e56aaedd7 (diff)
mxc_nand: make some internally used functions overwriteable
This patch prepares the driver to add v3 controller support later. The v3 controller is basically the same controller as v1 and v2, but with a completely different register layout. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/mxc_nand.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index b6aa7e3a967a..5130a8531024 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -115,6 +115,13 @@ struct mxc_nand_host {
115 uint8_t *data_buf; 115 uint8_t *data_buf;
116 unsigned int buf_start; 116 unsigned int buf_start;
117 int spare_len; 117 int spare_len;
118
119 void (*preset)(struct mtd_info *);
120 void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
121 void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
122 void (*send_page)(struct mtd_info *, unsigned int);
123 void (*send_read_id)(struct mxc_nand_host *);
124 uint16_t (*get_dev_status)(struct mxc_nand_host *);
118}; 125};
119 126
120/* OOB placement block for use with hardware ecc generation */ 127/* OOB placement block for use with hardware ecc generation */
@@ -212,7 +219,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
212 219
213/* This function issues the specified command to the NAND device and 220/* This function issues the specified command to the NAND device and
214 * waits for completion. */ 221 * waits for completion. */
215static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) 222static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
216{ 223{
217 DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); 224 DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
218 225
@@ -241,7 +248,7 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
241/* This function sends an address (or partial address) to the 248/* This function sends an address (or partial address) to the
242 * NAND device. The address is used to select the source/destination for 249 * NAND device. The address is used to select the source/destination for
243 * a NAND command. */ 250 * a NAND command. */
244static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast) 251static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
245{ 252{
246 DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); 253 DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
247 254
@@ -252,7 +259,7 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
252 wait_op_done(host, islast); 259 wait_op_done(host, islast);
253} 260}
254 261
255static void send_page(struct mtd_info *mtd, unsigned int ops) 262static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
256{ 263{
257 struct nand_chip *nand_chip = mtd->priv; 264 struct nand_chip *nand_chip = mtd->priv;
258 struct mxc_nand_host *host = nand_chip->priv; 265 struct mxc_nand_host *host = nand_chip->priv;
@@ -276,7 +283,7 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
276} 283}
277 284
278/* Request the NANDFC to perform a read of the NAND device ID. */ 285/* Request the NANDFC to perform a read of the NAND device ID. */
279static void send_read_id(struct mxc_nand_host *host) 286static void send_read_id_v1_v2(struct mxc_nand_host *host)
280{ 287{
281 struct nand_chip *this = &host->nand; 288 struct nand_chip *this = &host->nand;
282 289
@@ -302,7 +309,7 @@ static void send_read_id(struct mxc_nand_host *host)
302 309
303/* This function requests the NANDFC to perform a read of the 310/* This function requests the NANDFC to perform a read of the
304 * NAND device status and returns the current status. */ 311 * NAND device status and returns the current status. */
305static uint16_t get_dev_status(struct mxc_nand_host *host) 312static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
306{ 313{
307 void __iomem *main_buf = host->main_area0; 314 void __iomem *main_buf = host->main_area0;
308 uint32_t store; 315 uint32_t store;
@@ -381,7 +388,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
381 388
382 /* Check for status request */ 389 /* Check for status request */
383 if (host->status_request) 390 if (host->status_request)
384 return get_dev_status(host) & 0xFF; 391 return host->get_dev_status(host) & 0xFF;
385 392
386 ret = *(uint8_t *)(host->data_buf + host->buf_start); 393 ret = *(uint8_t *)(host->data_buf + host->buf_start);
387 host->buf_start++; 394 host->buf_start++;
@@ -517,39 +524,39 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
517 * we will used the saved column address to index into 524 * we will used the saved column address to index into
518 * the full page. 525 * the full page.
519 */ 526 */
520 send_addr(host, 0, page_addr == -1); 527 host->send_addr(host, 0, page_addr == -1);
521 if (mtd->writesize > 512) 528 if (mtd->writesize > 512)
522 /* another col addr cycle for 2k page */ 529 /* another col addr cycle for 2k page */
523 send_addr(host, 0, false); 530 host->send_addr(host, 0, false);
524 } 531 }
525 532
526 /* Write out page address, if necessary */ 533 /* Write out page address, if necessary */
527 if (page_addr != -1) { 534 if (page_addr != -1) {
528 /* paddr_0 - p_addr_7 */ 535 /* paddr_0 - p_addr_7 */
529 send_addr(host, (page_addr & 0xff), false); 536 host->send_addr(host, (page_addr & 0xff), false);
530 537
531 if (mtd->writesize > 512) { 538 if (mtd->writesize > 512) {
532 if (mtd->size >= 0x10000000) { 539 if (mtd->size >= 0x10000000) {
533 /* paddr_8 - paddr_15 */ 540 /* paddr_8 - paddr_15 */
534 send_addr(host, (page_addr >> 8) & 0xff, false); 541 host->send_addr(host, (page_addr >> 8) & 0xff, false);
535 send_addr(host, (page_addr >> 16) & 0xff, true); 542 host->send_addr(host, (page_addr >> 16) & 0xff, true);
536 } else 543 } else
537 /* paddr_8 - paddr_15 */ 544 /* paddr_8 - paddr_15 */
538 send_addr(host, (page_addr >> 8) & 0xff, true); 545 host->send_addr(host, (page_addr >> 8) & 0xff, true);
539 } else { 546 } else {
540 /* One more address cycle for higher density devices */ 547 /* One more address cycle for higher density devices */
541 if (mtd->size >= 0x4000000) { 548 if (mtd->size >= 0x4000000) {
542 /* paddr_8 - paddr_15 */ 549 /* paddr_8 - paddr_15 */
543 send_addr(host, (page_addr >> 8) & 0xff, false); 550 host->send_addr(host, (page_addr >> 8) & 0xff, false);
544 send_addr(host, (page_addr >> 16) & 0xff, true); 551 host->send_addr(host, (page_addr >> 16) & 0xff, true);
545 } else 552 } else
546 /* paddr_8 - paddr_15 */ 553 /* paddr_8 - paddr_15 */
547 send_addr(host, (page_addr >> 8) & 0xff, true); 554 host->send_addr(host, (page_addr >> 8) & 0xff, true);
548 } 555 }
549 } 556 }
550} 557}
551 558
552static void preset(struct mtd_info *mtd) 559static void preset_v1_v2(struct mtd_info *mtd)
553{ 560{
554 struct nand_chip *nand_chip = mtd->priv; 561 struct nand_chip *nand_chip = mtd->priv;
555 struct mxc_nand_host *host = nand_chip->priv; 562 struct mxc_nand_host *host = nand_chip->priv;
@@ -602,15 +609,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
602 /* Command pre-processing step */ 609 /* Command pre-processing step */
603 switch (command) { 610 switch (command) {
604 case NAND_CMD_RESET: 611 case NAND_CMD_RESET:
605 preset(mtd); 612 host->preset(mtd);
606 send_cmd(host, command, false); 613 host->send_cmd(host, command, false);
607 break; 614 break;
608 615
609 case NAND_CMD_STATUS: 616 case NAND_CMD_STATUS:
610 host->buf_start = 0; 617 host->buf_start = 0;
611 host->status_request = true; 618 host->status_request = true;
612 619
613 send_cmd(host, command, true); 620 host->send_cmd(host, command, true);
614 mxc_do_addr_cycle(mtd, column, page_addr); 621 mxc_do_addr_cycle(mtd, column, page_addr);
615 break; 622 break;
616 623
@@ -623,13 +630,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
623 630
624 command = NAND_CMD_READ0; /* only READ0 is valid */ 631 command = NAND_CMD_READ0; /* only READ0 is valid */
625 632
626 send_cmd(host, command, false); 633 host->send_cmd(host, command, false);
627 mxc_do_addr_cycle(mtd, column, page_addr); 634 mxc_do_addr_cycle(mtd, column, page_addr);
628 635
629 if (mtd->writesize > 512) 636 if (mtd->writesize > 512)
630 send_cmd(host, NAND_CMD_READSTART, true); 637 host->send_cmd(host, NAND_CMD_READSTART, true);
631 638
632 send_page(mtd, NFC_OUTPUT); 639 host->send_page(mtd, NFC_OUTPUT);
633 640
634 memcpy(host->data_buf, host->main_area0, mtd->writesize); 641 memcpy(host->data_buf, host->main_area0, mtd->writesize);
635 copy_spare(mtd, true); 642 copy_spare(mtd, true);
@@ -642,28 +649,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
642 649
643 host->buf_start = column; 650 host->buf_start = column;
644 651
645 send_cmd(host, command, false); 652 host->send_cmd(host, command, false);
646 mxc_do_addr_cycle(mtd, column, page_addr); 653 mxc_do_addr_cycle(mtd, column, page_addr);
647 break; 654 break;
648 655
649 case NAND_CMD_PAGEPROG: 656 case NAND_CMD_PAGEPROG:
650 memcpy(host->main_area0, host->data_buf, mtd->writesize); 657 memcpy(host->main_area0, host->data_buf, mtd->writesize);
651 copy_spare(mtd, false); 658 copy_spare(mtd, false);
652 send_page(mtd, NFC_INPUT); 659 host->send_page(mtd, NFC_INPUT);
653 send_cmd(host, command, true); 660 host->send_cmd(host, command, true);
654 mxc_do_addr_cycle(mtd, column, page_addr); 661 mxc_do_addr_cycle(mtd, column, page_addr);
655 break; 662 break;
656 663
657 case NAND_CMD_READID: 664 case NAND_CMD_READID:
658 send_cmd(host, command, true); 665 host->send_cmd(host, command, true);
659 mxc_do_addr_cycle(mtd, column, page_addr); 666 mxc_do_addr_cycle(mtd, column, page_addr);
660 send_read_id(host); 667 host->send_read_id(host);
661 host->buf_start = column; 668 host->buf_start = column;
662 break; 669 break;
663 670
664 case NAND_CMD_ERASE1: 671 case NAND_CMD_ERASE1:
665 case NAND_CMD_ERASE2: 672 case NAND_CMD_ERASE2:
666 send_cmd(host, command, false); 673 host->send_cmd(host, command, false);
667 mxc_do_addr_cycle(mtd, column, page_addr); 674 mxc_do_addr_cycle(mtd, column, page_addr);
668 675
669 break; 676 break;
@@ -760,6 +767,15 @@ static int __init mxcnd_probe(struct platform_device *pdev)
760 767
761 host->main_area0 = host->base; 768 host->main_area0 = host->base;
762 769
770 if (nfc_is_v1() || nfc_is_v21()) {
771 host->preset = preset_v1_v2;
772 host->send_cmd = send_cmd_v1_v2;
773 host->send_addr = send_addr_v1_v2;
774 host->send_page = send_page_v1_v2;
775 host->send_read_id = send_read_id_v1_v2;
776 host->get_dev_status = get_dev_status_v1_v2;
777 }
778
763 if (nfc_is_v21()) { 779 if (nfc_is_v21()) {
764 host->regs = host->base + 0x1e00; 780 host->regs = host->base + 0x1e00;
765 host->spare0 = host->base + 0x1000; 781 host->spare0 = host->base + 0x1000;