aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/arm-smmu.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 5a28ae892504..602b67d4f2d6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -48,6 +48,7 @@
48#include <linux/of_iommu.h> 48#include <linux/of_iommu.h>
49#include <linux/pci.h> 49#include <linux/pci.h>
50#include <linux/platform_device.h> 50#include <linux/platform_device.h>
51#include <linux/pm_runtime.h>
51#include <linux/slab.h> 52#include <linux/slab.h>
52#include <linux/spinlock.h> 53#include <linux/spinlock.h>
53 54
@@ -206,6 +207,8 @@ struct arm_smmu_device {
206 u32 num_global_irqs; 207 u32 num_global_irqs;
207 u32 num_context_irqs; 208 u32 num_context_irqs;
208 unsigned int *irqs; 209 unsigned int *irqs;
210 struct clk_bulk_data *clks;
211 int num_clks;
209 212
210 u32 cavium_id_base; /* Specific to Cavium */ 213 u32 cavium_id_base; /* Specific to Cavium */
211 214
@@ -1947,7 +1950,7 @@ struct arm_smmu_match_data {
1947}; 1950};
1948 1951
1949#define ARM_SMMU_MATCH_DATA(name, ver, imp) \ 1952#define ARM_SMMU_MATCH_DATA(name, ver, imp) \
1950static struct arm_smmu_match_data name = { .version = ver, .model = imp } 1953static const struct arm_smmu_match_data name = { .version = ver, .model = imp }
1951 1954
1952ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); 1955ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU);
1953ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); 1956ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU);
@@ -2150,6 +2153,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
2150 smmu->irqs[i] = irq; 2153 smmu->irqs[i] = irq;
2151 } 2154 }
2152 2155
2156 err = devm_clk_bulk_get_all(dev, &smmu->clks);
2157 if (err < 0) {
2158 dev_err(dev, "failed to get clocks %d\n", err);
2159 return err;
2160 }
2161 smmu->num_clks = err;
2162
2163 err = clk_bulk_prepare_enable(smmu->num_clks, smmu->clks);
2164 if (err)
2165 return err;
2166
2153 err = arm_smmu_device_cfg_probe(smmu); 2167 err = arm_smmu_device_cfg_probe(smmu);
2154 if (err) 2168 if (err)
2155 return err; 2169 return err;
@@ -2236,6 +2250,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
2236 2250
2237 /* Turn the thing off */ 2251 /* Turn the thing off */
2238 writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0); 2252 writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
2253
2254 clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks);
2255
2239 return 0; 2256 return 0;
2240} 2257}
2241 2258
@@ -2244,15 +2261,50 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev)
2244 arm_smmu_device_remove(pdev); 2261 arm_smmu_device_remove(pdev);
2245} 2262}
2246 2263
2247static int __maybe_unused arm_smmu_pm_resume(struct device *dev) 2264static int __maybe_unused arm_smmu_runtime_resume(struct device *dev)
2248{ 2265{
2249 struct arm_smmu_device *smmu = dev_get_drvdata(dev); 2266 struct arm_smmu_device *smmu = dev_get_drvdata(dev);
2267 int ret;
2268
2269 ret = clk_bulk_enable(smmu->num_clks, smmu->clks);
2270 if (ret)
2271 return ret;
2250 2272
2251 arm_smmu_device_reset(smmu); 2273 arm_smmu_device_reset(smmu);
2274
2252 return 0; 2275 return 0;
2253} 2276}
2254 2277
2255static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); 2278static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev)
2279{
2280 struct arm_smmu_device *smmu = dev_get_drvdata(dev);
2281
2282 clk_bulk_disable(smmu->num_clks, smmu->clks);
2283
2284 return 0;
2285}
2286
2287static int __maybe_unused arm_smmu_pm_resume(struct device *dev)
2288{
2289 if (pm_runtime_suspended(dev))
2290 return 0;
2291
2292 return arm_smmu_runtime_resume(dev);
2293}
2294
2295static int __maybe_unused arm_smmu_pm_suspend(struct device *dev)
2296{
2297 if (pm_runtime_suspended(dev))
2298 return 0;
2299
2300 return arm_smmu_runtime_suspend(dev);
2301}
2302
2303static const struct dev_pm_ops arm_smmu_pm_ops = {
2304 SET_SYSTEM_SLEEP_PM_OPS(arm_smmu_pm_suspend, arm_smmu_pm_resume)
2305 SET_RUNTIME_PM_OPS(arm_smmu_runtime_suspend,
2306 arm_smmu_runtime_resume, NULL)
2307};
2256 2308
2257static struct platform_driver arm_smmu_driver = { 2309static struct platform_driver arm_smmu_driver = {
2258 .driver = { 2310 .driver = {