aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/physmap_of.c239
2 files changed, 175 insertions, 66 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index cc6c73442435..6cd132c75187 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -362,7 +362,7 @@ config MTD_WALNUT
362 362
363config MTD_EBONY 363config MTD_EBONY
364 tristate "Flash devices mapped on IBM 440GP Ebony" 364 tristate "Flash devices mapped on IBM 440GP Ebony"
365 depends on MTD_JEDECPROBE && EBONY 365 depends on MTD_JEDECPROBE && EBONY && !PPC_MERGE
366 help 366 help
367 This enables access routines for the flash chips on the IBM 440GP 367 This enables access routines for the flash chips on the IBM 440GP
368 Ebony board. If you have one of these boards and would like to 368 Ebony board. If you have one of these boards and would like to
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index bbb42c35b69b..3df001bfee36 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -4,6 +4,9 @@
4 * Copyright (C) 2006 MontaVista Software Inc. 4 * Copyright (C) 2006 MontaVista Software Inc.
5 * Author: Vitaly Wool <vwool@ru.mvista.com> 5 * Author: Vitaly Wool <vwool@ru.mvista.com>
6 * 6 *
7 * Revised to handle newer style flash binding by:
8 * Copyright (C) 2007 David Gibson, IBM Corporation.
9 *
7 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your 12 * Free Software Foundation; either version 2 of the License, or (at your
@@ -30,56 +33,135 @@ struct physmap_flash_info {
30 struct map_info map; 33 struct map_info map;
31 struct resource *res; 34 struct resource *res;
32#ifdef CONFIG_MTD_PARTITIONS 35#ifdef CONFIG_MTD_PARTITIONS
33 int nr_parts;
34 struct mtd_partition *parts; 36 struct mtd_partition *parts;
35#endif 37#endif
36}; 38};
37 39
38static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
39#ifdef CONFIG_MTD_PARTITIONS
40static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
41#endif
42
43#ifdef CONFIG_MTD_PARTITIONS 40#ifdef CONFIG_MTD_PARTITIONS
44static int parse_flash_partitions(struct device_node *node, 41static int parse_obsolete_partitions(struct of_device *dev,
45 struct mtd_partition **parts) 42 struct physmap_flash_info *info,
43 struct device_node *dp)
46{ 44{
47 int i, plen, retval = -ENOMEM; 45 int i, plen, nr_parts;
48 const u32 *part; 46 const struct {
49 const char *name; 47 u32 offset, len;
48 } *part;
49 const char *names;
50 50
51 part = of_get_property(node, "partitions", &plen); 51 part = of_get_property(dp, "partitions", &plen);
52 if (part == NULL) 52 if (!part)
53 goto err; 53 return -ENOENT;
54 54
55 retval = plen / (2 * sizeof(u32)); 55 dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
56 *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL); 56
57 if (*parts == NULL) { 57 nr_parts = plen / sizeof(part[0]);
58
59 info->parts = kzalloc(nr_parts * sizeof(struct mtd_partition), GFP_KERNEL);
60 if (!info->parts) {
58 printk(KERN_ERR "Can't allocate the flash partition data!\n"); 61 printk(KERN_ERR "Can't allocate the flash partition data!\n");
59 goto err; 62 return -ENOMEM;
60 } 63 }
61 64
62 name = of_get_property(node, "partition-names", &plen); 65 names = of_get_property(dp, "partition-names", &plen);
63 66
64 for (i = 0; i < retval; i++) { 67 for (i = 0; i < nr_parts; i++) {
65 (*parts)[i].offset = *part++; 68 info->parts[i].offset = part->offset;
66 (*parts)[i].size = *part & ~1; 69 info->parts[i].size = part->len & ~1;
67 if (*part++ & 1) /* bit 0 set signifies read only partition */ 70 if (part->len & 1) /* bit 0 set signifies read only partition */
68 (*parts)[i].mask_flags = MTD_WRITEABLE; 71 info->parts[i].mask_flags = MTD_WRITEABLE;
69 72
70 if (name != NULL && plen > 0) { 73 if (names && (plen > 0)) {
71 int len = strlen(name) + 1; 74 int len = strlen(names) + 1;
72 75
73 (*parts)[i].name = (char *)name; 76 info->parts[i].name = (char *)names;
74 plen -= len; 77 plen -= len;
75 name += len; 78 names += len;
76 } else 79 } else {
77 (*parts)[i].name = "unnamed"; 80 info->parts[i].name = "unnamed";
81 }
82
83 part++;
78 } 84 }
79err: 85
80 return retval; 86 return nr_parts;
81} 87}
82#endif 88
89static int __devinit process_partitions(struct physmap_flash_info *info,
90 struct of_device *dev)
91{
92 const char *partname;
93 static const char *part_probe_types[]
94 = { "cmdlinepart", "RedBoot", NULL };
95 struct device_node *dp = dev->node, *pp;
96 int nr_parts, i;
97
98 /* First look for RedBoot table or partitions on the command
99 * line, these take precedence over device tree information */
100 nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
101 &info->parts, 0);
102 if (nr_parts > 0) {
103 add_mtd_partitions(info->mtd, info->parts, nr_parts);
104 return 0;
105 }
106
107 /* First count the subnodes */
108 nr_parts = 0;
109 for (pp = dp->child; pp; pp = pp->sibling)
110 nr_parts++;
111
112 if (nr_parts) {
113 info->parts = kzalloc(nr_parts * sizeof(struct mtd_partition),
114 GFP_KERNEL);
115 if (!info->parts) {
116 printk(KERN_ERR "Can't allocate the flash partition data!\n");
117 return -ENOMEM;
118 }
119
120 for (pp = dp->child, i = 0 ; pp; pp = pp->sibling, i++) {
121 const u32 *reg;
122 int len;
123
124 reg = of_get_property(pp, "reg", &len);
125 if (!reg || (len != 2*sizeof(u32))) {
126 dev_err(&dev->dev, "Invalid 'reg' on %s\n",
127 dp->full_name);
128 kfree(info->parts);
129 info->parts = NULL;
130 return -EINVAL;
131 }
132 info->parts[i].offset = reg[0];
133 info->parts[i].size = reg[1];
134
135 partname = of_get_property(pp, "label", &len);
136 if (!partname)
137 partname = of_get_property(pp, "name", &len);
138 info->parts[i].name = (char *)partname;
139
140 if (of_get_property(pp, "read-only", &len))
141 info->parts[i].mask_flags = MTD_WRITEABLE;
142 }
143 } else {
144 nr_parts = parse_obsolete_partitions(dev, info, dp);
145 }
146
147 if (nr_parts < 0)
148 return nr_parts;
149
150 if (nr_parts > 0)
151 add_mtd_partitions(info->mtd, info->parts, nr_parts);
152 else
153 add_mtd_device(info->mtd);
154
155 return 0;
156}
157#else /* MTD_PARTITIONS */
158static int __devinit process_partitions(struct physmap_flash_info *info,
159 struct device_node *dev)
160{
161 add_mtd_device(info->mtd);
162 return 0;
163}
164#endif /* MTD_PARTITIONS */
83 165
84static int of_physmap_remove(struct of_device *dev) 166static int of_physmap_remove(struct of_device *dev)
85{ 167{
@@ -92,7 +174,7 @@ static int of_physmap_remove(struct of_device *dev)
92 174
93 if (info->mtd != NULL) { 175 if (info->mtd != NULL) {
94#ifdef CONFIG_MTD_PARTITIONS 176#ifdef CONFIG_MTD_PARTITIONS
95 if (info->nr_parts) { 177 if (info->parts) {
96 del_mtd_partitions(info->mtd); 178 del_mtd_partitions(info->mtd);
97 kfree(info->parts); 179 kfree(info->parts);
98 } else { 180 } else {
@@ -115,17 +197,51 @@ static int of_physmap_remove(struct of_device *dev)
115 return 0; 197 return 0;
116} 198}
117 199
200/* Helper function to handle probing of the obsolete "direct-mapped"
201 * compatible binding, which has an extra "probe-type" property
202 * describing the type of flash probe necessary. */
203static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
204 struct map_info *map)
205{
206 struct device_node *dp = dev->node;
207 const char *of_probe;
208 struct mtd_info *mtd;
209 static const char *rom_probe_types[]
210 = { "cfi_probe", "jedec_probe", "map_rom"};
211 int i;
212
213 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
214 "flash binding\n");
215
216 of_probe = of_get_property(dp, "probe-type", NULL);
217 if (!of_probe) {
218 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
219 mtd = do_map_probe(rom_probe_types[i], map);
220 if (mtd)
221 return mtd;
222 }
223 return NULL;
224 } else if (strcmp(of_probe, "CFI") == 0) {
225 return do_map_probe("cfi_probe", map);
226 } else if (strcmp(of_probe, "JEDEC") == 0) {
227 return do_map_probe("jedec_probe", map);
228 } else {
229 if (strcmp(of_probe, "ROM") != 0)
230 dev_dbg(&dev->dev, "obsolete_probe: don't know probe type "
231 "'%s', mapping as rom\n", of_probe);
232 return do_map_probe("mtd_rom", map);
233 }
234}
235
118static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match) 236static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match)
119{ 237{
120 struct device_node *dp = dev->node; 238 struct device_node *dp = dev->node;
121 struct resource res; 239 struct resource res;
122 struct physmap_flash_info *info; 240 struct physmap_flash_info *info;
123 const char **probe_type; 241 const char *probe_type = (const char *)match->data;
124 const char *of_probe;
125 const u32 *width; 242 const u32 *width;
126 int err; 243 int err;
127 244
128
129 if (of_address_to_resource(dp, 0, &res)) { 245 if (of_address_to_resource(dp, 0, &res)) {
130 dev_err(&dev->dev, "Can't get the flash mapping!\n"); 246 dev_err(&dev->dev, "Can't get the flash mapping!\n");
131 err = -EINVAL; 247 err = -EINVAL;
@@ -174,21 +290,11 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
174 290
175 simple_map_init(&info->map); 291 simple_map_init(&info->map);
176 292
177 of_probe = of_get_property(dp, "probe-type", NULL); 293 if (probe_type)
178 if (of_probe == NULL) { 294 info->mtd = do_map_probe(probe_type, &info->map);
179 probe_type = rom_probe_types; 295 else
180 for (; info->mtd == NULL && *probe_type != NULL; probe_type++) 296 info->mtd = obsolete_probe(dev, &info->map);
181 info->mtd = do_map_probe(*probe_type, &info->map); 297
182 } else if (!strcmp(of_probe, "CFI"))
183 info->mtd = do_map_probe("cfi_probe", &info->map);
184 else if (!strcmp(of_probe, "JEDEC"))
185 info->mtd = do_map_probe("jedec_probe", &info->map);
186 else {
187 if (strcmp(of_probe, "ROM"))
188 dev_dbg(&dev->dev, "map_probe: don't know probe type "
189 "'%s', mapping as rom\n", of_probe);
190 info->mtd = do_map_probe("mtd_rom", &info->map);
191 }
192 if (info->mtd == NULL) { 298 if (info->mtd == NULL) {
193 dev_err(&dev->dev, "map_probe failed\n"); 299 dev_err(&dev->dev, "map_probe failed\n");
194 err = -ENXIO; 300 err = -ENXIO;
@@ -196,19 +302,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
196 } 302 }
197 info->mtd->owner = THIS_MODULE; 303 info->mtd->owner = THIS_MODULE;
198 304
199#ifdef CONFIG_MTD_PARTITIONS 305 return process_partitions(info, dev);
200 err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
201 if (err > 0) {
202 add_mtd_partitions(info->mtd, info->parts, err);
203 } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) {
204 dev_info(&dev->dev, "Using OF partition information\n");
205 add_mtd_partitions(info->mtd, info->parts, err);
206 info->nr_parts = err;
207 } else
208#endif
209
210 add_mtd_device(info->mtd);
211 return 0;
212 306
213err_out: 307err_out:
214 of_physmap_remove(dev); 308 of_physmap_remove(dev);
@@ -221,6 +315,21 @@ err_out:
221 315
222static struct of_device_id of_physmap_match[] = { 316static struct of_device_id of_physmap_match[] = {
223 { 317 {
318 .compatible = "cfi-flash",
319 .data = (void *)"cfi_probe",
320 },
321 {
322 /* FIXME: JEDEC chips can't be safely and reliably
323 * probed, although the mtd code gets it right in
324 * practice most of the time. We should use the
325 * vendor and device ids specified by the binding to
326 * bypass the heuristic probe code, but the mtd layer
327 * provides, at present, no interface for doing so
328 * :(. */
329 .compatible = "jedec-flash",
330 .data = (void *)"jedec_probe",
331 },
332 {
224 .type = "rom", 333 .type = "rom",
225 .compatible = "direct-mapped" 334 .compatible = "direct-mapped"
226 }, 335 },