]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/maps/sa1100-flash.c
Merge master.kernel.org:/home/rmk/linux-2.6-drvmodel
[linux-2.6-omap-h63xx.git] / drivers / mtd / maps / sa1100-flash.c
index 66b4c2780adcf53ec13174a40084d7504f7c3cb7..c8d0da19d897e461a18efaace5076bfc12111d59 100644 (file)
@@ -130,20 +130,21 @@ struct sa_subdev_info {
        char name[16];
        struct map_info map;
        struct mtd_info *mtd;
-       struct flash_platform_data *data;
+       struct flash_platform_data *plat;
 };
 
 struct sa_info {
        struct mtd_partition    *parts;
        struct mtd_info         *mtd;
        int                     num_subdev;
+       unsigned int            nr_parts;
        struct sa_subdev_info   subdev[0];
 };
 
 static void sa1100_set_vpp(struct map_info *map, int on)
 {
        struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
-       subdev->data->set_vpp(on);
+       subdev->plat->set_vpp(on);
 }
 
 static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
@@ -187,7 +188,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
                goto out;
        }
 
-       if (subdev->data->set_vpp)
+       if (subdev->plat->set_vpp)
                subdev->map.set_vpp = sa1100_set_vpp;
 
        subdev->map.phys = phys;
@@ -204,7 +205,7 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
         * Now let's probe for the actual flash.  Do it here since
         * specific machine settings might have been set above.
         */
-       subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
+       subdev->mtd = do_map_probe(subdev->plat->map_name, &subdev->map);
        if (subdev->mtd == NULL) {
                ret = -ENXIO;
                goto err;
@@ -223,13 +224,17 @@ static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *r
        return ret;
 }
 
-static void sa1100_destroy(struct sa_info *info)
+static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *plat)
 {
        int i;
 
        if (info->mtd) {
-               del_mtd_partitions(info->mtd);
-
+               if (info->nr_parts == 0)
+                       del_mtd_device(info->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+               else
+                       del_mtd_partitions(info->mtd);
+#endif
 #ifdef CONFIG_MTD_CONCAT
                if (info->mtd != info->subdev[0].mtd)
                        mtd_concat_destroy(info->mtd);
@@ -242,10 +247,13 @@ static void sa1100_destroy(struct sa_info *info)
        for (i = info->num_subdev - 1; i >= 0; i--)
                sa1100_destroy_subdev(&info->subdev[i]);
        kfree(info);
+
+       if (plat->exit)
+               plat->exit();
 }
 
 static struct sa_info *__init
-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
+sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
 {
        struct sa_info *info;
        int nr, size, i, ret = 0;
@@ -275,6 +283,12 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
 
        memset(info, 0, size);
 
+       if (plat->init) {
+               ret = plat->init();
+               if (ret)
+                       goto err;
+       }
+
        /*
         * Claim and then map the memory regions.
         */
@@ -287,8 +301,8 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
                        break;
 
                subdev->map.name = subdev->name;
-               sprintf(subdev->name, "sa1100-%d", i);
-               subdev->data = flash;
+               sprintf(subdev->name, "%s-%d", plat->name, i);
+               subdev->plat = plat;
 
                ret = sa1100_probe_subdev(subdev, res);
                if (ret)
@@ -309,7 +323,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
         * otherwise fail.  Either way, it'll be called "sa1100".
         */
        if (info->num_subdev == 1) {
-               strcpy(info->subdev[0].name, "sa1100");
+               strcpy(info->subdev[0].name, plat->name);
                info->mtd = info->subdev[0].mtd;
                ret = 0;
        } else if (info->num_subdev > 1) {
@@ -322,7 +336,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
                        cdev[i] = info->subdev[i].mtd;
 
                info->mtd = mtd_concat_create(cdev, info->num_subdev,
-                                             "sa1100");
+                                             plat->name);
                if (info->mtd == NULL)
                        ret = -ENXIO;
 #else
@@ -336,7 +350,7 @@ sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash
                return info;
 
  err:
-       sa1100_destroy(info);
+       sa1100_destroy(info, plat);
  out:
        return ERR_PTR(ret);
 }
@@ -346,16 +360,16 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int __init sa1100_mtd_probe(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct flash_platform_data *flash = pdev->dev.platform_data;
+       struct flash_platform_data *plat = pdev->dev.platform_data;
        struct mtd_partition *parts;
        const char *part_type = NULL;
        struct sa_info *info;
        int err, nr_parts = 0;
 
-       if (!flash)
+       if (!plat)
                return -ENODEV;
 
-       info = sa1100_setup_mtd(pdev, flash);
+       info = sa1100_setup_mtd(pdev, plat);
        if (IS_ERR(info)) {
                err = PTR_ERR(info);
                goto out;
@@ -372,8 +386,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
        } else
 #endif
        {
-               parts = flash->parts;
-               nr_parts = flash->nr_parts;
+               parts = plat->parts;
+               nr_parts = plat->nr_parts;
                part_type = "static";
        }
 
@@ -387,6 +401,8 @@ static int __init sa1100_mtd_probe(struct device *dev)
                add_mtd_partitions(info->mtd, parts, nr_parts);
        }
 
+       info->nr_parts = nr_parts;
+
        dev_set_drvdata(dev, info);
        err = 0;
 
@@ -397,8 +413,11 @@ static int __init sa1100_mtd_probe(struct device *dev)
 static int __exit sa1100_mtd_remove(struct device *dev)
 {
        struct sa_info *info = dev_get_drvdata(dev);
+       struct flash_platform_data *plat = dev->platform_data;
+
        dev_set_drvdata(dev, NULL);
-       sa1100_destroy(info);
+       sa1100_destroy(info, plat);
+
        return 0;
 }
 
@@ -421,9 +440,17 @@ static int sa1100_mtd_resume(struct device *dev)
                info->mtd->resume(info->mtd);
        return 0;
 }
+
+static void sa1100_mtd_shutdown(struct device *dev)
+{
+       struct sa_info *info = dev_get_drvdata(dev);
+       if (info && info->mtd->suspend(info->mtd) == 0)
+               info->mtd->resume(info->mtd);
+}
 #else
 #define sa1100_mtd_suspend NULL
 #define sa1100_mtd_resume  NULL
+#define sa1100_mtd_shutdown NULL
 #endif
 
 static struct device_driver sa1100_mtd_driver = {
@@ -433,6 +460,7 @@ static struct device_driver sa1100_mtd_driver = {
        .remove         = __exit_p(sa1100_mtd_remove),
        .suspend        = sa1100_mtd_suspend,
        .resume         = sa1100_mtd_resume,
+       .shutdown       = sa1100_mtd_shutdown,
 };
 
 static int __init sa1100_mtd_init(void)