]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/mtd/onenand/omap2.c
mtd: add "platform:" prefix for platform modalias
[mv-sheeva.git] / drivers / mtd / onenand / omap2.c
index da25a90af4a4df2ff1f731905d6dc11aac4a17b9..c849cacf4b2faab2679f1231982f6cb12e0aa192 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/flash.h>
 #include <plat/gpmc.h>
@@ -63,8 +64,13 @@ struct omap2_onenand {
        int dma_channel;
        int freq;
        int (*setup)(void __iomem *base, int freq);
+       struct regulator *regulator;
 };
 
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL,  };
+#endif
+
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
        struct omap2_onenand *c = data;
@@ -597,6 +603,30 @@ static void omap2_onenand_shutdown(struct platform_device *pdev)
        memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
 }
 
+static int omap2_onenand_enable(struct mtd_info *mtd)
+{
+       int ret;
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+
+       ret = regulator_enable(c->regulator);
+       if (ret != 0)
+               dev_err(&c->pdev->dev, "cant enable regulator\n");
+
+       return ret;
+}
+
+static int omap2_onenand_disable(struct mtd_info *mtd)
+{
+       int ret;
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+
+       ret = regulator_disable(c->regulator);
+       if (ret != 0)
+               dev_err(&c->pdev->dev, "cant disable regulator\n");
+
+       return ret;
+}
+
 static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 {
        struct omap_onenand_platform_data *pdata;
@@ -711,8 +741,18 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
                }
        }
 
+       if (pdata->regulator_can_sleep) {
+               c->regulator = regulator_get(&pdev->dev, "vonenand");
+               if (IS_ERR(c->regulator)) {
+                       dev_err(&pdev->dev,  "Failed to get regulator\n");
+                       goto err_release_dma;
+               }
+               c->onenand.enable = omap2_onenand_enable;
+               c->onenand.disable = omap2_onenand_disable;
+       }
+
        if ((r = onenand_scan(&c->mtd, 1)) < 0)
-               goto err_release_dma;
+               goto err_release_regulator;
 
        switch ((c->onenand.version_id >> 4) & 0xf) {
        case 0:
@@ -727,16 +767,21 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
        case 3:
                c->freq = 83;
                break;
+       case 4:
+               c->freq = 104;
+               break;
        }
 
 #ifdef CONFIG_MTD_PARTITIONS
-       if (pdata->parts != NULL)
-               r = add_mtd_partitions(&c->mtd, pdata->parts,
-                                      pdata->nr_parts);
+       r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
+       if (r > 0)
+               r = add_mtd_partitions(&c->mtd, c->parts, r);
+       else if (pdata->parts != NULL)
+               r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts);
        else
 #endif
                r = add_mtd_device(&c->mtd);
-       if (r < 0)
+       if (r)
                goto err_release_onenand;
 
        platform_set_drvdata(pdev, c);
@@ -745,6 +790,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 
 err_release_onenand:
        onenand_release(&c->mtd);
+err_release_regulator:
+       regulator_put(c->regulator);
 err_release_dma:
        if (c->dma_channel != -1)
                omap_free_dma(c->dma_channel);
@@ -760,6 +807,7 @@ err_release_mem_region:
 err_free_cs:
        gpmc_cs_free(c->gpmc_cs);
 err_kfree:
+       kfree(c->parts);
        kfree(c);
 
        return r;
@@ -769,18 +817,8 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 {
        struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
 
-       BUG_ON(c == NULL);
-
-#ifdef CONFIG_MTD_PARTITIONS
-       if (c->parts)
-               del_mtd_partitions(&c->mtd);
-       else
-               del_mtd_device(&c->mtd);
-#else
-       del_mtd_device(&c->mtd);
-#endif
-
        onenand_release(&c->mtd);
+       regulator_put(c->regulator);
        if (c->dma_channel != -1)
                omap_free_dma(c->dma_channel);
        omap2_onenand_shutdown(pdev);
@@ -792,6 +830,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
        iounmap(c->onenand.base);
        release_mem_region(c->phys_base, ONENAND_IO_SIZE);
        gpmc_cs_free(c->gpmc_cs);
+       kfree(c->parts);
        kfree(c);
 
        return 0;
@@ -821,7 +860,7 @@ static void __exit omap2_onenand_exit(void)
 module_init(omap2_onenand_init);
 module_exit(omap2_onenand_exit);
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
 MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");