aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/maps/physmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps/physmap.c')
-rw-r--r--drivers/mtd/maps/physmap.c130
1 files changed, 56 insertions, 74 deletions
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 4c18b98a311..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,6 +113,12 @@ 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++) {
@@ -122,8 +139,9 @@ static int physmap_flash_probe(struct platform_device *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_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);
@@ -159,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:
@@ -204,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
@@ -243,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)