• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
of_flash_remove(struct platform_device * dev)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. */
obsolete_probe(struct platform_device * dev,struct map_info * map)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 
of_get_probes(struct device_node * dp)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 
of_free_probes(const char * const * probes)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[];
of_flash_probe(struct platform_device * dev)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