diff options
Diffstat (limited to 'drivers/mtd/maps/physmap.c')
| -rw-r--r-- | drivers/mtd/maps/physmap.c | 151 |
1 files changed, 70 insertions, 81 deletions
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index d9603f7f965..f73cd461257 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -27,10 +27,8 @@ struct physmap_flash_info { struct mtd_info *mtd[MAX_RESOURCES]; struct mtd_info *cmtd; struct map_info map[MAX_RESOURCES]; -#ifdef CONFIG_MTD_PARTITIONS - int nr_parts; - struct mtd_partition *parts; -#endif + spinlock_t vpp_lock; + int vpp_refcnt; }; static int physmap_flash_remove(struct platform_device *dev) @@ -42,56 +40,69 @@ static int physmap_flash_remove(struct platform_device *dev) info = platform_get_drvdata(dev); if (info == NULL) return 0; - platform_set_drvdata(dev, NULL); - physmap_data = dev->dev.platform_data; + physmap_data = dev_get_platdata(&dev->dev); if (info->cmtd) { -#ifdef CONFIG_MTD_PARTITIONS - if (info->nr_parts || physmap_data->nr_parts) { - del_mtd_partitions(info->cmtd); - - if (info->nr_parts) - kfree(info->parts); - } else { - del_mtd_device(info->cmtd); - } -#else - del_mtd_device(info->cmtd); -#endif -#ifdef CONFIG_MTD_CONCAT + mtd_device_unregister(info->cmtd); if (info->cmtd != info->mtd[0]) mtd_concat_destroy(info->cmtd); -#endif } for (i = 0; i < MAX_RESOURCES; i++) { if (info->mtd[i] != NULL) map_destroy(info->mtd[i]); } + + if (physmap_data->exit) + physmap_data->exit(dev); + return 0; } -static const char *rom_probe_types[] = { - "cfi_probe", - "jedec_probe", - "qinfo_probe", - "map_rom", - NULL }; -#ifdef CONFIG_MTD_PARTITIONS -static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; -#endif +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 **probe_type; + const char * const *probe_type; + const char * const *part_types; int err = 0; int i; int devices_found = 0; - physmap_data = dev->dev.platform_data; + physmap_data = dev_get_platdata(&dev->dev); if (physmap_data == NULL) return -ENODEV; @@ -102,16 +113,22 @@ static int physmap_flash_probe(struct platform_device *dev) goto err_out; } + if (physmap_data->init) { + err = physmap_data->init(dev); + if (err) + goto err_out; + } + platform_set_drvdata(dev, info); for (i = 0; i < dev->num_resources; i++) { printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", - (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1), + (unsigned long long)resource_size(&dev->resource[i]), (unsigned long long)dev->resource[i].start); if (!devm_request_mem_region(&dev->dev, dev->resource[i].start, - dev->resource[i].end - dev->resource[i].start + 1, + resource_size(&dev->resource[i]), dev_name(&dev->dev))) { dev_err(&dev->dev, "Could not reserve memory region\n"); err = -ENOMEM; @@ -120,10 +137,11 @@ static int physmap_flash_probe(struct platform_device *dev) info->map[i].name = dev_name(&dev->dev); info->map[i].phys = dev->resource[i].start; - info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1; + info->map[i].size = resource_size(&dev->resource[i]); info->map[i].bankwidth = physmap_data->width; - info->map[i].set_vpp = physmap_data->set_vpp; + 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); @@ -136,8 +154,12 @@ static int physmap_flash_probe(struct platform_device *dev) simple_map_init(&info->map[i]); probe_type = rom_probe_types; - for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++) - info->mtd[i] = do_map_probe(*probe_type, &info->map[i]); + 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]); + } else + info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]); + if (info->mtd[i] == NULL) { dev_err(&dev->dev, "map_probe failed\n"); err = -ENXIO; @@ -155,37 +177,19 @@ static int physmap_flash_probe(struct platform_device *dev) /* * We detected multiple devices. Concatenate them together. */ -#ifdef CONFIG_MTD_CONCAT info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev)); if (info->cmtd == NULL) err = -ENXIO; -#else - printk(KERN_ERR "physmap-flash: multiple devices " - "found but MTD concat support disabled.\n"); - err = -ENXIO; -#endif } if (err) goto err_out; -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(info->cmtd, part_probe_types, - &info->parts, 0); - if (err > 0) { - add_mtd_partitions(info->cmtd, info->parts, err); - info->nr_parts = err; - return 0; - } + spin_lock_init(&info->vpp_lock); - if (physmap_data->nr_parts) { - printk(KERN_NOTICE "Using physmap partition information\n"); - add_mtd_partitions(info->cmtd, physmap_data->parts, - physmap_data->nr_parts); - return 0; - } -#endif + part_types = physmap_data->part_probe_types ? : part_probe_types; - add_mtd_device(info->cmtd); + mtd_device_parse_register(info->cmtd, part_types, NULL, + physmap_data->parts, physmap_data->nr_parts); return 0; err_out: @@ -200,9 +204,8 @@ static void physmap_flash_shutdown(struct platform_device *dev) int i; for (i = 0; i < MAX_RESOURCES && info->mtd[i]; i++) - if (info->mtd[i]->suspend && info->mtd[i]->resume) - if (info->mtd[i]->suspend(info->mtd[i]) == 0) - info->mtd[i]->resume(info->mtd[i]); + if (mtd_suspend(info->mtd[i]) == 0) + mtd_resume(info->mtd[i]); } #else #define physmap_flash_shutdown NULL @@ -239,23 +242,6 @@ static struct platform_device physmap_flash = { .num_resources = 1, .resource = &physmap_flash_resource, }; - -void physmap_configure(unsigned long addr, unsigned long size, - int bankwidth, void (*set_vpp)(struct map_info *, int)) -{ - physmap_flash_resource.start = addr; - physmap_flash_resource.end = addr + size - 1; - physmap_flash_data.width = bankwidth; - physmap_flash_data.set_vpp = set_vpp; -} - -#ifdef CONFIG_MTD_PARTITIONS -void physmap_set_partitions(struct mtd_partition *parts, int num_parts) -{ - physmap_flash_data.nr_parts = num_parts; - physmap_flash_data.parts = parts; -} -#endif #endif static int __init physmap_init(void) @@ -264,8 +250,11 @@ static int __init physmap_init(void) err = platform_driver_register(&physmap_flash_driver); #ifdef CONFIG_MTD_PHYSMAP_COMPAT - if (err == 0) - platform_device_register(&physmap_flash); + if (err == 0) { + err = platform_device_register(&physmap_flash); + if (err) + platform_driver_unregister(&physmap_flash_driver); + } #endif return err; |
