From 18d54e557c55fbf29d1a25fe2e1c01b0970f36cb Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:54 +0200 Subject: mtd: maps: physmap: Add SPDX header Add an SPDX header matching the MODULE_LICENSE("GPL") definition. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index cc2adbbcd60f..19ec105cbb2d 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Normal mappings of chips in physical memory * -- cgit v1.2.3 From 00142d6ffeb67b22e1f5259c9f3af540ed1d2b62 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:55 +0200 Subject: mtd: maps: physmap: Rename ->map and ->mtd into ->maps and ->mtds The ->map and ->mtd fields are actually arrays of map and mtd objects. Rename those fields into ->maps and ->mtds to make it obvious. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 55 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 19ec105cbb2d..4010afee4a33 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -25,9 +25,9 @@ #define MAX_RESOURCES 4 struct physmap_flash_info { - struct mtd_info *mtd[MAX_RESOURCES]; + struct mtd_info *mtds[MAX_RESOURCES]; struct mtd_info *cmtd; - struct map_info map[MAX_RESOURCES]; + struct map_info maps[MAX_RESOURCES]; spinlock_t vpp_lock; int vpp_refcnt; }; @@ -46,13 +46,13 @@ static int physmap_flash_remove(struct platform_device *dev) if (info->cmtd) { mtd_device_unregister(info->cmtd); - if (info->cmtd != info->mtd[0]) + if (info->cmtd != info->mtds[0]) mtd_concat_destroy(info->cmtd); } for (i = 0; i < MAX_RESOURCES; i++) { - if (info->mtd[i] != NULL) - map_destroy(info->mtd[i]); + if (info->mtds[i] != NULL) + map_destroy(info->mtds[i]); } if (physmap_data->exit) @@ -136,48 +136,49 @@ static int physmap_flash_probe(struct platform_device *dev) goto err_out; } - info->map[i].name = dev_name(&dev->dev); - info->map[i].phys = dev->resource[i].start; - info->map[i].size = resource_size(&dev->resource[i]); - info->map[i].bankwidth = physmap_data->width; - info->map[i].set_vpp = physmap_set_vpp; - info->map[i].pfow_base = physmap_data->pfow_base; - info->map[i].map_priv_1 = (unsigned long)dev; - - info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys, - info->map[i].size); - if (info->map[i].virt == NULL) { + info->maps[i].name = dev_name(&dev->dev); + info->maps[i].phys = dev->resource[i].start; + info->maps[i].size = resource_size(&dev->resource[i]); + info->maps[i].bankwidth = physmap_data->width; + info->maps[i].set_vpp = physmap_set_vpp; + info->maps[i].pfow_base = physmap_data->pfow_base; + info->maps[i].map_priv_1 = (unsigned long)dev; + + info->maps[i].virt = devm_ioremap(&dev->dev, + info->maps[i].phys, + info->maps[i].size); + if (info->maps[i].virt == NULL) { dev_err(&dev->dev, "Failed to ioremap flash region\n"); err = -EIO; goto err_out; } - simple_map_init(&info->map[i]); + simple_map_init(&info->maps[i]); probe_type = rom_probe_types; if (physmap_data->probe_type == NULL) { - for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) - info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); + for (; info->mtds[i] == NULL && *probe_type != NULL; probe_type++) + info->mtds[i] = do_map_probe(*probe_type, &info->maps[i]); } else - info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]); + info->mtds[i] = do_map_probe(physmap_data->probe_type, &info->maps[i]); - if (info->mtd[i] == NULL) { + if (info->mtds[i] == NULL) { dev_err(&dev->dev, "map_probe failed\n"); err = -ENXIO; goto err_out; } else { devices_found++; } - info->mtd[i]->dev.parent = &dev->dev; + info->mtds[i]->dev.parent = &dev->dev; } if (devices_found == 1) { - info->cmtd = info->mtd[0]; + info->cmtd = info->mtds[0]; } else if (devices_found > 1) { /* * We detected multiple devices. Concatenate them together. */ - info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev)); + info->cmtd = mtd_concat_create(info->mtds, devices_found, dev_name(&dev->dev)); if (info->cmtd == NULL) err = -ENXIO; } @@ -203,9 +204,9 @@ static void physmap_flash_shutdown(struct platform_device *dev) struct physmap_flash_info *info = platform_get_drvdata(dev); int i; - for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++) - if (mtd_suspend(info->mtd[i]) == 0) - mtd_resume(info->mtd[i]); + for (i = 0; i < MAX_RESOURCES && info->mtds[i]; i++) + if (mtd_suspend(info->mtds[i]) == 0) + mtd_resume(info->mtds[i]); } #else #define physmap_flash_shutdown NULL -- cgit v1.2.3 From c7f6dc60a319edac986486580b2fc31475ceba11 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:56 +0200 Subject: mtd: maps: physmap: Use platform_get_resource() to retrieve iomem resources Stop manipulating the dev->resource array directly and use the platform_get_resource() helper instead. While at it, fix the loop check so that we never overflow the info->maps and info->mtds array even if the number of resources attached to the platform dev is higher than MAX_RESOURCES. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 4010afee4a33..a097f0cf519a 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -122,23 +122,28 @@ static int physmap_flash_probe(struct platform_device *dev) platform_set_drvdata(dev, info); - for (i = 0; i < dev->num_resources; i++) { + for (i = 0; i < MAX_RESOURCES; i++) { + struct resource *res; + + res = platform_get_resource(dev, IORESOURCE_MEM, i); + if (!res) + break; + printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", - (unsigned long long)resource_size(&dev->resource[i]), - (unsigned long long)dev->resource[i].start); + (unsigned long long)resource_size(res), + (unsigned long long)res->start); - if (!devm_request_mem_region(&dev->dev, - dev->resource[i].start, - resource_size(&dev->resource[i]), - dev_name(&dev->dev))) { + if (!devm_request_mem_region(&dev->dev, res->start, + resource_size(res), + dev_name(&dev->dev))) { dev_err(&dev->dev, "Could not reserve memory region\n"); err = -ENOMEM; goto err_out; } info->maps[i].name = dev_name(&dev->dev); - info->maps[i].phys = dev->resource[i].start; - info->maps[i].size = resource_size(&dev->resource[i]); + info->maps[i].phys = res->start; + info->maps[i].size = resource_size(res); info->maps[i].bankwidth = physmap_data->width; info->maps[i].set_vpp = physmap_set_vpp; info->maps[i].pfow_base = physmap_data->pfow_base; @@ -172,9 +177,11 @@ static int physmap_flash_probe(struct platform_device *dev) info->mtds[i]->dev.parent = &dev->dev; } - if (devices_found == 1) { + if (!devices_found) { + err = -ENODEV; + } else if (devices_found == 1) { info->cmtd = info->mtds[0]; - } else if (devices_found > 1) { + } else { /* * We detected multiple devices. Concatenate them together. */ -- cgit v1.2.3 From 16f2101b4ddb34e4524623425a19cb7bbf7ced9c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:57 +0200 Subject: mtd: maps: physmap: Use dev_notice() and a %pR specifier Replace printk(KERN_NOTICE) by dev_notice() use the %pR specifier to print the iomem resource. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index a097f0cf519a..b98072a67d74 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -129,9 +129,8 @@ static int physmap_flash_probe(struct platform_device *dev) if (!res) break; - printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", - (unsigned long long)resource_size(res), - (unsigned long long)res->start); + dev_notice(&dev->dev, "physmap platform flash device: %pR\n", + res); if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res), -- cgit v1.2.3 From ea5bc54b12e822a2691c8b7348fae3badb6e376c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:58 +0200 Subject: mtd: maps: physmap: Use devm_ioremap_resource() Use devm_ioremap_resource() to replace the devm_request_mem_region() + devm_ioremap() combination. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index b98072a67d74..1d0f6f034a03 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -129,17 +129,15 @@ static int physmap_flash_probe(struct platform_device *dev) if (!res) break; - dev_notice(&dev->dev, "physmap platform flash device: %pR\n", - res); - - if (!devm_request_mem_region(&dev->dev, res->start, - resource_size(res), - dev_name(&dev->dev))) { - dev_err(&dev->dev, "Could not reserve memory region\n"); - err = -ENOMEM; + info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); + if (IS_ERR(info->maps[i].virt)) { + err = PTR_ERR(info->maps[i].virt); goto err_out; } + dev_notice(&dev->dev, "physmap platform flash device: %pR\n", + res); + info->maps[i].name = dev_name(&dev->dev); info->maps[i].phys = res->start; info->maps[i].size = resource_size(res); @@ -148,15 +146,6 @@ static int physmap_flash_probe(struct platform_device *dev) info->maps[i].pfow_base = physmap_data->pfow_base; info->maps[i].map_priv_1 = (unsigned long)dev; - info->maps[i].virt = devm_ioremap(&dev->dev, - info->maps[i].phys, - info->maps[i].size); - if (info->maps[i].virt == NULL) { - dev_err(&dev->dev, "Failed to ioremap flash region\n"); - err = -EIO; - goto err_out; - } - simple_map_init(&info->maps[i]); probe_type = rom_probe_types; -- cgit v1.2.3 From 51b436a2420e32258f78f0d7a53c8ad1c8569d3b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:48:59 +0200 Subject: mtd: maps: physmap: Remove the MAX_RESOURCES limitation Remove the MAX_RESOURCES limitation by dynamically allocating the ->mtds[] and ->maps[] at probe time based on the number of iomem resources attached to the platform device. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 1d0f6f034a03..86679d149a49 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -22,12 +22,11 @@ #include #include -#define MAX_RESOURCES 4 - struct physmap_flash_info { - struct mtd_info *mtds[MAX_RESOURCES]; + unsigned int nmaps; + struct mtd_info **mtds; struct mtd_info *cmtd; - struct map_info maps[MAX_RESOURCES]; + struct map_info *maps; spinlock_t vpp_lock; int vpp_refcnt; }; @@ -50,7 +49,7 @@ static int physmap_flash_remove(struct platform_device *dev) mtd_concat_destroy(info->cmtd); } - for (i = 0; i < MAX_RESOURCES; i++) { + for (i = 0; i < info->nmaps; i++) { if (info->mtds[i] != NULL) map_destroy(info->mtds[i]); } @@ -101,7 +100,6 @@ static int physmap_flash_probe(struct platform_device *dev) const char * const *part_types; int err = 0; int i; - int devices_found = 0; physmap_data = dev_get_platdata(&dev->dev); if (physmap_data == NULL) @@ -114,6 +112,24 @@ static int physmap_flash_probe(struct platform_device *dev) goto err_out; } + while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps)) + info->nmaps++; + + if (!info->nmaps) + return -ENODEV; + + info->maps = devm_kzalloc(&dev->dev, + sizeof(*info->maps) * info->nmaps, + GFP_KERNEL); + if (!info->maps) + return -ENOMEM; + + info->mtds = devm_kzalloc(&dev->dev, + sizeof(*info->mtds) * info->nmaps, + GFP_KERNEL); + if (!info->mtds) + return -ENOMEM; + if (physmap_data->init) { err = physmap_data->init(dev); if (err) @@ -122,13 +138,10 @@ static int physmap_flash_probe(struct platform_device *dev) platform_set_drvdata(dev, info); - for (i = 0; i < MAX_RESOURCES; i++) { + for (i = 0; i < info->nmaps; i++) { struct resource *res; res = platform_get_resource(dev, IORESOURCE_MEM, i); - if (!res) - break; - info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(info->maps[i].virt)) { err = PTR_ERR(info->maps[i].virt); @@ -159,21 +172,18 @@ static int physmap_flash_probe(struct platform_device *dev) dev_err(&dev->dev, "map_probe failed\n"); err = -ENXIO; goto err_out; - } else { - devices_found++; } info->mtds[i]->dev.parent = &dev->dev; } - if (!devices_found) { - err = -ENODEV; - } else if (devices_found == 1) { + if (info->nmaps == 1) { info->cmtd = info->mtds[0]; } else { /* * We detected multiple devices. Concatenate them together. */ - info->cmtd = mtd_concat_create(info->mtds, devices_found, dev_name(&dev->dev)); + info->cmtd = mtd_concat_create(info->mtds, info->nmaps, + dev_name(&dev->dev)); if (info->cmtd == NULL) err = -ENXIO; } @@ -199,7 +209,7 @@ static void physmap_flash_shutdown(struct platform_device *dev) struct physmap_flash_info *info = platform_get_drvdata(dev); int i; - for (i = 0; i < MAX_RESOURCES && info->mtds[i]; i++) + for (i = 0; i < info->nmaps && info->mtds[i]; i++) if (mtd_suspend(info->mtds[i]) == 0) mtd_resume(info->mtds[i]); } -- cgit v1.2.3 From 1e4f42084910067b2d37002afb6d1d1413552e1c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:00 +0200 Subject: mtd: maps: physmap: Check mtd_device_{parse_register, unregister}() ret code mtd_device_parse_register() and mtd_device_unregister() can fail, check their return code and propagate the error to the upper layer if needed. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 86679d149a49..9b34223c4635 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -35,7 +35,7 @@ static int physmap_flash_remove(struct platform_device *dev) { struct physmap_flash_info *info; struct physmap_flash_data *physmap_data; - int i; + int i, err; info = platform_get_drvdata(dev); if (info == NULL) @@ -44,7 +44,10 @@ static int physmap_flash_remove(struct platform_device *dev) physmap_data = dev_get_platdata(&dev->dev); if (info->cmtd) { - mtd_device_unregister(info->cmtd); + err = mtd_device_unregister(info->cmtd); + if (err) + return err; + if (info->cmtd != info->mtds[0]) mtd_concat_destroy(info->cmtd); } @@ -194,8 +197,12 @@ static int physmap_flash_probe(struct platform_device *dev) part_types = physmap_data->part_probe_types ? : part_probe_types; - mtd_device_parse_register(info->cmtd, part_types, NULL, - physmap_data->parts, physmap_data->nr_parts); + err = mtd_device_parse_register(info->cmtd, part_types, NULL, + physmap_data->parts, + physmap_data->nr_parts); + if (err) + goto err_out; + return 0; err_out: -- cgit v1.2.3 From 7abe5309de76337920f103d9e34ebd42a479533b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:01 +0200 Subject: mtd: maps: physmap: Return -ENOMEM directly when info allocation fails There's no point going to the err_out path since no resources have been allocated yet, just return -ENOMEM directly. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 9b34223c4635..7d30f3524d35 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -110,10 +110,8 @@ static int physmap_flash_probe(struct platform_device *dev) info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info), GFP_KERNEL); - if (info == NULL) { - err = -ENOMEM; - goto err_out; - } + if (!info) + return -ENOMEM; while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps)) info->nmaps++; -- cgit v1.2.3 From cb946bf6aaeb7c8151b18924d81370ffe6b7441b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:02 +0200 Subject: mtd: maps: physmap: Fix coding style issues reported by checkpatch Fix the following coding style issues: - != NULL and == NULL test replaced by ! (or nothing) - split over 80 chars lines - add missing braces in multi-line if() {} else {} statements Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/physmap.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 7d30f3524d35..e27051bc5dc6 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -38,7 +38,7 @@ static int physmap_flash_remove(struct platform_device *dev) int i, err; info = platform_get_drvdata(dev); - if (info == NULL) + if (!info) return 0; physmap_data = dev_get_platdata(&dev->dev); @@ -53,7 +53,7 @@ static int physmap_flash_remove(struct platform_device *dev) } for (i = 0; i < info->nmaps; i++) { - if (info->mtds[i] != NULL) + if (info->mtds[i]) map_destroy(info->mtds[i]); } @@ -90,10 +90,12 @@ static void physmap_set_vpp(struct map_info *map, int state) } static const char * const rom_probe_types[] = { - "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL }; + "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL +}; static const char * const part_probe_types[] = { - "cmdlinepart", "RedBoot", "afs", NULL }; + "cmdlinepart", "RedBoot", "afs", NULL +}; static int physmap_flash_probe(struct platform_device *dev) { @@ -105,11 +107,10 @@ static int physmap_flash_probe(struct platform_device *dev) int i; physmap_data = dev_get_platdata(&dev->dev); - if (physmap_data == NULL) + if (!physmap_data) return -ENODEV; - info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info), - GFP_KERNEL); + info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -163,13 +164,16 @@ static int physmap_flash_probe(struct platform_device *dev) simple_map_init(&info->maps[i]); probe_type = rom_probe_types; - if (physmap_data->probe_type == NULL) { - for (; info->mtds[i] == NULL && *probe_type != NULL; probe_type++) - info->mtds[i] = do_map_probe(*probe_type, &info->maps[i]); - } else - info->mtds[i] = do_map_probe(physmap_data->probe_type, &info->maps[i]); + if (!physmap_data->probe_type) { + for (; !info->mtds[i] && *probe_type; probe_type++) + info->mtds[i] = do_map_probe(*probe_type, + &info->maps[i]); + } else { + info->mtds[i] = do_map_probe(physmap_data->probe_type, + &info->maps[i]); + } - if (info->mtds[i] == NULL) { + if (!info->mtds[i]) { dev_err(&dev->dev, "map_probe failed\n"); err = -ENXIO; goto err_out; @@ -185,7 +189,7 @@ static int physmap_flash_probe(struct platform_device *dev) */ info->cmtd = mtd_concat_create(info->mtds, info->nmaps, dev_name(&dev->dev)); - if (info->cmtd == NULL) + if (!info->cmtd) err = -ENXIO; } if (err) @@ -231,7 +235,6 @@ static struct platform_driver physmap_flash_driver = { }, }; - #ifdef CONFIG_MTD_PHYSMAP_COMPAT static struct physmap_flash_data physmap_flash_data = { .width = CONFIG_MTD_PHYSMAP_BANKWIDTH, -- cgit v1.2.3 From 0c3def9b58d85ea8a8a8773d1151d8d554842d0a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:03 +0200 Subject: mtd: maps: Prepare merging of physmap and physmap_of We want to merge the physmap and physmap_of driver, but before we can do that we must prepare things to create physmap.o out of several .c files. Rename physmap.c into physmap-core.c and add a new Makefile rule to create physmap.o (right now it only contains physmap-core.o). Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/Makefile | 2 + drivers/mtd/maps/physmap-core.c | 295 ++++++++++++++++++++++++++++++++++++++++ drivers/mtd/maps/physmap.c | 295 ---------------------------------------- 3 files changed, 297 insertions(+), 295 deletions(-) create mode 100644 drivers/mtd/maps/physmap-core.c delete mode 100644 drivers/mtd/maps/physmap.c (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 51acf1fec19b..2574909edffd 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -17,6 +17,8 @@ obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o +physmap-objs-y += physmap-core.o +physmap-objs := $(physmap-objs-y) obj-$(CONFIG_MTD_PHYSMAP) += physmap.o physmap_of-objs-y += physmap_of_core.o physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c new file mode 100644 index 000000000000..e27051bc5dc6 --- /dev/null +++ b/drivers/mtd/maps/physmap-core.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Normal mappings of chips in physical memory + * + * Copyright (C) 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * 031022 - [jsun] add run-time configure and partition setup + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct physmap_flash_info { + unsigned int nmaps; + struct mtd_info **mtds; + struct mtd_info *cmtd; + struct map_info *maps; + spinlock_t vpp_lock; + int vpp_refcnt; +}; + +static int physmap_flash_remove(struct platform_device *dev) +{ + struct physmap_flash_info *info; + struct physmap_flash_data *physmap_data; + int i, err; + + info = platform_get_drvdata(dev); + if (!info) + return 0; + + physmap_data = dev_get_platdata(&dev->dev); + + if (info->cmtd) { + err = mtd_device_unregister(info->cmtd); + if (err) + return err; + + if (info->cmtd != info->mtds[0]) + mtd_concat_destroy(info->cmtd); + } + + for (i = 0; i < info->nmaps; i++) { + if (info->mtds[i]) + map_destroy(info->mtds[i]); + } + + if (physmap_data->exit) + physmap_data->exit(dev); + + return 0; +} + +static void physmap_set_vpp(struct map_info *map, int state) +{ + struct platform_device *pdev; + struct physmap_flash_data *physmap_data; + struct physmap_flash_info *info; + unsigned long flags; + + pdev = (struct platform_device *)map->map_priv_1; + physmap_data = dev_get_platdata(&pdev->dev); + + if (!physmap_data->set_vpp) + return; + + info = platform_get_drvdata(pdev); + + spin_lock_irqsave(&info->vpp_lock, flags); + if (state) { + if (++info->vpp_refcnt == 1) /* first nested 'on' */ + physmap_data->set_vpp(pdev, 1); + } else { + if (--info->vpp_refcnt == 0) /* last nested 'off' */ + physmap_data->set_vpp(pdev, 0); + } + spin_unlock_irqrestore(&info->vpp_lock, flags); +} + +static const char * const rom_probe_types[] = { + "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL +}; + +static const char * const part_probe_types[] = { + "cmdlinepart", "RedBoot", "afs", NULL +}; + +static int physmap_flash_probe(struct platform_device *dev) +{ + struct physmap_flash_data *physmap_data; + struct physmap_flash_info *info; + const char * const *probe_type; + const char * const *part_types; + int err = 0; + int i; + + physmap_data = dev_get_platdata(&dev->dev); + if (!physmap_data) + return -ENODEV; + + info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps)) + info->nmaps++; + + if (!info->nmaps) + return -ENODEV; + + info->maps = devm_kzalloc(&dev->dev, + sizeof(*info->maps) * info->nmaps, + GFP_KERNEL); + if (!info->maps) + return -ENOMEM; + + info->mtds = devm_kzalloc(&dev->dev, + sizeof(*info->mtds) * info->nmaps, + GFP_KERNEL); + if (!info->mtds) + return -ENOMEM; + + if (physmap_data->init) { + err = physmap_data->init(dev); + if (err) + goto err_out; + } + + platform_set_drvdata(dev, info); + + for (i = 0; i < info->nmaps; i++) { + struct resource *res; + + res = platform_get_resource(dev, IORESOURCE_MEM, i); + info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); + if (IS_ERR(info->maps[i].virt)) { + err = PTR_ERR(info->maps[i].virt); + goto err_out; + } + + dev_notice(&dev->dev, "physmap platform flash device: %pR\n", + res); + + info->maps[i].name = dev_name(&dev->dev); + info->maps[i].phys = res->start; + info->maps[i].size = resource_size(res); + info->maps[i].bankwidth = physmap_data->width; + info->maps[i].set_vpp = physmap_set_vpp; + info->maps[i].pfow_base = physmap_data->pfow_base; + info->maps[i].map_priv_1 = (unsigned long)dev; + + simple_map_init(&info->maps[i]); + + probe_type = rom_probe_types; + if (!physmap_data->probe_type) { + for (; !info->mtds[i] && *probe_type; probe_type++) + info->mtds[i] = do_map_probe(*probe_type, + &info->maps[i]); + } else { + info->mtds[i] = do_map_probe(physmap_data->probe_type, + &info->maps[i]); + } + + if (!info->mtds[i]) { + dev_err(&dev->dev, "map_probe failed\n"); + err = -ENXIO; + goto err_out; + } + info->mtds[i]->dev.parent = &dev->dev; + } + + if (info->nmaps == 1) { + info->cmtd = info->mtds[0]; + } else { + /* + * We detected multiple devices. Concatenate them together. + */ + info->cmtd = mtd_concat_create(info->mtds, info->nmaps, + dev_name(&dev->dev)); + if (!info->cmtd) + err = -ENXIO; + } + if (err) + goto err_out; + + spin_lock_init(&info->vpp_lock); + + part_types = physmap_data->part_probe_types ? : part_probe_types; + + err = mtd_device_parse_register(info->cmtd, part_types, NULL, + physmap_data->parts, + physmap_data->nr_parts); + if (err) + goto err_out; + + return 0; + +err_out: + physmap_flash_remove(dev); + return err; +} + +#ifdef CONFIG_PM +static void physmap_flash_shutdown(struct platform_device *dev) +{ + struct physmap_flash_info *info = platform_get_drvdata(dev); + int i; + + for (i = 0; i < info->nmaps && info->mtds[i]; i++) + if (mtd_suspend(info->mtds[i]) == 0) + mtd_resume(info->mtds[i]); +} +#else +#define physmap_flash_shutdown NULL +#endif + +static struct platform_driver physmap_flash_driver = { + .probe = physmap_flash_probe, + .remove = physmap_flash_remove, + .shutdown = physmap_flash_shutdown, + .driver = { + .name = "physmap-flash", + }, +}; + +#ifdef CONFIG_MTD_PHYSMAP_COMPAT +static struct physmap_flash_data physmap_flash_data = { + .width = CONFIG_MTD_PHYSMAP_BANKWIDTH, +}; + +static struct resource physmap_flash_resource = { + .start = CONFIG_MTD_PHYSMAP_START, + .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device physmap_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &physmap_flash_data, + }, + .num_resources = 1, + .resource = &physmap_flash_resource, +}; +#endif + +static int __init physmap_init(void) +{ + int err; + + err = platform_driver_register(&physmap_flash_driver); +#ifdef CONFIG_MTD_PHYSMAP_COMPAT + if (err == 0) { + err = platform_device_register(&physmap_flash); + if (err) + platform_driver_unregister(&physmap_flash_driver); + } +#endif + + return err; +} + +static void __exit physmap_exit(void) +{ +#ifdef CONFIG_MTD_PHYSMAP_COMPAT + platform_device_unregister(&physmap_flash); +#endif + platform_driver_unregister(&physmap_flash_driver); +} + +module_init(physmap_init); +module_exit(physmap_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Woodhouse "); +MODULE_DESCRIPTION("Generic configurable MTD map driver"); + +/* legacy platform drivers can't hotplug or coldplg */ +#ifndef CONFIG_MTD_PHYSMAP_COMPAT +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:physmap-flash"); +#endif diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c deleted file mode 100644 index e27051bc5dc6..000000000000 --- a/drivers/mtd/maps/physmap.c +++ /dev/null @@ -1,295 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Normal mappings of chips in physical memory - * - * Copyright (C) 2003 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * 031022 - [jsun] add run-time configure and partition setup - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct physmap_flash_info { - unsigned int nmaps; - struct mtd_info **mtds; - struct mtd_info *cmtd; - struct map_info *maps; - spinlock_t vpp_lock; - int vpp_refcnt; -}; - -static int physmap_flash_remove(struct platform_device *dev) -{ - struct physmap_flash_info *info; - struct physmap_flash_data *physmap_data; - int i, err; - - info = platform_get_drvdata(dev); - if (!info) - return 0; - - physmap_data = dev_get_platdata(&dev->dev); - - if (info->cmtd) { - err = mtd_device_unregister(info->cmtd); - if (err) - return err; - - if (info->cmtd != info->mtds[0]) - mtd_concat_destroy(info->cmtd); - } - - for (i = 0; i < info->nmaps; i++) { - if (info->mtds[i]) - map_destroy(info->mtds[i]); - } - - if (physmap_data->exit) - physmap_data->exit(dev); - - return 0; -} - -static void physmap_set_vpp(struct map_info *map, int state) -{ - struct platform_device *pdev; - struct physmap_flash_data *physmap_data; - struct physmap_flash_info *info; - unsigned long flags; - - pdev = (struct platform_device *)map->map_priv_1; - physmap_data = dev_get_platdata(&pdev->dev); - - if (!physmap_data->set_vpp) - return; - - info = platform_get_drvdata(pdev); - - spin_lock_irqsave(&info->vpp_lock, flags); - if (state) { - if (++info->vpp_refcnt == 1) /* first nested 'on' */ - physmap_data->set_vpp(pdev, 1); - } else { - if (--info->vpp_refcnt == 0) /* last nested 'off' */ - physmap_data->set_vpp(pdev, 0); - } - spin_unlock_irqrestore(&info->vpp_lock, flags); -} - -static const char * const rom_probe_types[] = { - "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL -}; - -static const char * const part_probe_types[] = { - "cmdlinepart", "RedBoot", "afs", NULL -}; - -static int physmap_flash_probe(struct platform_device *dev) -{ - struct physmap_flash_data *physmap_data; - struct physmap_flash_info *info; - const char * const *probe_type; - const char * const *part_types; - int err = 0; - int i; - - physmap_data = dev_get_platdata(&dev->dev); - if (!physmap_data) - return -ENODEV; - - info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps)) - info->nmaps++; - - if (!info->nmaps) - return -ENODEV; - - info->maps = devm_kzalloc(&dev->dev, - sizeof(*info->maps) * info->nmaps, - GFP_KERNEL); - if (!info->maps) - return -ENOMEM; - - info->mtds = devm_kzalloc(&dev->dev, - sizeof(*info->mtds) * info->nmaps, - GFP_KERNEL); - if (!info->mtds) - return -ENOMEM; - - if (physmap_data->init) { - err = physmap_data->init(dev); - if (err) - goto err_out; - } - - platform_set_drvdata(dev, info); - - for (i = 0; i < info->nmaps; i++) { - struct resource *res; - - res = platform_get_resource(dev, IORESOURCE_MEM, i); - info->maps[i].virt = devm_ioremap_resource(&dev->dev, res); - if (IS_ERR(info->maps[i].virt)) { - err = PTR_ERR(info->maps[i].virt); - goto err_out; - } - - dev_notice(&dev->dev, "physmap platform flash device: %pR\n", - res); - - info->maps[i].name = dev_name(&dev->dev); - info->maps[i].phys = res->start; - info->maps[i].size = resource_size(res); - info->maps[i].bankwidth = physmap_data->width; - info->maps[i].set_vpp = physmap_set_vpp; - info->maps[i].pfow_base = physmap_data->pfow_base; - info->maps[i].map_priv_1 = (unsigned long)dev; - - simple_map_init(&info->maps[i]); - - probe_type = rom_probe_types; - if (!physmap_data->probe_type) { - for (; !info->mtds[i] && *probe_type; probe_type++) - info->mtds[i] = do_map_probe(*probe_type, - &info->maps[i]); - } else { - info->mtds[i] = do_map_probe(physmap_data->probe_type, - &info->maps[i]); - } - - if (!info->mtds[i]) { - dev_err(&dev->dev, "map_probe failed\n"); - err = -ENXIO; - goto err_out; - } - info->mtds[i]->dev.parent = &dev->dev; - } - - if (info->nmaps == 1) { - info->cmtd = info->mtds[0]; - } else { - /* - * We detected multiple devices. Concatenate them together. - */ - info->cmtd = mtd_concat_create(info->mtds, info->nmaps, - dev_name(&dev->dev)); - if (!info->cmtd) - err = -ENXIO; - } - if (err) - goto err_out; - - spin_lock_init(&info->vpp_lock); - - part_types = physmap_data->part_probe_types ? : part_probe_types; - - err = mtd_device_parse_register(info->cmtd, part_types, NULL, - physmap_data->parts, - physmap_data->nr_parts); - if (err) - goto err_out; - - return 0; - -err_out: - physmap_flash_remove(dev); - return err; -} - -#ifdef CONFIG_PM -static void physmap_flash_shutdown(struct platform_device *dev) -{ - struct physmap_flash_info *info = platform_get_drvdata(dev); - int i; - - for (i = 0; i < info->nmaps && info->mtds[i]; i++) - if (mtd_suspend(info->mtds[i]) == 0) - mtd_resume(info->mtds[i]); -} -#else -#define physmap_flash_shutdown NULL -#endif - -static struct platform_driver physmap_flash_driver = { - .probe = physmap_flash_probe, - .remove = physmap_flash_remove, - .shutdown = physmap_flash_shutdown, - .driver = { - .name = "physmap-flash", - }, -}; - -#ifdef CONFIG_MTD_PHYSMAP_COMPAT -static struct physmap_flash_data physmap_flash_data = { - .width = CONFIG_MTD_PHYSMAP_BANKWIDTH, -}; - -static struct resource physmap_flash_resource = { - .start = CONFIG_MTD_PHYSMAP_START, - .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device physmap_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = &physmap_flash_data, - }, - .num_resources = 1, - .resource = &physmap_flash_resource, -}; -#endif - -static int __init physmap_init(void) -{ - int err; - - err = platform_driver_register(&physmap_flash_driver); -#ifdef CONFIG_MTD_PHYSMAP_COMPAT - if (err == 0) { - err = platform_device_register(&physmap_flash); - if (err) - platform_driver_unregister(&physmap_flash_driver); - } -#endif - - return err; -} - -static void __exit physmap_exit(void) -{ -#ifdef CONFIG_MTD_PHYSMAP_COMPAT - platform_device_unregister(&physmap_flash); -#endif - platform_driver_unregister(&physmap_flash_driver); -} - -module_init(physmap_init); -module_exit(physmap_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Woodhouse "); -MODULE_DESCRIPTION("Generic configurable MTD map driver"); - -/* legacy platform drivers can't hotplug or coldplg */ -#ifndef CONFIG_MTD_PHYSMAP_COMPAT -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:physmap-flash"); -#endif -- cgit v1.2.3 From 642b1e8dbed7bbbf8c4deb3c9a0496f17278badc Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:04 +0200 Subject: mtd: maps: Merge physmap_of.c into physmap-core.c There's no real reason to have two separate driver for the DT and pdata case. Just do what we do everywhere else and handle DT and pdata parsing in the same driver. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/Kconfig | 4 +- drivers/mtd/maps/Makefile | 7 +- drivers/mtd/maps/physmap-core.c | 261 +++++++++++++++++++++++--- drivers/mtd/maps/physmap_of_core.c | 368 ------------------------------------- 4 files changed, 240 insertions(+), 400 deletions(-) delete mode 100644 drivers/mtd/maps/physmap_of_core.c (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index afb36bff13a7..5bffebacce86 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -66,8 +66,8 @@ config MTD_PHYSMAP_BANKWIDTH used internally by the CFI drivers. config MTD_PHYSMAP_OF - tristate "Memory device in physical memory map based on OF description" - depends on OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_RAM) + bool "Memory device in physical memory map based on OF description" + depends on OF && MTD_PHYSMAP help This provides a 'mapping' driver which allows the NOR Flash, ROM and RAM driver code to communicate with chips which are mapped diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 2574909edffd..ad32b185a120 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -18,13 +18,10 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o physmap-objs-y += physmap-core.o +physmap-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o +physmap-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o physmap-objs := $(physmap-objs-y) obj-$(CONFIG_MTD_PHYSMAP) += physmap.o -physmap_of-objs-y += physmap_of_core.o -physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o -physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o -physmap_of-objs := $(physmap_of-objs-y) -obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o obj-$(CONFIG_MTD_PISMO) += pismo.o obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index e27051bc5dc6..07af8368d173 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -6,6 +6,13 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * 031022 - [jsun] add run-time configure and partition setup + * + * Device tree support: + * Copyright (C) 2006 MontaVista Software Inc. + * Author: Vitaly Wool + * + * Revised to handle newer style flash binding by: + * Copyright (C) 2007 David Gibson, IBM Corporation. */ #include @@ -20,7 +27,12 @@ #include #include #include +#include #include +#include + +#include "physmap_of_gemini.h" +#include "physmap_of_versatile.h" struct physmap_flash_info { unsigned int nmaps; @@ -29,6 +41,10 @@ struct physmap_flash_info { struct map_info *maps; spinlock_t vpp_lock; int vpp_refcnt; + const char *probe_type; + const char * const *part_types; + unsigned int nparts; + const struct mtd_partition *parts; }; static int physmap_flash_remove(struct platform_device *dev) @@ -41,8 +57,6 @@ static int physmap_flash_remove(struct platform_device *dev) if (!info) return 0; - physmap_data = dev_get_platdata(&dev->dev); - if (info->cmtd) { err = mtd_device_unregister(info->cmtd); if (err) @@ -57,7 +71,8 @@ static int physmap_flash_remove(struct platform_device *dev) map_destroy(info->mtds[i]); } - if (physmap_data->exit) + physmap_data = dev_get_platdata(&dev->dev); + if (physmap_data && physmap_data->exit) physmap_data->exit(dev); return 0; @@ -89,6 +104,172 @@ static void physmap_set_vpp(struct map_info *map, int state) spin_unlock_irqrestore(&info->vpp_lock, flags); } +#if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) +static const struct of_device_id of_flash_match[] = { + { + .compatible = "cfi-flash", + .data = "cfi_probe", + }, + { + /* + * FIXME: JEDEC chips can't be safely and reliably + * probed, although the mtd code gets it right in + * practice most of the time. We should use the + * vendor and device ids specified by the binding to + * bypass the heuristic probe code, but the mtd layer + * provides, at present, no interface for doing so + * :(. + */ + .compatible = "jedec-flash", + .data = "jedec_probe", + }, + { + .compatible = "mtd-ram", + .data = "map_ram", + }, + { + .compatible = "mtd-rom", + .data = "map_rom", + }, + { + .type = "rom", + .compatible = "direct-mapped" + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, of_flash_match); + +static const char * const of_default_part_probes[] = { + "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL +}; + +static const char * const *of_get_part_probes(struct platform_device *dev) +{ + struct device_node *dp = dev->dev.of_node; + const char **res; + int count; + + count = of_property_count_strings(dp, "linux,part-probe"); + if (count < 0) + return of_default_part_probes; + + res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL); + if (!res) + return NULL; + + count = of_property_read_string_array(dp, "linux,part-probe", res, + count); + if (count < 0) + return NULL; + + return res; +} + +static const char *of_select_probe_type(struct platform_device *dev) +{ + struct device_node *dp = dev->dev.of_node; + const struct of_device_id *match; + const char *probe_type; + + match = of_match_device(of_flash_match, &dev->dev); + probe_type = match->data; + if (probe_type) + return probe_type; + + dev_warn(&dev->dev, + "Device tree uses obsolete \"direct-mapped\" flash binding\n"); + + of_property_read_string(dp, "probe-type", &probe_type); + if (!probe_type) + return NULL; + + if (!strcmp(probe_type, "CFI")) { + probe_type = "cfi_probe"; + } else if (!strcmp(probe_type, "JEDEC")) { + probe_type = "jedec_probe"; + } else if (!strcmp(probe_type, "ROM")) { + probe_type = "map_rom"; + } else { + dev_warn(&dev->dev, + "obsolete_probe: don't know probe type '%s', mapping as rom\n", + probe_type); + probe_type = "map_rom"; + } + + return probe_type; +} + +static int physmap_flash_of_init(struct platform_device *dev) +{ + struct physmap_flash_info *info = platform_get_drvdata(dev); + struct device_node *dp = dev->dev.of_node; + const char *mtd_name = NULL; + int err, swap = 0; + bool map_indirect; + unsigned int i; + u32 bankwidth; + + if (!dp) + return -EINVAL; + + info->probe_type = of_select_probe_type(dev); + + info->part_types = of_get_part_probes(dev); + if (!info->part_types) + return -ENOMEM; + + of_property_read_string(dp, "linux,mtd-name", &mtd_name); + + map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access"); + + err = of_property_read_u32(dp, "bank-width", &bankwidth); + if (err) { + dev_err(&dev->dev, "Can't get bank width from device tree\n"); + return err; + } + + if (of_property_read_bool(dp, "big-endian")) + swap = CFI_BIG_ENDIAN; + else if (of_property_read_bool(dp, "little-endian")) + swap = CFI_LITTLE_ENDIAN; + + for (i = 0; i < info->nmaps; i++) { + info->maps[i].name = mtd_name; + info->maps[i].swap = swap; + info->maps[i].bankwidth = bankwidth; + info->maps[i].device_node = dp; + + err = of_flash_probe_gemini(dev, dp, &info->maps[i]); + if (err) + return err; + + err = of_flash_probe_versatile(dev, dp, &info->maps[i]); + if (err) + return err; + + /* + * On some platforms (e.g. MPC5200) a direct 1:1 mapping + * may cause problems with JFFS2 usage, as the local bus (LPB) + * doesn't support unaligned accesses as implemented in the + * JFFS2 code via memcpy(). By setting NO_XIP, the + * flash will not be exposed directly to the MTD users + * (e.g. JFFS2) any more. + */ + if (map_indirect) + info->maps[i].phys = NO_XIP; + } + + return 0; +} +#else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */ +#define of_flash_match NULL + +static int physmap_flash_of_init(struct platform_device *dev) +{ + return -ENOTSUPP; +} +#endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */ + static const char * const rom_probe_types[] = { "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL }; @@ -97,18 +278,46 @@ static const char * const part_probe_types[] = { "cmdlinepart", "RedBoot", "afs", NULL }; -static int physmap_flash_probe(struct platform_device *dev) +static int physmap_flash_pdata_init(struct platform_device *dev) { + struct physmap_flash_info *info = platform_get_drvdata(dev); struct physmap_flash_data *physmap_data; + unsigned int i; + int err; + + physmap_data = dev_get_platdata(&dev->dev); + if (!physmap_data) + return -EINVAL; + + info->probe_type = physmap_data->probe_type; + info->part_types = physmap_data->part_probe_types ? : part_probe_types; + info->parts = physmap_data->parts; + info->nparts = physmap_data->nr_parts; + + if (physmap_data->init) { + err = physmap_data->init(dev); + if (err) + return err; + } + + for (i = 0; i < info->nmaps; i++) { + info->maps[i].bankwidth = physmap_data->width; + info->maps[i].pfow_base = physmap_data->pfow_base; + info->maps[i].set_vpp = physmap_set_vpp; + } + + return 0; +} + +static int physmap_flash_probe(struct platform_device *dev) +{ struct physmap_flash_info *info; const char * const *probe_type; - const char * const *part_types; int err = 0; int i; - physmap_data = dev_get_platdata(&dev->dev); - if (!physmap_data) - return -ENODEV; + if (!dev->dev.of_node && !dev_get_platdata(&dev->dev)) + return -EINVAL; info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -132,14 +341,16 @@ static int physmap_flash_probe(struct platform_device *dev) if (!info->mtds) return -ENOMEM; - if (physmap_data->init) { - err = physmap_data->init(dev); - if (err) - goto err_out; - } - platform_set_drvdata(dev, info); + if (dev->dev.of_node) + err = physmap_flash_of_init(dev); + else + err = physmap_flash_pdata_init(dev); + + if (err) + return err; + for (i = 0; i < info->nmaps; i++) { struct resource *res; @@ -154,22 +365,22 @@ static int physmap_flash_probe(struct platform_device *dev) res); info->maps[i].name = dev_name(&dev->dev); - info->maps[i].phys = res->start; + + if (!info->maps[i].phys) + info->maps[i].phys = res->start; + info->maps[i].size = resource_size(res); - info->maps[i].bankwidth = physmap_data->width; - info->maps[i].set_vpp = physmap_set_vpp; - info->maps[i].pfow_base = physmap_data->pfow_base; info->maps[i].map_priv_1 = (unsigned long)dev; simple_map_init(&info->maps[i]); probe_type = rom_probe_types; - if (!physmap_data->probe_type) { + if (!info->probe_type) { for (; !info->mtds[i] && *probe_type; probe_type++) info->mtds[i] = do_map_probe(*probe_type, &info->maps[i]); } else { - info->mtds[i] = do_map_probe(physmap_data->probe_type, + info->mtds[i] = do_map_probe(info->probe_type, &info->maps[i]); } @@ -197,11 +408,9 @@ static int physmap_flash_probe(struct platform_device *dev) spin_lock_init(&info->vpp_lock); - part_types = physmap_data->part_probe_types ? : part_probe_types; - - err = mtd_device_parse_register(info->cmtd, part_types, NULL, - physmap_data->parts, - physmap_data->nr_parts); + mtd_set_of_node(info->cmtd, dev->dev.of_node); + err = mtd_device_parse_register(info->cmtd, info->part_types, NULL, + info->parts, info->nparts); if (err) goto err_out; @@ -232,6 +441,7 @@ static struct platform_driver physmap_flash_driver = { .shutdown = physmap_flash_shutdown, .driver = { .name = "physmap-flash", + .of_match_table = of_flash_match, }, }; @@ -286,6 +496,7 @@ module_exit(physmap_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); +MODULE_AUTHOR("Vitaly Wool "); MODULE_DESCRIPTION("Generic configurable MTD map driver"); /* legacy platform drivers can't hotplug or coldplg */ diff --git a/drivers/mtd/maps/physmap_of_core.c b/drivers/mtd/maps/physmap_of_core.c deleted file mode 100644 index ece605d78c21..000000000000 --- a/drivers/mtd/maps/physmap_of_core.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Flash mappings described by the OF (or flattened) device tree - * - * Copyright (C) 2006 MontaVista Software Inc. - * Author: Vitaly Wool - * - * Revised to handle newer style flash binding by: - * Copyright (C) 2007 David Gibson, IBM Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "physmap_of_gemini.h" -#include "physmap_of_versatile.h" - -struct of_flash_list { - struct mtd_info *mtd; - struct map_info map; -}; - -struct of_flash { - struct mtd_info *cmtd; - int list_size; /* number of elements in of_flash_list */ - struct of_flash_list list[0]; -}; - -static int of_flash_remove(struct platform_device *dev) -{ - struct of_flash *info; - int i; - - info = dev_get_drvdata(&dev->dev); - if (!info) - return 0; - dev_set_drvdata(&dev->dev, NULL); - - if (info->cmtd) { - mtd_device_unregister(info->cmtd); - if (info->cmtd != info->list[0].mtd) - mtd_concat_destroy(info->cmtd); - } - - for (i = 0; i < info->list_size; i++) - if (info->list[i].mtd) - map_destroy(info->list[i].mtd); - - return 0; -} - -static const char * const rom_probe_types[] = { - "cfi_probe", "jedec_probe", "map_rom" }; - -/* Helper function to handle probing of the obsolete "direct-mapped" - * compatible binding, which has an extra "probe-type" property - * describing the type of flash probe necessary. */ -static struct mtd_info *obsolete_probe(struct platform_device *dev, - struct map_info *map) -{ - struct device_node *dp = dev->dev.of_node; - const char *of_probe; - struct mtd_info *mtd; - int i; - - dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" " - "flash binding\n"); - - of_probe = of_get_property(dp, "probe-type", NULL); - if (!of_probe) { - for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) { - mtd = do_map_probe(rom_probe_types[i], map); - if (mtd) - return mtd; - } - return NULL; - } else if (strcmp(of_probe, "CFI") == 0) { - return do_map_probe("cfi_probe", map); - } else if (strcmp(of_probe, "JEDEC") == 0) { - return do_map_probe("jedec_probe", map); - } else { - if (strcmp(of_probe, "ROM") != 0) - dev_warn(&dev->dev, "obsolete_probe: don't know probe " - "type '%s', mapping as rom\n", of_probe); - return do_map_probe("map_rom", map); - } -} - -/* When partitions are set we look for a linux,part-probe property which - specifies the list of partition probers to use. If none is given then the - default is use. These take precedence over other device tree - information. */ -static const char * const part_probe_types_def[] = { - "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL }; - -static const char * const *of_get_probes(struct device_node *dp) -{ - const char **res; - int count; - - count = of_property_count_strings(dp, "linux,part-probe"); - if (count < 0) - return part_probe_types_def; - - res = kcalloc(count + 1, sizeof(*res), GFP_KERNEL); - if (!res) - return NULL; - - count = of_property_read_string_array(dp, "linux,part-probe", res, - count); - if (count < 0) - return NULL; - - return res; -} - -static void of_free_probes(const char * const *probes) -{ - if (probes != part_probe_types_def) - kfree(probes); -} - -static const struct of_device_id of_flash_match[]; -static int of_flash_probe(struct platform_device *dev) -{ - const char * const *part_probe_types; - const struct of_device_id *match; - struct device_node *dp = dev->dev.of_node; - struct resource res; - struct of_flash *info; - const char *probe_type; - const __be32 *width; - int err; - int i; - int count; - const __be32 *p; - int reg_tuple_size; - struct mtd_info **mtd_list = NULL; - resource_size_t res_size; - bool map_indirect; - const char *mtd_name = NULL; - - match = of_match_device(of_flash_match, &dev->dev); - if (!match) - return -EINVAL; - probe_type = match->data; - - reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32); - - of_property_read_string(dp, "linux,mtd-name", &mtd_name); - - /* - * Get number of "reg" tuples. Scan for MTD devices on area's - * described by each "reg" region. This makes it possible (including - * the concat support) to support the Intel P30 48F4400 chips which - * consists internally of 2 non-identical NOR chips on one die. - */ - p = of_get_property(dp, "reg", &count); - if (!p || count % reg_tuple_size != 0) { - dev_err(&dev->dev, "Malformed reg property on %pOF\n", - dev->dev.of_node); - err = -EINVAL; - goto err_flash_remove; - } - count /= reg_tuple_size; - - map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access"); - - err = -ENOMEM; - info = devm_kzalloc(&dev->dev, - sizeof(struct of_flash) + - sizeof(struct of_flash_list) * count, GFP_KERNEL); - if (!info) - goto err_flash_remove; - - dev_set_drvdata(&dev->dev, info); - - mtd_list = kcalloc(count, sizeof(*mtd_list), GFP_KERNEL); - if (!mtd_list) - goto err_flash_remove; - - for (i = 0; i < count; i++) { - err = -ENXIO; - if (of_address_to_resource(dp, i, &res)) { - /* - * Continue with next register tuple if this - * one is not mappable - */ - continue; - } - - dev_dbg(&dev->dev, "of_flash device: %pR\n", &res); - - err = -EBUSY; - res_size = resource_size(&res); - info->list[i].map.virt = devm_ioremap_resource(&dev->dev, &res); - if (IS_ERR(info->list[i].map.virt)) { - err = PTR_ERR(info->list[i].map.virt); - goto err_out; - } - - err = -ENXIO; - width = of_get_property(dp, "bank-width", NULL); - if (!width) { - dev_err(&dev->dev, "Can't get bank width from device" - " tree\n"); - goto err_out; - } - - info->list[i].map.name = mtd_name ?: dev_name(&dev->dev); - info->list[i].map.phys = res.start; - info->list[i].map.size = res_size; - info->list[i].map.bankwidth = be32_to_cpup(width); - info->list[i].map.device_node = dp; - - if (of_property_read_bool(dp, "big-endian")) - info->list[i].map.swap = CFI_BIG_ENDIAN; - else if (of_property_read_bool(dp, "little-endian")) - info->list[i].map.swap = CFI_LITTLE_ENDIAN; - - err = of_flash_probe_gemini(dev, dp, &info->list[i].map); - if (err) - goto err_out; - err = of_flash_probe_versatile(dev, dp, &info->list[i].map); - if (err) - goto err_out; - - simple_map_init(&info->list[i].map); - - /* - * On some platforms (e.g. MPC5200) a direct 1:1 mapping - * may cause problems with JFFS2 usage, as the local bus (LPB) - * doesn't support unaligned accesses as implemented in the - * JFFS2 code via memcpy(). By setting NO_XIP, the - * flash will not be exposed directly to the MTD users - * (e.g. JFFS2) any more. - */ - if (map_indirect) - info->list[i].map.phys = NO_XIP; - - if (probe_type) { - info->list[i].mtd = do_map_probe(probe_type, - &info->list[i].map); - } else { - info->list[i].mtd = obsolete_probe(dev, - &info->list[i].map); - } - - /* Fall back to mapping region as ROM */ - if (!info->list[i].mtd) { - dev_warn(&dev->dev, - "do_map_probe() failed for type %s\n", - probe_type); - - info->list[i].mtd = do_map_probe("map_rom", - &info->list[i].map); - } - mtd_list[i] = info->list[i].mtd; - - err = -ENXIO; - if (!info->list[i].mtd) { - dev_err(&dev->dev, "do_map_probe() failed\n"); - goto err_out; - } else { - info->list_size++; - } - info->list[i].mtd->dev.parent = &dev->dev; - } - - err = 0; - info->cmtd = NULL; - if (info->list_size == 1) { - info->cmtd = info->list[0].mtd; - } else if (info->list_size > 1) { - /* - * We detected multiple devices. Concatenate them together. - */ - info->cmtd = mtd_concat_create(mtd_list, info->list_size, - dev_name(&dev->dev)); - } - if (info->cmtd == NULL) - err = -ENXIO; - - if (err) - goto err_out; - - info->cmtd->dev.parent = &dev->dev; - mtd_set_of_node(info->cmtd, dp); - part_probe_types = of_get_probes(dp); - if (!part_probe_types) { - err = -ENOMEM; - goto err_out; - } - mtd_device_parse_register(info->cmtd, part_probe_types, NULL, - NULL, 0); - of_free_probes(part_probe_types); - - kfree(mtd_list); - - return 0; - -err_out: - kfree(mtd_list); -err_flash_remove: - of_flash_remove(dev); - - return err; -} - -static const struct of_device_id of_flash_match[] = { - { - .compatible = "cfi-flash", - .data = (void *)"cfi_probe", - }, - { - /* FIXME: JEDEC chips can't be safely and reliably - * probed, although the mtd code gets it right in - * practice most of the time. We should use the - * vendor and device ids specified by the binding to - * bypass the heuristic probe code, but the mtd layer - * provides, at present, no interface for doing so - * :(. */ - .compatible = "jedec-flash", - .data = (void *)"jedec_probe", - }, - { - .compatible = "mtd-ram", - .data = (void *)"map_ram", - }, - { - .compatible = "mtd-rom", - .data = (void *)"map_rom", - }, - { - .type = "rom", - .compatible = "direct-mapped" - }, - { }, -}; -MODULE_DEVICE_TABLE(of, of_flash_match); - -static struct platform_driver of_flash_driver = { - .driver = { - .name = "of-flash", - .of_match_table = of_flash_match, - }, - .probe = of_flash_probe, - .remove = of_flash_remove, -}; - -module_platform_driver(of_flash_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vitaly Wool "); -MODULE_DESCRIPTION("Device tree based MTD map driver"); -- cgit v1.2.3 From 6ca15cfa0788ebef365ce31d1e01ea30a389a895 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:05 +0200 Subject: mtd: maps: Rename physmap_of_{versatile, gemini} into physmap-{versatile, gemini} Now that the physmap_of driver is gone, the gemini and versative extensions are part of the physmap driver. Rename the source files and the config option to reflect this. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/Kconfig | 4 +- drivers/mtd/maps/Makefile | 4 +- drivers/mtd/maps/physmap-core.c | 4 +- drivers/mtd/maps/physmap-gemini.c | 97 ++++++++++++ drivers/mtd/maps/physmap-gemini.h | 17 +++ drivers/mtd/maps/physmap-versatile.c | 254 ++++++++++++++++++++++++++++++++ drivers/mtd/maps/physmap-versatile.h | 17 +++ drivers/mtd/maps/physmap_of_gemini.c | 97 ------------ drivers/mtd/maps/physmap_of_gemini.h | 17 --- drivers/mtd/maps/physmap_of_versatile.c | 254 -------------------------------- drivers/mtd/maps/physmap_of_versatile.h | 17 --- 11 files changed, 391 insertions(+), 391 deletions(-) create mode 100644 drivers/mtd/maps/physmap-gemini.c create mode 100644 drivers/mtd/maps/physmap-gemini.h create mode 100644 drivers/mtd/maps/physmap-versatile.c create mode 100644 drivers/mtd/maps/physmap-versatile.h delete mode 100644 drivers/mtd/maps/physmap_of_gemini.c delete mode 100644 drivers/mtd/maps/physmap_of_gemini.h delete mode 100644 drivers/mtd/maps/physmap_of_versatile.c delete mode 100644 drivers/mtd/maps/physmap_of_versatile.h (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 5bffebacce86..bb0d64e3fcd6 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -74,7 +74,7 @@ config MTD_PHYSMAP_OF physically into the CPU's memory. The mapping description here is taken from OF device tree. -config MTD_PHYSMAP_OF_VERSATILE +config MTD_PHYSMAP_VERSATILE bool "ARM Versatile OF-based physical memory map handling" depends on MTD_PHYSMAP_OF depends on MFD_SYSCON @@ -84,7 +84,7 @@ config MTD_PHYSMAP_OF_VERSATILE platforms, basically to add a VPP (write protection) callback so the flash can be taken out of write protection. -config MTD_PHYSMAP_OF_GEMINI +config MTD_PHYSMAP_GEMINI bool "Cortina Gemini OF-based physical memory map handling" depends on MTD_PHYSMAP_OF depends on MFD_SYSCON diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index ad32b185a120..ce737e15b7cf 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -18,8 +18,8 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o physmap-objs-y += physmap-core.o -physmap-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o -physmap-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o +physmap-objs-$(CONFIG_MTD_PHYSMAP_VERSATILE) += physmap-versatile.o +physmap-objs-$(CONFIG_MTD_PHYSMAP_GEMINI) += physmap-gemini.o physmap-objs := $(physmap-objs-y) obj-$(CONFIG_MTD_PHYSMAP) += physmap.o obj-$(CONFIG_MTD_PISMO) += pismo.o diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 07af8368d173..8a8af37576ff 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -31,8 +31,8 @@ #include #include -#include "physmap_of_gemini.h" -#include "physmap_of_versatile.h" +#include "physmap-gemini.h" +#include "physmap-versatile.h" struct physmap_flash_info { unsigned int nmaps; diff --git a/drivers/mtd/maps/physmap-gemini.c b/drivers/mtd/maps/physmap-gemini.c new file mode 100644 index 000000000000..1cf128a0526d --- /dev/null +++ b/drivers/mtd/maps/physmap-gemini.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cortina Systems Gemini OF physmap add-on + * Copyright (C) 2017 Linus Walleij + * + * This SoC has an elaborate flash control register, so we need to + * detect and set it up when booting on this platform. + */ +#include +#include +#include +#include +#include +#include +#include +#include "physmap-gemini.h" + +/* + * The Flash-relevant parts of the global status register + * These would also be relevant for a NAND driver. + */ +#define GLOBAL_STATUS 0x04 +#define FLASH_TYPE_MASK (0x3 << 24) +#define FLASH_TYPE_NAND_2K (0x3 << 24) +#define FLASH_TYPE_NAND_512 (0x2 << 24) +#define FLASH_TYPE_PARALLEL (0x1 << 24) +#define FLASH_TYPE_SERIAL (0x0 << 24) +/* if parallel */ +#define FLASH_WIDTH_16BIT (1 << 23) /* else 8 bit */ +/* if serial */ +#define FLASH_ATMEL (1 << 23) /* else STM */ + +#define FLASH_SIZE_MASK (0x3 << 21) +#define NAND_256M (0x3 << 21) /* and more */ +#define NAND_128M (0x2 << 21) +#define NAND_64M (0x1 << 21) +#define NAND_32M (0x0 << 21) +#define ATMEL_16M (0x3 << 21) /* and more */ +#define ATMEL_8M (0x2 << 21) +#define ATMEL_4M_2M (0x1 << 21) +#define ATMEL_1M (0x0 << 21) /* and less */ +#define STM_32M (1 << 22) /* and more */ +#define STM_16M (0 << 22) /* and less */ + +#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */ + +int of_flash_probe_gemini(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + struct regmap *rmap; + struct device *dev = &pdev->dev; + u32 val; + int ret; + + /* Multiplatform guard */ + if (!of_device_is_compatible(np, "cortina,gemini-flash")) + return 0; + + rmap = syscon_regmap_lookup_by_phandle(np, "syscon"); + if (IS_ERR(rmap)) { + dev_err(dev, "no syscon\n"); + return PTR_ERR(rmap); + } + + ret = regmap_read(rmap, GLOBAL_STATUS, &val); + if (ret) { + dev_err(dev, "failed to read global status register\n"); + return -ENODEV; + } + dev_dbg(dev, "global status reg: %08x\n", val); + + /* + * It would be contradictory if a physmap flash was NOT parallel. + */ + if ((val & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL) { + dev_err(dev, "flash is not parallel\n"); + return -ENODEV; + } + + /* + * Complain if DT data and hardware definition is different. + */ + if (val & FLASH_WIDTH_16BIT) { + if (map->bankwidth != 2) + dev_warn(dev, "flash hardware say flash is 16 bit wide but DT says it is %d bits wide\n", + map->bankwidth * 8); + } else { + if (map->bankwidth != 1) + dev_warn(dev, "flash hardware say flash is 8 bit wide but DT says it is %d bits wide\n", + map->bankwidth * 8); + } + + dev_info(&pdev->dev, "initialized Gemini-specific physmap control\n"); + + return 0; +} diff --git a/drivers/mtd/maps/physmap-gemini.h b/drivers/mtd/maps/physmap-gemini.h new file mode 100644 index 000000000000..72bd04ce3fdb --- /dev/null +++ b/drivers/mtd/maps/physmap-gemini.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include + +#ifdef CONFIG_MTD_PHYSMAP_GEMINI +int of_flash_probe_gemini(struct platform_device *pdev, + struct device_node *np, + struct map_info *map); +#else +static inline +int of_flash_probe_gemini(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + return 0; +} +#endif diff --git a/drivers/mtd/maps/physmap-versatile.c b/drivers/mtd/maps/physmap-versatile.c new file mode 100644 index 000000000000..0179d710bb3f --- /dev/null +++ b/drivers/mtd/maps/physmap-versatile.c @@ -0,0 +1,254 @@ +/* + * Versatile OF physmap driver add-on + * + * Copyright (c) 2016, Linaro Limited + * Author: Linus Walleij + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "physmap-versatile.h" + +static struct regmap *syscon_regmap; + +enum versatile_flashprot { + INTEGRATOR_AP_FLASHPROT, + INTEGRATOR_CP_FLASHPROT, + VERSATILE_FLASHPROT, + REALVIEW_FLASHPROT, +}; + +static const struct of_device_id syscon_match[] = { + { + .compatible = "arm,integrator-ap-syscon", + .data = (void *)INTEGRATOR_AP_FLASHPROT, + }, + { + .compatible = "arm,integrator-cp-syscon", + .data = (void *)INTEGRATOR_CP_FLASHPROT, + }, + { + .compatible = "arm,core-module-versatile", + .data = (void *)VERSATILE_FLASHPROT, + }, + { + .compatible = "arm,realview-eb-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pb1176-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pb11mp-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pba8-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + { + .compatible = "arm,realview-pbx-syscon", + .data = (void *)REALVIEW_FLASHPROT, + }, + {}, +}; + +/* + * Flash protection handling for the Integrator/AP + */ +#define INTEGRATOR_SC_CTRLS_OFFSET 0x08 +#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C +#define INTEGRATOR_SC_CTRL_FLVPPEN BIT(1) +#define INTEGRATOR_SC_CTRL_FLWP BIT(2) + +#define INTEGRATOR_EBI_CSR1_OFFSET 0x04 +/* The manual says bit 2, the code says bit 3, trust the code */ +#define INTEGRATOR_EBI_WRITE_ENABLE BIT(3) +#define INTEGRATOR_EBI_LOCK_OFFSET 0x20 +#define INTEGRATOR_EBI_LOCK_VAL 0xA05F + +static const struct of_device_id ebi_match[] = { + { .compatible = "arm,external-bus-interface"}, + { }, +}; + +static int ap_flash_init(struct platform_device *pdev) +{ + struct device_node *ebi; + void __iomem *ebi_base; + u32 val; + int ret; + + /* Look up the EBI */ + ebi = of_find_matching_node(NULL, ebi_match); + if (!ebi) { + return -ENODEV; + } + ebi_base = of_iomap(ebi, 0); + if (!ebi_base) + return -ENODEV; + + /* Clear VPP and write protection bits */ + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLC_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n"); + + /* Unlock the EBI */ + writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + + /* Enable write cycles on the EBI, CSR1 (flash) */ + val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + val |= INTEGRATOR_EBI_WRITE_ENABLE; + writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); + + /* Lock the EBI again */ + writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); + iounmap(ebi_base); + + return 0; +} + +static void ap_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + if (on) { + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLS_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + pr_err("error enabling AP VPP\n"); + } else { + ret = regmap_write(syscon_regmap, + INTEGRATOR_SC_CTRLC_OFFSET, + INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); + if (ret) + pr_err("error disabling AP VPP\n"); + } +} + +/* + * Flash protection handling for the Integrator/CP + */ + +#define INTCP_FLASHPROG_OFFSET 0x04 +#define CINTEGRATOR_FLVPPEN BIT(0) +#define CINTEGRATOR_FLWREN BIT(1) +#define CINTEGRATOR_FLMASK BIT(0)|BIT(1) + +static void cp_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + if (on) { + ret = regmap_update_bits(syscon_regmap, + INTCP_FLASHPROG_OFFSET, + CINTEGRATOR_FLMASK, + CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN); + if (ret) + pr_err("error setting CP VPP\n"); + } else { + ret = regmap_update_bits(syscon_regmap, + INTCP_FLASHPROG_OFFSET, + CINTEGRATOR_FLMASK, + 0); + if (ret) + pr_err("error setting CP VPP\n"); + } +} + +/* + * Flash protection handling for the Versatiles and RealViews + */ + +#define VERSATILE_SYS_FLASH_OFFSET 0x4C + +static void versatile_flash_set_vpp(struct map_info *map, int on) +{ + int ret; + + ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET, + 0x01, !!on); + if (ret) + pr_err("error setting Versatile VPP\n"); +} + +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + struct device_node *sysnp; + const struct of_device_id *devid; + struct regmap *rmap; + static enum versatile_flashprot versatile_flashprot; + int ret; + + /* Not all flash chips use this protection line */ + if (!of_device_is_compatible(np, "arm,versatile-flash")) + return 0; + + /* For first chip probed, look up the syscon regmap */ + if (!syscon_regmap) { + sysnp = of_find_matching_node_and_match(NULL, + syscon_match, + &devid); + if (!sysnp) + return -ENODEV; + + versatile_flashprot = (enum versatile_flashprot)devid->data; + rmap = syscon_node_to_regmap(sysnp); + if (IS_ERR(rmap)) + return PTR_ERR(rmap); + + syscon_regmap = rmap; + } + + switch (versatile_flashprot) { + case INTEGRATOR_AP_FLASHPROT: + ret = ap_flash_init(pdev); + if (ret) + return ret; + map->set_vpp = ap_flash_set_vpp; + dev_info(&pdev->dev, "Integrator/AP flash protection\n"); + break; + case INTEGRATOR_CP_FLASHPROT: + map->set_vpp = cp_flash_set_vpp; + dev_info(&pdev->dev, "Integrator/CP flash protection\n"); + break; + case VERSATILE_FLASHPROT: + case REALVIEW_FLASHPROT: + map->set_vpp = versatile_flash_set_vpp; + dev_info(&pdev->dev, "versatile/realview flash protection\n"); + break; + default: + dev_info(&pdev->dev, "device marked as Versatile flash " + "but no system controller was found\n"); + break; + } + + return 0; +} diff --git a/drivers/mtd/maps/physmap-versatile.h b/drivers/mtd/maps/physmap-versatile.h new file mode 100644 index 000000000000..9cf39d031f5a --- /dev/null +++ b/drivers/mtd/maps/physmap-versatile.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include + +#ifdef CONFIG_MTD_PHYSMAP_VERSATILE +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map); +#else +static inline +int of_flash_probe_versatile(struct platform_device *pdev, + struct device_node *np, + struct map_info *map) +{ + return 0; +} +#endif diff --git a/drivers/mtd/maps/physmap_of_gemini.c b/drivers/mtd/maps/physmap_of_gemini.c deleted file mode 100644 index 9df62ca721d5..000000000000 --- a/drivers/mtd/maps/physmap_of_gemini.c +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Cortina Systems Gemini OF physmap add-on - * Copyright (C) 2017 Linus Walleij - * - * This SoC has an elaborate flash control register, so we need to - * detect and set it up when booting on this platform. - */ -#include -#include -#include -#include -#include -#include -#include -#include "physmap_of_gemini.h" - -/* - * The Flash-relevant parts of the global status register - * These would also be relevant for a NAND driver. - */ -#define GLOBAL_STATUS 0x04 -#define FLASH_TYPE_MASK (0x3 << 24) -#define FLASH_TYPE_NAND_2K (0x3 << 24) -#define FLASH_TYPE_NAND_512 (0x2 << 24) -#define FLASH_TYPE_PARALLEL (0x1 << 24) -#define FLASH_TYPE_SERIAL (0x0 << 24) -/* if parallel */ -#define FLASH_WIDTH_16BIT (1 << 23) /* else 8 bit */ -/* if serial */ -#define FLASH_ATMEL (1 << 23) /* else STM */ - -#define FLASH_SIZE_MASK (0x3 << 21) -#define NAND_256M (0x3 << 21) /* and more */ -#define NAND_128M (0x2 << 21) -#define NAND_64M (0x1 << 21) -#define NAND_32M (0x0 << 21) -#define ATMEL_16M (0x3 << 21) /* and more */ -#define ATMEL_8M (0x2 << 21) -#define ATMEL_4M_2M (0x1 << 21) -#define ATMEL_1M (0x0 << 21) /* and less */ -#define STM_32M (1 << 22) /* and more */ -#define STM_16M (0 << 22) /* and less */ - -#define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */ - -int of_flash_probe_gemini(struct platform_device *pdev, - struct device_node *np, - struct map_info *map) -{ - struct regmap *rmap; - struct device *dev = &pdev->dev; - u32 val; - int ret; - - /* Multiplatform guard */ - if (!of_device_is_compatible(np, "cortina,gemini-flash")) - return 0; - - rmap = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(rmap)) { - dev_err(dev, "no syscon\n"); - return PTR_ERR(rmap); - } - - ret = regmap_read(rmap, GLOBAL_STATUS, &val); - if (ret) { - dev_err(dev, "failed to read global status register\n"); - return -ENODEV; - } - dev_dbg(dev, "global status reg: %08x\n", val); - - /* - * It would be contradictory if a physmap flash was NOT parallel. - */ - if ((val & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL) { - dev_err(dev, "flash is not parallel\n"); - return -ENODEV; - } - - /* - * Complain if DT data and hardware definition is different. - */ - if (val & FLASH_WIDTH_16BIT) { - if (map->bankwidth != 2) - dev_warn(dev, "flash hardware say flash is 16 bit wide but DT says it is %d bits wide\n", - map->bankwidth * 8); - } else { - if (map->bankwidth != 1) - dev_warn(dev, "flash hardware say flash is 8 bit wide but DT says it is %d bits wide\n", - map->bankwidth * 8); - } - - dev_info(&pdev->dev, "initialized Gemini-specific physmap control\n"); - - return 0; -} diff --git a/drivers/mtd/maps/physmap_of_gemini.h b/drivers/mtd/maps/physmap_of_gemini.h deleted file mode 100644 index 60e13a689d6a..000000000000 --- a/drivers/mtd/maps/physmap_of_gemini.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include - -#ifdef CONFIG_MTD_PHYSMAP_OF_GEMINI -int of_flash_probe_gemini(struct platform_device *pdev, - struct device_node *np, - struct map_info *map); -#else -static inline -int of_flash_probe_gemini(struct platform_device *pdev, - struct device_node *np, - struct map_info *map) -{ - return 0; -} -#endif diff --git a/drivers/mtd/maps/physmap_of_versatile.c b/drivers/mtd/maps/physmap_of_versatile.c deleted file mode 100644 index 03f2b6e7bc7e..000000000000 --- a/drivers/mtd/maps/physmap_of_versatile.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Versatile OF physmap driver add-on - * - * Copyright (c) 2016, Linaro Limited - * Author: Linus Walleij - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "physmap_of_versatile.h" - -static struct regmap *syscon_regmap; - -enum versatile_flashprot { - INTEGRATOR_AP_FLASHPROT, - INTEGRATOR_CP_FLASHPROT, - VERSATILE_FLASHPROT, - REALVIEW_FLASHPROT, -}; - -static const struct of_device_id syscon_match[] = { - { - .compatible = "arm,integrator-ap-syscon", - .data = (void *)INTEGRATOR_AP_FLASHPROT, - }, - { - .compatible = "arm,integrator-cp-syscon", - .data = (void *)INTEGRATOR_CP_FLASHPROT, - }, - { - .compatible = "arm,core-module-versatile", - .data = (void *)VERSATILE_FLASHPROT, - }, - { - .compatible = "arm,realview-eb-syscon", - .data = (void *)REALVIEW_FLASHPROT, - }, - { - .compatible = "arm,realview-pb1176-syscon", - .data = (void *)REALVIEW_FLASHPROT, - }, - { - .compatible = "arm,realview-pb11mp-syscon", - .data = (void *)REALVIEW_FLASHPROT, - }, - { - .compatible = "arm,realview-pba8-syscon", - .data = (void *)REALVIEW_FLASHPROT, - }, - { - .compatible = "arm,realview-pbx-syscon", - .data = (void *)REALVIEW_FLASHPROT, - }, - {}, -}; - -/* - * Flash protection handling for the Integrator/AP - */ -#define INTEGRATOR_SC_CTRLS_OFFSET 0x08 -#define INTEGRATOR_SC_CTRLC_OFFSET 0x0C -#define INTEGRATOR_SC_CTRL_FLVPPEN BIT(1) -#define INTEGRATOR_SC_CTRL_FLWP BIT(2) - -#define INTEGRATOR_EBI_CSR1_OFFSET 0x04 -/* The manual says bit 2, the code says bit 3, trust the code */ -#define INTEGRATOR_EBI_WRITE_ENABLE BIT(3) -#define INTEGRATOR_EBI_LOCK_OFFSET 0x20 -#define INTEGRATOR_EBI_LOCK_VAL 0xA05F - -static const struct of_device_id ebi_match[] = { - { .compatible = "arm,external-bus-interface"}, - { }, -}; - -static int ap_flash_init(struct platform_device *pdev) -{ - struct device_node *ebi; - void __iomem *ebi_base; - u32 val; - int ret; - - /* Look up the EBI */ - ebi = of_find_matching_node(NULL, ebi_match); - if (!ebi) { - return -ENODEV; - } - ebi_base = of_iomap(ebi, 0); - if (!ebi_base) - return -ENODEV; - - /* Clear VPP and write protection bits */ - ret = regmap_write(syscon_regmap, - INTEGRATOR_SC_CTRLC_OFFSET, - INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); - if (ret) - dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n"); - - /* Unlock the EBI */ - writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - - /* Enable write cycles on the EBI, CSR1 (flash) */ - val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - val |= INTEGRATOR_EBI_WRITE_ENABLE; - writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); - - /* Lock the EBI again */ - writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); - iounmap(ebi_base); - - return 0; -} - -static void ap_flash_set_vpp(struct map_info *map, int on) -{ - int ret; - - if (on) { - ret = regmap_write(syscon_regmap, - INTEGRATOR_SC_CTRLS_OFFSET, - INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); - if (ret) - pr_err("error enabling AP VPP\n"); - } else { - ret = regmap_write(syscon_regmap, - INTEGRATOR_SC_CTRLC_OFFSET, - INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); - if (ret) - pr_err("error disabling AP VPP\n"); - } -} - -/* - * Flash protection handling for the Integrator/CP - */ - -#define INTCP_FLASHPROG_OFFSET 0x04 -#define CINTEGRATOR_FLVPPEN BIT(0) -#define CINTEGRATOR_FLWREN BIT(1) -#define CINTEGRATOR_FLMASK BIT(0)|BIT(1) - -static void cp_flash_set_vpp(struct map_info *map, int on) -{ - int ret; - - if (on) { - ret = regmap_update_bits(syscon_regmap, - INTCP_FLASHPROG_OFFSET, - CINTEGRATOR_FLMASK, - CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN); - if (ret) - pr_err("error setting CP VPP\n"); - } else { - ret = regmap_update_bits(syscon_regmap, - INTCP_FLASHPROG_OFFSET, - CINTEGRATOR_FLMASK, - 0); - if (ret) - pr_err("error setting CP VPP\n"); - } -} - -/* - * Flash protection handling for the Versatiles and RealViews - */ - -#define VERSATILE_SYS_FLASH_OFFSET 0x4C - -static void versatile_flash_set_vpp(struct map_info *map, int on) -{ - int ret; - - ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET, - 0x01, !!on); - if (ret) - pr_err("error setting Versatile VPP\n"); -} - -int of_flash_probe_versatile(struct platform_device *pdev, - struct device_node *np, - struct map_info *map) -{ - struct device_node *sysnp; - const struct of_device_id *devid; - struct regmap *rmap; - static enum versatile_flashprot versatile_flashprot; - int ret; - - /* Not all flash chips use this protection line */ - if (!of_device_is_compatible(np, "arm,versatile-flash")) - return 0; - - /* For first chip probed, look up the syscon regmap */ - if (!syscon_regmap) { - sysnp = of_find_matching_node_and_match(NULL, - syscon_match, - &devid); - if (!sysnp) - return -ENODEV; - - versatile_flashprot = (enum versatile_flashprot)devid->data; - rmap = syscon_node_to_regmap(sysnp); - if (IS_ERR(rmap)) - return PTR_ERR(rmap); - - syscon_regmap = rmap; - } - - switch (versatile_flashprot) { - case INTEGRATOR_AP_FLASHPROT: - ret = ap_flash_init(pdev); - if (ret) - return ret; - map->set_vpp = ap_flash_set_vpp; - dev_info(&pdev->dev, "Integrator/AP flash protection\n"); - break; - case INTEGRATOR_CP_FLASHPROT: - map->set_vpp = cp_flash_set_vpp; - dev_info(&pdev->dev, "Integrator/CP flash protection\n"); - break; - case VERSATILE_FLASHPROT: - case REALVIEW_FLASHPROT: - map->set_vpp = versatile_flash_set_vpp; - dev_info(&pdev->dev, "versatile/realview flash protection\n"); - break; - default: - dev_info(&pdev->dev, "device marked as Versatile flash " - "but no system controller was found\n"); - break; - } - - return 0; -} diff --git a/drivers/mtd/maps/physmap_of_versatile.h b/drivers/mtd/maps/physmap_of_versatile.h deleted file mode 100644 index 0302502c9462..000000000000 --- a/drivers/mtd/maps/physmap_of_versatile.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include - -#ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE -int of_flash_probe_versatile(struct platform_device *pdev, - struct device_node *np, - struct map_info *map); -#else -static inline -int of_flash_probe_versatile(struct platform_device *pdev, - struct device_node *np, - struct map_info *map) -{ - return 0; -} -#endif -- cgit v1.2.3 From ba32ce95cbd9876eb7f5ec39af87829c8f13a337 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 19 Oct 2018 09:49:07 +0200 Subject: mtd: maps: Merge gpio-addr-flash.c into physmap-core.c Controlling some MSB address lines using GPIOs is just a small deviation from the generic physmap logic, and merging those two drivers allows us to share most of the probe logic, which is a good thing. Also, the gpio-addr-flash driver is unused since the removal of the blackfin arch in v4.17, so we can safely remove the old driver without risking breaking existing boards. Signed-off-by: Boris Brezillon Reviewed-by: Ricardo Ribalda Delgado Tested-by: Ricardo Ribalda Delgado Acked-by: Linus Walleij --- drivers/mtd/maps/Kconfig | 19 ++- drivers/mtd/maps/Makefile | 1 - drivers/mtd/maps/gpio-addr-flash.c | 281 ------------------------------------- drivers/mtd/maps/physmap-core.c | 150 +++++++++++++++++++- 4 files changed, 157 insertions(+), 294 deletions(-) delete mode 100644 drivers/mtd/maps/gpio-addr-flash.c (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index bb0d64e3fcd6..93b7ae32e277 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -94,6 +94,15 @@ config MTD_PHYSMAP_GEMINI platforms, some detection and setting up parallel mode on the external interface. +config MTD_PHYSMAP_GPIO_ADDR + bool "GPIO-assisted Flash Chip Support" + depends on MTD_PHYSMAP + depends on GPIOLIB || COMPILE_TEST + depends on MTD_COMPLEX_MAPPINGS + help + Extend the physmap driver to allow flashes to be partially + physically addressed and assisted by GPIOs. + config MTD_PMC_MSP_EVM tristate "CFI Flash device mapped on PMC-Sierra MSP" depends on PMC_MSP && MTD_CFI @@ -334,16 +343,6 @@ config MTD_PCMCIA_ANONYMOUS If unsure, say N. -config MTD_GPIO_ADDR - tristate "GPIO-assisted Flash Chip Support" - depends on GPIOLIB || COMPILE_TEST - depends on MTD_COMPLEX_MAPPINGS - help - Map driver which allows flashes to be partially physically addressed - and assisted by GPIOs. - - If compiled as a module, it will be called gpio-addr-flash. - config MTD_UCLINUX bool "Generic uClinux RAM/ROM filesystem support" depends on (MTD_RAM=y || MTD_ROM=y) && (!MMU || COLDFIRE) diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index ce737e15b7cf..ed1ef75244db 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -43,6 +43,5 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o -obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c deleted file mode 100644 index a20e85aa770e..000000000000 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * drivers/mtd/maps/gpio-addr-flash.c - * - * Handle the case where a flash device is mostly addressed using physical - * line and supplemented by GPIOs. This way you can hook up say a 8MiB flash - * to a 2MiB memory range and use the GPIOs to select a particular range. - * - * Copyright © 2000 Nicolas Pitre - * Copyright © 2005-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define win_mask(x) ((BIT(x)) - 1) - -#define DRIVER_NAME "gpio-addr-flash" - -/** - * struct async_state - keep GPIO flash state - * @mtd: MTD state for this mapping - * @map: MTD map state for this flash - * @gpios: Struct containing the array of GPIO descriptors - * @gpio_values: cached GPIO values - * @win_order: dedicated memory size (if no GPIOs) - */ -struct async_state { - struct mtd_info *mtd; - struct map_info map; - struct gpio_descs *gpios; - unsigned int gpio_values; - unsigned int win_order; -}; -#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1) - -/** - * gf_set_gpios() - set GPIO address lines to access specified flash offset - * @state: GPIO flash state - * @ofs: desired offset to access - * - * Rather than call the GPIO framework every time, cache the last-programmed - * value. This speeds up sequential accesses (which are by far the most common - * type). - */ -static void gf_set_gpios(struct async_state *state, unsigned long ofs) -{ - int i; - - ofs >>= state->win_order; - - if (ofs == state->gpio_values) - return; - - for (i = 0; i < state->gpios->ndescs; i++) { - if ((ofs & BIT(i)) == (state->gpio_values & BIT(i))) - continue; - - gpiod_set_value(state->gpios->desc[i], !!(ofs & BIT(i))); - } - - state->gpio_values = ofs; -} - -/** - * gf_read() - read a word at the specified offset - * @map: MTD map state - * @ofs: desired offset to read - */ -static map_word gf_read(struct map_info *map, unsigned long ofs) -{ - struct async_state *state = gf_map_info_to_state(map); - uint16_t word; - map_word test; - - gf_set_gpios(state, ofs); - - word = readw(map->virt + (ofs & win_mask(state->win_order))); - test.x[0] = word; - return test; -} - -/** - * gf_copy_from() - copy a chunk of data from the flash - * @map: MTD map state - * @to: memory to copy to - * @from: flash offset to copy from - * @len: how much to copy - * - * The "from" region may straddle more than one window, so toggle the GPIOs for - * each window region before reading its data. - */ -static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) -{ - struct async_state *state = gf_map_info_to_state(map); - - int this_len; - - while (len) { - this_len = from & win_mask(state->win_order); - this_len = BIT(state->win_order) - this_len; - this_len = min_t(int, len, this_len); - - gf_set_gpios(state, from); - memcpy_fromio(to, - map->virt + (from & win_mask(state->win_order)), - this_len); - len -= this_len; - from += this_len; - to += this_len; - } -} - -/** - * gf_write() - write a word at the specified offset - * @map: MTD map state - * @ofs: desired offset to write - */ -static void gf_write(struct map_info *map, map_word d1, unsigned long ofs) -{ - struct async_state *state = gf_map_info_to_state(map); - uint16_t d; - - gf_set_gpios(state, ofs); - - d = d1.x[0]; - writew(d, map->virt + (ofs & win_mask(state->win_order))); -} - -/** - * gf_copy_to() - copy a chunk of data to the flash - * @map: MTD map state - * @to: flash offset to copy to - * @from: memory to copy from - * @len: how much to copy - * - * See gf_copy_from() caveat. - */ -static void gf_copy_to(struct map_info *map, unsigned long to, - const void *from, ssize_t len) -{ - struct async_state *state = gf_map_info_to_state(map); - - int this_len; - - while (len) { - this_len = to & win_mask(state->win_order); - this_len = BIT(state->win_order) - this_len; - this_len = min_t(int, len, this_len); - - gf_set_gpios(state, to); - memcpy_toio(map->virt + (to & win_mask(state->win_order)), - from, len); - - len -= this_len; - to += this_len; - from += this_len; - } -} - -static const char * const part_probe_types[] = { - "cmdlinepart", "RedBoot", NULL }; - -/** - * gpio_flash_probe() - setup a mapping for a GPIO assisted flash - * @pdev: platform device - * - * The platform resource layout expected looks something like: - * struct mtd_partition partitions[] = { ... }; - * struct physmap_flash_data flash_data = { ... }; - * static struct gpiod_lookup_table addr_flash_gpios = { - * .dev_id = "gpio-addr-flash.0", - * .table = { - * GPIO_LOOKUP_IDX("gpio.0", 15, "addr", 0, GPIO_ACTIVE_HIGH), - * GPIO_LOOKUP_IDX("gpio.0", 16, "addr", 1, GPIO_ACTIVE_HIGH), - * ); - * }; - * gpiod_add_lookup_table(&addr_flash_gpios); - * - * struct resource flash_resource[] = { - * { - * .name = "cfi_probe", - * .start = 0x20000000, - * .end = 0x201fffff, - * .flags = IORESOURCE_MEM, - * }, - * }; - * struct platform_device flash_device = { - * .name = "gpio-addr-flash", - * .dev = { .platform_data = &flash_data, }, - * .num_resources = ARRAY_SIZE(flash_resource), - * .resource = flash_resource, - * ... - * }; - */ -static int gpio_flash_probe(struct platform_device *pdev) -{ - struct physmap_flash_data *pdata; - struct resource *memory; - struct async_state *state; - - pdata = dev_get_platdata(&pdev->dev); - memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (!memory) - return -EINVAL; - - state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->gpios = devm_gpiod_get_array(&pdev->dev, "addr", GPIOD_OUT_LOW); - if (IS_ERR(state->gpios)) - return PTR_ERR(state->gpios); - - state->win_order = get_bitmask_order(resource_size(memory)) - 1; - - state->map.name = DRIVER_NAME; - state->map.read = gf_read; - state->map.copy_from = gf_copy_from; - state->map.write = gf_write; - state->map.copy_to = gf_copy_to; - state->map.bankwidth = pdata->width; - state->map.size = BIT(state->win_order + state->gpios->ndescs); - state->map.virt = devm_ioremap_resource(&pdev->dev, memory); - if (IS_ERR(state->map.virt)) - return PTR_ERR(state->map.virt); - - state->map.phys = NO_XIP; - state->map.map_priv_1 = (unsigned long)state; - - platform_set_drvdata(pdev, state); - - dev_notice(&pdev->dev, "probing %d-bit flash bus\n", - state->map.bankwidth * 8); - state->mtd = do_map_probe(memory->name, &state->map); - if (!state->mtd) - return -ENXIO; - state->mtd->dev.parent = &pdev->dev; - - mtd_device_parse_register(state->mtd, part_probe_types, NULL, - pdata->parts, pdata->nr_parts); - - return 0; -} - -static int gpio_flash_remove(struct platform_device *pdev) -{ - struct async_state *state = platform_get_drvdata(pdev); - - mtd_device_unregister(state->mtd); - map_destroy(state->mtd); - return 0; -} - -static struct platform_driver gpio_flash_driver = { - .probe = gpio_flash_probe, - .remove = gpio_flash_remove, - .driver = { - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(gpio_flash_driver); - -MODULE_AUTHOR("Mike Frysinger "); -MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 8a8af37576ff..11e6239aadc7 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -13,6 +13,14 @@ * * Revised to handle newer style flash binding by: * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * GPIO address extension: + * Handle the case where a flash device is mostly addressed using physical + * line and supplemented by GPIOs. This way you can hook up say a 8MiB flash + * to a 2MiB memory range and use the GPIOs to select a particular range. + * + * Copyright © 2000 Nicolas Pitre + * Copyright © 2005-2009 Analog Devices Inc. */ #include @@ -30,6 +38,7 @@ #include #include #include +#include #include "physmap-gemini.h" #include "physmap-versatile.h" @@ -45,6 +54,9 @@ struct physmap_flash_info { const char * const *part_types; unsigned int nparts; const struct mtd_partition *parts; + struct gpio_descs *gpios; + unsigned int gpio_values; + unsigned int win_order; }; static int physmap_flash_remove(struct platform_device *dev) @@ -104,6 +116,119 @@ static void physmap_set_vpp(struct map_info *map, int state) spin_unlock_irqrestore(&info->vpp_lock, flags); } +#if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR) +static void physmap_set_addr_gpios(struct physmap_flash_info *info, + unsigned long ofs) +{ + unsigned int i; + + ofs >>= info->win_order; + if (info->gpio_values == ofs) + return; + + for (i = 0; i < info->gpios->ndescs; i++) { + if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values)) + continue; + + gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs)); + } +} + +#define win_mask(order) (BIT(order) - 1) + +static map_word physmap_addr_gpios_read(struct map_info *map, + unsigned long ofs) +{ + struct platform_device *pdev; + struct physmap_flash_info *info; + map_word mw; + u16 word; + + pdev = (struct platform_device *)map->map_priv_1; + info = platform_get_drvdata(pdev); + physmap_set_addr_gpios(info, ofs); + + word = readw(map->virt + (ofs & win_mask(info->win_order))); + mw.x[0] = word; + return mw; +} + +static void physmap_addr_gpios_copy_from(struct map_info *map, void *buf, + unsigned long ofs, ssize_t len) +{ + struct platform_device *pdev; + struct physmap_flash_info *info; + + pdev = (struct platform_device *)map->map_priv_1; + info = platform_get_drvdata(pdev); + + while (len) { + unsigned int winofs = ofs & win_mask(info->win_order); + unsigned int chunklen = min_t(unsigned int, len, + BIT(info->win_order) - winofs); + + physmap_set_addr_gpios(info, ofs); + memcpy_fromio(buf, map->virt + winofs, chunklen); + len -= chunklen; + buf += chunklen; + ofs += chunklen; + } +} + +static void physmap_addr_gpios_write(struct map_info *map, map_word mw, + unsigned long ofs) +{ + struct platform_device *pdev; + struct physmap_flash_info *info; + u16 word; + + pdev = (struct platform_device *)map->map_priv_1; + info = platform_get_drvdata(pdev); + physmap_set_addr_gpios(info, ofs); + + word = mw.x[0]; + writew(word, map->virt + (ofs & win_mask(info->win_order))); +} + +static void physmap_addr_gpios_copy_to(struct map_info *map, unsigned long ofs, + const void *buf, ssize_t len) +{ + struct platform_device *pdev; + struct physmap_flash_info *info; + + pdev = (struct platform_device *)map->map_priv_1; + info = platform_get_drvdata(pdev); + + while (len) { + unsigned int winofs = ofs & win_mask(info->win_order); + unsigned int chunklen = min_t(unsigned int, len, + BIT(info->win_order) - winofs); + + physmap_set_addr_gpios(info, ofs); + memcpy_toio(map->virt + winofs, buf, chunklen); + len -= chunklen; + buf += chunklen; + ofs += chunklen; + } +} + +static int physmap_addr_gpios_map_init(struct map_info *map) +{ + map->phys = NO_XIP; + map->read = physmap_addr_gpios_read; + map->copy_from = physmap_addr_gpios_copy_from; + map->write = physmap_addr_gpios_write; + map->copy_to = physmap_addr_gpios_copy_to; + + return 0; +} +#else +static int physmap_addr_gpios_map_init(struct map_info *map) +{ + return -ENOTSUPP; +} +#endif + #if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) static const struct of_device_id of_flash_match[] = { { @@ -343,6 +468,16 @@ static int physmap_flash_probe(struct platform_device *dev) platform_set_drvdata(dev, info); + info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr", + GPIOD_OUT_LOW); + if (IS_ERR(info->gpios)) + return PTR_ERR(info->gpios); + + if (info->gpios && info->nmaps > 1) { + dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n"); + return -EINVAL; + } + if (dev->dev.of_node) err = physmap_flash_of_init(dev); else @@ -369,10 +504,20 @@ static int physmap_flash_probe(struct platform_device *dev) if (!info->maps[i].phys) info->maps[i].phys = res->start; - info->maps[i].size = resource_size(res); + info->win_order = get_bitmask_order(resource_size(res)) - 1; + info->maps[i].size = BIT(info->win_order + + (info->gpios ? + info->gpios->ndescs : 0)); + info->maps[i].map_priv_1 = (unsigned long)dev; - simple_map_init(&info->maps[i]); + if (info->gpios) { + err = physmap_addr_gpios_map_init(&info->maps[i]); + if (err) + goto err_out; + } else { + simple_map_init(&info->maps[i]); + } probe_type = rom_probe_types; if (!info->probe_type) { @@ -497,6 +642,7 @@ module_exit(physmap_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); MODULE_AUTHOR("Vitaly Wool "); +MODULE_AUTHOR("Mike Frysinger "); MODULE_DESCRIPTION("Generic configurable MTD map driver"); /* legacy platform drivers can't hotplug or coldplg */ -- cgit v1.2.3 From 99f732b3a8656b148b3725192c8eac6982c6c80d Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Fri, 19 Oct 2018 09:49:08 +0200 Subject: mtd: maps: physmap: Invert logic on if/else branch It is preferred to have the positive statement on an if/else. While we are at it we replace the way we access rom_probe_types. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Boris Brezillon Acked-by: Linus Walleij --- drivers/mtd/maps/physmap-core.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 11e6239aadc7..e8c3b250d842 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -396,7 +396,7 @@ static int physmap_flash_of_init(struct platform_device *dev) #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */ static const char * const rom_probe_types[] = { - "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", NULL + "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom", }; static const char * const part_probe_types[] = { @@ -437,7 +437,6 @@ static int physmap_flash_pdata_init(struct platform_device *dev) static int physmap_flash_probe(struct platform_device *dev) { struct physmap_flash_info *info; - const char * const *probe_type; int err = 0; int i; @@ -519,14 +518,18 @@ static int physmap_flash_probe(struct platform_device *dev) simple_map_init(&info->maps[i]); } - probe_type = rom_probe_types; - if (!info->probe_type) { - for (; !info->mtds[i] && *probe_type; probe_type++) - info->mtds[i] = do_map_probe(*probe_type, - &info->maps[i]); - } else { + if (info->probe_type) { info->mtds[i] = do_map_probe(info->probe_type, &info->maps[i]); + } else { + int j; + + for (j = 0; j < ARRAY_SIZE(rom_probe_types); j++) { + info->mtds[i] = do_map_probe(rom_probe_types[j], + &info->maps[i]); + if (info->mtds[i]) + break; + } } if (!info->mtds[i]) { -- cgit v1.2.3 From d24dbd7541ff05617d4a14c579a09d33d66cf47f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 5 Oct 2018 00:41:42 +0200 Subject: mtd: maps: Get rid of the latch-addr-flash driver Looks like this driver was initially added to support the NOR on the DA830-EVM (Davinci) board, but the board file update was never merged. Keeping unused drivers just adds to the maintenance burden, so let's remove it if nobody uses it. Cc: David Griego Cc: Aleksey Makarov Cc: Sergei Shtylyov Cc: Savinay Dharmappa Signed-off-by: Boris Brezillon Acked-by: Sekhar Nori --- drivers/mtd/maps/Kconfig | 9 -- drivers/mtd/maps/Makefile | 1 - drivers/mtd/maps/latch-addr-flash.c | 229 ------------------------------------ 3 files changed, 239 deletions(-) delete mode 100644 drivers/mtd/maps/latch-addr-flash.c (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 93b7ae32e277..2edd8bcdbe1c 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -399,13 +399,4 @@ config MTD_PISMO When built as a module, it will be called pismo.ko -config MTD_LATCH_ADDR - tristate "Latch-assisted Flash Chip Support" - depends on MTD_COMPLEX_MAPPINGS - help - Map driver which allows flashes to be partially physically addressed - and have the upper address lines set by a board specific code. - - If compiled as a module, it will be called latch-addr-flash. - endmenu diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index ed1ef75244db..1146009f41df 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -43,5 +43,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o obj-$(CONFIG_MTD_VMU) += vmu-flash.o -obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c deleted file mode 100644 index 51db24b7f88d..000000000000 --- a/drivers/mtd/maps/latch-addr-flash.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Interface for NOR flash driver whose high address lines are latched - * - * Copyright © 2000 Nicolas Pitre - * Copyright © 2005-2008 Analog Devices Inc. - * Copyright © 2008 MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "latch-addr-flash" - -struct latch_addr_flash_info { - struct mtd_info *mtd; - struct map_info map; - struct resource *res; - - void (*set_window)(unsigned long offset, void *data); - void *data; - - /* cache; could be found out of res */ - unsigned long win_mask; - - spinlock_t lock; -}; - -static map_word lf_read(struct map_info *map, unsigned long ofs) -{ - struct latch_addr_flash_info *info; - map_word datum; - - info = (struct latch_addr_flash_info *)map->map_priv_1; - - spin_lock(&info->lock); - - info->set_window(ofs, info->data); - datum = inline_map_read(map, info->win_mask & ofs); - - spin_unlock(&info->lock); - - return datum; -} - -static void lf_write(struct map_info *map, map_word datum, unsigned long ofs) -{ - struct latch_addr_flash_info *info; - - info = (struct latch_addr_flash_info *)map->map_priv_1; - - spin_lock(&info->lock); - - info->set_window(ofs, info->data); - inline_map_write(map, datum, info->win_mask & ofs); - - spin_unlock(&info->lock); -} - -static void lf_copy_from(struct map_info *map, void *to, - unsigned long from, ssize_t len) -{ - struct latch_addr_flash_info *info = - (struct latch_addr_flash_info *) map->map_priv_1; - unsigned n; - - while (len > 0) { - n = info->win_mask + 1 - (from & info->win_mask); - if (n > len) - n = len; - - spin_lock(&info->lock); - - info->set_window(from, info->data); - memcpy_fromio(to, map->virt + (from & info->win_mask), n); - - spin_unlock(&info->lock); - - to += n; - from += n; - len -= n; - } -} - -static char *rom_probe_types[] = { "cfi_probe", NULL }; - -static int latch_addr_flash_remove(struct platform_device *dev) -{ - struct latch_addr_flash_info *info; - struct latch_addr_flash_data *latch_addr_data; - - info = platform_get_drvdata(dev); - if (info == NULL) - return 0; - - latch_addr_data = dev_get_platdata(&dev->dev); - - if (info->mtd != NULL) { - mtd_device_unregister(info->mtd); - map_destroy(info->mtd); - } - - if (info->map.virt != NULL) - iounmap(info->map.virt); - - if (info->res != NULL) - release_mem_region(info->res->start, resource_size(info->res)); - - kfree(info); - - if (latch_addr_data->done) - latch_addr_data->done(latch_addr_data->data); - - return 0; -} - -static int latch_addr_flash_probe(struct platform_device *dev) -{ - struct latch_addr_flash_data *latch_addr_data; - struct latch_addr_flash_info *info; - resource_size_t win_base = dev->resource->start; - resource_size_t win_size = resource_size(dev->resource); - char **probe_type; - int chipsel; - int err; - - latch_addr_data = dev_get_platdata(&dev->dev); - if (latch_addr_data == NULL) - return -ENODEV; - - pr_notice("latch-addr platform flash device: %#llx byte " - "window at %#.8llx\n", - (unsigned long long)win_size, (unsigned long long)win_base); - - chipsel = dev->id; - - if (latch_addr_data->init) { - err = latch_addr_data->init(latch_addr_data->data, chipsel); - if (err != 0) - return err; - } - - info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL); - if (info == NULL) { - err = -ENOMEM; - goto done; - } - - platform_set_drvdata(dev, info); - - info->res = request_mem_region(win_base, win_size, DRIVER_NAME); - if (info->res == NULL) { - dev_err(&dev->dev, "Could not reserve memory region\n"); - err = -EBUSY; - goto free_info; - } - - info->map.name = DRIVER_NAME; - info->map.size = latch_addr_data->size; - info->map.bankwidth = latch_addr_data->width; - - info->map.phys = NO_XIP; - info->map.virt = ioremap(win_base, win_size); - if (!info->map.virt) { - err = -ENOMEM; - goto free_res; - } - - info->map.map_priv_1 = (unsigned long)info; - - info->map.read = lf_read; - info->map.copy_from = lf_copy_from; - info->map.write = lf_write; - info->set_window = latch_addr_data->set_window; - info->data = latch_addr_data->data; - info->win_mask = win_size - 1; - - spin_lock_init(&info->lock); - - for (probe_type = rom_probe_types; !info->mtd && *probe_type; - probe_type++) - info->mtd = do_map_probe(*probe_type, &info->map); - - if (info->mtd == NULL) { - dev_err(&dev->dev, "map_probe failed\n"); - err = -ENODEV; - goto iounmap; - } - info->mtd->dev.parent = &dev->dev; - - mtd_device_register(info->mtd, latch_addr_data->parts, - latch_addr_data->nr_parts); - return 0; - -iounmap: - iounmap(info->map.virt); -free_res: - release_mem_region(info->res->start, resource_size(info->res)); -free_info: - kfree(info); -done: - if (latch_addr_data->done) - latch_addr_data->done(latch_addr_data->data); - return err; -} - -static struct platform_driver latch_addr_flash_driver = { - .probe = latch_addr_flash_probe, - .remove = latch_addr_flash_remove, - .driver = { - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(latch_addr_flash_driver); - -MODULE_AUTHOR("David Griego "); -MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper " - "address lines being set board specifically"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0126be38d98815d25d9ec4573541ed4315bf6a88 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 21 Nov 2018 00:04:18 +0900 Subject: kbuild: announce removal of SUBDIRS if used SUBDIRS has been kept as a backward compatibility since commit ("[PATCH] kbuild: external module support") in 2002. We do not need multiple ways to do the same thing, so I will remove SUBDIRS after the Linux 5.3 release. I cleaned up in-tree code, and updated the document so that nobody would try to use it. Meanwhile, display the following warning if SUBDIRS is used. Makefile:189: ================= WARNING ================ Makefile:190: 'SUBDIRS' will be removed after Linux 5.3 Makefile:191: Please use 'M=' or 'KBUILD_EXTMOD' instead Makefile:192: ========================================== Signed-off-by: Masahiro Yamada Acked-by: Boris Brezillon # for scx200_docflash.c Acked-by: Guenter Roeck # for scx200_wdt.c --- Documentation/kbuild/kbuild.txt | 7 +------ Makefile | 4 ++++ drivers/mtd/maps/scx200_docflash.c | 7 ------- drivers/watchdog/scx200_wdt.c | 7 ------- samples/connector/Makefile | 2 +- 5 files changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt index 8390c360d4b3..c9e3d93e7a89 100644 --- a/Documentation/kbuild/kbuild.txt +++ b/Documentation/kbuild/kbuild.txt @@ -81,12 +81,7 @@ KBUILD_EXTMOD -------------------------------------------------- Set the directory to look for the kernel source when building external modules. -The directory can be specified in several ways: -1) Use "M=..." on the command line -2) Environment variable KBUILD_EXTMOD -3) Environment variable SUBDIRS -The possibilities are listed in the order they take precedence. -Using "M=..." will always override the others. +Setting "M=..." takes precedence over KBUILD_EXTMOD. KBUILD_OUTPUT -------------------------------------------------- diff --git a/Makefile b/Makefile index 96b4ea5adf91..9fcd8f81809c 100644 --- a/Makefile +++ b/Makefile @@ -186,6 +186,10 @@ endif # Old syntax make ... SUBDIRS=$PWD is still supported # Setting the environment variable KBUILD_EXTMOD take precedence ifdef SUBDIRS + $(warning ================= WARNING ================) + $(warning 'SUBDIRS' will be removed after Linux 5.3) + $(warning Please use 'M=' or 'KBUILD_EXTMOD' instead) + $(warning ==========================================) KBUILD_EXTMOD ?= $(SUBDIRS) endif diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index f1c1f737d0d7..7f1a0e690c4f 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -216,10 +216,3 @@ static void __exit cleanup_scx200_docflash(void) module_init(init_scx200_docflash); module_exit(cleanup_scx200_docflash); - -/* - Local variables: - compile-command: "make -k -C ../../.. SUBDIRS=drivers/mtd/maps modules" - c-basic-offset: 8 - End: -*/ diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c index 836377cf9271..ec4063ebb41a 100644 --- a/drivers/watchdog/scx200_wdt.c +++ b/drivers/watchdog/scx200_wdt.c @@ -262,10 +262,3 @@ static void __exit scx200_wdt_cleanup(void) module_init(scx200_wdt_init); module_exit(scx200_wdt_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" - c-basic-offset: 8 - End: -*/ diff --git a/samples/connector/Makefile b/samples/connector/Makefile index fe3c8542ae4a..6ad71620e503 100644 --- a/samples/connector/Makefile +++ b/samples/connector/Makefile @@ -14,4 +14,4 @@ HOSTCFLAGS_ucon.o += -I$(objtree)/usr/include all: modules modules clean: - $(MAKE) -C ../.. SUBDIRS=$(CURDIR) $@ + $(MAKE) -C ../.. M=$(CURDIR) $@ -- cgit v1.2.3 From b3dd93030c3cdd3f191aa170ccafc2b4d316f4cc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 27 Nov 2018 21:53:57 +0100 Subject: mtd: maps: physmap: Leave assigned complex mappings SoC-specific drivers might provide their own map->xxx() implementations, and calling simple_map_init() unconditionally will override those implementations. Make sure map->read is NULL before calling simple_map_init(). Signed-off-by: Linus Walleij Signed-off-by: Boris Brezillon --- drivers/mtd/maps/physmap-core.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index e8c3b250d842..d9a3e4bebe5d 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -514,10 +514,20 @@ static int physmap_flash_probe(struct platform_device *dev) err = physmap_addr_gpios_map_init(&info->maps[i]); if (err) goto err_out; - } else { - simple_map_init(&info->maps[i]); } +#ifdef CONFIG_MTD_COMPLEX_MAPPINGS + /* + * Only use the simple_map implementation if map hooks are not + * implemented. Since map->read() is mandatory checking for its + * presence is enough. + */ + if (!info->maps[i].read) + simple_map_init(&info->maps[i]); +#else + simple_map_init(&info->maps[i]); +#endif + if (info->probe_type) { info->mtds[i] = do_map_probe(info->probe_type, &info->maps[i]); -- cgit v1.2.3 From 9d3b5086f6d42e358f491e5d841750587f3d8cf3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 27 Nov 2018 21:53:58 +0100 Subject: mtd: physmap_of_gemini: Handle pin control This enables the complex mapping for the Gemini and kicks in custom read/write functions that will wrap the existing simple functions in calls to enable/disable the parallel flash pins using pin controls. This is necessary on some hardware such as the D-Link DIR-685 where all flash pins are patched in/out at the same time, but some of the flash pins are in practice unused by the flash and have anyway been reused as GPIO. This concerns specifically CE1 on the Gemini. There is only one flash chip, so only CE0 is used, and the line for CE1 has been reused as chip select for the emulated SPI port connected to the display. If we try to use the same lines for flash and GPIO at the same time, one of them will loose: the GPIO line will disappear because it gets disconnected from the pin when the flash group is muxed out. Fix this by introducing two pin control states named simply "enabled" and "disabled" and only enable the flash lines when absolutely necessary (during read/write/copy). This way, they are available for GPIO at all other times and the display works. Collect all the state variables in a struct named struct gemini_flash and allocate this struct at probe time. Signed-off-by: Linus Walleij Signed-off-by: Boris Brezillon --- drivers/mtd/maps/Kconfig | 1 + drivers/mtd/maps/physmap-gemini.c | 110 +++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/maps') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 2edd8bcdbe1c..e0cf869c8544 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -88,6 +88,7 @@ config MTD_PHYSMAP_GEMINI bool "Cortina Gemini OF-based physical memory map handling" depends on MTD_PHYSMAP_OF depends on MFD_SYSCON + select MTD_COMPLEX_MAPPINGS default ARCH_GEMINI help This provides some extra DT physmap parsing for the Gemini diff --git a/drivers/mtd/maps/physmap-gemini.c b/drivers/mtd/maps/physmap-gemini.c index 1cf128a0526d..60775b208fc9 100644 --- a/drivers/mtd/maps/physmap-gemini.c +++ b/drivers/mtd/maps/physmap-gemini.c @@ -10,9 +10,11 @@ #include #include #include +#include #include #include #include +#include #include "physmap-gemini.h" /* @@ -44,6 +46,82 @@ #define FLASH_PARALLEL_HIGH_PIN_CNT (1 << 20) /* else low pin cnt */ +static const struct of_device_id syscon_match[] = { + { .compatible = "cortina,gemini-syscon" }, + { }, +}; + +struct gemini_flash { + struct device *dev; + struct pinctrl *p; + struct pinctrl_state *enabled_state; + struct pinctrl_state *disabled_state; +}; + +/* Static local state */ +static struct gemini_flash *gf; + +static void gemini_flash_enable_pins(void) +{ + int ret; + + if (IS_ERR(gf->enabled_state)) + return; + ret = pinctrl_select_state(gf->p, gf->enabled_state); + if (ret) + dev_err(gf->dev, "failed to enable pins\n"); +} + +static void gemini_flash_disable_pins(void) +{ + int ret; + + if (IS_ERR(gf->disabled_state)) + return; + ret = pinctrl_select_state(gf->p, gf->disabled_state); + if (ret) + dev_err(gf->dev, "failed to disable pins\n"); +} + +static map_word __xipram gemini_flash_map_read(struct map_info *map, + unsigned long ofs) +{ + map_word __xipram ret; + + gemini_flash_enable_pins(); + ret = inline_map_read(map, ofs); + gemini_flash_disable_pins(); + + return ret; +} + +static void __xipram gemini_flash_map_write(struct map_info *map, + const map_word datum, + unsigned long ofs) +{ + gemini_flash_enable_pins(); + inline_map_write(map, datum, ofs); + gemini_flash_disable_pins(); +} + +static void __xipram gemini_flash_map_copy_from(struct map_info *map, + void *to, unsigned long from, + ssize_t len) +{ + gemini_flash_enable_pins(); + inline_map_copy_from(map, to, from, len); + gemini_flash_disable_pins(); +} + +static void __xipram gemini_flash_map_copy_to(struct map_info *map, + unsigned long to, + const void *from, ssize_t len) +{ + gemini_flash_enable_pins(); + inline_map_copy_to(map, to, from, len); + gemini_flash_disable_pins(); +} + int of_flash_probe_gemini(struct platform_device *pdev, struct device_node *np, struct map_info *map) @@ -57,6 +135,11 @@ int of_flash_probe_gemini(struct platform_device *pdev, if (!of_device_is_compatible(np, "cortina,gemini-flash")) return 0; + gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL); + if (!gf) + return -ENOMEM; + gf->dev = dev; + rmap = syscon_regmap_lookup_by_phandle(np, "syscon"); if (IS_ERR(rmap)) { dev_err(dev, "no syscon\n"); @@ -91,7 +174,32 @@ int of_flash_probe_gemini(struct platform_device *pdev, map->bankwidth * 8); } - dev_info(&pdev->dev, "initialized Gemini-specific physmap control\n"); + gf->p = devm_pinctrl_get(dev); + if (IS_ERR(gf->p)) { + dev_err(dev, "no pinctrl handle\n"); + ret = PTR_ERR(gf->p); + return ret; + } + + gf->enabled_state = pinctrl_lookup_state(gf->p, "enabled"); + if (IS_ERR(gf->enabled_state)) + dev_err(dev, "no enabled pin control state\n"); + + gf->disabled_state = pinctrl_lookup_state(gf->p, "disabled"); + if (IS_ERR(gf->enabled_state)) { + dev_err(dev, "no disabled pin control state\n"); + } else { + ret = pinctrl_select_state(gf->p, gf->disabled_state); + if (ret) + dev_err(gf->dev, "failed to disable pins\n"); + } + + map->read = gemini_flash_map_read; + map->write = gemini_flash_map_write; + map->copy_from = gemini_flash_map_copy_from; + map->copy_to = gemini_flash_map_copy_to; + + dev_info(dev, "initialized Gemini-specific physmap control\n"); return 0; } -- cgit v1.2.3