diff options
author | Dinh Nguyen <dinguyen@altera.com> | 2012-09-27 12:58:06 -0400 |
---|---|---|
committer | Artem Bityutskiy <artem.bityutskiy@linux.intel.com> | 2012-11-15 08:37:46 -0500 |
commit | 30f9f2fb7ba032665c8cea7694c815f18ed47a34 (patch) | |
tree | c6c8d570b67f4544b39ed4b4725d899cd1b970f1 | |
parent | 2a0a288ec258bd38d8855fad9419aeb45b7e8499 (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.txt | 23 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/denali.h | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/denali_dt.c | 167 |
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 | |||
3 | Required 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 | |||
10 | The device tree may optionally contain sub-nodes describing partitions of the | ||
11 | address space. See partition.txt for more detail. | ||
12 | |||
13 | Examples: | ||
14 | |||
15 | nand: 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 | ||
73 | config 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 | |||
73 | config MTD_NAND_DENALI_SCRATCH_REG_ADDR | 80 | config 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 | |||
14 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o | 14 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o |
15 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o | 15 | obj-$(CONFIG_MTD_NAND_DENALI) += denali.o |
16 | obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o | 16 | obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o |
17 | obj-$(CONFIG_MTD_NAND_DENALI_DT) += denali_dt.o | ||
17 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o | 18 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o |
18 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o | 19 | obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o |
19 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | 20 | obj-$(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 | ||
470 | struct denali_nand_info { | 471 | struct 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 | |||
28 | struct denali_dt { | ||
29 | struct denali_nand_info denali; | ||
30 | struct clk *clk; | ||
31 | }; | ||
32 | |||
33 | static 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 | |||
51 | static const struct of_device_id denali_nand_dt_ids[] = { | ||
52 | { .compatible = "denali,denali-nand-dt" }, | ||
53 | { /* sentinel */ } | ||
54 | }; | ||
55 | |||
56 | MODULE_DEVICE_TABLE(of, denali_nand_dt_ids); | ||
57 | |||
58 | static u64 denali_dma_mask; | ||
59 | |||
60 | static 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 | |||
125 | out_disable_clk: | ||
126 | clk_disable_unprepare(dt->clk); | ||
127 | clk_put(dt->clk); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | static 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 | |||
143 | static 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 | |||
153 | static int __init denali_init_dt(void) | ||
154 | { | ||
155 | return platform_driver_register(&denali_dt_driver); | ||
156 | } | ||
157 | module_init(denali_init_dt); | ||
158 | |||
159 | static void __exit denali_exit_dt(void) | ||
160 | { | ||
161 | platform_driver_unregister(&denali_dt_driver); | ||
162 | } | ||
163 | module_exit(denali_exit_dt); | ||
164 | |||
165 | MODULE_LICENSE("GPL"); | ||
166 | MODULE_AUTHOR("Jamie Iles"); | ||
167 | MODULE_DESCRIPTION("DT driver for Denali NAND controller"); | ||