Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

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 
 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 != info->list[0].mtd) {
 51                 mtd_device_unregister(info->cmtd);
 52                 mtd_concat_destroy(info->cmtd);
 53         }
 54 
 55         if (info->cmtd)
 56                 mtd_device_unregister(info->cmtd);
 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("mtd_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 *cp;
120         int cplen;
121         unsigned int l;
122         unsigned int count;
123         const char **res;
124 
125         cp = of_get_property(dp, "linux,part-probe", &cplen);
126         if (cp == NULL)
127                 return part_probe_types_def;
128 
129         count = 0;
130         for (l = 0; l != cplen; l++)
131                 if (cp[l] == 0)
132                         count++;
133 
134         res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
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 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         struct mtd_part_parser_data ppdata;
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 (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 
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                 }
253 
254                 simple_map_init(&info->list[i].map);
255 
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 
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;
275 
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         }
286 
287         err = 0;
288         info->cmtd = NULL;
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                  */
295                 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
296                                                dev_name(&dev->dev));
297         }
298         if (info->cmtd == NULL)
299                 err = -ENXIO;
300 
301         if (err)
302                 goto err_out;
303 
304         ppdata.of_node = dp;
305         part_probe_types = of_get_probes(dp);
306         mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
307                         NULL, 0);
308         of_free_probes(part_probe_types);
309 
310         kfree(mtd_list);
311 
312         return 0;
313 
314 err_out:
315         kfree(mtd_list);
316 err_flash_remove:
317         of_flash_remove(dev);
318 
319         return err;
320 }
321 
322 static struct of_device_id of_flash_match[] = {
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         },
338         {
339                 .compatible     = "mtd-ram",
340                 .data           = (void *)"map_ram",
341         },
342         {
343                 .type           = "rom",
344                 .compatible     = "direct-mapped"
345         },
346         { },
347 };
348 MODULE_DEVICE_TABLE(of, of_flash_match);
349 
350 static struct platform_driver of_flash_driver = {
351         .driver = {
352                 .name = "of-flash",
353                 .owner = THIS_MODULE,
354                 .of_match_table = of_flash_match,
355         },
356         .probe          = of_flash_probe,
357         .remove         = of_flash_remove,
358 };
359 
360 module_platform_driver(of_flash_driver);
361 
362 MODULE_LICENSE("GPL");
363 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
364 MODULE_DESCRIPTION("Device tree based MTD map driver");
365 

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