diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/maps/physmap_of.c | 89 | ||||
-rw-r--r-- | drivers/mtd/ofpart.c | 74 |
4 files changed, 110 insertions, 62 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 661eac09f5cb..e8503341e3b1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
@@ -150,6 +150,14 @@ config MTD_AFS_PARTS | |||
150 | for your particular device. It won't happen automatically. The | 150 | for your particular device. It won't happen automatically. The |
151 | 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. | 151 | 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. |
152 | 152 | ||
153 | config MTD_OF_PARTS | ||
154 | tristate "Flash partition map based on OF description" | ||
155 | depends on PPC_OF && MTD_PARTITIONS | ||
156 | help | ||
157 | This provides a partition parsing function which derives | ||
158 | the partition map from the children of the flash node, | ||
159 | as described in Documentation/powerpc/booting-without-of.txt. | ||
160 | |||
153 | comment "User Modules And Translation Layers" | 161 | comment "User Modules And Translation Layers" |
154 | 162 | ||
155 | config MTD_CHAR | 163 | config MTD_CHAR |
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 7f0b04b4caa7..538e33d11d46 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o | |||
11 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o | 11 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o |
12 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o | 12 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o |
13 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o | 13 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o |
14 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o | ||
14 | 15 | ||
15 | # 'Users' - code which presents functionality to userspace. | 16 | # 'Users' - code which presents functionality to userspace. |
16 | obj-$(CONFIG_MTD_CHAR) += mtdchar.o | 17 | obj-$(CONFIG_MTD_CHAR) += mtdchar.o |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index d4bcd3f8c57c..49acd4171893 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -80,65 +80,6 @@ static int parse_obsolete_partitions(struct of_device *dev, | |||
80 | 80 | ||
81 | return nr_parts; | 81 | return nr_parts; |
82 | } | 82 | } |
83 | |||
84 | static int __devinit parse_partitions(struct of_flash *info, | ||
85 | struct of_device *dev) | ||
86 | { | ||
87 | const char *partname; | ||
88 | static const char *part_probe_types[] | ||
89 | = { "cmdlinepart", "RedBoot", NULL }; | ||
90 | struct device_node *dp = dev->node, *pp; | ||
91 | int nr_parts, i; | ||
92 | |||
93 | /* First look for RedBoot table or partitions on the command | ||
94 | * line, these take precedence over device tree information */ | ||
95 | nr_parts = parse_mtd_partitions(info->mtd, part_probe_types, | ||
96 | &info->parts, 0); | ||
97 | if (nr_parts > 0) | ||
98 | return nr_parts; | ||
99 | |||
100 | /* First count the subnodes */ | ||
101 | nr_parts = 0; | ||
102 | for (pp = of_get_next_child(dp, NULL); pp; | ||
103 | pp = of_get_next_child(dp, pp)) | ||
104 | nr_parts++; | ||
105 | |||
106 | if (nr_parts == 0) | ||
107 | return parse_obsolete_partitions(dev, info, dp); | ||
108 | |||
109 | info->parts = kzalloc(nr_parts * sizeof(*info->parts), | ||
110 | GFP_KERNEL); | ||
111 | if (!info->parts) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | for (pp = of_get_next_child(dp, NULL), i = 0; pp; | ||
115 | pp = of_get_next_child(dp, pp), i++) { | ||
116 | const u32 *reg; | ||
117 | int len; | ||
118 | |||
119 | reg = of_get_property(pp, "reg", &len); | ||
120 | if (!reg || (len != 2*sizeof(u32))) { | ||
121 | of_node_put(pp); | ||
122 | dev_err(&dev->dev, "Invalid 'reg' on %s\n", | ||
123 | dp->full_name); | ||
124 | kfree(info->parts); | ||
125 | info->parts = NULL; | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | info->parts[i].offset = reg[0]; | ||
129 | info->parts[i].size = reg[1]; | ||
130 | |||
131 | partname = of_get_property(pp, "label", &len); | ||
132 | if (!partname) | ||
133 | partname = of_get_property(pp, "name", &len); | ||
134 | info->parts[i].name = (char *)partname; | ||
135 | |||
136 | if (of_get_property(pp, "read-only", &len)) | ||
137 | info->parts[i].mask_flags = MTD_WRITEABLE; | ||
138 | } | ||
139 | |||
140 | return nr_parts; | ||
141 | } | ||
142 | #else /* MTD_PARTITIONS */ | 83 | #else /* MTD_PARTITIONS */ |
143 | #define OF_FLASH_PARTS(info) (0) | 84 | #define OF_FLASH_PARTS(info) (0) |
144 | #define parse_partitions(info, dev) (0) | 85 | #define parse_partitions(info, dev) (0) |
@@ -213,6 +154,10 @@ static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, | |||
213 | static int __devinit of_flash_probe(struct of_device *dev, | 154 | static int __devinit of_flash_probe(struct of_device *dev, |
214 | const struct of_device_id *match) | 155 | const struct of_device_id *match) |
215 | { | 156 | { |
157 | #ifdef CONFIG_MTD_PARTITIONS | ||
158 | static const char *part_probe_types[] | ||
159 | = { "cmdlinepart", "RedBoot", NULL }; | ||
160 | #endif | ||
216 | struct device_node *dp = dev->node; | 161 | struct device_node *dp = dev->node; |
217 | struct resource res; | 162 | struct resource res; |
218 | struct of_flash *info; | 163 | struct of_flash *info; |
@@ -275,13 +220,33 @@ static int __devinit of_flash_probe(struct of_device *dev, | |||
275 | } | 220 | } |
276 | info->mtd->owner = THIS_MODULE; | 221 | info->mtd->owner = THIS_MODULE; |
277 | 222 | ||
278 | err = parse_partitions(info, dev); | 223 | #ifdef CONFIG_MTD_PARTITIONS |
224 | /* First look for RedBoot table or partitions on the command | ||
225 | * line, these take precedence over device tree information */ | ||
226 | err = parse_mtd_partitions(info->mtd, part_probe_types, | ||
227 | &info->parts, 0); | ||
279 | if (err < 0) | 228 | if (err < 0) |
280 | goto err_out; | 229 | return err; |
230 | |||
231 | #ifdef CONFIG_MTD_OF_PARTS | ||
232 | if (err == 0) { | ||
233 | err = of_mtd_parse_partitions(&dev->dev, info->mtd, | ||
234 | dp, &info->parts); | ||
235 | if (err < 0) | ||
236 | return err; | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | if (err == 0) { | ||
241 | err = parse_obsolete_partitions(dev, info, dp); | ||
242 | if (err < 0) | ||
243 | return err; | ||
244 | } | ||
281 | 245 | ||
282 | if (err > 0) | 246 | if (err > 0) |
283 | add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err); | 247 | add_mtd_partitions(info->mtd, info->parts, err); |
284 | else | 248 | else |
249 | #endif | ||
285 | add_mtd_device(info->mtd); | 250 | add_mtd_device(info->mtd); |
286 | 251 | ||
287 | return 0; | 252 | return 0; |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c new file mode 100644 index 000000000000..f86e06934cd8 --- /dev/null +++ b/drivers/mtd/ofpart.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Flash partitions described by the OF (or flattened) device tree | ||
3 | * | ||
4 | * Copyright (C) 2006 MontaVista Software Inc. | ||
5 | * Author: Vitaly Wool <vwool@ru.mvista.com> | ||
6 | * | ||
7 | * Revised to handle newer style flash binding by: | ||
8 | * Copyright (C) 2007 David Gibson, IBM Corporation. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/mtd/mtd.h> | ||
20 | #include <linux/mtd/partitions.h> | ||
21 | |||
22 | int __devinit of_mtd_parse_partitions(struct device *dev, | ||
23 | struct mtd_info *mtd, | ||
24 | struct device_node *node, | ||
25 | struct mtd_partition **pparts) | ||
26 | { | ||
27 | const char *partname; | ||
28 | struct device_node *pp; | ||
29 | int nr_parts, i; | ||
30 | |||
31 | /* First count the subnodes */ | ||
32 | pp = NULL; | ||
33 | nr_parts = 0; | ||
34 | while ((pp = of_get_next_child(node, pp))) | ||
35 | nr_parts++; | ||
36 | |||
37 | if (nr_parts == 0) | ||
38 | return 0; | ||
39 | |||
40 | *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL); | ||
41 | if (!*pparts) | ||
42 | return -ENOMEM; | ||
43 | |||
44 | pp = NULL; | ||
45 | i = 0; | ||
46 | while ((pp = of_get_next_child(node, pp))) { | ||
47 | const u32 *reg; | ||
48 | int len; | ||
49 | |||
50 | reg = of_get_property(pp, "reg", &len); | ||
51 | if (!reg || (len != 2 * sizeof(u32))) { | ||
52 | of_node_put(pp); | ||
53 | dev_err(dev, "Invalid 'reg' on %s\n", node->full_name); | ||
54 | kfree(*pparts); | ||
55 | *pparts = NULL; | ||
56 | return -EINVAL; | ||
57 | } | ||
58 | (*pparts)[i].offset = reg[0]; | ||
59 | (*pparts)[i].size = reg[1]; | ||
60 | |||
61 | partname = of_get_property(pp, "label", &len); | ||
62 | if (!partname) | ||
63 | partname = of_get_property(pp, "name", &len); | ||
64 | (*pparts)[i].name = (char *)partname; | ||
65 | |||
66 | if (of_get_property(pp, "read-only", &len)) | ||
67 | (*pparts)[i].mask_flags = MTD_WRITEABLE; | ||
68 | |||
69 | i++; | ||
70 | } | ||
71 | |||
72 | return nr_parts; | ||
73 | } | ||
74 | EXPORT_SYMBOL(of_mtd_parse_partitions); | ||