blob: d11109762ac5ca311a1f9bb90711bca0855ebc83 [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;
Stefan Roese143070e2009-04-16 14:10:45 +020037 int list_size; /* number of elements in of_flash_list */
38 struct of_flash_list list[0];
Vitaly Woola2c2fe42006-12-06 13:17:49 +030039};
40
Grant Likely2dc11582010-08-06 09:25:50 -060041static int of_flash_remove(struct platform_device *dev)
Vitaly Woola2c2fe42006-12-06 13:17:49 +030042{
David Gibsonc4d5e372007-09-20 11:22:25 +100043 struct of_flash *info;
Stefan Roese143070e2009-04-16 14:10:45 +020044 int i;
Vitaly Woola2c2fe42006-12-06 13:17:49 +030045
46 info = dev_get_drvdata(&dev->dev);
David Gibsonc4d5e372007-09-20 11:22:25 +100047 if (!info)
Vitaly Woola2c2fe42006-12-06 13:17:49 +030048 return 0;
49 dev_set_drvdata(&dev->dev, NULL);
50
Stefan Roese143070e2009-04-16 14:10:45 +020051 if (info->cmtd != info->list[0].mtd) {
Jamie Iles984e6d82011-05-23 10:22:45 +010052 mtd_device_unregister(info->cmtd);
Stefan Roese143070e2009-04-16 14:10:45 +020053 mtd_concat_destroy(info->cmtd);
54 }
Stefan Roese143070e2009-04-16 14:10:45 +020055
Dmitry Eremin-Solenikovf44dcbd2011-06-02 17:59:59 +040056 if (info->cmtd)
Jamie Iles984e6d82011-05-23 10:22:45 +010057 mtd_device_unregister(info->cmtd);
Vitaly Woola2c2fe42006-12-06 13:17:49 +030058
Stefan Roese143070e2009-04-16 14:10:45 +020059 for (i = 0; i < info->list_size; i++) {
60 if (info->list[i].mtd)
61 map_destroy(info->list[i].mtd);
Vitaly Woola2c2fe42006-12-06 13:17:49 +030062
Stefan Roese143070e2009-04-16 14:10:45 +020063 if (info->list[i].map.virt)
64 iounmap(info->list[i].map.virt);
65
66 if (info->list[i].res) {
67 release_resource(info->list[i].res);
68 kfree(info->list[i].res);
69 }
Vitaly Woola2c2fe42006-12-06 13:17:49 +030070 }
Vitaly Woola2c2fe42006-12-06 13:17:49 +030071 return 0;
72}
73
Artem Bityutskiycce2a022013-03-12 10:42:56 +020074static const char * const rom_probe_types[] = {
75 "cfi_probe", "jedec_probe", "map_rom" };
76
David Gibson20991722007-09-07 13:23:53 +100077/* 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. */
Bill Pemberton06f25512012-11-19 13:23:07 -050080static struct mtd_info *obsolete_probe(struct platform_device *dev,
Greg Kroah-Hartmand8929942012-12-21 13:19:05 -080081 struct map_info *map)
David Gibson20991722007-09-07 13:23:53 +100082{
Grant Likely61c7a082010-04-13 16:12:29 -070083 struct device_node *dp = dev->dev.of_node;
David Gibson20991722007-09-07 13:23:53 +100084 const char *of_probe;
85 struct mtd_info *mtd;
David Gibson20991722007-09-07 13:23:53 +100086 int i;
87
88 dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
89 "flash binding\n");
90
91 of_probe = of_get_property(dp, "probe-type", NULL);
92 if (!of_probe) {
93 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
94 mtd = do_map_probe(rom_probe_types[i], map);
95 if (mtd)
96 return mtd;
97 }
98 return NULL;
99 } else if (strcmp(of_probe, "CFI") == 0) {
100 return do_map_probe("cfi_probe", map);
101 } else if (strcmp(of_probe, "JEDEC") == 0) {
102 return do_map_probe("jedec_probe", map);
103 } else {
104 if (strcmp(of_probe, "ROM") != 0)
David Gibsonc4d5e372007-09-20 11:22:25 +1000105 dev_warn(&dev->dev, "obsolete_probe: don't know probe "
106 "type '%s', mapping as rom\n", of_probe);
David Gibson20991722007-09-07 13:23:53 +1000107 return do_map_probe("mtd_rom", map);
108 }
109}
110
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700111/* When partitions are set we look for a linux,part-probe property which
112 specifies the list of partition probers to use. If none is given then the
113 default is use. These take precedence over other device tree
114 information. */
Artem Bityutskiycce2a022013-03-12 10:42:56 +0200115static const char * const part_probe_types_def[] = {
116 "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
117
118static const char * const *of_get_probes(struct device_node *dp)
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700119{
120 const char *cp;
121 int cplen;
122 unsigned int l;
123 unsigned int count;
124 const char **res;
125
126 cp = of_get_property(dp, "linux,part-probe", &cplen);
127 if (cp == NULL)
128 return part_probe_types_def;
129
130 count = 0;
131 for (l = 0; l != cplen; l++)
132 if (cp[l] == 0)
133 count++;
134
135 res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
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
Artem Bityutskiycce2a022013-03-12 10:42:56 +0200147static void of_free_probes(const char * const *probes)
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700148{
149 if (probes != part_probe_types_def)
150 kfree(probes);
151}
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700152
Grant Likelyb1608d62011-05-18 11:19:24 -0600153static struct of_device_id of_flash_match[];
Bill Pemberton06f25512012-11-19 13:23:07 -0500154static int of_flash_probe(struct platform_device *dev)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300155{
Artem Bityutskiycce2a022013-03-12 10:42:56 +0200156 const char * const *part_probe_types;
Grant Likelyb1608d62011-05-18 11:19:24 -0600157 const struct of_device_id *match;
Grant Likely61c7a082010-04-13 16:12:29 -0700158 struct device_node *dp = dev->dev.of_node;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300159 struct resource res;
David Gibsonc4d5e372007-09-20 11:22:25 +1000160 struct of_flash *info;
Grant Likely1c48a5c2011-02-17 02:43:24 -0700161 const char *probe_type;
Ian Munsie766f2712010-10-01 17:06:08 +1000162 const __be32 *width;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300163 int err;
Stefan Roese143070e2009-04-16 14:10:45 +0200164 int i;
165 int count;
Ian Munsie766f2712010-10-01 17:06:08 +1000166 const __be32 *p;
Stefan Roese143070e2009-04-16 14:10:45 +0200167 int reg_tuple_size;
168 struct mtd_info **mtd_list = NULL;
Wolfram Sang2763c502009-07-17 17:54:14 +0200169 resource_size_t res_size;
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400170 struct mtd_part_parser_data ppdata;
Stefan Roesed0788ce2012-08-17 15:22:32 +0200171 bool map_indirect;
Baruch Siach7dfe4be2012-12-23 13:10:50 +0200172 const char *mtd_name = NULL;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300173
Grant Likelyb1608d62011-05-18 11:19:24 -0600174 match = of_match_device(of_flash_match, &dev->dev);
175 if (!match)
Grant Likely1c48a5c2011-02-17 02:43:24 -0700176 return -EINVAL;
Grant Likelyb1608d62011-05-18 11:19:24 -0600177 probe_type = match->data;
Grant Likely1c48a5c2011-02-17 02:43:24 -0700178
Stefan Roese143070e2009-04-16 14:10:45 +0200179 reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
180
Jean-Christophe PLAGNIOL-VILLARDd68cbdd2012-11-07 16:32:16 +0100181 of_property_read_string(dp, "linux,mtd-name", &mtd_name);
182
Stefan Roese143070e2009-04-16 14:10:45 +0200183 /*
184 * Get number of "reg" tuples. Scan for MTD devices on area's
185 * described by each "reg" region. This makes it possible (including
186 * the concat support) to support the Intel P30 48F4400 chips which
187 * consists internally of 2 non-identical NOR chips on one die.
188 */
189 p = of_get_property(dp, "reg", &count);
190 if (count % reg_tuple_size != 0) {
191 dev_err(&dev->dev, "Malformed reg property on %s\n",
Grant Likely61c7a082010-04-13 16:12:29 -0700192 dev->dev.of_node->full_name);
Stefan Roese143070e2009-04-16 14:10:45 +0200193 err = -EINVAL;
vimal singhad4fbc72009-07-30 20:54:27 +0530194 goto err_flash_remove;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300195 }
Stefan Roese143070e2009-04-16 14:10:45 +0200196 count /= reg_tuple_size;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300197
Stefan Roesed0788ce2012-08-17 15:22:32 +0200198 map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
199
David Gibsonc4d5e372007-09-20 11:22:25 +1000200 err = -ENOMEM;
Ezequiel Garciaeb820382013-01-25 11:50:27 -0300201 info = devm_kzalloc(&dev->dev,
202 sizeof(struct of_flash) +
203 sizeof(struct of_flash_list) * count, GFP_KERNEL);
Stefan Roese143070e2009-04-16 14:10:45 +0200204 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
Jean-Christophe PLAGNIOL-VILLARDd68cbdd2012-11-07 16:32:16 +0100240 info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
Stefan Roese143070e2009-04-16 14:10:45 +0200241 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 Roese1648eaa2013-01-18 13:10:05 +0100244 info->list[i].map.device_node = dp;
Stefan Roese143070e2009-04-16 14:10:45 +0200245
246 err = -ENOMEM;
247 info->list[i].map.virt = ioremap(info->list[i].map.phys,
248 info->list[i].map.size);
249 if (!info->list[i].map.virt) {
250 dev_err(&dev->dev, "Failed to ioremap() flash"
251 " region\n");
252 goto err_out;
253 }
254
255 simple_map_init(&info->list[i].map);
256
Stefan Roesed0788ce2012-08-17 15:22:32 +0200257 /*
258 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
259 * may cause problems with JFFS2 usage, as the local bus (LPB)
260 * doesn't support unaligned accesses as implemented in the
261 * JFFS2 code via memcpy(). By setting NO_XIP, the
262 * flash will not be exposed directly to the MTD users
263 * (e.g. JFFS2) any more.
264 */
265 if (map_indirect)
266 info->list[i].map.phys = NO_XIP;
267
Stefan Roese143070e2009-04-16 14:10:45 +0200268 if (probe_type) {
269 info->list[i].mtd = do_map_probe(probe_type,
270 &info->list[i].map);
271 } else {
272 info->list[i].mtd = obsolete_probe(dev,
273 &info->list[i].map);
274 }
275 mtd_list[i] = info->list[i].mtd;
276
277 err = -ENXIO;
278 if (!info->list[i].mtd) {
279 dev_err(&dev->dev, "do_map_probe() failed\n");
280 goto err_out;
281 } else {
282 info->list_size++;
283 }
284 info->list[i].mtd->owner = THIS_MODULE;
285 info->list[i].mtd->dev.parent = &dev->dev;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300286 }
287
Stefan Roese143070e2009-04-16 14:10:45 +0200288 err = 0;
Anton Prinse58a66d2012-11-27 16:38:16 +0100289 info->cmtd = NULL;
Stefan Roese143070e2009-04-16 14:10:45 +0200290 if (info->list_size == 1) {
291 info->cmtd = info->list[0].mtd;
292 } else if (info->list_size > 1) {
293 /*
294 * We detected multiple devices. Concatenate them together.
295 */
Stefan Roese143070e2009-04-16 14:10:45 +0200296 info->cmtd = mtd_concat_create(mtd_list, info->list_size,
297 dev_name(&dev->dev));
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300298 }
Anton Prinse58a66d2012-11-27 16:38:16 +0100299 if (info->cmtd == NULL)
300 err = -ENXIO;
301
Stefan Roese143070e2009-04-16 14:10:45 +0200302 if (err)
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300303 goto err_out;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300304
Dmitry Eremin-Solenikov5f4ba9f2011-05-30 01:02:21 +0400305 ppdata.of_node = dp;
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700306 part_probe_types = of_get_probes(dp);
Dmitry Eremin-Solenikovf44dcbd2011-06-02 17:59:59 +0400307 mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
308 NULL, 0);
Jason Gunthorpe9d5da3a2010-03-09 12:27:56 -0700309 of_free_probes(part_probe_types);
Scott Wood9a310d22008-01-15 17:54:43 -0600310
Stefan Roese143070e2009-04-16 14:10:45 +0200311 kfree(mtd_list);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300312
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300313 return 0;
314
315err_out:
Stefan Roese143070e2009-04-16 14:10:45 +0200316 kfree(mtd_list);
vimal singhad4fbc72009-07-30 20:54:27 +0530317err_flash_remove:
David Gibsonc4d5e372007-09-20 11:22:25 +1000318 of_flash_remove(dev);
Stefan Roese143070e2009-04-16 14:10:45 +0200319
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300320 return err;
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300321}
322
David Gibsonc4d5e372007-09-20 11:22:25 +1000323static struct of_device_id of_flash_match[] = {
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300324 {
David Gibson20991722007-09-07 13:23:53 +1000325 .compatible = "cfi-flash",
326 .data = (void *)"cfi_probe",
327 },
328 {
329 /* FIXME: JEDEC chips can't be safely and reliably
330 * probed, although the mtd code gets it right in
331 * practice most of the time. We should use the
332 * vendor and device ids specified by the binding to
333 * bypass the heuristic probe code, but the mtd layer
334 * provides, at present, no interface for doing so
335 * :(. */
336 .compatible = "jedec-flash",
337 .data = (void *)"jedec_probe",
338 },
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300339 {
Wolfram Sangfc28c39f2009-07-17 14:39:23 +0200340 .compatible = "mtd-ram",
341 .data = (void *)"map_ram",
342 },
343 {
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300344 .type = "rom",
345 .compatible = "direct-mapped"
346 },
347 { },
348};
David Gibsonc4d5e372007-09-20 11:22:25 +1000349MODULE_DEVICE_TABLE(of, of_flash_match);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300350
Grant Likely1c48a5c2011-02-17 02:43:24 -0700351static struct platform_driver of_flash_driver = {
Grant Likely40182942010-04-13 16:13:02 -0700352 .driver = {
353 .name = "of-flash",
354 .owner = THIS_MODULE,
355 .of_match_table = of_flash_match,
356 },
David Gibsonc4d5e372007-09-20 11:22:25 +1000357 .probe = of_flash_probe,
358 .remove = of_flash_remove,
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300359};
360
Axel Linf99640d2011-11-27 20:45:03 +0800361module_platform_driver(of_flash_driver);
Vitaly Woola2c2fe42006-12-06 13:17:49 +0300362
363MODULE_LICENSE("GPL");
364MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
David Gibsonc4d5e372007-09-20 11:22:25 +1000365MODULE_DESCRIPTION("Device tree based MTD map driver");