aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/Kconfig8
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/maps/physmap_of.c89
-rw-r--r--drivers/mtd/ofpart.c74
-rw-r--r--include/linux/mtd/partitions.h9
5 files changed, 118 insertions, 63 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
153config 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
153comment "User Modules And Translation Layers" 161comment "User Modules And Translation Layers"
154 162
155config MTD_CHAR 163config 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
11obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o 11obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
12obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o 12obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
13obj-$(CONFIG_MTD_AFS_PARTS) += afs.o 13obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
14obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
14 15
15# 'Users' - code which presents functionality to userspace. 16# 'Users' - code which presents functionality to userspace.
16obj-$(CONFIG_MTD_CHAR) += mtdchar.o 17obj-$(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
84static 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,
213static int __devinit of_flash_probe(struct of_device *dev, 154static 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
22int __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}
74EXPORT_SYMBOL(of_mtd_parse_partitions);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index da6b3d6f12a7..7c37d7e55abc 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -71,5 +71,12 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
71 71
72#define put_partition_parser(p) do { module_put((p)->owner); } while(0) 72#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
73 73
74#endif 74struct device;
75struct device_node;
76
77int __devinit of_mtd_parse_partitions(struct device *dev,
78 struct mtd_info *mtd,
79 struct device_node *node,
80 struct mtd_partition **pparts);
75 81
82#endif