aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/physmap_of.c349
2 files changed, 218 insertions, 133 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..cf75a566442e 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -1,9 +1,12 @@
1/* 1/*
2 * Normal mappings of chips in physical memory for OF devices 2 * Flash mappings described by the OF (or flattened) device tree
3 * 3 *
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
@@ -12,102 +15,157 @@
12 15
13#include <linux/module.h> 16#include <linux/module.h>
14#include <linux/types.h> 17#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/init.h> 18#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/device.h> 19#include <linux/device.h>
19#include <linux/mtd/mtd.h> 20#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h> 21#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h> 22#include <linux/mtd/partitions.h>
22#include <linux/mtd/physmap.h> 23#include <linux/of.h>
23#include <asm/io.h> 24#include <linux/of_platform.h>
24#include <asm/prom.h>
25#include <asm/of_device.h>
26#include <asm/of_platform.h>
27 25
28struct physmap_flash_info { 26struct of_flash {
29 struct mtd_info *mtd; 27 struct mtd_info *mtd;
30 struct map_info map; 28 struct map_info map;
31 struct resource *res; 29 struct resource *res;
32#ifdef CONFIG_MTD_PARTITIONS 30#ifdef CONFIG_MTD_PARTITIONS
33 int nr_parts;
34 struct mtd_partition *parts; 31 struct mtd_partition *parts;
35#endif 32#endif
36}; 33};
37 34
38static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
39#ifdef CONFIG_MTD_PARTITIONS 35#ifdef CONFIG_MTD_PARTITIONS
40static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; 36#define OF_FLASH_PARTS(info) ((info)->parts)
41#endif
42 37
43#ifdef CONFIG_MTD_PARTITIONS 38static int parse_obsolete_partitions(struct of_device *dev,
44static int parse_flash_partitions(struct device_node *node, 39 struct of_flash *info,
45 struct mtd_partition **parts) 40 struct device_node *dp)
46{ 41{
47 int i, plen, retval = -ENOMEM; 42 int i, plen, nr_parts;
48 const u32 *part; 43 const struct {
49 const char *name; 44 u32 offset, len;
50 45 } *part;
51 part = of_get_property(node, "partitions", &plen); 46 const char *names;
52 if (part == NULL) 47
53 goto err; 48 part = of_get_property(dp, "partitions", &plen);
54 49 if (!part)
55 retval = plen / (2 * sizeof(u32)); 50 return 0; /* No partitions found */
56 *parts = kzalloc(retval * sizeof(struct mtd_partition), GFP_KERNEL); 51
57 if (*parts == NULL) { 52 dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
58 printk(KERN_ERR "Can't allocate the flash partition data!\n"); 53
59 goto err; 54 nr_parts = plen / sizeof(part[0]);
60 } 55
56 info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
57 if (!info->parts)
58 return -ENOMEM;
61 59
62 name = of_get_property(node, "partition-names", &plen); 60 names = of_get_property(dp, "partition-names", &plen);
63 61
64 for (i = 0; i < retval; i++) { 62 for (i = 0; i < nr_parts; i++) {
65 (*parts)[i].offset = *part++; 63 info->parts[i].offset = part->offset;
66 (*parts)[i].size = *part & ~1; 64 info->parts[i].size = part->len & ~1;
67 if (*part++ & 1) /* bit 0 set signifies read only partition */ 65 if (part->len & 1) /* bit 0 set signifies read only partition */
68 (*parts)[i].mask_flags = MTD_WRITEABLE; 66 info->parts[i].mask_flags = MTD_WRITEABLE;
69 67
70 if (name != NULL && plen > 0) { 68 if (names && (plen > 0)) {
71 int len = strlen(name) + 1; 69 int len = strlen(names) + 1;
72 70
73 (*parts)[i].name = (char *)name; 71 info->parts[i].name = (char *)names;
74 plen -= len; 72 plen -= len;
75 name += len; 73 names += len;
76 } else 74 } else {
77 (*parts)[i].name = "unnamed"; 75 info->parts[i].name = "unnamed";
76 }
77
78 part++;
78 } 79 }
79err: 80
80 return retval; 81 return nr_parts;
81} 82}
82#endif
83 83
84static int of_physmap_remove(struct of_device *dev) 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 add_mtd_partitions(info->mtd, info->parts, nr_parts);
99 return 0;
100 }
101
102 /* First count the subnodes */
103 nr_parts = 0;
104 for (pp = dp->child; pp; pp = pp->sibling)
105 nr_parts++;
106
107 if (nr_parts == 0)
108 return parse_obsolete_partitions(dev, info, dp);
109
110 info->parts = kzalloc(nr_parts * sizeof(*info->parts),
111 GFP_KERNEL);
112 if (!info->parts)
113 return -ENOMEM;
114
115 for (pp = dp->child, i = 0; pp; pp = pp->sibling, 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 dev_err(&dev->dev, "Invalid 'reg' on %s\n",
122 dp->full_name);
123 kfree(info->parts);
124 info->parts = NULL;
125 return -EINVAL;
126 }
127 info->parts[i].offset = reg[0];
128 info->parts[i].size = reg[1];
129
130 partname = of_get_property(pp, "label", &len);
131 if (!partname)
132 partname = of_get_property(pp, "name", &len);
133 info->parts[i].name = (char *)partname;
134
135 if (of_get_property(pp, "read-only", &len))
136 info->parts[i].mask_flags = MTD_WRITEABLE;
137 }
138
139 return nr_parts;
140}
141#else /* MTD_PARTITIONS */
142#define OF_FLASH_PARTS(info) (0)
143#define parse_partitions(info, dev) (0)
144#endif /* MTD_PARTITIONS */
145
146static int of_flash_remove(struct of_device *dev)
85{ 147{
86 struct physmap_flash_info *info; 148 struct of_flash *info;
87 149
88 info = dev_get_drvdata(&dev->dev); 150 info = dev_get_drvdata(&dev->dev);
89 if (info == NULL) 151 if (!info)
90 return 0; 152 return 0;
91 dev_set_drvdata(&dev->dev, NULL); 153 dev_set_drvdata(&dev->dev, NULL);
92 154
93 if (info->mtd != NULL) { 155 if (info->mtd) {
94#ifdef CONFIG_MTD_PARTITIONS 156 if (OF_FLASH_PARTS(info)) {
95 if (info->nr_parts) {
96 del_mtd_partitions(info->mtd); 157 del_mtd_partitions(info->mtd);
97 kfree(info->parts); 158 kfree(OF_FLASH_PARTS(info));
98 } else { 159 } else {
99 del_mtd_device(info->mtd); 160 del_mtd_device(info->mtd);
100 } 161 }
101#else
102 del_mtd_device(info->mtd);
103#endif
104 map_destroy(info->mtd); 162 map_destroy(info->mtd);
105 } 163 }
106 164
107 if (info->map.virt != NULL) 165 if (info->map.virt)
108 iounmap(info->map.virt); 166 iounmap(info->map.virt);
109 167
110 if (info->res != NULL) { 168 if (info->res) {
111 release_resource(info->res); 169 release_resource(info->res);
112 kfree(info->res); 170 kfree(info->res);
113 } 171 }
@@ -115,48 +173,79 @@ static int of_physmap_remove(struct of_device *dev)
115 return 0; 173 return 0;
116} 174}
117 175
118static int __devinit of_physmap_probe(struct of_device *dev, const struct of_device_id *match) 176/* Helper function to handle probing of the obsolete "direct-mapped"
177 * compatible binding, which has an extra "probe-type" property
178 * describing the type of flash probe necessary. */
179static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
180 struct map_info *map)
119{ 181{
120 struct device_node *dp = dev->node; 182 struct device_node *dp = dev->node;
121 struct resource res;
122 struct physmap_flash_info *info;
123 const char **probe_type;
124 const char *of_probe; 183 const char *of_probe;
184 struct mtd_info *mtd;
185 static const char *rom_probe_types[]
186 = { "cfi_probe", "jedec_probe", "map_rom"};
187 int i;
188
189 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
190 "flash binding\n");
191
192 of_probe = of_get_property(dp, "probe-type", NULL);
193 if (!of_probe) {
194 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
195 mtd = do_map_probe(rom_probe_types[i], map);
196 if (mtd)
197 return mtd;
198 }
199 return NULL;
200 } else if (strcmp(of_probe, "CFI") == 0) {
201 return do_map_probe("cfi_probe", map);
202 } else if (strcmp(of_probe, "JEDEC") == 0) {
203 return do_map_probe("jedec_probe", map);
204 } else {
205 if (strcmp(of_probe, "ROM") != 0)
206 dev_warn(&dev->dev, "obsolete_probe: don't know probe "
207 "type '%s', mapping as rom\n", of_probe);
208 return do_map_probe("mtd_rom", map);
209 }
210}
211
212static int __devinit of_flash_probe(struct of_device *dev,
213 const struct of_device_id *match)
214{
215 struct device_node *dp = dev->node;
216 struct resource res;
217 struct of_flash *info;
218 const char *probe_type = match->data;
125 const u32 *width; 219 const u32 *width;
126 int err; 220 int err;
127 221
128 222 err = -ENXIO;
129 if (of_address_to_resource(dp, 0, &res)) { 223 if (of_address_to_resource(dp, 0, &res)) {
130 dev_err(&dev->dev, "Can't get the flash mapping!\n"); 224 dev_err(&dev->dev, "Can't get IO address from device tree\n");
131 err = -EINVAL;
132 goto err_out; 225 goto err_out;
133 } 226 }
134 227
135 dev_dbg(&dev->dev, "physmap flash device: %.8llx at %.8llx\n", 228 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
136 (unsigned long long)res.end - res.start + 1, 229 (unsigned long long)res.start, (unsigned long long)res.end);
137 (unsigned long long)res.start);
138 230
139 info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); 231 err = -ENOMEM;
140 if (info == NULL) { 232 info = kzalloc(sizeof(*info), GFP_KERNEL);
141 err = -ENOMEM; 233 if (!info)
142 goto err_out; 234 goto err_out;
143 }
144 memset(info, 0, sizeof(*info)); 235 memset(info, 0, sizeof(*info));
145 236
146 dev_set_drvdata(&dev->dev, info); 237 dev_set_drvdata(&dev->dev, info);
147 238
239 err = -EBUSY;
148 info->res = request_mem_region(res.start, res.end - res.start + 1, 240 info->res = request_mem_region(res.start, res.end - res.start + 1,
149 dev->dev.bus_id); 241 dev->dev.bus_id);
150 if (info->res == NULL) { 242 if (!info->res)
151 dev_err(&dev->dev, "Could not reserve memory region\n");
152 err = -ENOMEM;
153 goto err_out; 243 goto err_out;
154 }
155 244
245 err = -ENXIO;
156 width = of_get_property(dp, "bank-width", NULL); 246 width = of_get_property(dp, "bank-width", NULL);
157 if (width == NULL) { 247 if (!width) {
158 dev_err(&dev->dev, "Can't get the flash bank width!\n"); 248 dev_err(&dev->dev, "Can't get bank width from device tree\n");
159 err = -EINVAL;
160 goto err_out; 249 goto err_out;
161 } 250 }
162 251
@@ -165,91 +254,87 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
165 info->map.size = res.end - res.start + 1; 254 info->map.size = res.end - res.start + 1;
166 info->map.bankwidth = *width; 255 info->map.bankwidth = *width;
167 256
257 err = -ENOMEM;
168 info->map.virt = ioremap(info->map.phys, info->map.size); 258 info->map.virt = ioremap(info->map.phys, info->map.size);
169 if (info->map.virt == NULL) { 259 if (!info->map.virt) {
170 dev_err(&dev->dev, "Failed to ioremap flash region\n"); 260 dev_err(&dev->dev, "Failed to ioremap() flash region\n");
171 err = EIO;
172 goto err_out; 261 goto err_out;
173 } 262 }
174 263
175 simple_map_init(&info->map); 264 simple_map_init(&info->map);
176 265
177 of_probe = of_get_property(dp, "probe-type", NULL); 266 if (probe_type)
178 if (of_probe == NULL) { 267 info->mtd = do_map_probe(probe_type, &info->map);
179 probe_type = rom_probe_types; 268 else
180 for (; info->mtd == NULL && *probe_type != NULL; probe_type++) 269 info->mtd = obsolete_probe(dev, &info->map);
181 info->mtd = do_map_probe(*probe_type, &info->map); 270
182 } else if (!strcmp(of_probe, "CFI")) 271 err = -ENXIO;
183 info->mtd = do_map_probe("cfi_probe", &info->map); 272 if (!info->mtd) {
184 else if (!strcmp(of_probe, "JEDEC")) 273 dev_err(&dev->dev, "do_map_probe() failed\n");
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) {
193 dev_err(&dev->dev, "map_probe failed\n");
194 err = -ENXIO;
195 goto err_out; 274 goto err_out;
196 } 275 }
197 info->mtd->owner = THIS_MODULE; 276 info->mtd->owner = THIS_MODULE;
198 277
199#ifdef CONFIG_MTD_PARTITIONS 278 err = parse_partitions(info, dev);
200 err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0); 279 if (err < 0)
201 if (err > 0) { 280 goto err_out;
202 add_mtd_partitions(info->mtd, info->parts, err); 281
203 } else if ((err = parse_flash_partitions(dp, &info->parts)) > 0) { 282 if (err > 0)
204 dev_info(&dev->dev, "Using OF partition information\n"); 283 add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err);
205 add_mtd_partitions(info->mtd, info->parts, err); 284 else
206 info->nr_parts = err; 285 add_mtd_device(info->mtd);
207 } else
208#endif
209 286
210 add_mtd_device(info->mtd);
211 return 0; 287 return 0;
212 288
213err_out: 289err_out:
214 of_physmap_remove(dev); 290 of_flash_remove(dev);
215 return err; 291 return err;
216
217 return 0;
218
219
220} 292}
221 293
222static struct of_device_id of_physmap_match[] = { 294static struct of_device_id of_flash_match[] = {
295 {
296 .compatible = "cfi-flash",
297 .data = (void *)"cfi_probe",
298 },
299 {
300 /* FIXME: JEDEC chips can't be safely and reliably
301 * probed, although the mtd code gets it right in
302 * practice most of the time. We should use the
303 * vendor and device ids specified by the binding to
304 * bypass the heuristic probe code, but the mtd layer
305 * provides, at present, no interface for doing so
306 * :(. */
307 .compatible = "jedec-flash",
308 .data = (void *)"jedec_probe",
309 },
223 { 310 {
224 .type = "rom", 311 .type = "rom",
225 .compatible = "direct-mapped" 312 .compatible = "direct-mapped"
226 }, 313 },
227 { }, 314 { },
228}; 315};
316MODULE_DEVICE_TABLE(of, of_flash_match);
229 317
230MODULE_DEVICE_TABLE(of, of_physmap_match); 318static struct of_platform_driver of_flash_driver = {
231 319 .name = "of-flash",
232 320 .match_table = of_flash_match,
233static struct of_platform_driver of_physmap_flash_driver = { 321 .probe = of_flash_probe,
234 .name = "physmap-flash", 322 .remove = of_flash_remove,
235 .match_table = of_physmap_match,
236 .probe = of_physmap_probe,
237 .remove = of_physmap_remove,
238}; 323};
239 324
240static int __init of_physmap_init(void) 325static int __init of_flash_init(void)
241{ 326{
242 return of_register_platform_driver(&of_physmap_flash_driver); 327 return of_register_platform_driver(&of_flash_driver);
243} 328}
244 329
245static void __exit of_physmap_exit(void) 330static void __exit of_flash_exit(void)
246{ 331{
247 of_unregister_platform_driver(&of_physmap_flash_driver); 332 of_unregister_platform_driver(&of_flash_driver);
248} 333}
249 334
250module_init(of_physmap_init); 335module_init(of_flash_init);
251module_exit(of_physmap_exit); 336module_exit(of_flash_exit);
252 337
253MODULE_LICENSE("GPL"); 338MODULE_LICENSE("GPL");
254MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>"); 339MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
255MODULE_DESCRIPTION("Configurable MTD map driver for OF"); 340MODULE_DESCRIPTION("Device tree based MTD map driver");