diff options
author | John Crispin <blogic@openwrt.org> | 2014-11-17 08:31:03 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2014-11-17 08:31:03 +0000 |
commit | df50919f2fb28a2a40e99e288dd096cfdb6c2512 (patch) | |
tree | ae28abbbaea74ce8f3e3f5c0d36f190f1ed1e603 /target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch | |
parent | 3f23afe354d3457f13ff8d0a0ca5f3ca99d0c7fd (diff) | |
download | upstream-df50919f2fb28a2a40e99e288dd096cfdb6c2512.tar.gz upstream-df50919f2fb28a2a40e99e288dd096cfdb6c2512.tar.bz2 upstream-df50919f2fb28a2a40e99e288dd096cfdb6c2512.zip |
lantiq: Concatenate multiple flash chips for lantiq-flash (fixed regression)
Signed-off-by: Maikel Bloemendal <openwrt@maikelenyvonne.nl>
Tested-by: Eddi De Pieri <eddi@depieri.net>
git-svn-id: svn://svn.openwrt.org/openwrt/branches/barrier_breaker@43284 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch')
-rw-r--r-- | target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch b/target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch new file mode 100644 index 0000000000..5c6d91cf70 --- /dev/null +++ b/target/linux/lantiq/patches-3.10/0202-owrt-lantiq-multiple-flash.patch @@ -0,0 +1,219 @@ +--- "a/drivers/mtd/maps/lantiq-flash.c" ++++ "b/drivers/mtd/maps/lantiq-flash.c" +@@ -20,6 +20,7 @@ + #include <linux/mtd/cfi.h> + #include <linux/platform_device.h> + #include <linux/mtd/physmap.h> ++#include <linux/mtd/concat.h> + #include <linux/of.h> + + #include <lantiq_soc.h> +@@ -39,10 +40,12 @@ + LTQ_NOR_NORMAL + }; + ++#define MAX_RESOURCES 4 ++ + struct ltq_mtd { +- struct resource *res; +- struct mtd_info *mtd; +- struct map_info *map; ++ struct mtd_info *mtd[MAX_RESOURCES]; ++ struct mtd_info *cmtd; ++ struct map_info map[MAX_RESOURCES]; + }; + + static const char ltq_map_name[] = "ltq_nor"; +@@ -110,12 +113,39 @@ + } + + static int ++ltq_mtd_remove(struct platform_device *pdev) ++{ ++ struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); ++ int i; ++ ++ if (ltq_mtd == NULL) ++ return 0; ++ ++ if (ltq_mtd->cmtd) { ++ mtd_device_unregister(ltq_mtd->cmtd); ++ if (ltq_mtd->cmtd != ltq_mtd->mtd[0]) ++ mtd_concat_destroy(ltq_mtd->cmtd); ++ } ++ ++ for (i = 0; i < MAX_RESOURCES; i++) { ++ if (ltq_mtd->mtd[i] != NULL) ++ map_destroy(ltq_mtd->mtd[i]); ++ } ++ ++ kfree(ltq_mtd); ++ ++ return 0; ++} ++ ++static int + ltq_mtd_probe(struct platform_device *pdev) + { + struct mtd_part_parser_data ppdata; + struct ltq_mtd *ltq_mtd; + struct cfi_private *cfi; +- int err; ++ int err = 0; ++ int i; ++ int devices_found = 0; + + static const char *rom_probe_types[] = { + "cfi_probe", "jedec_probe", NULL +@@ -131,88 +161,88 @@ + ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL); + platform_set_drvdata(pdev, ltq_mtd); + +- ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!ltq_mtd->res) { +- dev_err(&pdev->dev, "failed to get memory resource\n"); +- err = -ENOENT; +- goto err_out; +- } ++ for (i = 0; i < pdev->num_resources; i++) { ++ printk(KERN_NOTICE "lantiq nor flash device: %.8llx at %.8llx\n", ++ (unsigned long long)resource_size(&pdev->resource[i]), ++ (unsigned long long)pdev->resource[i].start); ++ ++ if (!devm_request_mem_region(&pdev->dev, ++ pdev->resource[i].start, ++ resource_size(&pdev->resource[i]), ++ dev_name(&pdev->dev))) { ++ dev_err(&pdev->dev, "Could not reserve memory region\n"); ++ err = -ENOMEM; ++ goto err_out; ++ } + +- ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL); +- if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) +- ltq_mtd->map->phys = NO_XIP; +- else +- ltq_mtd->map->phys = ltq_mtd->res->start; +- ltq_mtd->res->start; +- ltq_mtd->map->size = resource_size(ltq_mtd->res); +- ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res); +- if (IS_ERR(ltq_mtd->map->virt)) { +- err = PTR_ERR(ltq_mtd->map->virt); +- goto err_out; +- } ++ ltq_mtd->map[i].name = ltq_map_name; ++ ltq_mtd->map[i].bankwidth = 2; ++ ltq_mtd->map[i].read = ltq_read16; ++ ltq_mtd->map[i].write = ltq_write16; ++ ltq_mtd->map[i].copy_from = ltq_copy_from; ++ ltq_mtd->map[i].copy_to = ltq_copy_to; ++ ++ if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL)) ++ ltq_mtd->map[i].phys = NO_XIP; ++ else ++ ltq_mtd->map[i].phys = pdev->resource[i].start; ++ ltq_mtd->map[i].size = resource_size(&pdev->resource[i]); ++ ltq_mtd->map[i].virt = devm_ioremap(&pdev->dev, ltq_mtd->map[i].phys, ++ ltq_mtd->map[i].size); ++ if (ltq_mtd->map[i].virt == NULL) { ++ dev_err(&pdev->dev, "Failed to ioremap flash region\n"); ++ err = PTR_ERR(ltq_mtd->map[i].virt); ++ goto err_out; ++ } + +- ltq_mtd->map->name = ltq_map_name; +- ltq_mtd->map->bankwidth = 2; +- ltq_mtd->map->read = ltq_read16; +- ltq_mtd->map->write = ltq_write16; +- ltq_mtd->map->copy_from = ltq_copy_from; +- ltq_mtd->map->copy_to = ltq_copy_to; ++ ltq_mtd->map[i].map_priv_1 = LTQ_NOR_PROBING; ++ for (type = rom_probe_types; !ltq_mtd->mtd[i] && *type; type++) { ++ ltq_mtd->mtd[i] = do_map_probe(*type, <q_mtd->map[i]); ++ } ++ ltq_mtd->map[i].map_priv_1 = LTQ_NOR_NORMAL; + +- ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING; ++ if (!ltq_mtd->mtd[i]) { ++ dev_err(&pdev->dev, "probing failed\n"); ++ err = -ENXIO; ++ goto err_out; ++ } else { ++ devices_found++; ++ } + +- for (type = rom_probe_types; !ltq_mtd->mtd && *type; type++) { +- ltq_mtd->mtd = do_map_probe(*type, ltq_mtd->map); +- } +- +- ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL; ++ ltq_mtd->mtd[i]->owner = THIS_MODULE; ++ ltq_mtd->mtd[i]->dev.parent = &pdev->dev; + +- if (!ltq_mtd->mtd) { +- dev_err(&pdev->dev, "probing failed\n"); +- err = -ENXIO; +- goto err_free; ++ cfi = ltq_mtd->map[i].fldrv_priv; ++ cfi->addr_unlock1 ^= 1; ++ cfi->addr_unlock2 ^= 1; ++ } ++ ++ if (devices_found == 1) { ++ ltq_mtd->cmtd = ltq_mtd->mtd[0]; ++ } else if (devices_found > 1) { ++ /* ++ * We detected multiple devices. Concatenate them together. ++ */ ++ ltq_mtd->cmtd = mtd_concat_create(ltq_mtd->mtd, devices_found, dev_name(&pdev->dev)); ++ if (ltq_mtd->cmtd == NULL) ++ err = -ENXIO; + } + +- ltq_mtd->mtd->owner = THIS_MODULE; +- +- cfi = ltq_mtd->map->fldrv_priv; +- cfi->addr_unlock1 ^= 1; +- cfi->addr_unlock2 ^= 1; +- + ppdata.of_node = pdev->dev.of_node; +- err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, ++ err = mtd_device_parse_register(ltq_mtd->cmtd, ltq_probe_types, + &ppdata, NULL, 0); + if (err) { + dev_err(&pdev->dev, "failed to add partitions\n"); +- goto err_destroy; ++ goto err_out; + } + + return 0; + +-err_destroy: +- map_destroy(ltq_mtd->mtd); +-err_free: +- kfree(ltq_mtd->map); + err_out: +- kfree(ltq_mtd); ++ ltq_mtd_remove(pdev); + return err; + } + +-static int +-ltq_mtd_remove(struct platform_device *pdev) +-{ +- struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev); +- +- if (ltq_mtd) { +- if (ltq_mtd->mtd) { +- mtd_device_unregister(ltq_mtd->mtd); +- map_destroy(ltq_mtd->mtd); +- } +- kfree(ltq_mtd->map); +- kfree(ltq_mtd); +- } +- return 0; +-} +- + static const struct of_device_id ltq_mtd_match[] = { + { .compatible = "lantiq,nor" }, + {}, |