mtd: spear_smi: use devm_ functions consistently
[deliverable/linux.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. */
2dc11581 80static struct mtd_info * __devinit 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 };
9d5da3a9
JG
119static const char ** __devinit of_get_probes(struct device_node *dp)
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
148static void __devinit of_free_probes(const char **probes)
149{
150 if (probes != part_probe_types_def)
151 kfree(probes);
152}
9d5da3a9 153
b1608d69 154static struct of_device_id of_flash_match[];
1c48a5c9 155static int __devinit 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;
143070e7 172
b1608d69
GL
173 match = of_match_device(of_flash_match, &dev->dev);
174 if (!match)
1c48a5c9 175 return -EINVAL;
b1608d69 176 probe_type = match->data;
1c48a5c9 177
143070e7
SR
178 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
179
180 /*
181 * Get number of "reg" tuples. Scan for MTD devices on area's
182 * described by each "reg" region. This makes it possible (including
183 * the concat support) to support the Intel P30 48F4400 chips which
184 * consists internally of 2 non-identical NOR chips on one die.
185 */
186 p = of_get_property(dp, "reg", &count);
187 if (count % reg_tuple_size != 0) {
188 dev_err(&dev->dev, "Malformed reg property on %s\n",
61c7a080 189 dev->dev.of_node->full_name);
143070e7 190 err = -EINVAL;
ad4fbc79 191 goto err_flash_remove;
a2c2fe4b 192 }
143070e7 193 count /= reg_tuple_size;
a2c2fe4b 194
c4d5e375 195 err = -ENOMEM;
143070e7
SR
196 info = kzalloc(sizeof(struct of_flash) +
197 sizeof(struct of_flash_list) * count, GFP_KERNEL);
198 if (!info)
ad4fbc79 199 goto err_flash_remove;
a2c2fe4b
VW
200
201 dev_set_drvdata(&dev->dev, info);
202
e026255f 203 mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
ad4fbc79 204 if (!mtd_list)
205 goto err_flash_remove;
206
143070e7
SR
207 for (i = 0; i < count; i++) {
208 err = -ENXIO;
209 if (of_address_to_resource(dp, i, &res)) {
940fe282
SR
210 /*
211 * Continue with next register tuple if this
212 * one is not mappable
213 */
214 continue;
143070e7 215 }
a2c2fe4b 216
f9a5279c 217 dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
143070e7
SR
218
219 err = -EBUSY;
2763c508
WS
220 res_size = resource_size(&res);
221 info->list[i].res = request_mem_region(res.start, res_size,
143070e7
SR
222 dev_name(&dev->dev));
223 if (!info->list[i].res)
224 goto err_out;
225
226 err = -ENXIO;
227 width = of_get_property(dp, "bank-width", NULL);
228 if (!width) {
229 dev_err(&dev->dev, "Can't get bank width from device"
230 " tree\n");
231 goto err_out;
232 }
a2c2fe4b 233
143070e7
SR
234 info->list[i].map.name = dev_name(&dev->dev);
235 info->list[i].map.phys = res.start;
2763c508 236 info->list[i].map.size = res_size;
766f271a 237 info->list[i].map.bankwidth = be32_to_cpup(width);
143070e7
SR
238
239 err = -ENOMEM;
240 info->list[i].map.virt = ioremap(info->list[i].map.phys,
241 info->list[i].map.size);
242 if (!info->list[i].map.virt) {
243 dev_err(&dev->dev, "Failed to ioremap() flash"
244 " region\n");
245 goto err_out;
246 }
a2c2fe4b 247
143070e7 248 simple_map_init(&info->list[i].map);
a2c2fe4b 249
143070e7
SR
250 if (probe_type) {
251 info->list[i].mtd = do_map_probe(probe_type,
252 &info->list[i].map);
253 } else {
254 info->list[i].mtd = obsolete_probe(dev,
255 &info->list[i].map);
256 }
257 mtd_list[i] = info->list[i].mtd;
a2c2fe4b 258
143070e7
SR
259 err = -ENXIO;
260 if (!info->list[i].mtd) {
261 dev_err(&dev->dev, "do_map_probe() failed\n");
262 goto err_out;
263 } else {
264 info->list_size++;
265 }
266 info->list[i].mtd->owner = THIS_MODULE;
267 info->list[i].mtd->dev.parent = &dev->dev;
268 }
2099172d 269
143070e7
SR
270 err = 0;
271 if (info->list_size == 1) {
272 info->cmtd = info->list[0].mtd;
273 } else if (info->list_size > 1) {
274 /*
275 * We detected multiple devices. Concatenate them together.
276 */
143070e7
SR
277 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
278 dev_name(&dev->dev));
279 if (info->cmtd == NULL)
280 err = -ENXIO;
a2c2fe4b 281 }
143070e7
SR
282 if (err)
283 goto err_out;
a2c2fe4b 284
5f4ba9f9 285 ppdata.of_node = dp;
9d5da3a9 286 part_probe_types = of_get_probes(dp);
f44dcbd0
DES
287 mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
288 NULL, 0);
9d5da3a9 289 of_free_probes(part_probe_types);
9a310d21 290
143070e7 291 kfree(mtd_list);
a2c2fe4b 292
a2c2fe4b
VW
293 return 0;
294
295err_out:
143070e7 296 kfree(mtd_list);
ad4fbc79 297err_flash_remove:
c4d5e375 298 of_flash_remove(dev);
143070e7 299
a2c2fe4b 300 return err;
a2c2fe4b
VW
301}
302
c4d5e375 303static struct of_device_id of_flash_match[] = {
2099172d
DG
304 {
305 .compatible = "cfi-flash",
306 .data = (void *)"cfi_probe",
307 },
308 {
309 /* FIXME: JEDEC chips can't be safely and reliably
310 * probed, although the mtd code gets it right in
311 * practice most of the time. We should use the
312 * vendor and device ids specified by the binding to
313 * bypass the heuristic probe code, but the mtd layer
314 * provides, at present, no interface for doing so
315 * :(. */
316 .compatible = "jedec-flash",
317 .data = (void *)"jedec_probe",
318 },
fc28c39f
WS
319 {
320 .compatible = "mtd-ram",
321 .data = (void *)"map_ram",
322 },
a2c2fe4b
VW
323 {
324 .type = "rom",
325 .compatible = "direct-mapped"
326 },
327 { },
328};
c4d5e375 329MODULE_DEVICE_TABLE(of, of_flash_match);
a2c2fe4b 330
1c48a5c9 331static struct platform_driver of_flash_driver = {
4018294b
GL
332 .driver = {
333 .name = "of-flash",
334 .owner = THIS_MODULE,
335 .of_match_table = of_flash_match,
336 },
c4d5e375
DG
337 .probe = of_flash_probe,
338 .remove = of_flash_remove,
a2c2fe4b
VW
339};
340
f99640de 341module_platform_driver(of_flash_driver);
a2c2fe4b
VW
342
343MODULE_LICENSE("GPL");
344MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
c4d5e375 345MODULE_DESCRIPTION("Device tree based MTD map driver");
This page took 0.424698 seconds and 5 git commands to generate.