Commit 9ac4e613a88d7f6a7a9651d863e9c8f63b582718

Authored by Adrian Hunter
Committed by David Woodhouse
1 parent cf24dc85ff

mtd: OneNAND: OMAP2/3: prevent regulator sleeping while OneNAND is in use

Prevent OneNAND's voltage regulator from going to sleep while
OneNAND is in use, by explicitly enabling and disabling the
regulator as appropriate.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

Showing 2 changed files with 41 additions and 1 deletions Side-by-side Diff

arch/arm/plat-omap/include/plat/onenand.h
... ... @@ -23,6 +23,7 @@
23 23 int (*onenand_setup)(void __iomem *, int freq);
24 24 int dma_channel;
25 25 u8 flags;
  26 + u8 regulator_can_sleep;
26 27 };
27 28  
28 29 #define ONENAND_MAX_PARTITIONS 8
drivers/mtd/onenand/omap2.c
... ... @@ -35,6 +35,7 @@
35 35 #include <linux/dma-mapping.h>
36 36 #include <linux/io.h>
37 37 #include <linux/slab.h>
  38 +#include <linux/regulator/consumer.h>
38 39  
39 40 #include <asm/mach/flash.h>
40 41 #include <plat/gpmc.h>
... ... @@ -63,6 +64,7 @@
63 64 int dma_channel;
64 65 int freq;
65 66 int (*setup)(void __iomem *base, int freq);
  67 + struct regulator *regulator;
66 68 };
67 69  
68 70 #ifdef CONFIG_MTD_PARTITIONS
... ... @@ -601,6 +603,30 @@
601 603 memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
602 604 }
603 605  
  606 +static int omap2_onenand_enable(struct mtd_info *mtd)
  607 +{
  608 + int ret;
  609 + struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
  610 +
  611 + ret = regulator_enable(c->regulator);
  612 + if (ret != 0)
  613 + dev_err(&c->pdev->dev, "cant enable regulator\n");
  614 +
  615 + return ret;
  616 +}
  617 +
  618 +static int omap2_onenand_disable(struct mtd_info *mtd)
  619 +{
  620 + int ret;
  621 + struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
  622 +
  623 + ret = regulator_disable(c->regulator);
  624 + if (ret != 0)
  625 + dev_err(&c->pdev->dev, "cant disable regulator\n");
  626 +
  627 + return ret;
  628 +}
  629 +
604 630 static int __devinit omap2_onenand_probe(struct platform_device *pdev)
605 631 {
606 632 struct omap_onenand_platform_data *pdata;
607 633  
... ... @@ -715,8 +741,18 @@
715 741 }
716 742 }
717 743  
  744 + if (pdata->regulator_can_sleep) {
  745 + c->regulator = regulator_get(&pdev->dev, "vonenand");
  746 + if (IS_ERR(c->regulator)) {
  747 + dev_err(&pdev->dev, "Failed to get regulator\n");
  748 + goto err_release_dma;
  749 + }
  750 + c->onenand.enable = omap2_onenand_enable;
  751 + c->onenand.disable = omap2_onenand_disable;
  752 + }
  753 +
718 754 if ((r = onenand_scan(&c->mtd, 1)) < 0)
719   - goto err_release_dma;
  755 + goto err_release_regulator;
720 756  
721 757 switch ((c->onenand.version_id >> 4) & 0xf) {
722 758 case 0:
... ... @@ -751,6 +787,8 @@
751 787  
752 788 err_release_onenand:
753 789 onenand_release(&c->mtd);
  790 +err_release_regulator:
  791 + regulator_put(c->regulator);
754 792 err_release_dma:
755 793 if (c->dma_channel != -1)
756 794 omap_free_dma(c->dma_channel);
... ... @@ -777,6 +815,7 @@
777 815 struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
778 816  
779 817 onenand_release(&c->mtd);
  818 + regulator_put(c->regulator);
780 819 if (c->dma_channel != -1)
781 820 omap_free_dma(c->dma_channel);
782 821 omap2_onenand_shutdown(pdev);