aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/bf5xx_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/bf5xx_nand.c')
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c117
1 files changed, 72 insertions, 45 deletions
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 2974995e194d..a382e3dd0a5d 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -20,9 +20,6 @@
20 * - DMA supported in ECC_HW 20 * - DMA supported in ECC_HW
21 * - YAFFS tested as rootfs in both ECC_HW and ECC_SW 21 * - YAFFS tested as rootfs in both ECC_HW and ECC_SW
22 * 22 *
23 * TODO:
24 * Enable JFFS2 over NAND as rootfs
25 *
26 * This program is free software; you can redistribute it and/or modify 23 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or 25 * the Free Software Foundation; either version 2 of the License, or
@@ -206,7 +203,7 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
206 203
207 if (ctrl & NAND_CLE) 204 if (ctrl & NAND_CLE)
208 bfin_write_NFC_CMD(cmd); 205 bfin_write_NFC_CMD(cmd);
209 else 206 else if (ctrl & NAND_ALE)
210 bfin_write_NFC_ADDR(cmd); 207 bfin_write_NFC_ADDR(cmd);
211 SSYNC(); 208 SSYNC();
212} 209}
@@ -218,9 +215,9 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
218 */ 215 */
219static int bf5xx_nand_devready(struct mtd_info *mtd) 216static int bf5xx_nand_devready(struct mtd_info *mtd)
220{ 217{
221 unsigned short val = bfin_read_NFC_IRQSTAT(); 218 unsigned short val = bfin_read_NFC_STAT();
222 219
223 if ((val & NBUSYIRQ) == NBUSYIRQ) 220 if ((val & NBUSY) == NBUSY)
224 return 1; 221 return 1;
225 else 222 else
226 return 0; 223 return 0;
@@ -317,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
317static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, 314static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
318 u_char *read_ecc, u_char *calc_ecc) 315 u_char *read_ecc, u_char *calc_ecc)
319{ 316{
320 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 317 struct nand_chip *chip = mtd->priv;
321 struct bf5xx_nand_platform *plat = info->platform;
322 unsigned short page_size = (plat->page_size ? 512 : 256);
323 int ret; 318 int ret;
324 319
325 ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); 320 ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
326 321
327 /* If page size is 512, correct second 256 bytes */ 322 /* If ecc size is 512, correct second 256 bytes */
328 if (page_size == 512) { 323 if (chip->ecc.size == 512) {
329 dat += 256; 324 dat += 256;
330 read_ecc += 8; 325 read_ecc += 3;
331 calc_ecc += 8; 326 calc_ecc += 3;
332 ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); 327 ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
333 } 328 }
334 329
@@ -344,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
344 const u_char *dat, u_char *ecc_code) 339 const u_char *dat, u_char *ecc_code)
345{ 340{
346 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 341 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
347 struct bf5xx_nand_platform *plat = info->platform; 342 struct nand_chip *chip = mtd->priv;
348 u16 page_size = (plat->page_size ? 512 : 256);
349 u16 ecc0, ecc1; 343 u16 ecc0, ecc1;
350 u32 code[2]; 344 u32 code[2];
351 u8 *p; 345 u8 *p;
352 346
353 /* first 4 bytes ECC code for 256 page size */ 347 /* first 3 bytes ECC code for 256 page size */
354 ecc0 = bfin_read_NFC_ECC0(); 348 ecc0 = bfin_read_NFC_ECC0();
355 ecc1 = bfin_read_NFC_ECC1(); 349 ecc1 = bfin_read_NFC_ECC1();
356 350
@@ -358,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
358 352
359 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); 353 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
360 354
361 /* first 3 bytes in ecc_code for 256 page size */
362 p = (u8 *) code; 355 p = (u8 *) code;
363 memcpy(ecc_code, p, 3); 356 memcpy(ecc_code, p, 3);
364 357
365 /* second 4 bytes ECC code for 512 page size */ 358 /* second 3 bytes ECC code for 512 ecc size */
366 if (page_size == 512) { 359 if (chip->ecc.size == 512) {
367 ecc0 = bfin_read_NFC_ECC2(); 360 ecc0 = bfin_read_NFC_ECC2();
368 ecc1 = bfin_read_NFC_ECC3(); 361 ecc1 = bfin_read_NFC_ECC3();
369 code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); 362 code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
@@ -483,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
483 uint8_t *buf, int is_read) 476 uint8_t *buf, int is_read)
484{ 477{
485 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 478 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
486 struct bf5xx_nand_platform *plat = info->platform; 479 struct nand_chip *chip = mtd->priv;
487 unsigned short page_size = (plat->page_size ? 512 : 256);
488 unsigned short val; 480 unsigned short val;
489 481
490 dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", 482 dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
@@ -498,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
498 */ 490 */
499 if (is_read) 491 if (is_read)
500 invalidate_dcache_range((unsigned int)buf, 492 invalidate_dcache_range((unsigned int)buf,
501 (unsigned int)(buf + page_size)); 493 (unsigned int)(buf + chip->ecc.size));
502 else 494 else
503 flush_dcache_range((unsigned int)buf, 495 flush_dcache_range((unsigned int)buf,
504 (unsigned int)(buf + page_size)); 496 (unsigned int)(buf + chip->ecc.size));
505 497
506 /* 498 /*
507 * This register must be written before each page is 499 * This register must be written before each page is
@@ -510,6 +502,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
510 */ 502 */
511 bfin_write_NFC_RST(ECC_RST); 503 bfin_write_NFC_RST(ECC_RST);
512 SSYNC(); 504 SSYNC();
505 while (bfin_read_NFC_RST() & ECC_RST)
506 cpu_relax();
513 507
514 disable_dma(CH_NFC); 508 disable_dma(CH_NFC);
515 clear_dma_irqstat(CH_NFC); 509 clear_dma_irqstat(CH_NFC);
@@ -520,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
520 514
521 /* The DMAs have different size on BF52x and BF54x */ 515 /* The DMAs have different size on BF52x and BF54x */
522#ifdef CONFIG_BF52x 516#ifdef CONFIG_BF52x
523 set_dma_x_count(CH_NFC, (page_size >> 1)); 517 set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
524 set_dma_x_modify(CH_NFC, 2); 518 set_dma_x_modify(CH_NFC, 2);
525 val = DI_EN | WDSIZE_16; 519 val = DI_EN | WDSIZE_16;
526#endif 520#endif
527 521
528#ifdef CONFIG_BF54x 522#ifdef CONFIG_BF54x
529 set_dma_x_count(CH_NFC, (page_size >> 2)); 523 set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
530 set_dma_x_modify(CH_NFC, 4); 524 set_dma_x_modify(CH_NFC, 4);
531 val = DI_EN | WDSIZE_32; 525 val = DI_EN | WDSIZE_32;
532#endif 526#endif
@@ -548,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
548 uint8_t *buf, int len) 542 uint8_t *buf, int len)
549{ 543{
550 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 544 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
551 struct bf5xx_nand_platform *plat = info->platform; 545 struct nand_chip *chip = mtd->priv;
552 unsigned short page_size = (plat->page_size ? 512 : 256);
553 546
554 dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); 547 dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
555 548
556 if (len == page_size) 549 if (len == chip->ecc.size)
557 bf5xx_nand_dma_rw(mtd, buf, 1); 550 bf5xx_nand_dma_rw(mtd, buf, 1);
558 else 551 else
559 bf5xx_nand_read_buf(mtd, buf, len); 552 bf5xx_nand_read_buf(mtd, buf, len);
@@ -563,17 +556,32 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
563 const uint8_t *buf, int len) 556 const uint8_t *buf, int len)
564{ 557{
565 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 558 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
566 struct bf5xx_nand_platform *plat = info->platform; 559 struct nand_chip *chip = mtd->priv;
567 unsigned short page_size = (plat->page_size ? 512 : 256);
568 560
569 dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); 561 dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
570 562
571 if (len == page_size) 563 if (len == chip->ecc.size)
572 bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); 564 bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
573 else 565 else
574 bf5xx_nand_write_buf(mtd, buf, len); 566 bf5xx_nand_write_buf(mtd, buf, len);
575} 567}
576 568
569static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
570 uint8_t *buf, int page)
571{
572 bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
573 bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
574
575 return 0;
576}
577
578static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
579 const uint8_t *buf)
580{
581 bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
582 bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
583}
584
577/* 585/*
578 * System initialization functions 586 * System initialization functions
579 */ 587 */
@@ -627,15 +635,14 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
627 635
628 /* setup NFC_CTL register */ 636 /* setup NFC_CTL register */
629 dev_info(info->device, 637 dev_info(info->device,
630 "page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n", 638 "data_width=%d, wr_dly=%d, rd_dly=%d\n",
631 (plat->page_size ? 512 : 256),
632 (plat->data_width ? 16 : 8), 639 (plat->data_width ? 16 : 8),
633 plat->wr_dly, plat->rd_dly); 640 plat->wr_dly, plat->rd_dly);
634 641
635 val = (plat->page_size << NFC_PG_SIZE_OFFSET) | 642 val = (1 << NFC_PG_SIZE_OFFSET) |
636 (plat->data_width << NFC_NWIDTH_OFFSET) | 643 (plat->data_width << NFC_NWIDTH_OFFSET) |
637 (plat->rd_dly << NFC_RDDLY_OFFSET) | 644 (plat->rd_dly << NFC_RDDLY_OFFSET) |
638 (plat->rd_dly << NFC_WRDLY_OFFSET); 645 (plat->wr_dly << NFC_WRDLY_OFFSET);
639 dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val); 646 dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
640 647
641 bfin_write_NFC_CTL(val); 648 bfin_write_NFC_CTL(val);
@@ -698,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
698 return 0; 705 return 0;
699} 706}
700 707
708static int bf5xx_nand_scan(struct mtd_info *mtd)
709{
710 struct nand_chip *chip = mtd->priv;
711 int ret;
712
713 ret = nand_scan_ident(mtd, 1);
714 if (ret)
715 return ret;
716
717 if (hardware_ecc) {
718 /*
719 * for nand with page size > 512B, think it as several sections with 512B
720 */
721 if (likely(mtd->writesize >= 512)) {
722 chip->ecc.size = 512;
723 chip->ecc.bytes = 6;
724 } else {
725 chip->ecc.size = 256;
726 chip->ecc.bytes = 3;
727 bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
728 SSYNC();
729 }
730 }
731
732 return nand_scan_tail(mtd);
733}
734
701/* 735/*
702 * bf5xx_nand_probe 736 * bf5xx_nand_probe
703 * 737 *
@@ -783,27 +817,20 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
783 chip->badblock_pattern = &bootrom_bbt; 817 chip->badblock_pattern = &bootrom_bbt;
784 chip->ecc.layout = &bootrom_ecclayout; 818 chip->ecc.layout = &bootrom_ecclayout;
785#endif 819#endif
786
787 if (plat->page_size == NFC_PG_SIZE_256) {
788 chip->ecc.bytes = 3;
789 chip->ecc.size = 256;
790 } else if (plat->page_size == NFC_PG_SIZE_512) {
791 chip->ecc.bytes = 6;
792 chip->ecc.size = 512;
793 }
794
795 chip->read_buf = bf5xx_nand_dma_read_buf; 820 chip->read_buf = bf5xx_nand_dma_read_buf;
796 chip->write_buf = bf5xx_nand_dma_write_buf; 821 chip->write_buf = bf5xx_nand_dma_write_buf;
797 chip->ecc.calculate = bf5xx_nand_calculate_ecc; 822 chip->ecc.calculate = bf5xx_nand_calculate_ecc;
798 chip->ecc.correct = bf5xx_nand_correct_data; 823 chip->ecc.correct = bf5xx_nand_correct_data;
799 chip->ecc.mode = NAND_ECC_HW; 824 chip->ecc.mode = NAND_ECC_HW;
800 chip->ecc.hwctl = bf5xx_nand_enable_hwecc; 825 chip->ecc.hwctl = bf5xx_nand_enable_hwecc;
826 chip->ecc.read_page_raw = bf5xx_nand_read_page_raw;
827 chip->ecc.write_page_raw = bf5xx_nand_write_page_raw;
801 } else { 828 } else {
802 chip->ecc.mode = NAND_ECC_SOFT; 829 chip->ecc.mode = NAND_ECC_SOFT;
803 } 830 }
804 831
805 /* scan hardware nand chip and setup mtd info data struct */ 832 /* scan hardware nand chip and setup mtd info data struct */
806 if (nand_scan(mtd, 1)) { 833 if (bf5xx_nand_scan(mtd)) {
807 err = -ENXIO; 834 err = -ENXIO;
808 goto out_err_nand_scan; 835 goto out_err_nand_scan;
809 } 836 }