mtd: physmap_of: fix cmdline partition method w/o linux, mtd-name
[linux-2.6-block.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;
143070e7
SR
37 int list_size; /* number of elements in of_flash_list */
38 struct of_flash_list list[0];
a2c2fe4b
VW
39};
40
2dc11581 41static int of_flash_remove(struct platform_device *dev)
a2c2fe4b 42{
c4d5e375 43 struct of_flash *info;
143070e7 44 int i;
a2c2fe4b
VW
45
46 info = dev_get_drvdata(&dev->dev);
c4d5e375 47 if (!info)
a2c2fe4b
VW
48 return 0;
49 dev_set_drvdata(&dev->dev, NULL);
50
143070e7 51 if (info->cmtd != info->list[0].mtd) {
984e6d8e 52 mtd_device_unregister(info->cmtd);
143070e7
SR
53 mtd_concat_destroy(info->cmtd);
54 }
143070e7 55
f44dcbd0 56 if (info->cmtd)
984e6d8e 57 mtd_device_unregister(info->cmtd);
a2c2fe4b 58
143070e7
SR
59 for (i = 0; i < info->list_size; i++) {
60 if (info->list[i].mtd)
61 map_destroy(info->list[i].mtd);
a2c2fe4b 62
143070e7
SR
63 if (info->list[i].map.virt)
64 iounmap(info->list[i].map.virt);
65
66 if (info->list[i].res) {
67 release_resource(info->list[i].res);
68 kfree(info->list[i].res);
69 }
a2c2fe4b
VW
70 }
71
143070e7
SR
72 kfree(info);
73
a2c2fe4b
VW
74 return 0;
75}
76
2099172d
DG
77/* Helper function to handle probing of the obsolete "direct-mapped"
78 * compatible binding, which has an extra "probe-type" property
79 * describing the type of flash probe necessary. */
06f25510 80static struct mtd_info *obsolete_probe(struct platform_device *dev,
2099172d 81 struct map_info *map)
a2c2fe4b 82{
61c7a080 83 struct device_node *dp = dev->dev.of_node;
a2c2fe4b 84 const char *of_probe;
2099172d
DG
85 struct mtd_info *mtd;
86 static const char *rom_probe_types[]
87 = { "cfi_probe", "jedec_probe", "map_rom"};
88 int i;
89
90 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
91 "flash binding\n");
92
93 of_probe = of_get_property(dp, "probe-type", NULL);
94 if (!of_probe) {
95 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
96 mtd = do_map_probe(rom_probe_types[i], map);
97 if (mtd)
98 return mtd;
99 }
100 return NULL;
101 } else if (strcmp(of_probe, "CFI") == 0) {
102 return do_map_probe("cfi_probe", map);
103 } else if (strcmp(of_probe, "JEDEC") == 0) {
104 return do_map_probe("jedec_probe", map);
105 } else {
106 if (strcmp(of_probe, "ROM") != 0)
c4d5e375
DG
107 dev_warn(&dev->dev, "obsolete_probe: don't know probe "
108 "type '%s', mapping as rom\n", of_probe);
2099172d
DG
109 return do_map_probe("mtd_rom", map);
110 }
111}
112
9d5da3a9
JG
113/* When partitions are set we look for a linux,part-probe property which
114 specifies the list of partition probers to use. If none is given then the
115 default is use. These take precedence over other device tree
116 information. */
5f4ba9f9 117static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
fbcf62a3 118 "ofpart", "ofoldpart", NULL };
06f25510 119static const char **of_get_probes(struct device_node *dp)
9d5da3a9
JG
120{
121 const char *cp;
122 int cplen;
123 unsigned int l;
124 unsigned int count;
125 const char **res;
126
127 cp = of_get_property(dp, "linux,part-probe", &cplen);
128 if (cp == NULL)
129 return part_probe_types_def;
130
131 count = 0;
132 for (l = 0; l != cplen; l++)
133 if (cp[l] == 0)
134 count++;
135
136 res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
137 count = 0;
138 while (cplen > 0) {
139 res[count] = cp;
140 l = strlen(cp) + 1;
141 cp += l;
142 cplen -= l;
143 count++;
144 }
145 return res;
146}
147
06f25510 148static void of_free_probes(const char **probes)
9d5da3a9
JG
149{
150 if (probes != part_probe_types_def)
151 kfree(probes);
152}
9d5da3a9 153
b1608d69 154static struct of_device_id of_flash_match[];
06f25510 155static int of_flash_probe(struct platform_device *dev)
a2c2fe4b 156{
9d5da3a9 157 const char **part_probe_types;
b1608d69 158 const struct of_device_id *match;
61c7a080 159 struct device_node *dp = dev->dev.of_node;
a2c2fe4b 160 struct resource res;
c4d5e375 161 struct of_flash *info;
1c48a5c9 162 const char *probe_type;
766f271a 163 const __be32 *width;
a2c2fe4b 164 int err;
143070e7
SR
165 int i;
166 int count;
766f271a 167 const __be32 *p;
143070e7
SR
168 int reg_tuple_size;
169 struct mtd_info **mtd_list = NULL;
2763c508 170 resource_size_t res_size;
5f4ba9f9 171 struct mtd_part_parser_data ppdata;
d0788ce4 172 bool map_indirect;
7dfe4be3 173 const char *mtd_name = NULL;
143070e7 174
b1608d69
GL
175 match = of_match_device(of_flash_match, &dev->dev);
176 if (!match)
1c48a5c9 177 return -EINVAL;
b1608d69 178 probe_type = match->data;
1c48a5c9 179
143070e7
SR
180 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
181
d68cbdd4
JCPV
182 of_property_read_string(dp, "linux,mtd-name", &mtd_name);
183
143070e7
SR
184 /*
185 * Get number of "reg" tuples. Scan for MTD devices on area's
186 * described by each "reg" region. This makes it possible (including
187 * the concat support) to support the Intel P30 48F4400 chips which
188 * consists internally of 2 non-identical NOR chips on one die.
189 */
190 p = of_get_property(dp, "reg", &count);
191 if (count % reg_tuple_size != 0) {
192 dev_err(&dev->dev, "Malformed reg property on %s\n",
61c7a080 193 dev->dev.of_node->full_name);
143070e7 194 err = -EINVAL;
ad4fbc79 195 goto err_flash_remove;
a2c2fe4b 196 }
143070e7 197 count /= reg_tuple_size;
a2c2fe4b 198
d0788ce4
SR
199 map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
200
c4d5e375 201 err = -ENOMEM;
143070e7
SR
202 info = kzalloc(sizeof(struct of_flash) +
203 sizeof(struct of_flash_list) * count, GFP_KERNEL);
204 if (!info)
ad4fbc79 205 goto err_flash_remove;
a2c2fe4b
VW
206
207 dev_set_drvdata(&dev->dev, info);
208
e026255f 209 mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
ad4fbc79 210 if (!mtd_list)
211 goto err_flash_remove;
212
143070e7
SR
213 for (i = 0; i < count; i++) {
214 err = -ENXIO;
215 if (of_address_to_resource(dp, i, &res)) {
940fe282
SR
216 /*
217 * Continue with next register tuple if this
218 * one is not mappable
219 */
220 continue;
143070e7 221 }
a2c2fe4b 222
f9a5279c 223 dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
143070e7
SR
224
225 err = -EBUSY;
2763c508
WS
226 res_size = resource_size(&res);
227 info->list[i].res = request_mem_region(res.start, res_size,
143070e7
SR
228 dev_name(&dev->dev));
229 if (!info->list[i].res)
230 goto err_out;
231
232 err = -ENXIO;
233 width = of_get_property(dp, "bank-width", NULL);
234 if (!width) {
235 dev_err(&dev->dev, "Can't get bank width from device"
236 " tree\n");
237 goto err_out;
238 }
a2c2fe4b 239
d68cbdd4 240 info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
143070e7 241 info->list[i].map.phys = res.start;
2763c508 242 info->list[i].map.size = res_size;
766f271a 243 info->list[i].map.bankwidth = be32_to_cpup(width);
143070e7
SR
244
245 err = -ENOMEM;
246 info->list[i].map.virt = ioremap(info->list[i].map.phys,
247 info->list[i].map.size);
248 if (!info->list[i].map.virt) {
249 dev_err(&dev->dev, "Failed to ioremap() flash"
250 " region\n");
251 goto err_out;
252 }
a2c2fe4b 253
143070e7 254 simple_map_init(&info->list[i].map);
a2c2fe4b 255
d0788ce4
SR
256 /*
257 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
258 * may cause problems with JFFS2 usage, as the local bus (LPB)
259 * doesn't support unaligned accesses as implemented in the
260 * JFFS2 code via memcpy(). By setting NO_XIP, the
261 * flash will not be exposed directly to the MTD users
262 * (e.g. JFFS2) any more.
263 */
264 if (map_indirect)
265 info->list[i].map.phys = NO_XIP;
266
143070e7
SR
267 if (probe_type) {
268 info->list[i].mtd = do_map_probe(probe_type,
269 &info->list[i].map);
270 } else {
271 info->list[i].mtd = obsolete_probe(dev,
272 &info->list[i].map);
273 }
274 mtd_list[i] = info->list[i].mtd;
a2c2fe4b 275
143070e7
SR
276 err = -ENXIO;
277 if (!info->list[i].mtd) {
278 dev_err(&dev->dev, "do_map_probe() failed\n");
279 goto err_out;
280 } else {
281 info->list_size++;
282 }
283 info->list[i].mtd->owner = THIS_MODULE;
284 info->list[i].mtd->dev.parent = &dev->dev;
285 }
2099172d 286
143070e7 287 err = 0;
e58a66d8 288 info->cmtd = NULL;
143070e7
SR
289 if (info->list_size == 1) {
290 info->cmtd = info->list[0].mtd;
291 } else if (info->list_size > 1) {
292 /*
293 * We detected multiple devices. Concatenate them together.
294 */
143070e7
SR
295 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
296 dev_name(&dev->dev));
a2c2fe4b 297 }
e58a66d8
AP
298 if (info->cmtd == NULL)
299 err = -ENXIO;
300
143070e7
SR
301 if (err)
302 goto err_out;
a2c2fe4b 303
5f4ba9f9 304 ppdata.of_node = dp;
9d5da3a9 305 part_probe_types = of_get_probes(dp);
f44dcbd0
DES
306 mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
307 NULL, 0);
9d5da3a9 308 of_free_probes(part_probe_types);
9a310d21 309
143070e7 310 kfree(mtd_list);
a2c2fe4b 311
a2c2fe4b
VW
312 return 0;
313
314err_out:
143070e7 315 kfree(mtd_list);
ad4fbc79 316err_flash_remove:
c4d5e375 317 of_flash_remove(dev);
143070e7 318
a2c2fe4b 319 return err;
a2c2fe4b
VW
320}
321
c4d5e375 322static struct of_device_id of_flash_match[] = {
2099172d
DG
323 {
324 .compatible = "cfi-flash",
325 .data = (void *)"cfi_probe",
326 },
327 {
328 /* FIXME: JEDEC chips can't be safely and reliably
329 * probed, although the mtd code gets it right in
330 * practice most of the time. We should use the
331 * vendor and device ids specified by the binding to
332 * bypass the heuristic probe code, but the mtd layer
333 * provides, at present, no interface for doing so
334 * :(. */
335 .compatible = "jedec-flash",
336 .data = (void *)"jedec_probe",
337 },
fc28c39f
WS
338 {
339 .compatible = "mtd-ram",
340 .data = (void *)"map_ram",
341 },
a2c2fe4b
VW
342 {
343 .type = "rom",
344 .compatible = "direct-mapped"
345 },
346 { },
347};
c4d5e375 348MODULE_DEVICE_TABLE(of, of_flash_match);
a2c2fe4b 349
1c48a5c9 350static struct platform_driver of_flash_driver = {
4018294b
GL
351 .driver = {
352 .name = "of-flash",
353 .owner = THIS_MODULE,
354 .of_match_table = of_flash_match,
355 },
c4d5e375
DG
356 .probe = of_flash_probe,
357 .remove = of_flash_remove,
a2c2fe4b
VW
358};
359
f99640de 360module_platform_driver(of_flash_driver);
a2c2fe4b
VW
361
362MODULE_LICENSE("GPL");
363MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
c4d5e375 364MODULE_DESCRIPTION("Device tree based MTD map driver");