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