diff options
author | Jamie Lentin <jm@lentin.co.uk> | 2012-04-18 06:06:41 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2012-05-14 22:29:11 -0400 |
commit | a0fabf722c9dc73a3eed24ce166476ddb00eda1e (patch) | |
tree | 1a7aec13bc1eee977cb2e5fbeaa0f9540aab5b84 | |
parent | 9007d1007317658d5b32bda9f59c797c59ce4d47 (diff) |
mtd: Add orion_nand devicetree bindings
Allow a NAND chip using the orion_nand driver to be described using devicetree.
Changes since last submission (V4) [Addressing comments by]:-
* WARN when bank-width is out of range [Andrew Lunn]
Changes since last submission (V3):-
* Document all parameters [Grant Likely]
* Convert bank-width to be in bytes
* Add explicit defaults for cle, ale and bank-width
Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r-- | Documentation/devicetree/bindings/mtd/orion-nand.txt | 50 | ||||
-rw-r--r-- | drivers/mtd/nand/orion_nand.c | 47 |
2 files changed, 94 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/mtd/orion-nand.txt b/Documentation/devicetree/bindings/mtd/orion-nand.txt new file mode 100644 index 000000000000..b2356b7d2fa4 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/orion-nand.txt | |||
@@ -0,0 +1,50 @@ | |||
1 | NAND support for Marvell Orion SoC platforms | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "mrvl,orion-nand". | ||
5 | - reg : Base physical address of the NAND and length of memory mapped | ||
6 | region | ||
7 | |||
8 | Optional properties: | ||
9 | - cle : Address line number connected to CLE. Default is 0 | ||
10 | - ale : Address line number connected to ALE. Default is 1 | ||
11 | - bank-width : Width in bytes of the device. Default is 1 | ||
12 | - chip-delay : Chip dependent delay for transferring data from array to read | ||
13 | registers in usecs | ||
14 | |||
15 | The device tree may optionally contain sub-nodes describing partitions of the | ||
16 | address space. See partition.txt for more detail. | ||
17 | |||
18 | Example: | ||
19 | |||
20 | nand@f4000000 { | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <1>; | ||
23 | cle = <0>; | ||
24 | ale = <1>; | ||
25 | bank-width = <1>; | ||
26 | chip-delay = <25>; | ||
27 | compatible = "mrvl,orion-nand"; | ||
28 | reg = <0xf4000000 0x400>; | ||
29 | |||
30 | partition@0 { | ||
31 | label = "u-boot"; | ||
32 | reg = <0x0000000 0x100000>; | ||
33 | read-only; | ||
34 | }; | ||
35 | |||
36 | partition@100000 { | ||
37 | label = "uImage"; | ||
38 | reg = <0x0100000 0x200000>; | ||
39 | }; | ||
40 | |||
41 | partition@300000 { | ||
42 | label = "dtb"; | ||
43 | reg = <0x0300000 0x100000>; | ||
44 | }; | ||
45 | |||
46 | partition@400000 { | ||
47 | label = "root"; | ||
48 | reg = <0x0400000 0x7d00000>; | ||
49 | }; | ||
50 | }; | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 1d3bfb26080c..0f50ef38b87b 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/of.h> | ||
16 | #include <linux/mtd/mtd.h> | 17 | #include <linux/mtd/mtd.h> |
17 | #include <linux/mtd/nand.h> | 18 | #include <linux/mtd/nand.h> |
18 | #include <linux/mtd/partitions.h> | 19 | #include <linux/mtd/partitions.h> |
@@ -74,11 +75,13 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
74 | static int __init orion_nand_probe(struct platform_device *pdev) | 75 | static int __init orion_nand_probe(struct platform_device *pdev) |
75 | { | 76 | { |
76 | struct mtd_info *mtd; | 77 | struct mtd_info *mtd; |
78 | struct mtd_part_parser_data ppdata = {}; | ||
77 | struct nand_chip *nc; | 79 | struct nand_chip *nc; |
78 | struct orion_nand_data *board; | 80 | struct orion_nand_data *board; |
79 | struct resource *res; | 81 | struct resource *res; |
80 | void __iomem *io_base; | 82 | void __iomem *io_base; |
81 | int ret = 0; | 83 | int ret = 0; |
84 | u32 val = 0; | ||
82 | 85 | ||
83 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); | 86 | nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); |
84 | if (!nc) { | 87 | if (!nc) { |
@@ -101,7 +104,32 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
101 | goto no_res; | 104 | goto no_res; |
102 | } | 105 | } |
103 | 106 | ||
104 | board = pdev->dev.platform_data; | 107 | if (pdev->dev.of_node) { |
108 | board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data), | ||
109 | GFP_KERNEL); | ||
110 | if (!board) { | ||
111 | printk(KERN_ERR "orion_nand: failed to allocate board structure.\n"); | ||
112 | ret = -ENOMEM; | ||
113 | goto no_res; | ||
114 | } | ||
115 | if (!of_property_read_u32(pdev->dev.of_node, "cle", &val)) | ||
116 | board->cle = (u8)val; | ||
117 | else | ||
118 | board->cle = 0; | ||
119 | if (!of_property_read_u32(pdev->dev.of_node, "ale", &val)) | ||
120 | board->ale = (u8)val; | ||
121 | else | ||
122 | board->ale = 1; | ||
123 | if (!of_property_read_u32(pdev->dev.of_node, | ||
124 | "bank-width", &val)) | ||
125 | board->width = (u8)val * 8; | ||
126 | else | ||
127 | board->width = 8; | ||
128 | if (!of_property_read_u32(pdev->dev.of_node, | ||
129 | "chip-delay", &val)) | ||
130 | board->chip_delay = (u8)val; | ||
131 | } else | ||
132 | board = pdev->dev.platform_data; | ||
105 | 133 | ||
106 | mtd->priv = nc; | 134 | mtd->priv = nc; |
107 | mtd->owner = THIS_MODULE; | 135 | mtd->owner = THIS_MODULE; |
@@ -115,6 +143,10 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
115 | if (board->chip_delay) | 143 | if (board->chip_delay) |
116 | nc->chip_delay = board->chip_delay; | 144 | nc->chip_delay = board->chip_delay; |
117 | 145 | ||
146 | WARN(board->width > 16, | ||
147 | "%d bit bus width out of range", | ||
148 | board->width); | ||
149 | |||
118 | if (board->width == 16) | 150 | if (board->width == 16) |
119 | nc->options |= NAND_BUSWIDTH_16; | 151 | nc->options |= NAND_BUSWIDTH_16; |
120 | 152 | ||
@@ -129,8 +161,9 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
129 | } | 161 | } |
130 | 162 | ||
131 | mtd->name = "orion_nand"; | 163 | mtd->name = "orion_nand"; |
132 | ret = mtd_device_parse_register(mtd, NULL, NULL, board->parts, | 164 | ppdata.of_node = pdev->dev.of_node; |
133 | board->nr_parts); | 165 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, |
166 | board->parts, board->nr_parts); | ||
134 | if (ret) { | 167 | if (ret) { |
135 | nand_release(mtd); | 168 | nand_release(mtd); |
136 | goto no_dev; | 169 | goto no_dev; |
@@ -161,11 +194,19 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) | |||
161 | return 0; | 194 | return 0; |
162 | } | 195 | } |
163 | 196 | ||
197 | #ifdef CONFIG_OF | ||
198 | static struct of_device_id orion_nand_of_match_table[] = { | ||
199 | { .compatible = "mrvl,orion-nand", }, | ||
200 | {}, | ||
201 | }; | ||
202 | #endif | ||
203 | |||
164 | static struct platform_driver orion_nand_driver = { | 204 | static struct platform_driver orion_nand_driver = { |
165 | .remove = __devexit_p(orion_nand_remove), | 205 | .remove = __devexit_p(orion_nand_remove), |
166 | .driver = { | 206 | .driver = { |
167 | .name = "orion_nand", | 207 | .name = "orion_nand", |
168 | .owner = THIS_MODULE, | 208 | .owner = THIS_MODULE, |
209 | .of_match_table = of_match_ptr(orion_nand_of_match_table), | ||
169 | }, | 210 | }, |
170 | }; | 211 | }; |
171 | 212 | ||