Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / mtd / maps / physmap-core.c
blob001ed5deb622aacfa82b58c0ac7dcf03a3b1085c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
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>
39 #include <linux/io.h>
40 #include <linux/of_device.h>
41 #include <linux/pm_runtime.h>
42 #include <linux/gpio/consumer.h>
44 #include "physmap-bt1-rom.h"
45 #include "physmap-gemini.h"
46 #include "physmap-ixp4xx.h"
47 #include "physmap-versatile.h"
49 struct physmap_flash_info {
50 unsigned int nmaps;
51 struct mtd_info **mtds;
52 struct mtd_info *cmtd;
53 struct map_info *maps;
54 spinlock_t vpp_lock;
55 int vpp_refcnt;
56 const char *probe_type;
57 const char * const *part_types;
58 unsigned int nparts;
59 const struct mtd_partition *parts;
60 struct gpio_descs *gpios;
61 unsigned int gpio_values;
62 unsigned int win_order;
65 static int physmap_flash_remove(struct platform_device *dev)
67 struct physmap_flash_info *info;
68 struct physmap_flash_data *physmap_data;
69 int i, err = 0;
71 info = platform_get_drvdata(dev);
72 if (!info)
73 goto out;
75 if (info->cmtd) {
76 err = mtd_device_unregister(info->cmtd);
77 if (err)
78 goto out;
80 if (info->cmtd != info->mtds[0])
81 mtd_concat_destroy(info->cmtd);
84 for (i = 0; i < info->nmaps; i++) {
85 if (info->mtds[i])
86 map_destroy(info->mtds[i]);
89 physmap_data = dev_get_platdata(&dev->dev);
90 if (physmap_data && physmap_data->exit)
91 physmap_data->exit(dev);
93 out:
94 pm_runtime_put(&dev->dev);
95 pm_runtime_disable(&dev->dev);
96 return err;
99 static void physmap_set_vpp(struct map_info *map, int state)
101 struct platform_device *pdev;
102 struct physmap_flash_data *physmap_data;
103 struct physmap_flash_info *info;
104 unsigned long flags;
106 pdev = (struct platform_device *)map->map_priv_1;
107 physmap_data = dev_get_platdata(&pdev->dev);
109 if (!physmap_data->set_vpp)
110 return;
112 info = platform_get_drvdata(pdev);
114 spin_lock_irqsave(&info->vpp_lock, flags);
115 if (state) {
116 if (++info->vpp_refcnt == 1) /* first nested 'on' */
117 physmap_data->set_vpp(pdev, 1);
118 } else {
119 if (--info->vpp_refcnt == 0) /* last nested 'off' */
120 physmap_data->set_vpp(pdev, 0);
122 spin_unlock_irqrestore(&info->vpp_lock, flags);
125 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR)
126 static void physmap_set_addr_gpios(struct physmap_flash_info *info,
127 unsigned long ofs)
129 unsigned int i;
131 ofs >>= info->win_order;
132 if (info->gpio_values == ofs)
133 return;
135 for (i = 0; i < info->gpios->ndescs; i++) {
136 if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values))
137 continue;
139 gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs));
142 info->gpio_values = ofs;
145 #define win_mask(order) (BIT(order) - 1)
147 static map_word physmap_addr_gpios_read(struct map_info *map,
148 unsigned long ofs)
150 struct platform_device *pdev;
151 struct physmap_flash_info *info;
152 map_word mw;
153 u16 word;
155 pdev = (struct platform_device *)map->map_priv_1;
156 info = platform_get_drvdata(pdev);
157 physmap_set_addr_gpios(info, ofs);
159 word = readw(map->virt + (ofs & win_mask(info->win_order)));
160 mw.x[0] = word;
161 return mw;
164 static void physmap_addr_gpios_copy_from(struct map_info *map, void *buf,
165 unsigned long ofs, ssize_t len)
167 struct platform_device *pdev;
168 struct physmap_flash_info *info;
170 pdev = (struct platform_device *)map->map_priv_1;
171 info = platform_get_drvdata(pdev);
173 while (len) {
174 unsigned int winofs = ofs & win_mask(info->win_order);
175 unsigned int chunklen = min_t(unsigned int, len,
176 BIT(info->win_order) - winofs);
178 physmap_set_addr_gpios(info, ofs);
179 memcpy_fromio(buf, map->virt + winofs, chunklen);
180 len -= chunklen;
181 buf += chunklen;
182 ofs += chunklen;
186 static void physmap_addr_gpios_write(struct map_info *map, map_word mw,
187 unsigned long ofs)
189 struct platform_device *pdev;
190 struct physmap_flash_info *info;
191 u16 word;
193 pdev = (struct platform_device *)map->map_priv_1;
194 info = platform_get_drvdata(pdev);
195 physmap_set_addr_gpios(info, ofs);
197 word = mw.x[0];
198 writew(word, map->virt + (ofs & win_mask(info->win_order)));
201 static void physmap_addr_gpios_copy_to(struct map_info *map, unsigned long ofs,
202 const void *buf, ssize_t len)
204 struct platform_device *pdev;
205 struct physmap_flash_info *info;
207 pdev = (struct platform_device *)map->map_priv_1;
208 info = platform_get_drvdata(pdev);
210 while (len) {
211 unsigned int winofs = ofs & win_mask(info->win_order);
212 unsigned int chunklen = min_t(unsigned int, len,
213 BIT(info->win_order) - winofs);
215 physmap_set_addr_gpios(info, ofs);
216 memcpy_toio(map->virt + winofs, buf, chunklen);
217 len -= chunklen;
218 buf += chunklen;
219 ofs += chunklen;
223 static int physmap_addr_gpios_map_init(struct map_info *map)
225 map->phys = NO_XIP;
226 map->read = physmap_addr_gpios_read;
227 map->copy_from = physmap_addr_gpios_copy_from;
228 map->write = physmap_addr_gpios_write;
229 map->copy_to = physmap_addr_gpios_copy_to;
231 return 0;
233 #else
234 static int physmap_addr_gpios_map_init(struct map_info *map)
236 return -ENOTSUPP;
238 #endif
240 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF)
241 static const struct of_device_id of_flash_match[] = {
243 .compatible = "cfi-flash",
244 .data = "cfi_probe",
248 * FIXME: JEDEC chips can't be safely and reliably
249 * probed, although the mtd code gets it right in
250 * practice most of the time. We should use the
251 * vendor and device ids specified by the binding to
252 * bypass the heuristic probe code, but the mtd layer
253 * provides, at present, no interface for doing so
254 * :(.
256 .compatible = "jedec-flash",
257 .data = "jedec_probe",
260 .compatible = "mtd-ram",
261 .data = "map_ram",
264 .compatible = "mtd-rom",
265 .data = "map_rom",
268 .type = "rom",
269 .compatible = "direct-mapped"
271 { /* sentinel */ },
273 MODULE_DEVICE_TABLE(of, of_flash_match);
275 static const char * const of_default_part_probes[] = {
276 "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL
279 static const char * const *of_get_part_probes(struct platform_device *dev)
281 struct device_node *dp = dev->dev.of_node;
282 const char **res;
283 int count;
285 count = of_property_count_strings(dp, "linux,part-probe");
286 if (count < 0)
287 return of_default_part_probes;
289 res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL);
290 if (!res)
291 return NULL;
293 count = of_property_read_string_array(dp, "linux,part-probe", res,
294 count);
295 if (count < 0)
296 return NULL;
298 return res;
301 static const char *of_select_probe_type(struct platform_device *dev)
303 struct device_node *dp = dev->dev.of_node;
304 const struct of_device_id *match;
305 const char *probe_type;
307 match = of_match_device(of_flash_match, &dev->dev);
308 probe_type = match->data;
309 if (probe_type)
310 return probe_type;
312 dev_warn(&dev->dev,
313 "Device tree uses obsolete \"direct-mapped\" flash binding\n");
315 of_property_read_string(dp, "probe-type", &probe_type);
316 if (!probe_type)
317 return NULL;
319 if (!strcmp(probe_type, "CFI")) {
320 probe_type = "cfi_probe";
321 } else if (!strcmp(probe_type, "JEDEC")) {
322 probe_type = "jedec_probe";
323 } else if (!strcmp(probe_type, "ROM")) {
324 probe_type = "map_rom";
325 } else {
326 dev_warn(&dev->dev,
327 "obsolete_probe: don't know probe type '%s', mapping as rom\n",
328 probe_type);
329 probe_type = "map_rom";
332 return probe_type;
335 static int physmap_flash_of_init(struct platform_device *dev)
337 struct physmap_flash_info *info = platform_get_drvdata(dev);
338 struct device_node *dp = dev->dev.of_node;
339 const char *mtd_name = NULL;
340 int err, swap = 0;
341 bool map_indirect;
342 unsigned int i;
343 u32 bankwidth;
345 if (!dp)
346 return -EINVAL;
348 info->probe_type = of_select_probe_type(dev);
350 info->part_types = of_get_part_probes(dev);
351 if (!info->part_types)
352 return -ENOMEM;
354 of_property_read_string(dp, "linux,mtd-name", &mtd_name);
356 map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
358 err = of_property_read_u32(dp, "bank-width", &bankwidth);
359 if (err) {
360 dev_err(&dev->dev, "Can't get bank width from device tree\n");
361 return err;
364 if (of_property_read_bool(dp, "big-endian"))
365 swap = CFI_BIG_ENDIAN;
366 else if (of_property_read_bool(dp, "little-endian"))
367 swap = CFI_LITTLE_ENDIAN;
369 for (i = 0; i < info->nmaps; i++) {
370 info->maps[i].name = mtd_name;
371 info->maps[i].swap = swap;
372 info->maps[i].bankwidth = bankwidth;
373 info->maps[i].device_node = dp;
375 err = of_flash_probe_bt1_rom(dev, dp, &info->maps[i]);
376 if (err)
377 return err;
379 err = of_flash_probe_gemini(dev, dp, &info->maps[i]);
380 if (err)
381 return err;
383 err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]);
384 if (err)
385 return err;
387 err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
388 if (err)
389 return err;
392 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
393 * may cause problems with JFFS2 usage, as the local bus (LPB)
394 * doesn't support unaligned accesses as implemented in the
395 * JFFS2 code via memcpy(). By setting NO_XIP, the
396 * flash will not be exposed directly to the MTD users
397 * (e.g. JFFS2) any more.
399 if (map_indirect)
400 info->maps[i].phys = NO_XIP;
403 return 0;
405 #else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
406 #define of_flash_match NULL
408 static int physmap_flash_of_init(struct platform_device *dev)
410 return -ENOTSUPP;
412 #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
414 static const char * const rom_probe_types[] = {
415 "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom",
418 static const char * const part_probe_types[] = {
419 "cmdlinepart", "RedBoot", "afs", NULL
422 static int physmap_flash_pdata_init(struct platform_device *dev)
424 struct physmap_flash_info *info = platform_get_drvdata(dev);
425 struct physmap_flash_data *physmap_data;
426 unsigned int i;
427 int err;
429 physmap_data = dev_get_platdata(&dev->dev);
430 if (!physmap_data)
431 return -EINVAL;
433 info->probe_type = physmap_data->probe_type;
434 info->part_types = physmap_data->part_probe_types ? : part_probe_types;
435 info->parts = physmap_data->parts;
436 info->nparts = physmap_data->nr_parts;
438 if (physmap_data->init) {
439 err = physmap_data->init(dev);
440 if (err)
441 return err;
444 for (i = 0; i < info->nmaps; i++) {
445 info->maps[i].bankwidth = physmap_data->width;
446 info->maps[i].pfow_base = physmap_data->pfow_base;
447 info->maps[i].set_vpp = physmap_set_vpp;
450 return 0;
453 static int physmap_flash_probe(struct platform_device *dev)
455 struct physmap_flash_info *info;
456 int err = 0;
457 int i;
459 if (!dev->dev.of_node && !dev_get_platdata(&dev->dev))
460 return -EINVAL;
462 info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
463 if (!info)
464 return -ENOMEM;
466 while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps))
467 info->nmaps++;
469 if (!info->nmaps)
470 return -ENODEV;
472 info->maps = devm_kzalloc(&dev->dev,
473 sizeof(*info->maps) * info->nmaps,
474 GFP_KERNEL);
475 if (!info->maps)
476 return -ENOMEM;
478 info->mtds = devm_kzalloc(&dev->dev,
479 sizeof(*info->mtds) * info->nmaps,
480 GFP_KERNEL);
481 if (!info->mtds)
482 return -ENOMEM;
484 platform_set_drvdata(dev, info);
486 info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr",
487 GPIOD_OUT_LOW);
488 if (IS_ERR(info->gpios))
489 return PTR_ERR(info->gpios);
491 if (info->gpios && info->nmaps > 1) {
492 dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n");
493 return -EINVAL;
496 pm_runtime_enable(&dev->dev);
497 pm_runtime_get_sync(&dev->dev);
499 if (dev->dev.of_node)
500 err = physmap_flash_of_init(dev);
501 else
502 err = physmap_flash_pdata_init(dev);
504 if (err) {
505 pm_runtime_put(&dev->dev);
506 pm_runtime_disable(&dev->dev);
507 return err;
510 for (i = 0; i < info->nmaps; i++) {
511 struct resource *res;
513 res = platform_get_resource(dev, IORESOURCE_MEM, i);
514 info->maps[i].virt = devm_ioremap_resource(&dev->dev, res);
515 if (IS_ERR(info->maps[i].virt)) {
516 err = PTR_ERR(info->maps[i].virt);
517 goto err_out;
520 dev_notice(&dev->dev, "physmap platform flash device: %pR\n",
521 res);
523 if (!info->maps[i].name)
524 info->maps[i].name = dev_name(&dev->dev);
526 if (!info->maps[i].phys)
527 info->maps[i].phys = res->start;
529 info->win_order = get_bitmask_order(resource_size(res)) - 1;
530 info->maps[i].size = BIT(info->win_order +
531 (info->gpios ?
532 info->gpios->ndescs : 0));
534 info->maps[i].map_priv_1 = (unsigned long)dev;
536 if (info->gpios) {
537 err = physmap_addr_gpios_map_init(&info->maps[i]);
538 if (err)
539 goto err_out;
542 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
544 * Only use the simple_map implementation if map hooks are not
545 * implemented. Since map->read() is mandatory checking for its
546 * presence is enough.
548 if (!info->maps[i].read)
549 simple_map_init(&info->maps[i]);
550 #else
551 simple_map_init(&info->maps[i]);
552 #endif
554 if (info->probe_type) {
555 info->mtds[i] = do_map_probe(info->probe_type,
556 &info->maps[i]);
557 } else {
558 int j;
560 for (j = 0; j < ARRAY_SIZE(rom_probe_types); j++) {
561 info->mtds[i] = do_map_probe(rom_probe_types[j],
562 &info->maps[i]);
563 if (info->mtds[i])
564 break;
568 if (!info->mtds[i]) {
569 dev_err(&dev->dev, "map_probe failed\n");
570 err = -ENXIO;
571 goto err_out;
573 info->mtds[i]->dev.parent = &dev->dev;
576 if (info->nmaps == 1) {
577 info->cmtd = info->mtds[0];
578 } else {
580 * We detected multiple devices. Concatenate them together.
582 info->cmtd = mtd_concat_create(info->mtds, info->nmaps,
583 dev_name(&dev->dev));
584 if (!info->cmtd)
585 err = -ENXIO;
587 if (err)
588 goto err_out;
590 spin_lock_init(&info->vpp_lock);
592 mtd_set_of_node(info->cmtd, dev->dev.of_node);
593 err = mtd_device_parse_register(info->cmtd, info->part_types, NULL,
594 info->parts, info->nparts);
595 if (err)
596 goto err_out;
598 return 0;
600 err_out:
601 physmap_flash_remove(dev);
602 return err;
605 #ifdef CONFIG_PM
606 static void physmap_flash_shutdown(struct platform_device *dev)
608 struct physmap_flash_info *info = platform_get_drvdata(dev);
609 int i;
611 for (i = 0; i < info->nmaps && info->mtds[i]; i++)
612 if (mtd_suspend(info->mtds[i]) == 0)
613 mtd_resume(info->mtds[i]);
615 #else
616 #define physmap_flash_shutdown NULL
617 #endif
619 static struct platform_driver physmap_flash_driver = {
620 .probe = physmap_flash_probe,
621 .remove = physmap_flash_remove,
622 .shutdown = physmap_flash_shutdown,
623 .driver = {
624 .name = "physmap-flash",
625 .of_match_table = of_flash_match,
629 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
630 static struct physmap_flash_data physmap_flash_data = {
631 .width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
634 static struct resource physmap_flash_resource = {
635 .start = CONFIG_MTD_PHYSMAP_START,
636 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
637 .flags = IORESOURCE_MEM,
640 static struct platform_device physmap_flash = {
641 .name = "physmap-flash",
642 .id = 0,
643 .dev = {
644 .platform_data = &physmap_flash_data,
646 .num_resources = 1,
647 .resource = &physmap_flash_resource,
649 #endif
651 static int __init physmap_init(void)
653 int err;
655 err = platform_driver_register(&physmap_flash_driver);
656 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
657 if (err == 0) {
658 err = platform_device_register(&physmap_flash);
659 if (err)
660 platform_driver_unregister(&physmap_flash_driver);
662 #endif
664 return err;
667 static void __exit physmap_exit(void)
669 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
670 platform_device_unregister(&physmap_flash);
671 #endif
672 platform_driver_unregister(&physmap_flash_driver);
675 module_init(physmap_init);
676 module_exit(physmap_exit);
678 MODULE_LICENSE("GPL");
679 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
680 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
681 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
682 MODULE_DESCRIPTION("Generic configurable MTD map driver");
684 /* legacy platform drivers can't hotplug or coldplg */
685 #ifndef CONFIG_MTD_PHYSMAP_COMPAT
686 /* work with hotplug and coldplug */
687 MODULE_ALIAS("platform:physmap-flash");
688 #endif