Version:  2.0.40 2.2.26 2.4.37 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us