Commit 9ac4e613a88d7f6a7a9651d863e9c8f63b582718
Committed by
David Woodhouse
1 parent
cf24dc85ff
Exists in
master
and in
4 other branches
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
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); |