Lines Matching +full:physmap +full:- +full:flash
1 // SPDX-License-Identifier: GPL-2.0+
8 * 031022 - [jsun] add run-time configure and partition setup
14 * Revised to handle newer style flash binding by:
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
23 * Copyright © 2005-2009 Analog Devices Inc.
36 #include <linux/mtd/physmap.h>
44 #include "physmap-bt1-rom.h"
45 #include "physmap-gemini.h"
46 #include "physmap-ixp4xx.h"
47 #include "physmap-versatile.h"
73 err = -EINVAL; in physmap_flash_remove()
77 if (info->cmtd) { in physmap_flash_remove()
78 err = mtd_device_unregister(info->cmtd); in physmap_flash_remove()
82 if (info->cmtd != info->mtds[0]) in physmap_flash_remove()
83 mtd_concat_destroy(info->cmtd); in physmap_flash_remove()
86 for (i = 0; i < info->nmaps; i++) { in physmap_flash_remove()
87 if (info->mtds[i]) in physmap_flash_remove()
88 map_destroy(info->mtds[i]); in physmap_flash_remove()
91 physmap_data = dev_get_platdata(&dev->dev); in physmap_flash_remove()
92 if (physmap_data && physmap_data->exit) in physmap_flash_remove()
93 physmap_data->exit(dev); in physmap_flash_remove()
96 pm_runtime_put(&dev->dev); in physmap_flash_remove()
97 pm_runtime_disable(&dev->dev); in physmap_flash_remove()
108 pdev = (struct platform_device *)map->map_priv_1; in physmap_set_vpp()
109 physmap_data = dev_get_platdata(&pdev->dev); in physmap_set_vpp()
111 if (!physmap_data->set_vpp) in physmap_set_vpp()
116 spin_lock_irqsave(&info->vpp_lock, flags); in physmap_set_vpp()
118 if (++info->vpp_refcnt == 1) /* first nested 'on' */ in physmap_set_vpp()
119 physmap_data->set_vpp(pdev, 1); in physmap_set_vpp()
121 if (--info->vpp_refcnt == 0) /* last nested 'off' */ in physmap_set_vpp()
122 physmap_data->set_vpp(pdev, 0); in physmap_set_vpp()
124 spin_unlock_irqrestore(&info->vpp_lock, flags); in physmap_set_vpp()
133 ofs >>= info->win_order; in physmap_set_addr_gpios()
134 if (info->gpio_values == ofs) in physmap_set_addr_gpios()
137 for (i = 0; i < info->gpios->ndescs; i++) { in physmap_set_addr_gpios()
138 if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values)) in physmap_set_addr_gpios()
141 gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs)); in physmap_set_addr_gpios()
144 info->gpio_values = ofs; in physmap_set_addr_gpios()
147 #define win_mask(order) (BIT(order) - 1)
157 pdev = (struct platform_device *)map->map_priv_1; in physmap_addr_gpios_read()
161 word = readw(map->virt + (ofs & win_mask(info->win_order))); in physmap_addr_gpios_read()
172 pdev = (struct platform_device *)map->map_priv_1; in physmap_addr_gpios_copy_from()
176 unsigned int winofs = ofs & win_mask(info->win_order); in physmap_addr_gpios_copy_from()
178 BIT(info->win_order) - winofs); in physmap_addr_gpios_copy_from()
181 memcpy_fromio(buf, map->virt + winofs, chunklen); in physmap_addr_gpios_copy_from()
182 len -= chunklen; in physmap_addr_gpios_copy_from()
195 pdev = (struct platform_device *)map->map_priv_1; in physmap_addr_gpios_write()
200 writew(word, map->virt + (ofs & win_mask(info->win_order))); in physmap_addr_gpios_write()
209 pdev = (struct platform_device *)map->map_priv_1; in physmap_addr_gpios_copy_to()
213 unsigned int winofs = ofs & win_mask(info->win_order); in physmap_addr_gpios_copy_to()
215 BIT(info->win_order) - winofs); in physmap_addr_gpios_copy_to()
218 memcpy_toio(map->virt + winofs, buf, chunklen); in physmap_addr_gpios_copy_to()
219 len -= chunklen; in physmap_addr_gpios_copy_to()
227 map->phys = NO_XIP; in physmap_addr_gpios_map_init()
228 map->read = physmap_addr_gpios_read; in physmap_addr_gpios_map_init()
229 map->copy_from = physmap_addr_gpios_copy_from; in physmap_addr_gpios_map_init()
230 map->write = physmap_addr_gpios_write; in physmap_addr_gpios_map_init()
231 map->copy_to = physmap_addr_gpios_copy_to; in physmap_addr_gpios_map_init()
238 return -ENOTSUPP; in physmap_addr_gpios_map_init()
245 .compatible = "cfi-flash",
258 .compatible = "jedec-flash",
262 .compatible = "mtd-ram",
266 .compatible = "mtd-rom",
271 .compatible = "direct-mapped"
283 struct device_node *dp = dev->dev.of_node; in of_get_part_probes()
287 count = of_property_count_strings(dp, "linux,part-probe"); in of_get_part_probes()
291 res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL); in of_get_part_probes()
295 count = of_property_read_string_array(dp, "linux,part-probe", res, in of_get_part_probes()
305 struct device_node *dp = dev->dev.of_node; in of_select_probe_type()
309 match = of_match_device(of_flash_match, &dev->dev); in of_select_probe_type()
310 probe_type = match->data; in of_select_probe_type()
314 dev_warn(&dev->dev, in of_select_probe_type()
315 "Device tree uses obsolete \"direct-mapped\" flash binding\n"); in of_select_probe_type()
317 of_property_read_string(dp, "probe-type", &probe_type); in of_select_probe_type()
328 dev_warn(&dev->dev, in of_select_probe_type()
340 struct device_node *dp = dev->dev.of_node; in physmap_flash_of_init()
348 return -EINVAL; in physmap_flash_of_init()
350 info->probe_type = of_select_probe_type(dev); in physmap_flash_of_init()
352 info->part_types = of_get_part_probes(dev); in physmap_flash_of_init()
353 if (!info->part_types) in physmap_flash_of_init()
354 return -ENOMEM; in physmap_flash_of_init()
356 of_property_read_string(dp, "linux,mtd-name", &mtd_name); in physmap_flash_of_init()
358 map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access"); in physmap_flash_of_init()
360 err = of_property_read_u32(dp, "bank-width", &bankwidth); in physmap_flash_of_init()
362 dev_err(&dev->dev, "Can't get bank width from device tree\n"); in physmap_flash_of_init()
366 if (of_property_read_bool(dp, "big-endian")) in physmap_flash_of_init()
368 else if (of_property_read_bool(dp, "little-endian")) in physmap_flash_of_init()
371 for (i = 0; i < info->nmaps; i++) { in physmap_flash_of_init()
372 info->maps[i].name = mtd_name; in physmap_flash_of_init()
373 info->maps[i].swap = swap; in physmap_flash_of_init()
374 info->maps[i].bankwidth = bankwidth; in physmap_flash_of_init()
375 info->maps[i].device_node = dp; in physmap_flash_of_init()
377 err = of_flash_probe_bt1_rom(dev, dp, &info->maps[i]); in physmap_flash_of_init()
381 err = of_flash_probe_gemini(dev, dp, &info->maps[i]); in physmap_flash_of_init()
385 err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]); in physmap_flash_of_init()
389 err = of_flash_probe_versatile(dev, dp, &info->maps[i]); in physmap_flash_of_init()
398 * flash will not be exposed directly to the MTD users in physmap_flash_of_init()
402 info->maps[i].phys = NO_XIP; in physmap_flash_of_init()
412 return -ENOTSUPP; in physmap_flash_of_init()
431 physmap_data = dev_get_platdata(&dev->dev); in physmap_flash_pdata_init()
433 return -EINVAL; in physmap_flash_pdata_init()
435 info->probe_type = physmap_data->probe_type; in physmap_flash_pdata_init()
436 info->part_types = physmap_data->part_probe_types ? : part_probe_types; in physmap_flash_pdata_init()
437 info->parts = physmap_data->parts; in physmap_flash_pdata_init()
438 info->nparts = physmap_data->nr_parts; in physmap_flash_pdata_init()
440 if (physmap_data->init) { in physmap_flash_pdata_init()
441 err = physmap_data->init(dev); in physmap_flash_pdata_init()
446 for (i = 0; i < info->nmaps; i++) { in physmap_flash_pdata_init()
447 info->maps[i].bankwidth = physmap_data->width; in physmap_flash_pdata_init()
448 info->maps[i].pfow_base = physmap_data->pfow_base; in physmap_flash_pdata_init()
449 info->maps[i].set_vpp = physmap_set_vpp; in physmap_flash_pdata_init()
461 if (!dev->dev.of_node && !dev_get_platdata(&dev->dev)) in physmap_flash_probe()
462 return -EINVAL; in physmap_flash_probe()
464 info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); in physmap_flash_probe()
466 return -ENOMEM; in physmap_flash_probe()
468 while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps)) in physmap_flash_probe()
469 info->nmaps++; in physmap_flash_probe()
471 if (!info->nmaps) in physmap_flash_probe()
472 return -ENODEV; in physmap_flash_probe()
474 info->maps = devm_kzalloc(&dev->dev, in physmap_flash_probe()
475 sizeof(*info->maps) * info->nmaps, in physmap_flash_probe()
477 if (!info->maps) in physmap_flash_probe()
478 return -ENOMEM; in physmap_flash_probe()
480 info->mtds = devm_kzalloc(&dev->dev, in physmap_flash_probe()
481 sizeof(*info->mtds) * info->nmaps, in physmap_flash_probe()
483 if (!info->mtds) in physmap_flash_probe()
484 return -ENOMEM; in physmap_flash_probe()
488 info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr", in physmap_flash_probe()
490 if (IS_ERR(info->gpios)) in physmap_flash_probe()
491 return PTR_ERR(info->gpios); in physmap_flash_probe()
493 if (info->gpios && info->nmaps > 1) { in physmap_flash_probe()
494 dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n"); in physmap_flash_probe()
495 return -EINVAL; in physmap_flash_probe()
498 pm_runtime_enable(&dev->dev); in physmap_flash_probe()
499 pm_runtime_get_sync(&dev->dev); in physmap_flash_probe()
501 if (dev->dev.of_node) in physmap_flash_probe()
507 pm_runtime_put(&dev->dev); in physmap_flash_probe()
508 pm_runtime_disable(&dev->dev); in physmap_flash_probe()
512 for (i = 0; i < info->nmaps; i++) { in physmap_flash_probe()
516 info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); in physmap_flash_probe()
517 if (IS_ERR(info->maps[i].virt)) { in physmap_flash_probe()
518 err = PTR_ERR(info->maps[i].virt); in physmap_flash_probe()
522 dev_notice(&dev->dev, "physmap platform flash device: %pR\n", in physmap_flash_probe()
525 if (!info->maps[i].name) in physmap_flash_probe()
526 info->maps[i].name = dev_name(&dev->dev); in physmap_flash_probe()
528 if (!info->maps[i].phys) in physmap_flash_probe()
529 info->maps[i].phys = res->start; in physmap_flash_probe()
531 info->win_order = get_bitmask_order(resource_size(res)) - 1; in physmap_flash_probe()
532 info->maps[i].size = BIT(info->win_order + in physmap_flash_probe()
533 (info->gpios ? in physmap_flash_probe()
534 info->gpios->ndescs : 0)); in physmap_flash_probe()
536 info->maps[i].map_priv_1 = (unsigned long)dev; in physmap_flash_probe()
538 if (info->gpios) { in physmap_flash_probe()
539 err = physmap_addr_gpios_map_init(&info->maps[i]); in physmap_flash_probe()
547 * implemented. Since map->read() is mandatory checking for its in physmap_flash_probe()
550 if (!info->maps[i].read) in physmap_flash_probe()
551 simple_map_init(&info->maps[i]); in physmap_flash_probe()
553 simple_map_init(&info->maps[i]); in physmap_flash_probe()
556 if (info->probe_type) { in physmap_flash_probe()
557 info->mtds[i] = do_map_probe(info->probe_type, in physmap_flash_probe()
558 &info->maps[i]); in physmap_flash_probe()
563 info->mtds[i] = do_map_probe(rom_probe_types[j], in physmap_flash_probe()
564 &info->maps[i]); in physmap_flash_probe()
565 if (info->mtds[i]) in physmap_flash_probe()
570 if (!info->mtds[i]) { in physmap_flash_probe()
571 dev_err(&dev->dev, "map_probe failed\n"); in physmap_flash_probe()
572 err = -ENXIO; in physmap_flash_probe()
575 info->mtds[i]->dev.parent = &dev->dev; in physmap_flash_probe()
578 if (info->nmaps == 1) { in physmap_flash_probe()
579 info->cmtd = info->mtds[0]; in physmap_flash_probe()
584 info->cmtd = mtd_concat_create(info->mtds, info->nmaps, in physmap_flash_probe()
585 dev_name(&dev->dev)); in physmap_flash_probe()
586 if (!info->cmtd) in physmap_flash_probe()
587 err = -ENXIO; in physmap_flash_probe()
592 spin_lock_init(&info->vpp_lock); in physmap_flash_probe()
594 mtd_set_of_node(info->cmtd, dev->dev.of_node); in physmap_flash_probe()
595 err = mtd_device_parse_register(info->cmtd, info->part_types, NULL, in physmap_flash_probe()
596 info->parts, info->nparts); in physmap_flash_probe()
613 for (i = 0; i < info->nmaps && info->mtds[i]; i++) in physmap_flash_shutdown()
614 if (mtd_suspend(info->mtds[i]) == 0) in physmap_flash_shutdown()
615 mtd_resume(info->mtds[i]); in physmap_flash_shutdown()
626 .name = "physmap-flash",
638 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
643 .name = "physmap-flash",
689 MODULE_ALIAS("platform:physmap-flash");