diff options
author | Boojin Kim <boojin.kim@samsung.com> | 2011-09-01 20:44:29 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2011-09-14 01:40:00 -0400 |
commit | a2f5203fec3c06d68a6bb45ad41f2adebf9ac5e0 (patch) | |
tree | 86ae77b928884c0c10c9c0076dca3886ab6538f7 | |
parent | 7703eac96abd119dcfbb04f287a5127462d18269 (diff) |
DMA: PL330: Add support runtime PM for PL330 DMAC
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/pl330.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 00eee59e8b33..0b99af18f9a1 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/amba/bus.h> | 18 | #include <linux/amba/bus.h> |
19 | #include <linux/amba/pl330.h> | 19 | #include <linux/amba/pl330.h> |
20 | #include <linux/pm_runtime.h> | ||
20 | 21 | ||
21 | #define NR_DEFAULT_DESC 16 | 22 | #define NR_DEFAULT_DESC 16 |
22 | 23 | ||
@@ -83,6 +84,8 @@ struct dma_pl330_dmac { | |||
83 | 84 | ||
84 | /* Peripheral channels connected to this DMAC */ | 85 | /* Peripheral channels connected to this DMAC */ |
85 | struct dma_pl330_chan *peripherals; /* keep at end */ | 86 | struct dma_pl330_chan *peripherals; /* keep at end */ |
87 | |||
88 | struct clk *clk; | ||
86 | }; | 89 | }; |
87 | 90 | ||
88 | struct dma_pl330_desc { | 91 | struct dma_pl330_desc { |
@@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
696 | goto probe_err1; | 699 | goto probe_err1; |
697 | } | 700 | } |
698 | 701 | ||
702 | pdmac->clk = clk_get(&adev->dev, "dma"); | ||
703 | if (IS_ERR(pdmac->clk)) { | ||
704 | dev_err(&adev->dev, "Cannot get operation clock.\n"); | ||
705 | ret = -EINVAL; | ||
706 | goto probe_err1; | ||
707 | } | ||
708 | |||
709 | amba_set_drvdata(adev, pdmac); | ||
710 | |||
711 | #ifdef CONFIG_PM_RUNTIME | ||
712 | /* to use the runtime PM helper functions */ | ||
713 | pm_runtime_enable(&adev->dev); | ||
714 | |||
715 | /* enable the power domain */ | ||
716 | if (pm_runtime_get_sync(&adev->dev)) { | ||
717 | dev_err(&adev->dev, "failed to get runtime pm\n"); | ||
718 | ret = -ENODEV; | ||
719 | goto probe_err1; | ||
720 | } | ||
721 | #else | ||
722 | /* enable dma clk */ | ||
723 | clk_enable(pdmac->clk); | ||
724 | #endif | ||
725 | |||
699 | irq = adev->irq[0]; | 726 | irq = adev->irq[0]; |
700 | ret = request_irq(irq, pl330_irq_handler, 0, | 727 | ret = request_irq(irq, pl330_irq_handler, 0, |
701 | dev_name(&adev->dev), pi); | 728 | dev_name(&adev->dev), pi); |
@@ -771,8 +798,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) | |||
771 | goto probe_err4; | 798 | goto probe_err4; |
772 | } | 799 | } |
773 | 800 | ||
774 | amba_set_drvdata(adev, pdmac); | ||
775 | |||
776 | dev_info(&adev->dev, | 801 | dev_info(&adev->dev, |
777 | "Loaded driver for PL330 DMAC-%d\n", adev->periphid); | 802 | "Loaded driver for PL330 DMAC-%d\n", adev->periphid); |
778 | dev_info(&adev->dev, | 803 | dev_info(&adev->dev, |
@@ -833,6 +858,13 @@ static int __devexit pl330_remove(struct amba_device *adev) | |||
833 | res = &adev->res; | 858 | res = &adev->res; |
834 | release_mem_region(res->start, resource_size(res)); | 859 | release_mem_region(res->start, resource_size(res)); |
835 | 860 | ||
861 | #ifdef CONFIG_PM_RUNTIME | ||
862 | pm_runtime_put(&adev->dev); | ||
863 | pm_runtime_disable(&adev->dev); | ||
864 | #else | ||
865 | clk_disable(pdmac->clk); | ||
866 | #endif | ||
867 | |||
836 | kfree(pdmac); | 868 | kfree(pdmac); |
837 | 869 | ||
838 | return 0; | 870 | return 0; |
@@ -846,10 +878,49 @@ static struct amba_id pl330_ids[] = { | |||
846 | { 0, 0 }, | 878 | { 0, 0 }, |
847 | }; | 879 | }; |
848 | 880 | ||
881 | #ifdef CONFIG_PM_RUNTIME | ||
882 | static int pl330_runtime_suspend(struct device *dev) | ||
883 | { | ||
884 | struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev); | ||
885 | |||
886 | if (!pdmac) { | ||
887 | dev_err(dev, "failed to get dmac\n"); | ||
888 | return -ENODEV; | ||
889 | } | ||
890 | |||
891 | clk_disable(pdmac->clk); | ||
892 | |||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | static int pl330_runtime_resume(struct device *dev) | ||
897 | { | ||
898 | struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev); | ||
899 | |||
900 | if (!pdmac) { | ||
901 | dev_err(dev, "failed to get dmac\n"); | ||
902 | return -ENODEV; | ||
903 | } | ||
904 | |||
905 | clk_enable(pdmac->clk); | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | #else | ||
910 | #define pl330_runtime_suspend NULL | ||
911 | #define pl330_runtime_resume NULL | ||
912 | #endif /* CONFIG_PM_RUNTIME */ | ||
913 | |||
914 | static const struct dev_pm_ops pl330_pm_ops = { | ||
915 | .runtime_suspend = pl330_runtime_suspend, | ||
916 | .runtime_resume = pl330_runtime_resume, | ||
917 | }; | ||
918 | |||
849 | static struct amba_driver pl330_driver = { | 919 | static struct amba_driver pl330_driver = { |
850 | .drv = { | 920 | .drv = { |
851 | .owner = THIS_MODULE, | 921 | .owner = THIS_MODULE, |
852 | .name = "dma-pl330", | 922 | .name = "dma-pl330", |
923 | .pm = &pl330_pm_ops, | ||
853 | }, | 924 | }, |
854 | .id_table = pl330_ids, | 925 | .id_table = pl330_ids, |
855 | .probe = pl330_probe, | 926 | .probe = pl330_probe, |