diff options
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 58 |
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) \ |
| 1950 | static struct arm_smmu_match_data name = { .version = ver, .model = imp } | 1953 | static const struct arm_smmu_match_data name = { .version = ver, .model = imp } |
| 1951 | 1954 | ||
| 1952 | ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); | 1955 | ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); |
| 1953 | ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); | 1956 | ARM_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 | ||
| 2247 | static int __maybe_unused arm_smmu_pm_resume(struct device *dev) | 2264 | static 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 | ||
| 2255 | static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume); | 2278 | static 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 | |||
| 2287 | static 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 | |||
| 2295 | static 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 | |||
| 2303 | static 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 | ||
| 2257 | static struct platform_driver arm_smmu_driver = { | 2309 | static struct platform_driver arm_smmu_driver = { |
| 2258 | .driver = { | 2310 | .driver = { |
