aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/blackfin/include/asm/nand.h3
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c86
2 files changed, 48 insertions, 41 deletions
diff --git a/arch/blackfin/include/asm/nand.h b/arch/blackfin/include/asm/nand.h
index 3a1e79dfc8d9..256c50d8d465 100644
--- a/arch/blackfin/include/asm/nand.h
+++ b/arch/blackfin/include/asm/nand.h
@@ -15,8 +15,6 @@
15 * partitions = mtd partition list 15 * partitions = mtd partition list
16 */ 16 */
17 17
18#define NFC_PG_SIZE_256 0
19#define NFC_PG_SIZE_512 1
20#define NFC_PG_SIZE_OFFSET 9 18#define NFC_PG_SIZE_OFFSET 9
21 19
22#define NFC_NWIDTH_8 0 20#define NFC_NWIDTH_8 0
@@ -30,7 +28,6 @@
30 28
31struct bf5xx_nand_platform { 29struct bf5xx_nand_platform {
32 /* NAND chip information */ 30 /* NAND chip information */
33 unsigned short page_size;
34 unsigned short data_width; 31 unsigned short data_width;
35 32
36 /* RD/WR strobe delay timing information, all times in SCLK cycles */ 33 /* RD/WR strobe delay timing information, all times in SCLK cycles */
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 8070ff359a41..3784f4137994 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -314,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
314static 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,
315 u_char *read_ecc, u_char *calc_ecc) 315 u_char *read_ecc, u_char *calc_ecc)
316{ 316{
317 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 317 struct nand_chip *chip = mtd->priv;
318 struct bf5xx_nand_platform *plat = info->platform;
319 unsigned short page_size = (plat->page_size ? 512 : 256);
320 int ret; 318 int ret;
321 319
322 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);
323 321
324 /* If page size is 512, correct second 256 bytes */ 322 /* If ecc size is 512, correct second 256 bytes */
325 if (page_size == 512) { 323 if (chip->ecc.size == 512) {
326 dat += 256; 324 dat += 256;
327 read_ecc += 8; 325 read_ecc += 3;
328 calc_ecc += 8; 326 calc_ecc += 3;
329 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);
330 } 328 }
331 329
@@ -341,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
341 const u_char *dat, u_char *ecc_code) 339 const u_char *dat, u_char *ecc_code)
342{ 340{
343 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 341 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
344 struct bf5xx_nand_platform *plat = info->platform; 342 struct nand_chip *chip = mtd->priv;
345 u16 page_size = (plat->page_size ? 512 : 256);
346 u16 ecc0, ecc1; 343 u16 ecc0, ecc1;
347 u32 code[2]; 344 u32 code[2];
348 u8 *p; 345 u8 *p;
349 346
350 /* first 4 bytes ECC code for 256 page size */ 347 /* first 3 bytes ECC code for 256 page size */
351 ecc0 = bfin_read_NFC_ECC0(); 348 ecc0 = bfin_read_NFC_ECC0();
352 ecc1 = bfin_read_NFC_ECC1(); 349 ecc1 = bfin_read_NFC_ECC1();
353 350
@@ -355,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
355 352
356 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); 353 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
357 354
358 /* first 3 bytes in ecc_code for 256 page size */
359 p = (u8 *) code; 355 p = (u8 *) code;
360 memcpy(ecc_code, p, 3); 356 memcpy(ecc_code, p, 3);
361 357
362 /* second 4 bytes ECC code for 512 page size */ 358 /* second 3 bytes ECC code for 512 ecc size */
363 if (page_size == 512) { 359 if (chip->ecc.size == 512) {
364 ecc0 = bfin_read_NFC_ECC2(); 360 ecc0 = bfin_read_NFC_ECC2();
365 ecc1 = bfin_read_NFC_ECC3(); 361 ecc1 = bfin_read_NFC_ECC3();
366 code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); 362 code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
@@ -480,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
480 uint8_t *buf, int is_read) 476 uint8_t *buf, int is_read)
481{ 477{
482 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 478 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
483 struct bf5xx_nand_platform *plat = info->platform; 479 struct nand_chip *chip = mtd->priv;
484 unsigned short page_size = (plat->page_size ? 512 : 256);
485 unsigned short val; 480 unsigned short val;
486 481
487 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",
@@ -495,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
495 */ 490 */
496 if (is_read) 491 if (is_read)
497 invalidate_dcache_range((unsigned int)buf, 492 invalidate_dcache_range((unsigned int)buf,
498 (unsigned int)(buf + page_size)); 493 (unsigned int)(buf + chip->ecc.size));
499 else 494 else
500 flush_dcache_range((unsigned int)buf, 495 flush_dcache_range((unsigned int)buf,
501 (unsigned int)(buf + page_size)); 496 (unsigned int)(buf + chip->ecc.size));
502 497
503 /* 498 /*
504 * This register must be written before each page is 499 * This register must be written before each page is
@@ -519,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
519 514
520 /* The DMAs have different size on BF52x and BF54x */ 515 /* The DMAs have different size on BF52x and BF54x */
521#ifdef CONFIG_BF52x 516#ifdef CONFIG_BF52x
522 set_dma_x_count(CH_NFC, (page_size >> 1)); 517 set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
523 set_dma_x_modify(CH_NFC, 2); 518 set_dma_x_modify(CH_NFC, 2);
524 val = DI_EN | WDSIZE_16; 519 val = DI_EN | WDSIZE_16;
525#endif 520#endif
526 521
527#ifdef CONFIG_BF54x 522#ifdef CONFIG_BF54x
528 set_dma_x_count(CH_NFC, (page_size >> 2)); 523 set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
529 set_dma_x_modify(CH_NFC, 4); 524 set_dma_x_modify(CH_NFC, 4);
530 val = DI_EN | WDSIZE_32; 525 val = DI_EN | WDSIZE_32;
531#endif 526#endif
@@ -547,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
547 uint8_t *buf, int len) 542 uint8_t *buf, int len)
548{ 543{
549 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 544 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
550 struct bf5xx_nand_platform *plat = info->platform; 545 struct nand_chip *chip = mtd->priv;
551 unsigned short page_size = (plat->page_size ? 512 : 256);
552 546
553 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);
554 548
555 if (len == page_size) 549 if (len == chip->ecc.size)
556 bf5xx_nand_dma_rw(mtd, buf, 1); 550 bf5xx_nand_dma_rw(mtd, buf, 1);
557 else 551 else
558 bf5xx_nand_read_buf(mtd, buf, len); 552 bf5xx_nand_read_buf(mtd, buf, len);
@@ -562,12 +556,11 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
562 const uint8_t *buf, int len) 556 const uint8_t *buf, int len)
563{ 557{
564 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); 558 struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
565 struct bf5xx_nand_platform *plat = info->platform; 559 struct nand_chip *chip = mtd->priv;
566 unsigned short page_size = (plat->page_size ? 512 : 256);
567 560
568 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);
569 562
570 if (len == page_size) 563 if (len == chip->ecc.size)
571 bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); 564 bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
572 else 565 else
573 bf5xx_nand_write_buf(mtd, buf, len); 566 bf5xx_nand_write_buf(mtd, buf, len);
@@ -642,12 +635,11 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
642 635
643 /* setup NFC_CTL register */ 636 /* setup NFC_CTL register */
644 dev_info(info->device, 637 dev_info(info->device,
645 "page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n", 638 "data_width=%d, wr_dly=%d, rd_dly=%d\n",
646 (plat->page_size ? 512 : 256),
647 (plat->data_width ? 16 : 8), 639 (plat->data_width ? 16 : 8),
648 plat->wr_dly, plat->rd_dly); 640 plat->wr_dly, plat->rd_dly);
649 641
650 val = (plat->page_size << NFC_PG_SIZE_OFFSET) | 642 val = (1 << NFC_PG_SIZE_OFFSET) |
651 (plat->data_width << NFC_NWIDTH_OFFSET) | 643 (plat->data_width << NFC_NWIDTH_OFFSET) |
652 (plat->rd_dly << NFC_RDDLY_OFFSET) | 644 (plat->rd_dly << NFC_RDDLY_OFFSET) |
653 (plat->wr_dly << NFC_WRDLY_OFFSET); 645 (plat->wr_dly << NFC_WRDLY_OFFSET);
@@ -713,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
713 return 0; 705 return 0;
714} 706}
715 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
716/* 735/*
717 * bf5xx_nand_probe 736 * bf5xx_nand_probe
718 * 737 *
@@ -798,15 +817,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
798 chip->badblock_pattern = &bootrom_bbt; 817 chip->badblock_pattern = &bootrom_bbt;
799 chip->ecc.layout = &bootrom_ecclayout; 818 chip->ecc.layout = &bootrom_ecclayout;
800#endif 819#endif
801
802 if (plat->page_size == NFC_PG_SIZE_256) {
803 chip->ecc.bytes = 3;
804 chip->ecc.size = 256;
805 } else if (plat->page_size == NFC_PG_SIZE_512) {
806 chip->ecc.bytes = 6;
807 chip->ecc.size = 512;
808 }
809
810 chip->read_buf = bf5xx_nand_dma_read_buf; 820 chip->read_buf = bf5xx_nand_dma_read_buf;
811 chip->write_buf = bf5xx_nand_dma_write_buf; 821 chip->write_buf = bf5xx_nand_dma_write_buf;
812 chip->ecc.calculate = bf5xx_nand_calculate_ecc; 822 chip->ecc.calculate = bf5xx_nand_calculate_ecc;
@@ -820,7 +830,7 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
820 } 830 }
821 831
822 /* scan hardware nand chip and setup mtd info data struct */ 832 /* scan hardware nand chip and setup mtd info data struct */
823 if (nand_scan(mtd, 1)) { 833 if (bf5xx_nand_scan(mtd)) {
824 err = -ENXIO; 834 err = -ENXIO;
825 goto out_err_nand_scan; 835 goto out_err_nand_scan;
826 } 836 }