]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mtd/maps/physmap_of_core.c
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[karo-tx-linux.git] / drivers / mtd / maps / physmap_of_core.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 #include "physmap_of_gemini.h"
28 #include "physmap_of_versatile.h"
29
30 struct of_flash_list {
31         struct mtd_info *mtd;
32         struct map_info map;
33         struct resource *res;
34 };
35
36 struct of_flash {
37         struct mtd_info         *cmtd;
38         int list_size; /* number of elements in of_flash_list */
39         struct of_flash_list    list[0];
40 };
41
42 static int of_flash_remove(struct platform_device *dev)
43 {
44         struct of_flash *info;
45         int i;
46
47         info = dev_get_drvdata(&dev->dev);
48         if (!info)
49                 return 0;
50         dev_set_drvdata(&dev->dev, NULL);
51
52         if (info->cmtd) {
53                 mtd_device_unregister(info->cmtd);
54                 if (info->cmtd != info->list[0].mtd)
55                         mtd_concat_destroy(info->cmtd);
56         }
57
58         for (i = 0; i < info->list_size; i++) {
59                 if (info->list[i].mtd)
60                         map_destroy(info->list[i].mtd);
61
62                 if (info->list[i].map.virt)
63                         iounmap(info->list[i].map.virt);
64
65                 if (info->list[i].res) {
66                         release_resource(info->list[i].res);
67                         kfree(info->list[i].res);
68                 }
69         }
70         return 0;
71 }
72
73 static const char * const rom_probe_types[] = {
74         "cfi_probe", "jedec_probe", "map_rom" };
75
76 /* Helper function to handle probing of the obsolete "direct-mapped"
77  * compatible binding, which has an extra "probe-type" property
78  * describing the type of flash probe necessary. */
79 static struct mtd_info *obsolete_probe(struct platform_device *dev,
80                                        struct map_info *map)
81 {
82         struct device_node *dp = dev->dev.of_node;
83         const char *of_probe;
84         struct mtd_info *mtd;
85         int i;
86
87         dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
88                  "flash binding\n");
89
90         of_probe = of_get_property(dp, "probe-type", NULL);
91         if (!of_probe) {
92                 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
93                         mtd = do_map_probe(rom_probe_types[i], map);
94                         if (mtd)
95                                 return mtd;
96                 }
97                 return NULL;
98         } else if (strcmp(of_probe, "CFI") == 0) {
99                 return do_map_probe("cfi_probe", map);
100         } else if (strcmp(of_probe, "JEDEC") == 0) {
101                 return do_map_probe("jedec_probe", map);
102         } else {
103                 if (strcmp(of_probe, "ROM") != 0)
104                         dev_warn(&dev->dev, "obsolete_probe: don't know probe "
105                                  "type '%s', mapping as rom\n", of_probe);
106                 return do_map_probe("map_rom", map);
107         }
108 }
109
110 /* When partitions are set we look for a linux,part-probe property which
111    specifies the list of partition probers to use. If none is given then the
112    default is use. These take precedence over other device tree
113    information. */
114 static const char * const part_probe_types_def[] = {
115         "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
116
117 static const char * const *of_get_probes(struct device_node *dp)
118 {
119         const char **res;
120         int count;
121
122         count = of_property_count_strings(dp, "linux,part-probe");
123         if (count < 0)
124                 return part_probe_types_def;
125
126         res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL);
127         if (!res)
128                 return NULL;
129
130         count = of_property_read_string_array(dp, "linux,part-probe", res,
131                                               count);
132         if (count < 0)
133                 return NULL;
134
135         return res;
136 }
137
138 static void of_free_probes(const char * const *probes)
139 {
140         if (probes != part_probe_types_def)
141                 kfree(probes);
142 }
143
144 static const struct of_device_id of_flash_match[];
145 static int of_flash_probe(struct platform_device *dev)
146 {
147         const char * const *part_probe_types;
148         const struct of_device_id *match;
149         struct device_node *dp = dev->dev.of_node;
150         struct resource res;
151         struct of_flash *info;
152         const char *probe_type;
153         const __be32 *width;
154         int err;
155         int i;
156         int count;
157         const __be32 *p;
158         int reg_tuple_size;
159         struct mtd_info **mtd_list = NULL;
160         resource_size_t res_size;
161         bool map_indirect;
162         const char *mtd_name = NULL;
163
164         match = of_match_device(of_flash_match, &dev->dev);
165         if (!match)
166                 return -EINVAL;
167         probe_type = match->data;
168
169         reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
170
171         of_property_read_string(dp, "linux,mtd-name", &mtd_name);
172
173         /*
174          * Get number of "reg" tuples. Scan for MTD devices on area's
175          * described by each "reg" region. This makes it possible (including
176          * the concat support) to support the Intel P30 48F4400 chips which
177          * consists internally of 2 non-identical NOR chips on one die.
178          */
179         p = of_get_property(dp, "reg", &count);
180         if (!p || count % reg_tuple_size != 0) {
181                 dev_err(&dev->dev, "Malformed reg property on %s\n",
182                                 dev->dev.of_node->full_name);
183                 err = -EINVAL;
184                 goto err_flash_remove;
185         }
186         count /= reg_tuple_size;
187
188         map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
189
190         err = -ENOMEM;
191         info = devm_kzalloc(&dev->dev,
192                             sizeof(struct of_flash) +
193                             sizeof(struct of_flash_list) * count, GFP_KERNEL);
194         if (!info)
195                 goto err_flash_remove;
196
197         dev_set_drvdata(&dev->dev, info);
198
199         mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
200         if (!mtd_list)
201                 goto err_flash_remove;
202
203         for (i = 0; i < count; i++) {
204                 err = -ENXIO;
205                 if (of_address_to_resource(dp, i, &res)) {
206                         /*
207                          * Continue with next register tuple if this
208                          * one is not mappable
209                          */
210                         continue;
211                 }
212
213                 dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
214
215                 err = -EBUSY;
216                 res_size = resource_size(&res);
217                 info->list[i].res = request_mem_region(res.start, res_size,
218                                                        dev_name(&dev->dev));
219                 if (!info->list[i].res)
220                         goto err_out;
221
222                 err = -ENXIO;
223                 width = of_get_property(dp, "bank-width", NULL);
224                 if (!width) {
225                         dev_err(&dev->dev, "Can't get bank width from device"
226                                 " tree\n");
227                         goto err_out;
228                 }
229
230                 info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
231                 info->list[i].map.phys = res.start;
232                 info->list[i].map.size = res_size;
233                 info->list[i].map.bankwidth = be32_to_cpup(width);
234                 info->list[i].map.device_node = dp;
235
236                 err = of_flash_probe_gemini(dev, dp, &info->list[i].map);
237                 if (err)
238                         return err;
239                 err = of_flash_probe_versatile(dev, dp, &info->list[i].map);
240                 if (err)
241                         return err;
242
243                 err = -ENOMEM;
244                 info->list[i].map.virt = ioremap(info->list[i].map.phys,
245                                                  info->list[i].map.size);
246                 if (!info->list[i].map.virt) {
247                         dev_err(&dev->dev, "Failed to ioremap() flash"
248                                 " region\n");
249                         goto err_out;
250                 }
251
252                 simple_map_init(&info->list[i].map);
253
254                 /*
255                  * On some platforms (e.g. MPC5200) a direct 1:1 mapping
256                  * may cause problems with JFFS2 usage, as the local bus (LPB)
257                  * doesn't support unaligned accesses as implemented in the
258                  * JFFS2 code via memcpy(). By setting NO_XIP, the
259                  * flash will not be exposed directly to the MTD users
260                  * (e.g. JFFS2) any more.
261                  */
262                 if (map_indirect)
263                         info->list[i].map.phys = NO_XIP;
264
265                 if (probe_type) {
266                         info->list[i].mtd = do_map_probe(probe_type,
267                                                          &info->list[i].map);
268                 } else {
269                         info->list[i].mtd = obsolete_probe(dev,
270                                                            &info->list[i].map);
271                 }
272
273                 /* Fall back to mapping region as ROM */
274                 if (!info->list[i].mtd) {
275                         dev_warn(&dev->dev,
276                                 "do_map_probe() failed for type %s\n",
277                                  probe_type);
278
279                         info->list[i].mtd = do_map_probe("map_rom",
280                                                          &info->list[i].map);
281                 }
282                 mtd_list[i] = info->list[i].mtd;
283
284                 err = -ENXIO;
285                 if (!info->list[i].mtd) {
286                         dev_err(&dev->dev, "do_map_probe() failed\n");
287                         goto err_out;
288                 } else {
289                         info->list_size++;
290                 }
291                 info->list[i].mtd->dev.parent = &dev->dev;
292         }
293
294         err = 0;
295         info->cmtd = NULL;
296         if (info->list_size == 1) {
297                 info->cmtd = info->list[0].mtd;
298         } else if (info->list_size > 1) {
299                 /*
300                  * We detected multiple devices. Concatenate them together.
301                  */
302                 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
303                                                dev_name(&dev->dev));
304         }
305         if (info->cmtd == NULL)
306                 err = -ENXIO;
307
308         if (err)
309                 goto err_out;
310
311         info->cmtd->dev.parent = &dev->dev;
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");