]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/blob - drivers/mtd/maps/physmap_of.c
Merge branch 'drm-nouveau-fixes-3.8' of git://anongit.freedesktop.org/git/nouveau...
[android-sdk/kernel-video.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  */
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/init.h>
19 #include <linux/device.h>
20 #include <linux/mtd/mtd.h>
21 #include <linux/mtd/map.h>
22 #include <linux/mtd/partitions.h>
23 #include <linux/mtd/concat.h>
24 #include <linux/of.h>
25 #include <linux/of_address.h>
26 #include <linux/of_platform.h>
27 #include <linux/slab.h>
29 struct of_flash_list {
30         struct mtd_info *mtd;
31         struct map_info map;
32         struct resource *res;
33 };
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 };
41 static int of_flash_remove(struct platform_device *dev)
42 {
43         struct of_flash *info;
44         int i;
46         info = dev_get_drvdata(&dev->dev);
47         if (!info)
48                 return 0;
49         dev_set_drvdata(&dev->dev, NULL);
51         if (info->cmtd != info->list[0].mtd) {
52                 mtd_device_unregister(info->cmtd);
53                 mtd_concat_destroy(info->cmtd);
54         }
56         if (info->cmtd)
57                 mtd_device_unregister(info->cmtd);
59         for (i = 0; i < info->list_size; i++) {
60                 if (info->list[i].mtd)
61                         map_destroy(info->list[i].mtd);
63                 if (info->list[i].map.virt)
64                         iounmap(info->list[i].map.virt);
66                 if (info->list[i].res) {
67                         release_resource(info->list[i].res);
68                         kfree(info->list[i].res);
69                 }
70         }
72         kfree(info);
74         return 0;
75 }
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. */
80 static struct mtd_info *obsolete_probe(struct platform_device *dev,
81                                        struct map_info *map)
82 {
83         struct device_node *dp = dev->dev.of_node;
84         const char *of_probe;
85         struct mtd_info *mtd;
86         static const char *rom_probe_types[]
87                 = { "cfi_probe", "jedec_probe", "map_rom"};
88         int i;
90         dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
91                  "flash binding\n");
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)
107                         dev_warn(&dev->dev, "obsolete_probe: don't know probe "
108                                  "type '%s', mapping as rom\n", of_probe);
109                 return do_map_probe("mtd_rom", map);
110         }
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. */
117 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
118                                         "ofpart", "ofoldpart", NULL };
119 static const char **of_get_probes(struct device_node *dp)
121         const char *cp;
122         int cplen;
123         unsigned int l;
124         unsigned int count;
125         const char **res;
127         cp = of_get_property(dp, "linux,part-probe", &cplen);
128         if (cp == NULL)
129                 return part_probe_types_def;
131         count = 0;
132         for (l = 0; l != cplen; l++)
133                 if (cp[l] == 0)
134                         count++;
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;
148 static void of_free_probes(const char **probes)
150         if (probes != part_probe_types_def)
151                 kfree(probes);
154 static struct of_device_id of_flash_match[];
155 static int of_flash_probe(struct platform_device *dev)
157         const char **part_probe_types;
158         const struct of_device_id *match;
159         struct device_node *dp = dev->dev.of_node;
160         struct resource res;
161         struct of_flash *info;
162         const char *probe_type;
163         const __be32 *width;
164         int err;
165         int i;
166         int count;
167         const __be32 *p;
168         int reg_tuple_size;
169         struct mtd_info **mtd_list = NULL;
170         resource_size_t res_size;
171         struct mtd_part_parser_data ppdata;
172         bool map_indirect;
173         const char *mtd_name = NULL;
175         match = of_match_device(of_flash_match, &dev->dev);
176         if (!match)
177                 return -EINVAL;
178         probe_type = match->data;
180         reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
182         of_property_read_string(dp, "linux,mtd-name", &mtd_name);
184         /*
185          * Get number of "reg" tuples. Scan for MTD devices on area's
186          * described by each "reg" region. This makes it possible (including
187          * the concat support) to support the Intel P30 48F4400 chips which
188          * consists internally of 2 non-identical NOR chips on one die.
189          */
190         p = of_get_property(dp, "reg", &count);
191         if (count % reg_tuple_size != 0) {
192                 dev_err(&dev->dev, "Malformed reg property on %s\n",
193                                 dev->dev.of_node->full_name);
194                 err = -EINVAL;
195                 goto err_flash_remove;
196         }
197         count /= reg_tuple_size;
199         map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
201         err = -ENOMEM;
202         info = kzalloc(sizeof(struct of_flash) +
203                        sizeof(struct of_flash_list) * count, GFP_KERNEL);
204         if (!info)
205                 goto err_flash_remove;
207         dev_set_drvdata(&dev->dev, info);
209         mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
210         if (!mtd_list)
211                 goto err_flash_remove;
213         for (i = 0; i < count; i++) {
214                 err = -ENXIO;
215                 if (of_address_to_resource(dp, i, &res)) {
216                         /*
217                          * Continue with next register tuple if this
218                          * one is not mappable
219                          */
220                         continue;
221                 }
223                 dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
225                 err = -EBUSY;
226                 res_size = resource_size(&res);
227                 info->list[i].res = request_mem_region(res.start, res_size,
228                                                        dev_name(&dev->dev));
229                 if (!info->list[i].res)
230                         goto err_out;
232                 err = -ENXIO;
233                 width = of_get_property(dp, "bank-width", NULL);
234                 if (!width) {
235                         dev_err(&dev->dev, "Can't get bank width from device"
236                                 " tree\n");
237                         goto err_out;
238                 }
240                 info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
241                 info->list[i].map.phys = res.start;
242                 info->list[i].map.size = res_size;
243                 info->list[i].map.bankwidth = be32_to_cpup(width);
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                 }
254                 simple_map_init(&info->list[i].map);
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;
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;
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         }
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;
301         if (err)
302                 goto err_out;
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);
310         kfree(mtd_list);
312         return 0;
314 err_out:
315         kfree(mtd_list);
316 err_flash_remove:
317         of_flash_remove(dev);
319         return err;
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);
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 };
360 module_platform_driver(of_flash_driver);
362 MODULE_LICENSE("GPL");
363 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
364 MODULE_DESCRIPTION("Device tree based MTD map driver");