aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/atmel_nand.c136
1 files changed, 98 insertions, 38 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 35b4fb55dbd6..ae7e37d9ac17 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -27,6 +27,10 @@
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/moduleparam.h> 28#include <linux/moduleparam.h>
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/of.h>
31#include <linux/of_device.h>
32#include <linux/of_gpio.h>
33#include <linux/of_mtd.h>
30#include <linux/mtd/mtd.h> 34#include <linux/mtd/mtd.h>
31#include <linux/mtd/nand.h> 35#include <linux/mtd/nand.h>
32#include <linux/mtd/partitions.h> 36#include <linux/mtd/partitions.h>
@@ -34,22 +38,10 @@
34#include <linux/dmaengine.h> 38#include <linux/dmaengine.h>
35#include <linux/gpio.h> 39#include <linux/gpio.h>
36#include <linux/io.h> 40#include <linux/io.h>
41#include <linux/platform_data/atmel.h>
37 42
38#include <mach/board.h>
39#include <mach/cpu.h> 43#include <mach/cpu.h>
40 44
41#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
42#define hard_ecc 1
43#else
44#define hard_ecc 0
45#endif
46
47#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
48#define no_ecc 1
49#else
50#define no_ecc 0
51#endif
52
53static int use_dma = 1; 45static int use_dma = 1;
54module_param(use_dma, int, 0); 46module_param(use_dma, int, 0);
55 47
@@ -95,7 +87,7 @@ struct atmel_nand_host {
95 struct mtd_info mtd; 87 struct mtd_info mtd;
96 void __iomem *io_base; 88 void __iomem *io_base;
97 dma_addr_t io_phys; 89 dma_addr_t io_phys;
98 struct atmel_nand_data *board; 90 struct atmel_nand_data board;
99 struct device *dev; 91 struct device *dev;
100 void __iomem *ecc; 92 void __iomem *ecc;
101 93
@@ -113,8 +105,8 @@ static int cpu_has_dma(void)
113 */ 105 */
114static void atmel_nand_enable(struct atmel_nand_host *host) 106static void atmel_nand_enable(struct atmel_nand_host *host)
115{ 107{
116 if (gpio_is_valid(host->board->enable_pin)) 108 if (gpio_is_valid(host->board.enable_pin))
117 gpio_set_value(host->board->enable_pin, 0); 109 gpio_set_value(host->board.enable_pin, 0);
118} 110}
119 111
120/* 112/*
@@ -122,8 +114,8 @@ static void atmel_nand_enable(struct atmel_nand_host *host)
122 */ 114 */
123static void atmel_nand_disable(struct atmel_nand_host *host) 115static void atmel_nand_disable(struct atmel_nand_host *host)
124{ 116{
125 if (gpio_is_valid(host->board->enable_pin)) 117 if (gpio_is_valid(host->board.enable_pin))
126 gpio_set_value(host->board->enable_pin, 1); 118 gpio_set_value(host->board.enable_pin, 1);
127} 119}
128 120
129/* 121/*
@@ -144,9 +136,9 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
144 return; 136 return;
145 137
146 if (ctrl & NAND_CLE) 138 if (ctrl & NAND_CLE)
147 writeb(cmd, host->io_base + (1 << host->board->cle)); 139 writeb(cmd, host->io_base + (1 << host->board.cle));
148 else 140 else
149 writeb(cmd, host->io_base + (1 << host->board->ale)); 141 writeb(cmd, host->io_base + (1 << host->board.ale));
150} 142}
151 143
152/* 144/*
@@ -157,8 +149,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
157 struct nand_chip *nand_chip = mtd->priv; 149 struct nand_chip *nand_chip = mtd->priv;
158 struct atmel_nand_host *host = nand_chip->priv; 150 struct atmel_nand_host *host = nand_chip->priv;
159 151
160 return gpio_get_value(host->board->rdy_pin) ^ 152 return gpio_get_value(host->board.rdy_pin) ^
161 !!host->board->rdy_pin_active_low; 153 !!host->board.rdy_pin_active_low;
162} 154}
163 155
164/* 156/*
@@ -273,7 +265,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
273 if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) 265 if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
274 return; 266 return;
275 267
276 if (host->board->bus_width_16) 268 if (host->board.bus_width_16)
277 atmel_read_buf16(mtd, buf, len); 269 atmel_read_buf16(mtd, buf, len);
278 else 270 else
279 atmel_read_buf8(mtd, buf, len); 271 atmel_read_buf8(mtd, buf, len);
@@ -289,7 +281,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
289 if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) 281 if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
290 return; 282 return;
291 283
292 if (host->board->bus_width_16) 284 if (host->board.bus_width_16)
293 atmel_write_buf16(mtd, buf, len); 285 atmel_write_buf16(mtd, buf, len);
294 else 286 else
295 atmel_write_buf8(mtd, buf, len); 287 atmel_write_buf8(mtd, buf, len);
@@ -481,6 +473,56 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
481 } 473 }
482} 474}
483 475
476#if defined(CONFIG_OF)
477static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
478 struct device_node *np)
479{
480 u32 val;
481 int ecc_mode;
482 struct atmel_nand_data *board = &host->board;
483 enum of_gpio_flags flags;
484
485 if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
486 if (val >= 32) {
487 dev_err(host->dev, "invalid addr-offset %u\n", val);
488 return -EINVAL;
489 }
490 board->ale = val;
491 }
492
493 if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) {
494 if (val >= 32) {
495 dev_err(host->dev, "invalid cmd-offset %u\n", val);
496 return -EINVAL;
497 }
498 board->cle = val;
499 }
500
501 ecc_mode = of_get_nand_ecc_mode(np);
502
503 board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode;
504
505 board->on_flash_bbt = of_get_nand_on_flash_bbt(np);
506
507 if (of_get_nand_bus_width(np) == 16)
508 board->bus_width_16 = 1;
509
510 board->rdy_pin = of_get_gpio_flags(np, 0, &flags);
511 board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW);
512
513 board->enable_pin = of_get_gpio(np, 1);
514 board->det_pin = of_get_gpio(np, 2);
515
516 return 0;
517}
518#else
519static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
520 struct device_node *np)
521{
522 return -EINVAL;
523}
524#endif
525
484/* 526/*
485 * Probe for the NAND device. 527 * Probe for the NAND device.
486 */ 528 */
@@ -491,6 +533,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
491 struct nand_chip *nand_chip; 533 struct nand_chip *nand_chip;
492 struct resource *regs; 534 struct resource *regs;
493 struct resource *mem; 535 struct resource *mem;
536 struct mtd_part_parser_data ppdata = {};
494 int res; 537 int res;
495 538
496 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 539 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -517,8 +560,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
517 560
518 mtd = &host->mtd; 561 mtd = &host->mtd;
519 nand_chip = &host->nand_chip; 562 nand_chip = &host->nand_chip;
520 host->board = pdev->dev.platform_data;
521 host->dev = &pdev->dev; 563 host->dev = &pdev->dev;
564 if (pdev->dev.of_node) {
565 res = atmel_of_init_port(host, pdev->dev.of_node);
566 if (res)
567 goto err_nand_ioremap;
568 } else {
569 memcpy(&host->board, pdev->dev.platform_data,
570 sizeof(struct atmel_nand_data));
571 }
522 572
523 nand_chip->priv = host; /* link the private data structures */ 573 nand_chip->priv = host; /* link the private data structures */
524 mtd->priv = nand_chip; 574 mtd->priv = nand_chip;
@@ -529,26 +579,25 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
529 nand_chip->IO_ADDR_W = host->io_base; 579 nand_chip->IO_ADDR_W = host->io_base;
530 nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; 580 nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
531 581
532 if (gpio_is_valid(host->board->rdy_pin)) 582 if (gpio_is_valid(host->board.rdy_pin))
533 nand_chip->dev_ready = atmel_nand_device_ready; 583 nand_chip->dev_ready = atmel_nand_device_ready;
534 584
585 nand_chip->ecc.mode = host->board.ecc_mode;
586
535 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); 587 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
536 if (!regs && hard_ecc) { 588 if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
537 printk(KERN_ERR "atmel_nand: can't get I/O resource " 589 printk(KERN_ERR "atmel_nand: can't get I/O resource "
538 "regs\nFalling back on software ECC\n"); 590 "regs\nFalling back on software ECC\n");
591 nand_chip->ecc.mode = NAND_ECC_SOFT;
539 } 592 }
540 593
541 nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ 594 if (nand_chip->ecc.mode == NAND_ECC_HW) {
542 if (no_ecc)
543 nand_chip->ecc.mode = NAND_ECC_NONE;
544 if (hard_ecc && regs) {
545 host->ecc = ioremap(regs->start, resource_size(regs)); 595 host->ecc = ioremap(regs->start, resource_size(regs));
546 if (host->ecc == NULL) { 596 if (host->ecc == NULL) {
547 printk(KERN_ERR "atmel_nand: ioremap failed\n"); 597 printk(KERN_ERR "atmel_nand: ioremap failed\n");
548 res = -EIO; 598 res = -EIO;
549 goto err_ecc_ioremap; 599 goto err_ecc_ioremap;
550 } 600 }
551 nand_chip->ecc.mode = NAND_ECC_HW;
552 nand_chip->ecc.calculate = atmel_nand_calculate; 601 nand_chip->ecc.calculate = atmel_nand_calculate;
553 nand_chip->ecc.correct = atmel_nand_correct; 602 nand_chip->ecc.correct = atmel_nand_correct;
554 nand_chip->ecc.hwctl = atmel_nand_hwctl; 603 nand_chip->ecc.hwctl = atmel_nand_hwctl;
@@ -558,7 +607,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
558 607
559 nand_chip->chip_delay = 20; /* 20us command delay time */ 608 nand_chip->chip_delay = 20; /* 20us command delay time */
560 609
561 if (host->board->bus_width_16) /* 16-bit bus width */ 610 if (host->board.bus_width_16) /* 16-bit bus width */
562 nand_chip->options |= NAND_BUSWIDTH_16; 611 nand_chip->options |= NAND_BUSWIDTH_16;
563 612
564 nand_chip->read_buf = atmel_read_buf; 613 nand_chip->read_buf = atmel_read_buf;
@@ -567,15 +616,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
567 platform_set_drvdata(pdev, host); 616 platform_set_drvdata(pdev, host);
568 atmel_nand_enable(host); 617 atmel_nand_enable(host);
569 618
570 if (gpio_is_valid(host->board->det_pin)) { 619 if (gpio_is_valid(host->board.det_pin)) {
571 if (gpio_get_value(host->board->det_pin)) { 620 if (gpio_get_value(host->board.det_pin)) {
572 printk(KERN_INFO "No SmartMedia card inserted.\n"); 621 printk(KERN_INFO "No SmartMedia card inserted.\n");
573 res = -ENXIO; 622 res = -ENXIO;
574 goto err_no_card; 623 goto err_no_card;
575 } 624 }
576 } 625 }
577 626
578 if (on_flash_bbt) { 627 if (host->board.on_flash_bbt || on_flash_bbt) {
579 printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); 628 printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
580 nand_chip->bbt_options |= NAND_BBT_USE_FLASH; 629 nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
581 } 630 }
@@ -650,8 +699,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
650 } 699 }
651 700
652 mtd->name = "atmel_nand"; 701 mtd->name = "atmel_nand";
653 res = mtd_device_parse_register(mtd, NULL, 0, 702 ppdata.of_node = pdev->dev.of_node;
654 host->board->parts, host->board->num_parts); 703 res = mtd_device_parse_register(mtd, NULL, &ppdata,
704 host->board.parts, host->board.num_parts);
655 if (!res) 705 if (!res)
656 return res; 706 return res;
657 707
@@ -695,11 +745,21 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
695 return 0; 745 return 0;
696} 746}
697 747
748#if defined(CONFIG_OF)
749static const struct of_device_id atmel_nand_dt_ids[] = {
750 { .compatible = "atmel,at91rm9200-nand" },
751 { /* sentinel */ }
752};
753
754MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
755#endif
756
698static struct platform_driver atmel_nand_driver = { 757static struct platform_driver atmel_nand_driver = {
699 .remove = __exit_p(atmel_nand_remove), 758 .remove = __exit_p(atmel_nand_remove),
700 .driver = { 759 .driver = {
701 .name = "atmel_nand", 760 .name = "atmel_nand",
702 .owner = THIS_MODULE, 761 .owner = THIS_MODULE,
762 .of_match_table = of_match_ptr(atmel_nand_dt_ids),
703 }, 763 },
704}; 764};
705 765