2 * Flash mappings described by the OF (or flattened) device tree
4 * Copyright (C) 2006 MontaVista Software Inc.
5 * Author: Vitaly Wool <vwool@ru.mvista.com>
7 * Revised to handle newer style flash binding by:
8 * Copyright (C) 2007 David Gibson, IBM Corporation.
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.
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/mtd/cfi_endian.h>
25 #include <linux/of_address.h>
26 #include <linux/of_platform.h>
27 #include <linux/slab.h>
28 #include "physmap_of_gemini.h"
29 #include "physmap_of_versatile.h"
31 struct of_flash_list
{
37 struct mtd_info
*cmtd
;
38 int list_size
; /* number of elements in of_flash_list */
39 struct of_flash_list list
[0];
42 static int of_flash_remove(struct platform_device
*dev
)
44 struct of_flash
*info
;
47 info
= dev_get_drvdata(&dev
->dev
);
50 dev_set_drvdata(&dev
->dev
, NULL
);
53 mtd_device_unregister(info
->cmtd
);
54 if (info
->cmtd
!= info
->list
[0].mtd
)
55 mtd_concat_destroy(info
->cmtd
);
58 for (i
= 0; i
< info
->list_size
; i
++)
59 if (info
->list
[i
].mtd
)
60 map_destroy(info
->list
[i
].mtd
);
65 static const char * const rom_probe_types
[] = {
66 "cfi_probe", "jedec_probe", "map_rom" };
68 /* Helper function to handle probing of the obsolete "direct-mapped"
69 * compatible binding, which has an extra "probe-type" property
70 * describing the type of flash probe necessary. */
71 static struct mtd_info
*obsolete_probe(struct platform_device
*dev
,
74 struct device_node
*dp
= dev
->dev
.of_node
;
79 dev_warn(&dev
->dev
, "Device tree uses obsolete \"direct-mapped\" "
82 of_probe
= of_get_property(dp
, "probe-type", NULL
);
84 for (i
= 0; i
< ARRAY_SIZE(rom_probe_types
); i
++) {
85 mtd
= do_map_probe(rom_probe_types
[i
], map
);
90 } else if (strcmp(of_probe
, "CFI") == 0) {
91 return do_map_probe("cfi_probe", map
);
92 } else if (strcmp(of_probe
, "JEDEC") == 0) {
93 return do_map_probe("jedec_probe", map
);
95 if (strcmp(of_probe
, "ROM") != 0)
96 dev_warn(&dev
->dev
, "obsolete_probe: don't know probe "
97 "type '%s', mapping as rom\n", of_probe
);
98 return do_map_probe("map_rom", map
);
102 /* When partitions are set we look for a linux,part-probe property which
103 specifies the list of partition probers to use. If none is given then the
104 default is use. These take precedence over other device tree
106 static const char * const part_probe_types_def
[] = {
107 "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL
};
109 static const char * const *of_get_probes(struct device_node
*dp
)
114 count
= of_property_count_strings(dp
, "linux,part-probe");
116 return part_probe_types_def
;
118 res
= kcalloc(count
+ 1, sizeof(*res
), GFP_KERNEL
);
122 count
= of_property_read_string_array(dp
, "linux,part-probe", res
,
130 static void of_free_probes(const char * const *probes
)
132 if (probes
!= part_probe_types_def
)
136 static const struct of_device_id of_flash_match
[];
137 static int of_flash_probe(struct platform_device
*dev
)
139 const char * const *part_probe_types
;
140 const struct of_device_id
*match
;
141 struct device_node
*dp
= dev
->dev
.of_node
;
143 struct of_flash
*info
;
144 const char *probe_type
;
151 struct mtd_info
**mtd_list
= NULL
;
152 resource_size_t res_size
;
154 const char *mtd_name
= NULL
;
156 match
= of_match_device(of_flash_match
, &dev
->dev
);
159 probe_type
= match
->data
;
161 reg_tuple_size
= (of_n_addr_cells(dp
) + of_n_size_cells(dp
)) * sizeof(u32
);
163 of_property_read_string(dp
, "linux,mtd-name", &mtd_name
);
166 * Get number of "reg" tuples. Scan for MTD devices on area's
167 * described by each "reg" region. This makes it possible (including
168 * the concat support) to support the Intel P30 48F4400 chips which
169 * consists internally of 2 non-identical NOR chips on one die.
171 p
= of_get_property(dp
, "reg", &count
);
172 if (!p
|| count
% reg_tuple_size
!= 0) {
173 dev_err(&dev
->dev
, "Malformed reg property on %pOF\n",
176 goto err_flash_remove
;
178 count
/= reg_tuple_size
;
180 map_indirect
= of_property_read_bool(dp
, "no-unaligned-direct-access");
183 info
= devm_kzalloc(&dev
->dev
,
184 sizeof(struct of_flash
) +
185 sizeof(struct of_flash_list
) * count
, GFP_KERNEL
);
187 goto err_flash_remove
;
189 dev_set_drvdata(&dev
->dev
, info
);
191 mtd_list
= kcalloc(count
, sizeof(*mtd_list
), GFP_KERNEL
);
193 goto err_flash_remove
;
195 for (i
= 0; i
< count
; i
++) {
197 if (of_address_to_resource(dp
, i
, &res
)) {
199 * Continue with next register tuple if this
200 * one is not mappable
205 dev_dbg(&dev
->dev
, "of_flash device: %pR\n", &res
);
208 res_size
= resource_size(&res
);
209 info
->list
[i
].map
.virt
= devm_ioremap_resource(&dev
->dev
, &res
);
210 if (IS_ERR(info
->list
[i
].map
.virt
)) {
211 err
= PTR_ERR(info
->list
[i
].map
.virt
);
216 width
= of_get_property(dp
, "bank-width", NULL
);
218 dev_err(&dev
->dev
, "Can't get bank width from device"
223 info
->list
[i
].map
.name
= mtd_name
?: dev_name(&dev
->dev
);
224 info
->list
[i
].map
.phys
= res
.start
;
225 info
->list
[i
].map
.size
= res_size
;
226 info
->list
[i
].map
.bankwidth
= be32_to_cpup(width
);
227 info
->list
[i
].map
.device_node
= dp
;
229 if (of_property_read_bool(dp
, "big-endian"))
230 info
->list
[i
].map
.swap
= CFI_BIG_ENDIAN
;
231 else if (of_property_read_bool(dp
, "little-endian"))
232 info
->list
[i
].map
.swap
= CFI_LITTLE_ENDIAN
;
234 err
= of_flash_probe_gemini(dev
, dp
, &info
->list
[i
].map
);
237 err
= of_flash_probe_versatile(dev
, dp
, &info
->list
[i
].map
);
241 simple_map_init(&info
->list
[i
].map
);
244 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
245 * may cause problems with JFFS2 usage, as the local bus (LPB)
246 * doesn't support unaligned accesses as implemented in the
247 * JFFS2 code via memcpy(). By setting NO_XIP, the
248 * flash will not be exposed directly to the MTD users
249 * (e.g. JFFS2) any more.
252 info
->list
[i
].map
.phys
= NO_XIP
;
255 info
->list
[i
].mtd
= do_map_probe(probe_type
,
258 info
->list
[i
].mtd
= obsolete_probe(dev
,
262 /* Fall back to mapping region as ROM */
263 if (!info
->list
[i
].mtd
) {
265 "do_map_probe() failed for type %s\n",
268 info
->list
[i
].mtd
= do_map_probe("map_rom",
271 mtd_list
[i
] = info
->list
[i
].mtd
;
274 if (!info
->list
[i
].mtd
) {
275 dev_err(&dev
->dev
, "do_map_probe() failed\n");
280 info
->list
[i
].mtd
->dev
.parent
= &dev
->dev
;
285 if (info
->list_size
== 1) {
286 info
->cmtd
= info
->list
[0].mtd
;
287 } else if (info
->list_size
> 1) {
289 * We detected multiple devices. Concatenate them together.
291 info
->cmtd
= mtd_concat_create(mtd_list
, info
->list_size
,
292 dev_name(&dev
->dev
));
294 if (info
->cmtd
== NULL
)
300 info
->cmtd
->dev
.parent
= &dev
->dev
;
301 mtd_set_of_node(info
->cmtd
, dp
);
302 part_probe_types
= of_get_probes(dp
);
303 if (!part_probe_types
) {
307 mtd_device_parse_register(info
->cmtd
, part_probe_types
, NULL
,
309 of_free_probes(part_probe_types
);
318 of_flash_remove(dev
);
323 static const struct of_device_id of_flash_match
[] = {
325 .compatible
= "cfi-flash",
326 .data
= (void *)"cfi_probe",
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
336 .compatible
= "jedec-flash",
337 .data
= (void *)"jedec_probe",
340 .compatible
= "mtd-ram",
341 .data
= (void *)"map_ram",
344 .compatible
= "mtd-rom",
345 .data
= (void *)"map_rom",
349 .compatible
= "direct-mapped"
353 MODULE_DEVICE_TABLE(of
, of_flash_match
);
355 static struct platform_driver of_flash_driver
= {
358 .of_match_table
= of_flash_match
,
360 .probe
= of_flash_probe
,
361 .remove
= of_flash_remove
,
364 module_platform_driver(of_flash_driver
);
366 MODULE_LICENSE("GPL");
367 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
368 MODULE_DESCRIPTION("Device tree based MTD map driver");