]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/mtd/maps/physmap_of.c
Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify
[net-next-2.6.git] / drivers / mtd / maps / physmap_of.c
CommitLineData
a2c2fe4b 1/*
c4d5e375 2 * Flash mappings described by the OF (or flattened) device tree
a2c2fe4b
VW
3 *
4 * Copyright (C) 2006 MontaVista Software Inc.
5 * Author: Vitaly Wool <vwool@ru.mvista.com>
6 *
2099172d
DG
7 * Revised to handle newer style flash binding by:
8 * Copyright (C) 2007 David Gibson, IBM Corporation.
9 *
a2c2fe4b
VW
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/types.h>
a2c2fe4b 18#include <linux/init.h>
a2c2fe4b
VW
19#include <linux/device.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
143070e7 23#include <linux/mtd/concat.h>
c4d5e375 24#include <linux/of.h>
7a50d06e 25#include <linux/of_address.h>
c4d5e375 26#include <linux/of_platform.h>
5a0e3ad6 27#include <linux/slab.h>
a2c2fe4b 28
143070e7
SR
29struct of_flash_list {
30 struct mtd_info *mtd;
31 struct map_info map;
32 struct resource *res;
33};
34
c4d5e375 35struct of_flash {
143070e7 36 struct mtd_info *cmtd;
a2c2fe4b 37#ifdef CONFIG_MTD_PARTITIONS
a2c2fe4b
VW
38 struct mtd_partition *parts;
39#endif
143070e7
SR
40 int list_size; /* number of elements in of_flash_list */
41 struct of_flash_list list[0];
a2c2fe4b
VW
42};
43
a2c2fe4b 44#ifdef CONFIG_MTD_PARTITIONS
c4d5e375 45#define OF_FLASH_PARTS(info) ((info)->parts)
a2c2fe4b 46
2dc11581 47static int parse_obsolete_partitions(struct platform_device *dev,
c4d5e375 48 struct of_flash *info,
2099172d 49 struct device_node *dp)
a2c2fe4b 50{
2099172d
DG
51 int i, plen, nr_parts;
52 const struct {
766f271a 53 __be32 offset, len;
2099172d
DG
54 } *part;
55 const char *names;
a2c2fe4b 56
2099172d
DG
57 part = of_get_property(dp, "partitions", &plen);
58 if (!part)
c4d5e375 59 return 0; /* No partitions found */
a2c2fe4b 60
2099172d
DG
61 dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
62
63 nr_parts = plen / sizeof(part[0]);
64
c4d5e375
DG
65 info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
66 if (!info->parts)
2099172d 67 return -ENOMEM;
a2c2fe4b 68
2099172d 69 names = of_get_property(dp, "partition-names", &plen);
a2c2fe4b 70
2099172d 71 for (i = 0; i < nr_parts; i++) {
766f271a
IM
72 info->parts[i].offset = be32_to_cpu(part->offset);
73 info->parts[i].size = be32_to_cpu(part->len) & ~1;
74 if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
2099172d 75 info->parts[i].mask_flags = MTD_WRITEABLE;
a2c2fe4b 76
2099172d
DG
77 if (names && (plen > 0)) {
78 int len = strlen(names) + 1;
a2c2fe4b 79
2099172d 80 info->parts[i].name = (char *)names;
a2c2fe4b 81 plen -= len;
2099172d
DG
82 names += len;
83 } else {
84 info->parts[i].name = "unnamed";
85 }
86
87 part++;
a2c2fe4b 88 }
2099172d
DG
89
90 return nr_parts;
a2c2fe4b 91}
2099172d 92#else /* MTD_PARTITIONS */
c4d5e375
DG
93#define OF_FLASH_PARTS(info) (0)
94#define parse_partitions(info, dev) (0)
2099172d 95#endif /* MTD_PARTITIONS */
a2c2fe4b 96
2dc11581 97static int of_flash_remove(struct platform_device *dev)
a2c2fe4b 98{
c4d5e375 99 struct of_flash *info;
143070e7 100 int i;
a2c2fe4b
VW
101
102 info = dev_get_drvdata(&dev->dev);
c4d5e375 103 if (!info)
a2c2fe4b
VW
104 return 0;
105 dev_set_drvdata(&dev->dev, NULL);
106
143070e7
SR
107#ifdef CONFIG_MTD_CONCAT
108 if (info->cmtd != info->list[0].mtd) {
109 del_mtd_device(info->cmtd);
110 mtd_concat_destroy(info->cmtd);
111 }
112#endif
113
114 if (info->cmtd) {
c4d5e375 115 if (OF_FLASH_PARTS(info)) {
143070e7 116 del_mtd_partitions(info->cmtd);
c4d5e375 117 kfree(OF_FLASH_PARTS(info));
a2c2fe4b 118 } else {
143070e7 119 del_mtd_device(info->cmtd);
a2c2fe4b 120 }
a2c2fe4b
VW
121 }
122
143070e7
SR
123 for (i = 0; i < info->list_size; i++) {
124 if (info->list[i].mtd)
125 map_destroy(info->list[i].mtd);
a2c2fe4b 126
143070e7
SR
127 if (info->list[i].map.virt)
128 iounmap(info->list[i].map.virt);
129
130 if (info->list[i].res) {
131 release_resource(info->list[i].res);
132 kfree(info->list[i].res);
133 }
a2c2fe4b
VW
134 }
135
143070e7
SR
136 kfree(info);
137
a2c2fe4b
VW
138 return 0;
139}
140
2099172d
DG
141/* Helper function to handle probing of the obsolete "direct-mapped"
142 * compatible binding, which has an extra "probe-type" property
143 * describing the type of flash probe necessary. */
2dc11581 144static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
2099172d 145 struct map_info *map)
a2c2fe4b 146{
61c7a080 147 struct device_node *dp = dev->dev.of_node;
a2c2fe4b 148 const char *of_probe;
2099172d
DG
149 struct mtd_info *mtd;
150 static const char *rom_probe_types[]
151 = { "cfi_probe", "jedec_probe", "map_rom"};
152 int i;
153
154 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
155 "flash binding\n");
156
157 of_probe = of_get_property(dp, "probe-type", NULL);
158 if (!of_probe) {
159 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
160 mtd = do_map_probe(rom_probe_types[i], map);
161 if (mtd)
162 return mtd;
163 }
164 return NULL;
165 } else if (strcmp(of_probe, "CFI") == 0) {
166 return do_map_probe("cfi_probe", map);
167 } else if (strcmp(of_probe, "JEDEC") == 0) {
168 return do_map_probe("jedec_probe", map);
169 } else {
170 if (strcmp(of_probe, "ROM") != 0)
c4d5e375
DG
171 dev_warn(&dev->dev, "obsolete_probe: don't know probe "
172 "type '%s', mapping as rom\n", of_probe);
2099172d
DG
173 return do_map_probe("mtd_rom", map);
174 }
175}
176
9d5da3a9
JG
177#ifdef CONFIG_MTD_PARTITIONS
178/* When partitions are set we look for a linux,part-probe property which
179 specifies the list of partition probers to use. If none is given then the
180 default is use. These take precedence over other device tree
181 information. */
182static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
183static const char ** __devinit of_get_probes(struct device_node *dp)
184{
185 const char *cp;
186 int cplen;
187 unsigned int l;
188 unsigned int count;
189 const char **res;
190
191 cp = of_get_property(dp, "linux,part-probe", &cplen);
192 if (cp == NULL)
193 return part_probe_types_def;
194
195 count = 0;
196 for (l = 0; l != cplen; l++)
197 if (cp[l] == 0)
198 count++;
199
200 res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
201 count = 0;
202 while (cplen > 0) {
203 res[count] = cp;
204 l = strlen(cp) + 1;
205 cp += l;
206 cplen -= l;
207 count++;
208 }
209 return res;
210}
211
212static void __devinit of_free_probes(const char **probes)
213{
214 if (probes != part_probe_types_def)
215 kfree(probes);
216}
217#endif
218
2dc11581 219static int __devinit of_flash_probe(struct platform_device *dev,
c4d5e375 220 const struct of_device_id *match)
a2c2fe4b 221{
9a310d21 222#ifdef CONFIG_MTD_PARTITIONS
9d5da3a9 223 const char **part_probe_types;
9a310d21 224#endif
61c7a080 225 struct device_node *dp = dev->dev.of_node;
a2c2fe4b 226 struct resource res;
c4d5e375
DG
227 struct of_flash *info;
228 const char *probe_type = match->data;
766f271a 229 const __be32 *width;
a2c2fe4b 230 int err;
143070e7
SR
231 int i;
232 int count;
766f271a 233 const __be32 *p;
143070e7
SR
234 int reg_tuple_size;
235 struct mtd_info **mtd_list = NULL;
2763c508 236 resource_size_t res_size;
143070e7
SR
237
238 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
239
240 /*
241 * Get number of "reg" tuples. Scan for MTD devices on area's
242 * described by each "reg" region. This makes it possible (including
243 * the concat support) to support the Intel P30 48F4400 chips which
244 * consists internally of 2 non-identical NOR chips on one die.
245 */
246 p = of_get_property(dp, "reg", &count);
247 if (count % reg_tuple_size != 0) {
248 dev_err(&dev->dev, "Malformed reg property on %s\n",
61c7a080 249 dev->dev.of_node->full_name);
143070e7 250 err = -EINVAL;
ad4fbc79 251 goto err_flash_remove;
a2c2fe4b 252 }
143070e7 253 count /= reg_tuple_size;
a2c2fe4b 254
c4d5e375 255 err = -ENOMEM;
143070e7
SR
256 info = kzalloc(sizeof(struct of_flash) +
257 sizeof(struct of_flash_list) * count, GFP_KERNEL);
258 if (!info)
ad4fbc79 259 goto err_flash_remove;
a2c2fe4b
VW
260
261 dev_set_drvdata(&dev->dev, info);
262
e026255f 263 mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
ad4fbc79 264 if (!mtd_list)
265 goto err_flash_remove;
266
143070e7
SR
267 for (i = 0; i < count; i++) {
268 err = -ENXIO;
269 if (of_address_to_resource(dp, i, &res)) {
940fe282
SR
270 /*
271 * Continue with next register tuple if this
272 * one is not mappable
273 */
274 continue;
143070e7 275 }
a2c2fe4b 276
143070e7
SR
277 dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
278 (unsigned long long)res.start,
279 (unsigned long long)res.end);
280
281 err = -EBUSY;
2763c508
WS
282 res_size = resource_size(&res);
283 info->list[i].res = request_mem_region(res.start, res_size,
143070e7
SR
284 dev_name(&dev->dev));
285 if (!info->list[i].res)
286 goto err_out;
287
288 err = -ENXIO;
289 width = of_get_property(dp, "bank-width", NULL);
290 if (!width) {
291 dev_err(&dev->dev, "Can't get bank width from device"
292 " tree\n");
293 goto err_out;
294 }
a2c2fe4b 295
143070e7
SR
296 info->list[i].map.name = dev_name(&dev->dev);
297 info->list[i].map.phys = res.start;
2763c508 298 info->list[i].map.size = res_size;
766f271a 299 info->list[i].map.bankwidth = be32_to_cpup(width);
143070e7
SR
300
301 err = -ENOMEM;
302 info->list[i].map.virt = ioremap(info->list[i].map.phys,
303 info->list[i].map.size);
304 if (!info->list[i].map.virt) {
305 dev_err(&dev->dev, "Failed to ioremap() flash"
306 " region\n");
307 goto err_out;
308 }
a2c2fe4b 309
143070e7 310 simple_map_init(&info->list[i].map);
a2c2fe4b 311
143070e7
SR
312 if (probe_type) {
313 info->list[i].mtd = do_map_probe(probe_type,
314 &info->list[i].map);
315 } else {
316 info->list[i].mtd = obsolete_probe(dev,
317 &info->list[i].map);
318 }
319 mtd_list[i] = info->list[i].mtd;
a2c2fe4b 320
143070e7
SR
321 err = -ENXIO;
322 if (!info->list[i].mtd) {
323 dev_err(&dev->dev, "do_map_probe() failed\n");
324 goto err_out;
325 } else {
326 info->list_size++;
327 }
328 info->list[i].mtd->owner = THIS_MODULE;
329 info->list[i].mtd->dev.parent = &dev->dev;
330 }
2099172d 331
143070e7
SR
332 err = 0;
333 if (info->list_size == 1) {
334 info->cmtd = info->list[0].mtd;
335 } else if (info->list_size > 1) {
336 /*
337 * We detected multiple devices. Concatenate them together.
338 */
339#ifdef CONFIG_MTD_CONCAT
340 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
341 dev_name(&dev->dev));
342 if (info->cmtd == NULL)
343 err = -ENXIO;
344#else
345 printk(KERN_ERR "physmap_of: multiple devices "
346 "found but MTD concat support disabled.\n");
347 err = -ENXIO;
348#endif
a2c2fe4b 349 }
143070e7
SR
350 if (err)
351 goto err_out;
a2c2fe4b 352
9a310d21 353#ifdef CONFIG_MTD_PARTITIONS
9d5da3a9 354 part_probe_types = of_get_probes(dp);
143070e7
SR
355 err = parse_mtd_partitions(info->cmtd, part_probe_types,
356 &info->parts, 0);
9d5da3a9
JG
357 if (err < 0) {
358 of_free_probes(part_probe_types);
00b275db 359 goto err_out;
9d5da3a9
JG
360 }
361 of_free_probes(part_probe_types);
9a310d21
SW
362
363#ifdef CONFIG_MTD_OF_PARTS
364 if (err == 0) {
69fd3a8d 365 err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
9a310d21 366 if (err < 0)
00b275db 367 goto err_out;
9a310d21
SW
368 }
369#endif
370
371 if (err == 0) {
372 err = parse_obsolete_partitions(dev, info, dp);
373 if (err < 0)
00b275db 374 goto err_out;
9a310d21 375 }
a2c2fe4b 376
c4d5e375 377 if (err > 0)
143070e7 378 add_mtd_partitions(info->cmtd, info->parts, err);
c4d5e375 379 else
9a310d21 380#endif
143070e7
SR
381 add_mtd_device(info->cmtd);
382
383 kfree(mtd_list);
a2c2fe4b 384
a2c2fe4b
VW
385 return 0;
386
387err_out:
143070e7 388 kfree(mtd_list);
ad4fbc79 389err_flash_remove:
c4d5e375 390 of_flash_remove(dev);
143070e7 391
a2c2fe4b 392 return err;
a2c2fe4b
VW
393}
394
c4d5e375 395static struct of_device_id of_flash_match[] = {
2099172d
DG
396 {
397 .compatible = "cfi-flash",
398 .data = (void *)"cfi_probe",
399 },
400 {
401 /* FIXME: JEDEC chips can't be safely and reliably
402 * probed, although the mtd code gets it right in
403 * practice most of the time. We should use the
404 * vendor and device ids specified by the binding to
405 * bypass the heuristic probe code, but the mtd layer
406 * provides, at present, no interface for doing so
407 * :(. */
408 .compatible = "jedec-flash",
409 .data = (void *)"jedec_probe",
410 },
fc28c39f
WS
411 {
412 .compatible = "mtd-ram",
413 .data = (void *)"map_ram",
414 },
a2c2fe4b
VW
415 {
416 .type = "rom",
417 .compatible = "direct-mapped"
418 },
419 { },
420};
c4d5e375 421MODULE_DEVICE_TABLE(of, of_flash_match);
a2c2fe4b 422
c4d5e375 423static struct of_platform_driver of_flash_driver = {
4018294b
GL
424 .driver = {
425 .name = "of-flash",
426 .owner = THIS_MODULE,
427 .of_match_table = of_flash_match,
428 },
c4d5e375
DG
429 .probe = of_flash_probe,
430 .remove = of_flash_remove,
a2c2fe4b
VW
431};
432
c4d5e375 433static int __init of_flash_init(void)
a2c2fe4b 434{
c4d5e375 435 return of_register_platform_driver(&of_flash_driver);
a2c2fe4b
VW
436}
437
c4d5e375 438static void __exit of_flash_exit(void)
a2c2fe4b 439{
c4d5e375 440 of_unregister_platform_driver(&of_flash_driver);
a2c2fe4b
VW
441}
442
c4d5e375
DG
443module_init(of_flash_init);
444module_exit(of_flash_exit);
a2c2fe4b
VW
445
446MODULE_LICENSE("GPL");
447MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
c4d5e375 448MODULE_DESCRIPTION("Device tree based MTD map driver");