aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDinh Nguyen <dinguyen@altera.com>2012-09-27 12:58:06 -0400
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-11-15 08:37:46 -0500
commit30f9f2fb7ba032665c8cea7694c815f18ed47a34 (patch)
treec6c8d570b67f4544b39ed4b4725d899cd1b970f1
parent2a0a288ec258bd38d8855fad9419aeb45b7e8499 (diff)
mtd: denali: add a DT driver
Add a device tree version of the Denali NAND driver. Based on an original patch from Jamie Iles to add a MMIO version of this driver. Signed-off-by: Dinh Nguyen <dinguyen@altera.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
-rw-r--r--Documentation/devicetree/bindings/mtd/denali-nand.txt23
-rw-r--r--drivers/mtd/nand/Kconfig9
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/denali.h1
-rw-r--r--drivers/mtd/nand/denali_dt.c167
5 files changed, 200 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/mtd/denali-nand.txt b/Documentation/devicetree/bindings/mtd/denali-nand.txt
new file mode 100644
index 000000000000..b04d03a1d499
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/denali-nand.txt
@@ -0,0 +1,23 @@
1* Denali NAND controller
2
3Required properties:
4 - compatible : should be "denali,denali-nand-dt"
5 - reg : should contain registers location and length for data and reg.
6 - reg-names: Should contain the reg names "nand_data" and "denali_reg"
7 - interrupts : The interrupt number.
8 - dm-mask : DMA bit mask
9
10The device tree may optionally contain sub-nodes describing partitions of the
11address space. See partition.txt for more detail.
12
13Examples:
14
15nand: nand@ff900000 {
16 #address-cells = <1>;
17 #size-cells = <1>;
18 compatible = "denali,denali-nand-dt";
19 reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
20 reg-names = "nand_data", "denali_reg";
21 interrupts = <0 144 4>;
22 dma-mask = <0xffffffff>;
23};
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5102e87f8df0..ee803d611e4e 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -69,7 +69,14 @@ config MTD_NAND_DENALI_PCI
69 help 69 help
70 Enable the driver for NAND flash on Intel Moorestown, using the 70 Enable the driver for NAND flash on Intel Moorestown, using the
71 Denali NAND controller core. 71 Denali NAND controller core.
72 72
73config MTD_NAND_DENALI_DT
74 tristate "Support Denali NAND controller as a DT device"
75 depends on HAVE_CLK && MTD_NAND_DENALI
76 help
77 Enable the driver for NAND flash on platforms using a Denali NAND
78 controller as a DT device.
79
73config MTD_NAND_DENALI_SCRATCH_REG_ADDR 80config MTD_NAND_DENALI_SCRATCH_REG_ADDR
74 hex "Denali NAND size scratch register address" 81 hex "Denali NAND size scratch register address"
75 default "0xFF108018" 82 default "0xFF108018"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 96a6171c9d8f..38358c90771e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
14obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o 14obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
15obj-$(CONFIG_MTD_NAND_DENALI) += denali.o 15obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
16obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o 16obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o
17obj-$(CONFIG_MTD_NAND_DENALI_DT) += denali_dt.o
17obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o 18obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
18obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o 19obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
19obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o 20obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index e5aa99583e43..cec5712862c9 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -466,6 +466,7 @@ struct nand_buf {
466 466
467#define INTEL_CE4100 1 467#define INTEL_CE4100 1
468#define INTEL_MRST 2 468#define INTEL_MRST 2
469#define DT 3
469 470
470struct denali_nand_info { 471struct denali_nand_info {
471 struct mtd_info mtd; 472 struct mtd_info mtd;
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
new file mode 100644
index 000000000000..fbabbaa04374
--- /dev/null
+++ b/drivers/mtd/nand/denali_dt.c
@@ -0,0 +1,167 @@
1/*
2 * NAND Flash Controller Device Driver for DT
3 *
4 * Copyright © 2011, Picochip.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15#include <linux/clk.h>
16#include <linux/err.h>
17#include <linux/io.h>
18#include <linux/ioport.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/slab.h>
25
26#include "denali.h"
27
28struct denali_dt {
29 struct denali_nand_info denali;
30 struct clk *clk;
31};
32
33static void __iomem *request_and_map(struct device *dev,
34 const struct resource *res)
35{
36 void __iomem *ptr;
37
38 if (!devm_request_mem_region(dev, res->start, resource_size(res),
39 "denali-dt")) {
40 dev_err(dev, "unable to request %s\n", res->name);
41 return NULL;
42 }
43
44 ptr = devm_ioremap_nocache(dev, res->start, resource_size(res));
45 if (!res)
46 dev_err(dev, "ioremap_nocache of %s failed!", res->name);
47
48 return ptr;
49}
50
51static const struct of_device_id denali_nand_dt_ids[] = {
52 { .compatible = "denali,denali-nand-dt" },
53 { /* sentinel */ }
54 };
55
56MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
57
58static u64 denali_dma_mask;
59
60static int __devinit denali_dt_probe(struct platform_device *ofdev)
61{
62 struct resource *denali_reg, *nand_data;
63 struct denali_dt *dt;
64 struct denali_nand_info *denali;
65 int ret;
66 const struct of_device_id *of_id;
67
68 of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev);
69 if (of_id) {
70 ofdev->id_entry = of_id->data;
71 } else {
72 pr_err("Failed to find the right device id.\n");
73 return -ENOMEM;
74 }
75
76 dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL);
77 if (!dt)
78 return -ENOMEM;
79 denali = &dt->denali;
80
81 denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg");
82 nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data");
83 if (!denali_reg || !nand_data) {
84 dev_err(&ofdev->dev, "resources not completely defined\n");
85 return -EINVAL;
86 }
87
88 denali->platform = DT;
89 denali->dev = &ofdev->dev;
90 denali->irq = platform_get_irq(ofdev, 0);
91 if (denali->irq < 0) {
92 dev_err(&ofdev->dev, "no irq defined\n");
93 return -ENXIO;
94 }
95
96 denali->flash_reg = request_and_map(&ofdev->dev, denali_reg);
97 if (!denali->flash_reg)
98 return -ENOMEM;
99
100 denali->flash_mem = request_and_map(&ofdev->dev, nand_data);
101 if (!denali->flash_mem)
102 return -ENOMEM;
103
104 if (!of_property_read_u32(ofdev->dev.of_node,
105 "dma-mask", (u32 *)&denali_dma_mask)) {
106 denali->dev->dma_mask = &denali_dma_mask;
107 } else {
108 denali->dev->dma_mask = NULL;
109 }
110
111 dt->clk = clk_get(&ofdev->dev, NULL);
112 if (IS_ERR(dt->clk)) {
113 dev_err(&ofdev->dev, "no clk available\n");
114 return PTR_ERR(dt->clk);
115 }
116 clk_prepare_enable(dt->clk);
117
118 ret = denali_init(denali);
119 if (ret)
120 goto out_disable_clk;
121
122 platform_set_drvdata(ofdev, dt);
123 return 0;
124
125out_disable_clk:
126 clk_disable_unprepare(dt->clk);
127 clk_put(dt->clk);
128
129 return ret;
130}
131
132static int __devexit denali_dt_remove(struct platform_device *ofdev)
133{
134 struct denali_dt *dt = platform_get_drvdata(ofdev);
135
136 denali_remove(&dt->denali);
137 clk_disable(dt->clk);
138 clk_put(dt->clk);
139
140 return 0;
141}
142
143static struct platform_driver denali_dt_driver = {
144 .probe = denali_dt_probe,
145 .remove = __devexit_p(denali_dt_remove),
146 .driver = {
147 .name = "denali-nand-dt",
148 .owner = THIS_MODULE,
149 .of_match_table = of_match_ptr(denali_nand_dt_ids),
150 },
151};
152
153static int __init denali_init_dt(void)
154{
155 return platform_driver_register(&denali_dt_driver);
156}
157module_init(denali_init_dt);
158
159static void __exit denali_exit_dt(void)
160{
161 platform_driver_unregister(&denali_dt_driver);
162}
163module_exit(denali_exit_dt);
164
165MODULE_LICENSE("GPL");
166MODULE_AUTHOR("Jamie Iles");
167MODULE_DESCRIPTION("DT driver for Denali NAND controller");