1 // SPDX-License-Identifier: GPL-2.0+
3 * Normal mappings of chips in physical memory
5 * Copyright (C) 2003 MontaVista Software Inc.
6 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
8 * 031022 - [jsun] add run-time configure and partition setup
10 * Device tree support:
11 * Copyright (C) 2006 MontaVista Software Inc.
12 * Author: Vitaly Wool <vwool@ru.mvista.com>
14 * Revised to handle newer style flash binding by:
15 * Copyright (C) 2007 David Gibson, IBM Corporation.
17 * GPIO address extension:
18 * Handle the case where a flash device is mostly addressed using physical
19 * line and supplemented by GPIOs. This way you can hook up say a 8MiB flash
20 * to a 2MiB memory range and use the GPIOs to select a particular range.
22 * Copyright © 2000 Nicolas Pitre <nico@cam.org>
23 * Copyright © 2005-2009 Analog Devices Inc.
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/init.h>
30 #include <linux/slab.h>
31 #include <linux/device.h>
32 #include <linux/platform_device.h>
33 #include <linux/mtd/mtd.h>
34 #include <linux/mtd/map.h>
35 #include <linux/mtd/partitions.h>
36 #include <linux/mtd/physmap.h>
37 #include <linux/mtd/concat.h>
38 #include <linux/mtd/cfi_endian.h>
40 #include <linux/of_device.h>
41 #include <linux/gpio/consumer.h>
43 #include "physmap-gemini.h"
44 #include "physmap-versatile.h"
46 struct physmap_flash_info
{
48 struct mtd_info
**mtds
;
49 struct mtd_info
*cmtd
;
50 struct map_info
*maps
;
53 const char *probe_type
;
54 const char * const *part_types
;
56 const struct mtd_partition
*parts
;
57 struct gpio_descs
*gpios
;
58 unsigned int gpio_values
;
59 unsigned int win_order
;
62 static int physmap_flash_remove(struct platform_device
*dev
)
64 struct physmap_flash_info
*info
;
65 struct physmap_flash_data
*physmap_data
;
68 info
= platform_get_drvdata(dev
);
73 err
= mtd_device_unregister(info
->cmtd
);
77 if (info
->cmtd
!= info
->mtds
[0])
78 mtd_concat_destroy(info
->cmtd
);
81 for (i
= 0; i
< info
->nmaps
; i
++) {
83 map_destroy(info
->mtds
[i
]);
86 physmap_data
= dev_get_platdata(&dev
->dev
);
87 if (physmap_data
&& physmap_data
->exit
)
88 physmap_data
->exit(dev
);
93 static void physmap_set_vpp(struct map_info
*map
, int state
)
95 struct platform_device
*pdev
;
96 struct physmap_flash_data
*physmap_data
;
97 struct physmap_flash_info
*info
;
100 pdev
= (struct platform_device
*)map
->map_priv_1
;
101 physmap_data
= dev_get_platdata(&pdev
->dev
);
103 if (!physmap_data
->set_vpp
)
106 info
= platform_get_drvdata(pdev
);
108 spin_lock_irqsave(&info
->vpp_lock
, flags
);
110 if (++info
->vpp_refcnt
== 1) /* first nested 'on' */
111 physmap_data
->set_vpp(pdev
, 1);
113 if (--info
->vpp_refcnt
== 0) /* last nested 'off' */
114 physmap_data
->set_vpp(pdev
, 0);
116 spin_unlock_irqrestore(&info
->vpp_lock
, flags
);
119 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR)
120 static void physmap_set_addr_gpios(struct physmap_flash_info
*info
,
125 ofs
>>= info
->win_order
;
126 if (info
->gpio_values
== ofs
)
129 for (i
= 0; i
< info
->gpios
->ndescs
; i
++) {
130 if ((BIT(i
) & ofs
) == (BIT(i
) & info
->gpio_values
))
133 gpiod_set_value(info
->gpios
->desc
[i
], !!(BIT(i
) & ofs
));
137 #define win_mask(order) (BIT(order) - 1)
139 static map_word
physmap_addr_gpios_read(struct map_info
*map
,
142 struct platform_device
*pdev
;
143 struct physmap_flash_info
*info
;
147 pdev
= (struct platform_device
*)map
->map_priv_1
;
148 info
= platform_get_drvdata(pdev
);
149 physmap_set_addr_gpios(info
, ofs
);
151 word
= readw(map
->virt
+ (ofs
& win_mask(info
->win_order
)));
156 static void physmap_addr_gpios_copy_from(struct map_info
*map
, void *buf
,
157 unsigned long ofs
, ssize_t len
)
159 struct platform_device
*pdev
;
160 struct physmap_flash_info
*info
;
162 pdev
= (struct platform_device
*)map
->map_priv_1
;
163 info
= platform_get_drvdata(pdev
);
166 unsigned int winofs
= ofs
& win_mask(info
->win_order
);
167 unsigned int chunklen
= min_t(unsigned int, len
,
168 BIT(info
->win_order
) - winofs
);
170 physmap_set_addr_gpios(info
, ofs
);
171 memcpy_fromio(buf
, map
->virt
+ winofs
, chunklen
);
178 static void physmap_addr_gpios_write(struct map_info
*map
, map_word mw
,
181 struct platform_device
*pdev
;
182 struct physmap_flash_info
*info
;
185 pdev
= (struct platform_device
*)map
->map_priv_1
;
186 info
= platform_get_drvdata(pdev
);
187 physmap_set_addr_gpios(info
, ofs
);
190 writew(word
, map
->virt
+ (ofs
& win_mask(info
->win_order
)));
193 static void physmap_addr_gpios_copy_to(struct map_info
*map
, unsigned long ofs
,
194 const void *buf
, ssize_t len
)
196 struct platform_device
*pdev
;
197 struct physmap_flash_info
*info
;
199 pdev
= (struct platform_device
*)map
->map_priv_1
;
200 info
= platform_get_drvdata(pdev
);
203 unsigned int winofs
= ofs
& win_mask(info
->win_order
);
204 unsigned int chunklen
= min_t(unsigned int, len
,
205 BIT(info
->win_order
) - winofs
);
207 physmap_set_addr_gpios(info
, ofs
);
208 memcpy_toio(map
->virt
+ winofs
, buf
, chunklen
);
215 static int physmap_addr_gpios_map_init(struct map_info
*map
)
218 map
->read
= physmap_addr_gpios_read
;
219 map
->copy_from
= physmap_addr_gpios_copy_from
;
220 map
->write
= physmap_addr_gpios_write
;
221 map
->copy_to
= physmap_addr_gpios_copy_to
;
226 static int physmap_addr_gpios_map_init(struct map_info
*map
)
232 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF)
233 static const struct of_device_id of_flash_match
[] = {
235 .compatible
= "cfi-flash",
240 * FIXME: JEDEC chips can't be safely and reliably
241 * probed, although the mtd code gets it right in
242 * practice most of the time. We should use the
243 * vendor and device ids specified by the binding to
244 * bypass the heuristic probe code, but the mtd layer
245 * provides, at present, no interface for doing so
248 .compatible
= "jedec-flash",
249 .data
= "jedec_probe",
252 .compatible
= "mtd-ram",
256 .compatible
= "mtd-rom",
261 .compatible
= "direct-mapped"
265 MODULE_DEVICE_TABLE(of
, of_flash_match
);
267 static const char * const of_default_part_probes
[] = {
268 "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL
271 static const char * const *of_get_part_probes(struct platform_device
*dev
)
273 struct device_node
*dp
= dev
->dev
.of_node
;
277 count
= of_property_count_strings(dp
, "linux,part-probe");
279 return of_default_part_probes
;
281 res
= devm_kcalloc(&dev
->dev
, count
+ 1, sizeof(*res
), GFP_KERNEL
);
285 count
= of_property_read_string_array(dp
, "linux,part-probe", res
,
293 static const char *of_select_probe_type(struct platform_device
*dev
)
295 struct device_node
*dp
= dev
->dev
.of_node
;
296 const struct of_device_id
*match
;
297 const char *probe_type
;
299 match
= of_match_device(of_flash_match
, &dev
->dev
);
300 probe_type
= match
->data
;
305 "Device tree uses obsolete \"direct-mapped\" flash binding\n");
307 of_property_read_string(dp
, "probe-type", &probe_type
);
311 if (!strcmp(probe_type
, "CFI")) {
312 probe_type
= "cfi_probe";
313 } else if (!strcmp(probe_type
, "JEDEC")) {
314 probe_type
= "jedec_probe";
315 } else if (!strcmp(probe_type
, "ROM")) {
316 probe_type
= "map_rom";
319 "obsolete_probe: don't know probe type '%s', mapping as rom\n",
321 probe_type
= "map_rom";
327 static int physmap_flash_of_init(struct platform_device
*dev
)
329 struct physmap_flash_info
*info
= platform_get_drvdata(dev
);
330 struct device_node
*dp
= dev
->dev
.of_node
;
331 const char *mtd_name
= NULL
;
340 info
->probe_type
= of_select_probe_type(dev
);
342 info
->part_types
= of_get_part_probes(dev
);
343 if (!info
->part_types
)
346 of_property_read_string(dp
, "linux,mtd-name", &mtd_name
);
348 map_indirect
= of_property_read_bool(dp
, "no-unaligned-direct-access");
350 err
= of_property_read_u32(dp
, "bank-width", &bankwidth
);
352 dev_err(&dev
->dev
, "Can't get bank width from device tree\n");
356 if (of_property_read_bool(dp
, "big-endian"))
357 swap
= CFI_BIG_ENDIAN
;
358 else if (of_property_read_bool(dp
, "little-endian"))
359 swap
= CFI_LITTLE_ENDIAN
;
361 for (i
= 0; i
< info
->nmaps
; i
++) {
362 info
->maps
[i
].name
= mtd_name
;
363 info
->maps
[i
].swap
= swap
;
364 info
->maps
[i
].bankwidth
= bankwidth
;
365 info
->maps
[i
].device_node
= dp
;
367 err
= of_flash_probe_gemini(dev
, dp
, &info
->maps
[i
]);
371 err
= of_flash_probe_versatile(dev
, dp
, &info
->maps
[i
]);
376 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
377 * may cause problems with JFFS2 usage, as the local bus (LPB)
378 * doesn't support unaligned accesses as implemented in the
379 * JFFS2 code via memcpy(). By setting NO_XIP, the
380 * flash will not be exposed directly to the MTD users
381 * (e.g. JFFS2) any more.
384 info
->maps
[i
].phys
= NO_XIP
;
389 #else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
390 #define of_flash_match NULL
392 static int physmap_flash_of_init(struct platform_device
*dev
)
396 #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
398 static const char * const rom_probe_types
[] = {
399 "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom",
402 static const char * const part_probe_types
[] = {
403 "cmdlinepart", "RedBoot", "afs", NULL
406 static int physmap_flash_pdata_init(struct platform_device
*dev
)
408 struct physmap_flash_info
*info
= platform_get_drvdata(dev
);
409 struct physmap_flash_data
*physmap_data
;
413 physmap_data
= dev_get_platdata(&dev
->dev
);
417 info
->probe_type
= physmap_data
->probe_type
;
418 info
->part_types
= physmap_data
->part_probe_types
? : part_probe_types
;
419 info
->parts
= physmap_data
->parts
;
420 info
->nparts
= physmap_data
->nr_parts
;
422 if (physmap_data
->init
) {
423 err
= physmap_data
->init(dev
);
428 for (i
= 0; i
< info
->nmaps
; i
++) {
429 info
->maps
[i
].bankwidth
= physmap_data
->width
;
430 info
->maps
[i
].pfow_base
= physmap_data
->pfow_base
;
431 info
->maps
[i
].set_vpp
= physmap_set_vpp
;
437 static int physmap_flash_probe(struct platform_device
*dev
)
439 struct physmap_flash_info
*info
;
443 if (!dev
->dev
.of_node
&& !dev_get_platdata(&dev
->dev
))
446 info
= devm_kzalloc(&dev
->dev
, sizeof(*info
), GFP_KERNEL
);
450 while (platform_get_resource(dev
, IORESOURCE_MEM
, info
->nmaps
))
456 info
->maps
= devm_kzalloc(&dev
->dev
,
457 sizeof(*info
->maps
) * info
->nmaps
,
462 info
->mtds
= devm_kzalloc(&dev
->dev
,
463 sizeof(*info
->mtds
) * info
->nmaps
,
468 platform_set_drvdata(dev
, info
);
470 info
->gpios
= devm_gpiod_get_array_optional(&dev
->dev
, "addr",
472 if (IS_ERR(info
->gpios
))
473 return PTR_ERR(info
->gpios
);
475 if (info
->gpios
&& info
->nmaps
> 1) {
476 dev_err(&dev
->dev
, "addr-gpios only supported for nmaps == 1\n");
480 if (dev
->dev
.of_node
)
481 err
= physmap_flash_of_init(dev
);
483 err
= physmap_flash_pdata_init(dev
);
488 for (i
= 0; i
< info
->nmaps
; i
++) {
489 struct resource
*res
;
491 res
= platform_get_resource(dev
, IORESOURCE_MEM
, i
);
492 info
->maps
[i
].virt
= devm_ioremap_resource(&dev
->dev
, res
);
493 if (IS_ERR(info
->maps
[i
].virt
)) {
494 err
= PTR_ERR(info
->maps
[i
].virt
);
498 dev_notice(&dev
->dev
, "physmap platform flash device: %pR\n",
501 info
->maps
[i
].name
= dev_name(&dev
->dev
);
503 if (!info
->maps
[i
].phys
)
504 info
->maps
[i
].phys
= res
->start
;
506 info
->win_order
= get_bitmask_order(resource_size(res
)) - 1;
507 info
->maps
[i
].size
= BIT(info
->win_order
+
509 info
->gpios
->ndescs
: 0));
511 info
->maps
[i
].map_priv_1
= (unsigned long)dev
;
514 err
= physmap_addr_gpios_map_init(&info
->maps
[i
]);
519 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
521 * Only use the simple_map implementation if map hooks are not
522 * implemented. Since map->read() is mandatory checking for its
523 * presence is enough.
525 if (!info
->maps
[i
].read
)
526 simple_map_init(&info
->maps
[i
]);
528 simple_map_init(&info
->maps
[i
]);
531 if (info
->probe_type
) {
532 info
->mtds
[i
] = do_map_probe(info
->probe_type
,
537 for (j
= 0; j
< ARRAY_SIZE(rom_probe_types
); j
++) {
538 info
->mtds
[i
] = do_map_probe(rom_probe_types
[j
],
545 if (!info
->mtds
[i
]) {
546 dev_err(&dev
->dev
, "map_probe failed\n");
550 info
->mtds
[i
]->dev
.parent
= &dev
->dev
;
553 if (info
->nmaps
== 1) {
554 info
->cmtd
= info
->mtds
[0];
557 * We detected multiple devices. Concatenate them together.
559 info
->cmtd
= mtd_concat_create(info
->mtds
, info
->nmaps
,
560 dev_name(&dev
->dev
));
567 spin_lock_init(&info
->vpp_lock
);
569 mtd_set_of_node(info
->cmtd
, dev
->dev
.of_node
);
570 err
= mtd_device_parse_register(info
->cmtd
, info
->part_types
, NULL
,
571 info
->parts
, info
->nparts
);
578 physmap_flash_remove(dev
);
583 static void physmap_flash_shutdown(struct platform_device
*dev
)
585 struct physmap_flash_info
*info
= platform_get_drvdata(dev
);
588 for (i
= 0; i
< info
->nmaps
&& info
->mtds
[i
]; i
++)
589 if (mtd_suspend(info
->mtds
[i
]) == 0)
590 mtd_resume(info
->mtds
[i
]);
593 #define physmap_flash_shutdown NULL
596 static struct platform_driver physmap_flash_driver
= {
597 .probe
= physmap_flash_probe
,
598 .remove
= physmap_flash_remove
,
599 .shutdown
= physmap_flash_shutdown
,
601 .name
= "physmap-flash",
602 .of_match_table
= of_flash_match
,
606 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
607 static struct physmap_flash_data physmap_flash_data
= {
608 .width
= CONFIG_MTD_PHYSMAP_BANKWIDTH
,
611 static struct resource physmap_flash_resource
= {
612 .start
= CONFIG_MTD_PHYSMAP_START
,
613 .end
= CONFIG_MTD_PHYSMAP_START
+ CONFIG_MTD_PHYSMAP_LEN
- 1,
614 .flags
= IORESOURCE_MEM
,
617 static struct platform_device physmap_flash
= {
618 .name
= "physmap-flash",
621 .platform_data
= &physmap_flash_data
,
624 .resource
= &physmap_flash_resource
,
628 static int __init
physmap_init(void)
632 err
= platform_driver_register(&physmap_flash_driver
);
633 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
635 err
= platform_device_register(&physmap_flash
);
637 platform_driver_unregister(&physmap_flash_driver
);
644 static void __exit
physmap_exit(void)
646 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
647 platform_device_unregister(&physmap_flash
);
649 platform_driver_unregister(&physmap_flash_driver
);
652 module_init(physmap_init
);
653 module_exit(physmap_exit
);
655 MODULE_LICENSE("GPL");
656 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
657 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
658 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
659 MODULE_DESCRIPTION("Generic configurable MTD map driver");
661 /* legacy platform drivers can't hotplug or coldplg */
662 #ifndef CONFIG_MTD_PHYSMAP_COMPAT
663 /* work with hotplug and coldplug */
664 MODULE_ALIAS("platform:physmap-flash");