Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Normal mappings of chips in physical memory
4 *
5 * Copyright (C) 2003 MontaVista Software Inc.
6 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
7 *
8 * 031022 - [jsun] add run-time configure and partition setup
9 *
10 * Device tree support:
11 * Copyright (C) 2006 MontaVista Software Inc.
12 * Author: Vitaly Wool <vwool@ru.mvista.com>
13 *
14 * Revised to handle newer style flash binding by:
15 * Copyright (C) 2007 David Gibson, IBM Corporation.
16 *
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.
21 *
22 * Copyright © 2000 Nicolas Pitre <nico@cam.org>
23 * Copyright © 2005-2009 Analog Devices Inc.
24 */
25
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/property.h>
34#include <linux/mtd/mtd.h>
35#include <linux/mtd/map.h>
36#include <linux/mtd/partitions.h>
37#include <linux/mtd/physmap.h>
38#include <linux/mtd/concat.h>
39#include <linux/mtd/cfi_endian.h>
40#include <linux/io.h>
41#include <linux/of.h>
42#include <linux/pm_runtime.h>
43#include <linux/gpio/consumer.h>
44
45#include "physmap-gemini.h"
46#include "physmap-ixp4xx.h"
47#include "physmap-versatile.h"
48
49struct 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;
63};
64
65static void physmap_flash_remove(struct platform_device *dev)
66{
67 struct physmap_flash_info *info;
68 struct physmap_flash_data *physmap_data;
69 int i;
70
71 info = platform_get_drvdata(dev);
72
73 if (info->cmtd) {
74 WARN_ON(mtd_device_unregister(info->cmtd));
75
76 if (info->cmtd != info->mtds[0])
77 mtd_concat_destroy(info->cmtd);
78 }
79
80 for (i = 0; i < info->nmaps; i++) {
81 if (info->mtds[i])
82 map_destroy(info->mtds[i]);
83 }
84
85 physmap_data = dev_get_platdata(&dev->dev);
86 if (physmap_data && physmap_data->exit)
87 physmap_data->exit(dev);
88
89 pm_runtime_put(&dev->dev);
90 pm_runtime_disable(&dev->dev);
91}
92
93static void physmap_set_vpp(struct map_info *map, int state)
94{
95 struct platform_device *pdev;
96 struct physmap_flash_data *physmap_data;
97 struct physmap_flash_info *info;
98 unsigned long flags;
99
100 pdev = (struct platform_device *)map->map_priv_1;
101 physmap_data = dev_get_platdata(&pdev->dev);
102
103 if (!physmap_data->set_vpp)
104 return;
105
106 info = platform_get_drvdata(pdev);
107
108 spin_lock_irqsave(&info->vpp_lock, flags);
109 if (state) {
110 if (++info->vpp_refcnt == 1) /* first nested 'on' */
111 physmap_data->set_vpp(pdev, 1);
112 } else {
113 if (--info->vpp_refcnt == 0) /* last nested 'off' */
114 physmap_data->set_vpp(pdev, 0);
115 }
116 spin_unlock_irqrestore(&info->vpp_lock, flags);
117}
118
119#if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR)
120static void physmap_set_addr_gpios(struct physmap_flash_info *info,
121 unsigned long ofs)
122{
123 unsigned int i;
124
125 ofs >>= info->win_order;
126 if (info->gpio_values == ofs)
127 return;
128
129 for (i = 0; i < info->gpios->ndescs; i++) {
130 if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values))
131 continue;
132
133 gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs));
134 }
135
136 info->gpio_values = ofs;
137}
138
139#define win_mask(order) (BIT(order) - 1)
140
141static map_word physmap_addr_gpios_read(struct map_info *map,
142 unsigned long ofs)
143{
144 struct platform_device *pdev;
145 struct physmap_flash_info *info;
146 map_word mw;
147 u16 word;
148
149 pdev = (struct platform_device *)map->map_priv_1;
150 info = platform_get_drvdata(pdev);
151 physmap_set_addr_gpios(info, ofs);
152
153 word = readw(map->virt + (ofs & win_mask(info->win_order)));
154 mw.x[0] = word;
155 return mw;
156}
157
158static void physmap_addr_gpios_copy_from(struct map_info *map, void *buf,
159 unsigned long ofs, ssize_t len)
160{
161 struct platform_device *pdev;
162 struct physmap_flash_info *info;
163
164 pdev = (struct platform_device *)map->map_priv_1;
165 info = platform_get_drvdata(pdev);
166
167 while (len) {
168 unsigned int winofs = ofs & win_mask(info->win_order);
169 unsigned int chunklen = min_t(unsigned int, len,
170 BIT(info->win_order) - winofs);
171
172 physmap_set_addr_gpios(info, ofs);
173 memcpy_fromio(buf, map->virt + winofs, chunklen);
174 len -= chunklen;
175 buf += chunklen;
176 ofs += chunklen;
177 }
178}
179
180static void physmap_addr_gpios_write(struct map_info *map, map_word mw,
181 unsigned long ofs)
182{
183 struct platform_device *pdev;
184 struct physmap_flash_info *info;
185 u16 word;
186
187 pdev = (struct platform_device *)map->map_priv_1;
188 info = platform_get_drvdata(pdev);
189 physmap_set_addr_gpios(info, ofs);
190
191 word = mw.x[0];
192 writew(word, map->virt + (ofs & win_mask(info->win_order)));
193}
194
195static void physmap_addr_gpios_copy_to(struct map_info *map, unsigned long ofs,
196 const void *buf, ssize_t len)
197{
198 struct platform_device *pdev;
199 struct physmap_flash_info *info;
200
201 pdev = (struct platform_device *)map->map_priv_1;
202 info = platform_get_drvdata(pdev);
203
204 while (len) {
205 unsigned int winofs = ofs & win_mask(info->win_order);
206 unsigned int chunklen = min_t(unsigned int, len,
207 BIT(info->win_order) - winofs);
208
209 physmap_set_addr_gpios(info, ofs);
210 memcpy_toio(map->virt + winofs, buf, chunklen);
211 len -= chunklen;
212 buf += chunklen;
213 ofs += chunklen;
214 }
215}
216
217static int physmap_addr_gpios_map_init(struct map_info *map)
218{
219 map->phys = NO_XIP;
220 map->read = physmap_addr_gpios_read;
221 map->copy_from = physmap_addr_gpios_copy_from;
222 map->write = physmap_addr_gpios_write;
223 map->copy_to = physmap_addr_gpios_copy_to;
224
225 return 0;
226}
227#else
228static int physmap_addr_gpios_map_init(struct map_info *map)
229{
230 return -ENOTSUPP;
231}
232#endif
233
234#if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF)
235static const struct of_device_id of_flash_match[] = {
236 {
237 .compatible = "cfi-flash",
238 .data = "cfi_probe",
239 },
240 {
241 /*
242 * FIXME: JEDEC chips can't be safely and reliably
243 * probed, although the mtd code gets it right in
244 * practice most of the time. We should use the
245 * vendor and device ids specified by the binding to
246 * bypass the heuristic probe code, but the mtd layer
247 * provides, at present, no interface for doing so
248 * :(.
249 */
250 .compatible = "jedec-flash",
251 .data = "jedec_probe",
252 },
253 {
254 .compatible = "mtd-ram",
255 .data = "map_ram",
256 },
257 {
258 .compatible = "mtd-rom",
259 .data = "map_rom",
260 },
261 {
262 .type = "rom",
263 .compatible = "direct-mapped"
264 },
265 { /* sentinel */ },
266};
267MODULE_DEVICE_TABLE(of, of_flash_match);
268
269static const char * const of_default_part_probes[] = {
270 "cmdlinepart", "ofpart", "ofoldpart", "RedBoot", NULL
271};
272
273static const char * const *of_get_part_probes(struct platform_device *dev)
274{
275 struct device_node *dp = dev->dev.of_node;
276 const char **res;
277 int count;
278
279 count = of_property_count_strings(dp, "linux,part-probe");
280 if (count < 0)
281 return of_default_part_probes;
282
283 res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL);
284 if (!res)
285 return NULL;
286
287 count = of_property_read_string_array(dp, "linux,part-probe", res,
288 count);
289 if (count < 0)
290 return NULL;
291
292 return res;
293}
294
295static const char *of_select_probe_type(struct platform_device *dev)
296{
297 struct device_node *dp = dev->dev.of_node;
298 const char *probe_type;
299
300 probe_type = device_get_match_data(&dev->dev);
301 if (probe_type)
302 return probe_type;
303
304 dev_warn(&dev->dev,
305 "Device tree uses obsolete \"direct-mapped\" flash binding\n");
306
307 of_property_read_string(dp, "probe-type", &probe_type);
308 if (!probe_type)
309 return NULL;
310
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";
317 } else {
318 dev_warn(&dev->dev,
319 "obsolete_probe: don't know probe type '%s', mapping as rom\n",
320 probe_type);
321 probe_type = "map_rom";
322 }
323
324 return probe_type;
325}
326
327static int physmap_flash_of_init(struct platform_device *dev)
328{
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;
332 int err, swap = 0;
333 bool map_indirect;
334 unsigned int i;
335 u32 bankwidth;
336
337 if (!dp)
338 return -EINVAL;
339
340 info->probe_type = of_select_probe_type(dev);
341
342 info->part_types = of_get_part_probes(dev);
343 if (!info->part_types)
344 return -ENOMEM;
345
346 of_property_read_string(dp, "linux,mtd-name", &mtd_name);
347
348 map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
349
350 err = of_property_read_u32(dp, "bank-width", &bankwidth);
351 if (err) {
352 dev_err(&dev->dev, "Can't get bank width from device tree\n");
353 return err;
354 }
355
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;
360
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;
366
367 err = of_flash_probe_gemini(dev, dp, &info->maps[i]);
368 if (err)
369 return err;
370
371 err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]);
372 if (err)
373 return err;
374
375 err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
376 if (err)
377 return err;
378
379 /*
380 * On some platforms (e.g. MPC5200) a direct 1:1 mapping
381 * may cause problems with JFFS2 usage, as the local bus (LPB)
382 * doesn't support unaligned accesses as implemented in the
383 * JFFS2 code via memcpy(). By setting NO_XIP, the
384 * flash will not be exposed directly to the MTD users
385 * (e.g. JFFS2) any more.
386 */
387 if (map_indirect)
388 info->maps[i].phys = NO_XIP;
389 }
390
391 return 0;
392}
393#else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
394#define of_flash_match NULL
395
396static int physmap_flash_of_init(struct platform_device *dev)
397{
398 return -ENOTSUPP;
399}
400#endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
401
402static const char * const rom_probe_types[] = {
403 "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom",
404};
405
406static const char * const part_probe_types[] = {
407 "cmdlinepart", "RedBoot", "afs", NULL
408};
409
410static int physmap_flash_pdata_init(struct platform_device *dev)
411{
412 struct physmap_flash_info *info = platform_get_drvdata(dev);
413 struct physmap_flash_data *physmap_data;
414 unsigned int i;
415 int err;
416
417 physmap_data = dev_get_platdata(&dev->dev);
418 if (!physmap_data)
419 return -EINVAL;
420
421 info->probe_type = physmap_data->probe_type;
422 info->part_types = physmap_data->part_probe_types ? : part_probe_types;
423 info->parts = physmap_data->parts;
424 info->nparts = physmap_data->nr_parts;
425
426 if (physmap_data->init) {
427 err = physmap_data->init(dev);
428 if (err)
429 return err;
430 }
431
432 for (i = 0; i < info->nmaps; i++) {
433 info->maps[i].bankwidth = physmap_data->width;
434 info->maps[i].pfow_base = physmap_data->pfow_base;
435 info->maps[i].set_vpp = physmap_set_vpp;
436 }
437
438 return 0;
439}
440
441static int physmap_flash_probe(struct platform_device *dev)
442{
443 struct physmap_flash_info *info;
444 int err = 0;
445 int i;
446
447 if (!dev->dev.of_node && !dev_get_platdata(&dev->dev))
448 return -EINVAL;
449
450 info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
451 if (!info)
452 return -ENOMEM;
453
454 while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps))
455 info->nmaps++;
456
457 if (!info->nmaps)
458 return -ENODEV;
459
460 info->maps = devm_kzalloc(&dev->dev,
461 sizeof(*info->maps) * info->nmaps,
462 GFP_KERNEL);
463 if (!info->maps)
464 return -ENOMEM;
465
466 info->mtds = devm_kzalloc(&dev->dev,
467 sizeof(*info->mtds) * info->nmaps,
468 GFP_KERNEL);
469 if (!info->mtds)
470 return -ENOMEM;
471
472 platform_set_drvdata(dev, info);
473
474 info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr",
475 GPIOD_OUT_LOW);
476 if (IS_ERR(info->gpios))
477 return PTR_ERR(info->gpios);
478
479 if (info->gpios && info->nmaps > 1) {
480 dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n");
481 return -EINVAL;
482 }
483
484 pm_runtime_enable(&dev->dev);
485 pm_runtime_get_sync(&dev->dev);
486
487 if (dev->dev.of_node)
488 err = physmap_flash_of_init(dev);
489 else
490 err = physmap_flash_pdata_init(dev);
491
492 if (err) {
493 pm_runtime_put(&dev->dev);
494 pm_runtime_disable(&dev->dev);
495 return err;
496 }
497
498 for (i = 0; i < info->nmaps; i++) {
499 struct resource *res;
500
501 info->maps[i].virt = devm_platform_get_and_ioremap_resource(dev, i, &res);
502 if (IS_ERR(info->maps[i].virt)) {
503 err = PTR_ERR(info->maps[i].virt);
504 goto err_out;
505 }
506
507 dev_notice(&dev->dev, "physmap platform flash device: %pR\n",
508 res);
509
510 if (!info->maps[i].name)
511 info->maps[i].name = dev_name(&dev->dev);
512
513 if (!info->maps[i].phys)
514 info->maps[i].phys = res->start;
515
516 info->win_order = fls64(resource_size(res)) - 1;
517 info->maps[i].size = BIT(info->win_order +
518 (info->gpios ?
519 info->gpios->ndescs : 0));
520
521 info->maps[i].map_priv_1 = (unsigned long)dev;
522
523 if (info->gpios) {
524 err = physmap_addr_gpios_map_init(&info->maps[i]);
525 if (err)
526 goto err_out;
527 }
528
529#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
530 /*
531 * Only use the simple_map implementation if map hooks are not
532 * implemented. Since map->read() is mandatory checking for its
533 * presence is enough.
534 */
535 if (!info->maps[i].read)
536 simple_map_init(&info->maps[i]);
537#else
538 simple_map_init(&info->maps[i]);
539#endif
540
541 if (info->probe_type) {
542 info->mtds[i] = do_map_probe(info->probe_type,
543 &info->maps[i]);
544
545 /* Fall back to mapping region as ROM */
546 if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) &&
547 strcmp(info->probe_type, "map_rom")) {
548 dev_warn(&dev->dev,
549 "map_probe() failed for type %s\n",
550 info->probe_type);
551
552 info->mtds[i] = do_map_probe("map_rom",
553 &info->maps[i]);
554 }
555 } else {
556 int j;
557
558 for (j = 0; j < ARRAY_SIZE(rom_probe_types); j++) {
559 info->mtds[i] = do_map_probe(rom_probe_types[j],
560 &info->maps[i]);
561 if (info->mtds[i])
562 break;
563 }
564 }
565
566 if (!info->mtds[i]) {
567 dev_err(&dev->dev, "map_probe failed\n");
568 err = -ENXIO;
569 goto err_out;
570 }
571 info->mtds[i]->dev.parent = &dev->dev;
572 }
573
574 if (info->nmaps == 1) {
575 info->cmtd = info->mtds[0];
576 } else {
577 /*
578 * We detected multiple devices. Concatenate them together.
579 */
580 info->cmtd = mtd_concat_create(info->mtds, info->nmaps,
581 dev_name(&dev->dev));
582 if (!info->cmtd)
583 err = -ENXIO;
584 }
585 if (err)
586 goto err_out;
587
588 spin_lock_init(&info->vpp_lock);
589
590 mtd_set_of_node(info->cmtd, dev->dev.of_node);
591 err = mtd_device_parse_register(info->cmtd, info->part_types, NULL,
592 info->parts, info->nparts);
593 if (err)
594 goto err_out;
595
596 return 0;
597
598err_out:
599 physmap_flash_remove(dev);
600 return err;
601}
602
603#ifdef CONFIG_PM
604static void physmap_flash_shutdown(struct platform_device *dev)
605{
606 struct physmap_flash_info *info = platform_get_drvdata(dev);
607 int i;
608
609 for (i = 0; i < info->nmaps && info->mtds[i]; i++)
610 if (mtd_suspend(info->mtds[i]) == 0)
611 mtd_resume(info->mtds[i]);
612}
613#else
614#define physmap_flash_shutdown NULL
615#endif
616
617static struct platform_driver physmap_flash_driver = {
618 .probe = physmap_flash_probe,
619 .remove = physmap_flash_remove,
620 .shutdown = physmap_flash_shutdown,
621 .driver = {
622 .name = "physmap-flash",
623 .of_match_table = of_flash_match,
624 },
625};
626
627#ifdef CONFIG_MTD_PHYSMAP_COMPAT
628static struct physmap_flash_data physmap_flash_data = {
629 .width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
630};
631
632static struct resource physmap_flash_resource = {
633 .start = CONFIG_MTD_PHYSMAP_START,
634 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
635 .flags = IORESOURCE_MEM,
636};
637
638static struct platform_device physmap_flash = {
639 .name = "physmap-flash",
640 .id = 0,
641 .dev = {
642 .platform_data = &physmap_flash_data,
643 },
644 .num_resources = 1,
645 .resource = &physmap_flash_resource,
646};
647#endif
648
649static int __init physmap_init(void)
650{
651 int err;
652
653 err = platform_driver_register(&physmap_flash_driver);
654#ifdef CONFIG_MTD_PHYSMAP_COMPAT
655 if (err == 0) {
656 err = platform_device_register(&physmap_flash);
657 if (err)
658 platform_driver_unregister(&physmap_flash_driver);
659 }
660#endif
661
662 return err;
663}
664
665static void __exit physmap_exit(void)
666{
667#ifdef CONFIG_MTD_PHYSMAP_COMPAT
668 platform_device_unregister(&physmap_flash);
669#endif
670 platform_driver_unregister(&physmap_flash_driver);
671}
672
673module_init(physmap_init);
674module_exit(physmap_exit);
675
676MODULE_LICENSE("GPL");
677MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
678MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
679MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
680MODULE_DESCRIPTION("Generic configurable MTD map driver");
681
682/* legacy platform drivers can't hotplug or coldplg */
683#ifndef CONFIG_MTD_PHYSMAP_COMPAT
684/* work with hotplug and coldplug */
685MODULE_ALIAS("platform:physmap-flash");
686#endif