blob: 55c4e2eefdc623fab13a8d55082cd829fc9a2ee4 [file] [log] [blame]
Vitaly Woola2c2fe42006-12-06 13:17:49 +03001/*
David Gibsonc4d5e372007-09-20 11:22:25 +10002 * Flash mappings described by the OF (or flattened) device tree
Vitaly Woola2c2fe42006-12-06 13:17:49 +03003 *
4 * Copyright (C) 2006 MontaVista Software Inc.
5 * Author: Vitaly Wool <vwool@ru.mvista.com>
6 *
David Gibson20991722007-09-07 13:23:53 +10007 * Revised to handle newer style flash binding by:
8 * Copyright (C) 2007 David Gibson, IBM Corporation.
9 *
Vitaly Woola2c2fe42006-12-06 13:17:49 +030010 * 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>
Vitaly Woola2c2fe42006-12-06 13:17:49 +030018#include <linux/init.h>
Vitaly Woola2c2fe42006-12-06 13:17:49 +030019#include <linux/device.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
Stefan Roese143070e2009-04-16 14:10:45 +020023#include <linux/mtd/concat.h>
David Gibsonc4d5e372007-09-20 11:22:25 +100024#include <linux/of.h>
Graeme Smecher7a50d062010-08-17 10:13:44 -070025#include <linux/of_address.h>
David Gibsonc4d5e372007-09-20 11:22:25 +100026#include <linux/of_platform.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Vitaly Woola2c2fe42006-12-06 13:17:49 +030028
Stefan Roese143070e2009-04-16 14:10:45 +020029struct of_flash_list {
30 struct mtd_info *mtd;
31 struct map_info map;
32 struct resource *res;
33};
34
David Gibsonc4d5e372007-09-20 11:22:25 +100035struct of_flash {
Stefan Roese143070e2009-04-16 14:10:45 +020036 struct mtd_info *cmtd;
Vitaly Woola2c2fe42006-12-06 13:17:49 +030037 struct mtd_partition *parts;
Stefan Roese143070e2009-04-16 14:10:45 +020038 int list_size; /* number of elements in of_flash_list */
39 struct of_flash_list list[0];
Vitaly Woola2c2fe42006-12-06 13:17:49 +030040};
41
David Gibsonc4d5e372007-09-20 11:22:25 +100042#define OF_FLASH_PARTS(info) ((info)->parts)
Vitaly Woola2c2fe42006-12-06 13:17:49 +030043
Grant Likely2dc11582010-08-06 09:25:50 -060044static int of_flash_remove(struct platform_device *dev)
Vitaly Woola2c2fe42006-12-06 13:17:49 +030045{
David Gibsonc4d5e372007-09-20 11:22:25 +100046 struct of_flash *info;
Stefan Roese143070e2009-04-16 14:10:45 +020047 int i;
Vitaly Woola2c2fe42006-12-06 13:17:49 +030048
49 info = dev_get_drvdata(&dev->dev);
David Gibsonc4d5e372007-09-20 11:22:25 +100050 if (!info)
Vitaly Woola2c2fe42006-12-06 13:17:49 +030051 return 0;
52 dev_set_drvdata(&dev->dev, NULL);
53
Stefan Roese143070e2009-04-16 14:10:45 +020054 if (info->cmtd != info->list[0].mtd) {
Jamie Iles984e6d82011-05-23 10:22:45 +010055 mtd_device_unregister(info->cmtd);
Stefan Roese143070e2009-04-16 14:10:45 +020056 mtd_concat_destroy(info->cmtd);
57 }
Stefan Roese143070e2009-04-16 14:10:45 +020058
59 if (info->cmtd) {
Jamie Iles984e6d82011-05-23 10:22:45 +010060 if (OF_FLASH_PARTS(info))
David Gibsonc4d5e372007-09-20 11:22:25 +100061 kfree(OF_FLASH_PARTS(info));
Jamie Iles984e6d82011-05-23 10:22:45 +010062 mtd_device_unregister(info->cmtd);
Vitaly Woola2c2fe42006-12-06 13:17:49 +030063 }
64
Stefan Roese143070e2009-04-16 14:10:45 +020065 for (i = 0; i < info->list_size; i++) {
66 if (info->list[i].mtd)
67 map_destroy(info->list[i].mtd);
Vitaly Woola2c2fe42006-12-06 13:17:49 +030068
Stefan Roese143070e2009-04-16 14:10:45 +020069 if (info->list[i].map.virt)
70 iounmap(info->list[i].map.virt);
71
72 if (info->list[i].res) {
73 release_resource(info->list[i].res);
74 kfree(info->list[i].res);
75 }
Vitaly Woola2c2fe42006-12-06 13:17:49 +030076 }
77
Stefan Roese143070e2009-04-16 14:10:45 +020078 kfree(info);
79
Vitaly Woola2c2fe42006-12-06 13:17:49 +030080 return 0;
81}
82
David Gibson20991722007-09-07 13:23:53 +100083/* Helper function to handle probing of the obsolete "direct-mapped"
84 * compatible binding, which has an extra "probe-type" property
85 * describing the type of flash probe necessary. */
Grant Likely2dc11582010-08-06 09:25:50 -060086static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
David Gibson20991722007-09-07 13:23:53 +100087 struct map_info *map)
88{
Grant Likely61c7a082010-04-13 16:12:29 -070089 struct device_node *dp = dev->dev.of_node;
David Gibson20991722007-09-07 13:23:53 +100090 const char *of_probe;
91 struct mtd_info *mtd;
92 static const char *rom_probe_types[]
93 = { "cfi_probe", "jedec_probe", "map_rom"};
94 int i;
95
96 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
97 "flash binding\n");
98
99 of_probe = of_get_property(dp, "probe-type", NULL);
100 if (!of_probe) {
101 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
102 mtd = do_map_probe(rom_probe_types[i], map);
103 if (mtd)
104 return mtd;
105 }
106 return NULL;
107 } else if (strcmp(of_probe, "CFI") == 0) {
108 return do_map_probe("cfi_probe", map);
109 } else if (strcmp(of_probe, "JEDEC") == 0) {
110 return do_map_probe("jedec_probe", map);
111 } else {
112 if (strcmp(of_probe, "ROM") != 0)
David Gibsonc4d5e372007-09-20 11:22:25 +1000113 dev_warn(&dev->dev, "obsolete_probe: don't know probe "
114 "type '%s', mapping as rom\n", of_probe);
David Gibson20991722007-09-07 13:23:53 +1000115 return do_map_probe("mtd_rom", map);
116 }
117}
118
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700119/* When partitions are set we look for a linux,part-probe property which
120 specifies the list of partition probers to use. If none is given then the
121 default is use. These take precedence over other device tree
122 information. */
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400123static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
Dmitry Eremin-Solenikovfbcf62a2011-05-30 01:26:17 +0400124 "ofpart", "ofoldpart", NULL };
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700125static const char ** __devinit of_get_probes(struct device_node *dp)
126{
127 const char *cp;
128 int cplen;
129 unsigned int l;
130 unsigned int count;
131 const char **res;
132
133 cp = of_get_property(dp, "linux,part-probe", &cplen);
134 if (cp == NULL)
135 return part_probe_types_def;
136
137 count = 0;
138 for (l = 0; l != cplen; l++)
139 if (cp[l] == 0)
140 count++;
141
142 res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
143 count = 0;
144 while (cplen > 0) {
145 res[count] = cp;
146 l = strlen(cp) + 1;
147 cp += l;
148 cplen -= l;
149 count++;
150 }
151 return res;
152}
153
154static void __devinit of_free_probes(const char **probes)
155{
156 if (probes != part_probe_types_def)
157 kfree(probes);
158}
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700159
Grant Likelyb1608d62011-05-18 11:19:24 -0600160static struct of_device_id of_flash_match[];
Grant Likely1c48a5c2011-02-17 02:43:24 -0700161static int __devinit of_flash_probe(struct platform_device *dev)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300162{
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700163 const char **part_probe_types;
Grant Likelyb1608d62011-05-18 11:19:24 -0600164 const struct of_device_id *match;
Grant Likely61c7a082010-04-13 16:12:29 -0700165 struct device_node *dp = dev->dev.of_node;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300166 struct resource res;
David Gibsonc4d5e372007-09-20 11:22:25 +1000167 struct of_flash *info;
Grant Likely1c48a5c2011-02-17 02:43:24 -0700168 const char *probe_type;
Ian Munsie766f2712010-10-01 17:06:08 +1000169 const __be32 *width;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300170 int err;
Stefan Roese143070e2009-04-16 14:10:45 +0200171 int i;
172 int count;
Ian Munsie766f2712010-10-01 17:06:08 +1000173 const __be32 *p;
Stefan Roese143070e2009-04-16 14:10:45 +0200174 int reg_tuple_size;
175 struct mtd_info **mtd_list = NULL;
Wolfram Sang2763c502009-07-17 17:54:14 +0200176 resource_size_t res_size;
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400177 struct mtd_part_parser_data ppdata;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300178
Grant Likelyb1608d62011-05-18 11:19:24 -0600179 match = of_match_device(of_flash_match, &dev->dev);
180 if (!match)
Grant Likely1c48a5c2011-02-17 02:43:24 -0700181 return -EINVAL;
Grant Likelyb1608d62011-05-18 11:19:24 -0600182 probe_type = match->data;
Grant Likely1c48a5c2011-02-17 02:43:24 -0700183
Stefan Roese143070e2009-04-16 14:10:45 +0200184 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
185
186 /*
187 * Get number of "reg" tuples. Scan for MTD devices on area's
188 * described by each "reg" region. This makes it possible (including
189 * the concat support) to support the Intel P30 48F4400 chips which
190 * consists internally of 2 non-identical NOR chips on one die.
191 */
192 p = of_get_property(dp, "reg", &count);
193 if (count % reg_tuple_size != 0) {
194 dev_err(&dev->dev, "Malformed reg property on %s\n",
Grant Likely61c7a082010-04-13 16:12:29 -0700195 dev->dev.of_node->full_name);
Stefan Roese143070e2009-04-16 14:10:45 +0200196 err = -EINVAL;
vimal singhad4fbc72009-07-30 20:54:27 +0530197 goto err_flash_remove;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300198 }
Stefan Roese143070e2009-04-16 14:10:45 +0200199 count /= reg_tuple_size;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300200
David Gibsonc4d5e372007-09-20 11:22:25 +1000201 err = -ENOMEM;
Stefan Roese143070e2009-04-16 14:10:45 +0200202 info = kzalloc(sizeof(struct of_flash) +
203 sizeof(struct of_flash_list) * count, GFP_KERNEL);
204 if (!info)
vimal singhad4fbc72009-07-30 20:54:27 +0530205 goto err_flash_remove;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300206
207 dev_set_drvdata(&dev->dev, info);
208
Julia Lawalle0262552009-12-29 20:15:23 +0100209 mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
vimal singhad4fbc72009-07-30 20:54:27 +0530210 if (!mtd_list)
211 goto err_flash_remove;
212
Stefan Roese143070e2009-04-16 14:10:45 +0200213 for (i = 0; i < count; i++) {
214 err = -ENXIO;
215 if (of_address_to_resource(dp, i, &res)) {
Stefan Roese940fe282010-10-08 14:41:27 +0200216 /*
217 * Continue with next register tuple if this
218 * one is not mappable
219 */
220 continue;
Stefan Roese143070e2009-04-16 14:10:45 +0200221 }
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300222
Joe Perchesf9a52792010-11-12 13:37:57 -0800223 dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
Stefan Roese143070e2009-04-16 14:10:45 +0200224
225 err = -EBUSY;
Wolfram Sang2763c502009-07-17 17:54:14 +0200226 res_size = resource_size(&res);
227 info->list[i].res = request_mem_region(res.start, res_size,
Stefan Roese143070e2009-04-16 14:10:45 +0200228 dev_name(&dev->dev));
229 if (!info->list[i].res)
230 goto err_out;
231
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 }
239
240 info->list[i].map.name = dev_name(&dev->dev);
241 info->list[i].map.phys = res.start;
Wolfram Sang2763c502009-07-17 17:54:14 +0200242 info->list[i].map.size = res_size;
Ian Munsie766f2712010-10-01 17:06:08 +1000243 info->list[i].map.bankwidth = be32_to_cpup(width);
Stefan Roese143070e2009-04-16 14:10:45 +0200244
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 if (probe_type) {
257 info->list[i].mtd = do_map_probe(probe_type,
258 &info->list[i].map);
259 } else {
260 info->list[i].mtd = obsolete_probe(dev,
261 &info->list[i].map);
262 }
263 mtd_list[i] = info->list[i].mtd;
264
265 err = -ENXIO;
266 if (!info->list[i].mtd) {
267 dev_err(&dev->dev, "do_map_probe() failed\n");
268 goto err_out;
269 } else {
270 info->list_size++;
271 }
272 info->list[i].mtd->owner = THIS_MODULE;
273 info->list[i].mtd->dev.parent = &dev->dev;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300274 }
275
Stefan Roese143070e2009-04-16 14:10:45 +0200276 err = 0;
277 if (info->list_size == 1) {
278 info->cmtd = info->list[0].mtd;
279 } else if (info->list_size > 1) {
280 /*
281 * We detected multiple devices. Concatenate them together.
282 */
Stefan Roese143070e2009-04-16 14:10:45 +0200283 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
284 dev_name(&dev->dev));
285 if (info->cmtd == NULL)
286 err = -ENXIO;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300287 }
Stefan Roese143070e2009-04-16 14:10:45 +0200288 if (err)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300289 goto err_out;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300290
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400291 ppdata.of_node = dp;
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700292 part_probe_types = of_get_probes(dp);
Stefan Roese143070e2009-04-16 14:10:45 +0200293 err = parse_mtd_partitions(info->cmtd, part_probe_types,
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400294 &info->parts, &ppdata);
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700295 if (err < 0) {
296 of_free_probes(part_probe_types);
Julia Lawall00b275d2010-06-01 16:34:20 +0200297 goto err_out;
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700298 }
299 of_free_probes(part_probe_types);
Scott Wood9a310d22008-01-15 17:54:43 -0600300
Jamie Iles984e6d82011-05-23 10:22:45 +0100301 mtd_device_register(info->cmtd, info->parts, err);
Stefan Roese143070e2009-04-16 14:10:45 +0200302
303 kfree(mtd_list);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300304
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300305 return 0;
306
307err_out:
Stefan Roese143070e2009-04-16 14:10:45 +0200308 kfree(mtd_list);
vimal singhad4fbc72009-07-30 20:54:27 +0530309err_flash_remove:
David Gibsonc4d5e372007-09-20 11:22:25 +1000310 of_flash_remove(dev);
Stefan Roese143070e2009-04-16 14:10:45 +0200311
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300312 return err;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300313}
314
David Gibsonc4d5e372007-09-20 11:22:25 +1000315static struct of_device_id of_flash_match[] = {
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300316 {
David Gibson20991722007-09-07 13:23:53 +1000317 .compatible = "cfi-flash",
318 .data = (void *)"cfi_probe",
319 },
320 {
321 /* FIXME: JEDEC chips can't be safely and reliably
322 * probed, although the mtd code gets it right in
323 * practice most of the time. We should use the
324 * vendor and device ids specified by the binding to
325 * bypass the heuristic probe code, but the mtd layer
326 * provides, at present, no interface for doing so
327 * :(. */
328 .compatible = "jedec-flash",
329 .data = (void *)"jedec_probe",
330 },
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300331 {
Wolfram Sangfc28c39f2009-07-17 14:39:23 +0200332 .compatible = "mtd-ram",
333 .data = (void *)"map_ram",
334 },
335 {
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300336 .type = "rom",
337 .compatible = "direct-mapped"
338 },
339 { },
340};
David Gibsonc4d5e372007-09-20 11:22:25 +1000341MODULE_DEVICE_TABLE(of, of_flash_match);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300342
Grant Likely1c48a5c2011-02-17 02:43:24 -0700343static struct platform_driver of_flash_driver = {
Grant Likely40182942010-04-13 16:13:02 -0700344 .driver = {
345 .name = "of-flash",
346 .owner = THIS_MODULE,
347 .of_match_table = of_flash_match,
348 },
David Gibsonc4d5e372007-09-20 11:22:25 +1000349 .probe = of_flash_probe,
350 .remove = of_flash_remove,
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300351};
352
David Gibsonc4d5e372007-09-20 11:22:25 +1000353static int __init of_flash_init(void)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300354{
Grant Likely1c48a5c2011-02-17 02:43:24 -0700355 return platform_driver_register(&of_flash_driver);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300356}
357
David Gibsonc4d5e372007-09-20 11:22:25 +1000358static void __exit of_flash_exit(void)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300359{
Grant Likely1c48a5c2011-02-17 02:43:24 -0700360 platform_driver_unregister(&of_flash_driver);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300361}
362
David Gibsonc4d5e372007-09-20 11:22:25 +1000363module_init(of_flash_init);
364module_exit(of_flash_exit);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300365
366MODULE_LICENSE("GPL");
367MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
David Gibsonc4d5e372007-09-20 11:22:25 +1000368MODULE_DESCRIPTION("Device tree based MTD map driver");