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.c93
1 files changed, 71 insertions, 22 deletions
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index e87a57297328..9af2a2cc1153 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -91,6 +91,41 @@ static const unsigned short bfin_nfc_pin_req[] =
91 P_NAND_ALE, 91 P_NAND_ALE,
92 0}; 92 0};
93 93
94#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
95static uint8_t bbt_pattern[] = { 0xff };
96
97static struct nand_bbt_descr bootrom_bbt = {
98 .options = 0,
99 .offs = 63,
100 .len = 1,
101 .pattern = bbt_pattern,
102};
103
104static struct nand_ecclayout bootrom_ecclayout = {
105 .eccbytes = 24,
106 .eccpos = {
107 0x8 * 0, 0x8 * 0 + 1, 0x8 * 0 + 2,
108 0x8 * 1, 0x8 * 1 + 1, 0x8 * 1 + 2,
109 0x8 * 2, 0x8 * 2 + 1, 0x8 * 2 + 2,
110 0x8 * 3, 0x8 * 3 + 1, 0x8 * 3 + 2,
111 0x8 * 4, 0x8 * 4 + 1, 0x8 * 4 + 2,
112 0x8 * 5, 0x8 * 5 + 1, 0x8 * 5 + 2,
113 0x8 * 6, 0x8 * 6 + 1, 0x8 * 6 + 2,
114 0x8 * 7, 0x8 * 7 + 1, 0x8 * 7 + 2
115 },
116 .oobfree = {
117 { 0x8 * 0 + 3, 5 },
118 { 0x8 * 1 + 3, 5 },
119 { 0x8 * 2 + 3, 5 },
120 { 0x8 * 3 + 3, 5 },
121 { 0x8 * 4 + 3, 5 },
122 { 0x8 * 5 + 3, 5 },
123 { 0x8 * 6 + 3, 5 },
124 { 0x8 * 7 + 3, 5 },
125 }
126};
127#endif
128
94/* 129/*
95 * Data structures for bf5xx nand flash controller driver 130 * Data structures for bf5xx nand flash controller driver
96 */ 131 */
@@ -273,7 +308,7 @@ static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
273 dat += 256; 308 dat += 256;
274 read_ecc += 8; 309 read_ecc += 8;
275 calc_ecc += 8; 310 calc_ecc += 8;
276 ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); 311 ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
277 } 312 }
278 313
279 return ret; 314 return ret;
@@ -298,7 +333,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
298 ecc0 = bfin_read_NFC_ECC0(); 333 ecc0 = bfin_read_NFC_ECC0();
299 ecc1 = bfin_read_NFC_ECC1(); 334 ecc1 = bfin_read_NFC_ECC1();
300 335
301 code[0] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11); 336 code[0] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
302 337
303 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); 338 dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
304 339
@@ -310,7 +345,7 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
310 if (page_size == 512) { 345 if (page_size == 512) {
311 ecc0 = bfin_read_NFC_ECC2(); 346 ecc0 = bfin_read_NFC_ECC2();
312 ecc1 = bfin_read_NFC_ECC3(); 347 ecc1 = bfin_read_NFC_ECC3();
313 code[1] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11); 348 code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
314 349
315 /* second 3 bytes in ecc_code for second 256 350 /* second 3 bytes in ecc_code for second 256
316 * bytes of 512 page size 351 * bytes of 512 page size
@@ -514,7 +549,6 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
514/* 549/*
515 * System initialization functions 550 * System initialization functions
516 */ 551 */
517
518static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info) 552static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
519{ 553{
520 int ret; 554 int ret;
@@ -547,6 +581,13 @@ static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
547 return 0; 581 return 0;
548} 582}
549 583
584static void bf5xx_nand_dma_remove(struct bf5xx_nand_info *info)
585{
586 /* Free NFC DMA channel */
587 if (hardware_ecc)
588 free_dma(CH_NFC);
589}
590
550/* 591/*
551 * BF5XX NFC hardware initialization 592 * BF5XX NFC hardware initialization
552 * - pin mux setup 593 * - pin mux setup
@@ -605,7 +646,7 @@ static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
605#endif 646#endif
606} 647}
607 648
608static int bf5xx_nand_remove(struct platform_device *pdev) 649static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
609{ 650{
610 struct bf5xx_nand_info *info = to_nand_info(pdev); 651 struct bf5xx_nand_info *info = to_nand_info(pdev);
611 struct mtd_info *mtd = NULL; 652 struct mtd_info *mtd = NULL;
@@ -623,6 +664,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
623 } 664 }
624 665
625 peripheral_free_list(bfin_nfc_pin_req); 666 peripheral_free_list(bfin_nfc_pin_req);
667 bf5xx_nand_dma_remove(info);
626 668
627 /* free the common resources */ 669 /* free the common resources */
628 kfree(info); 670 kfree(info);
@@ -638,7 +680,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
638 * it can allocate all necessary resources then calls the 680 * it can allocate all necessary resources then calls the
639 * nand layer to look for devices 681 * nand layer to look for devices
640 */ 682 */
641static int bf5xx_nand_probe(struct platform_device *pdev) 683static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
642{ 684{
643 struct bf5xx_nand_platform *plat = to_nand_plat(pdev); 685 struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
644 struct bf5xx_nand_info *info = NULL; 686 struct bf5xx_nand_info *info = NULL;
@@ -648,22 +690,21 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
648 690
649 dev_dbg(&pdev->dev, "(%p)\n", pdev); 691 dev_dbg(&pdev->dev, "(%p)\n", pdev);
650 692
651 if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
652 printk(KERN_ERR DRV_NAME
653 ": Requesting Peripherals failed\n");
654 return -EFAULT;
655 }
656
657 if (!plat) { 693 if (!plat) {
658 dev_err(&pdev->dev, "no platform specific information\n"); 694 dev_err(&pdev->dev, "no platform specific information\n");
659 goto exit_error; 695 return -EINVAL;
696 }
697
698 if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
699 dev_err(&pdev->dev, "requesting Peripherals failed\n");
700 return -EFAULT;
660 } 701 }
661 702
662 info = kzalloc(sizeof(*info), GFP_KERNEL); 703 info = kzalloc(sizeof(*info), GFP_KERNEL);
663 if (info == NULL) { 704 if (info == NULL) {
664 dev_err(&pdev->dev, "no memory for flash info\n"); 705 dev_err(&pdev->dev, "no memory for flash info\n");
665 err = -ENOMEM; 706 err = -ENOMEM;
666 goto exit_error; 707 goto out_err_kzalloc;
667 } 708 }
668 709
669 platform_set_drvdata(pdev, info); 710 platform_set_drvdata(pdev, info);
@@ -707,11 +748,16 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
707 748
708 /* initialise the hardware */ 749 /* initialise the hardware */
709 err = bf5xx_nand_hw_init(info); 750 err = bf5xx_nand_hw_init(info);
710 if (err != 0) 751 if (err)
711 goto exit_error; 752 goto out_err_hw_init;
712 753
713 /* setup hardware ECC data struct */ 754 /* setup hardware ECC data struct */
714 if (hardware_ecc) { 755 if (hardware_ecc) {
756#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
757 chip->badblock_pattern = &bootrom_bbt;
758 chip->ecc.layout = &bootrom_ecclayout;
759#endif
760
715 if (plat->page_size == NFC_PG_SIZE_256) { 761 if (plat->page_size == NFC_PG_SIZE_256) {
716 chip->ecc.bytes = 3; 762 chip->ecc.bytes = 3;
717 chip->ecc.size = 256; 763 chip->ecc.size = 256;
@@ -733,7 +779,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
733 /* scan hardware nand chip and setup mtd info data struct */ 779 /* scan hardware nand chip and setup mtd info data struct */
734 if (nand_scan(mtd, 1)) { 780 if (nand_scan(mtd, 1)) {
735 err = -ENXIO; 781 err = -ENXIO;
736 goto exit_error; 782 goto out_err_nand_scan;
737 } 783 }
738 784
739 /* add NAND partition */ 785 /* add NAND partition */
@@ -742,11 +788,14 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
742 dev_dbg(&pdev->dev, "initialised ok\n"); 788 dev_dbg(&pdev->dev, "initialised ok\n");
743 return 0; 789 return 0;
744 790
745exit_error: 791out_err_nand_scan:
746 bf5xx_nand_remove(pdev); 792 bf5xx_nand_dma_remove(info);
793out_err_hw_init:
794 platform_set_drvdata(pdev, NULL);
795 kfree(info);
796out_err_kzalloc:
797 peripheral_free_list(bfin_nfc_pin_req);
747 798
748 if (err == 0)
749 err = -EINVAL;
750 return err; 799 return err;
751} 800}
752 801
@@ -775,7 +824,7 @@ static int bf5xx_nand_resume(struct platform_device *dev)
775/* driver device registration */ 824/* driver device registration */
776static struct platform_driver bf5xx_nand_driver = { 825static struct platform_driver bf5xx_nand_driver = {
777 .probe = bf5xx_nand_probe, 826 .probe = bf5xx_nand_probe,
778 .remove = bf5xx_nand_remove, 827 .remove = __devexit_p(bf5xx_nand_remove),
779 .suspend = bf5xx_nand_suspend, 828 .suspend = bf5xx_nand_suspend,
780 .resume = bf5xx_nand_resume, 829 .resume = bf5xx_nand_resume,
781 .driver = { 830 .driver = {