diff options
Diffstat (limited to 'drivers/clocksource/sh_mtu2.c')
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index d9b76ca64a61..c5eea858054a 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/pm_domain.h> | 34 | #include <linux/pm_domain.h> |
35 | #include <linux/pm_runtime.h> | ||
35 | 36 | ||
36 | struct sh_mtu2_priv { | 37 | struct sh_mtu2_priv { |
37 | void __iomem *mapbase; | 38 | void __iomem *mapbase; |
@@ -123,6 +124,9 @@ static int sh_mtu2_enable(struct sh_mtu2_priv *p) | |||
123 | { | 124 | { |
124 | int ret; | 125 | int ret; |
125 | 126 | ||
127 | pm_runtime_get_sync(&p->pdev->dev); | ||
128 | dev_pm_syscore_device(&p->pdev->dev, true); | ||
129 | |||
126 | /* enable clock */ | 130 | /* enable clock */ |
127 | ret = clk_enable(p->clk); | 131 | ret = clk_enable(p->clk); |
128 | if (ret) { | 132 | if (ret) { |
@@ -157,6 +161,9 @@ static void sh_mtu2_disable(struct sh_mtu2_priv *p) | |||
157 | 161 | ||
158 | /* stop clock */ | 162 | /* stop clock */ |
159 | clk_disable(p->clk); | 163 | clk_disable(p->clk); |
164 | |||
165 | dev_pm_syscore_device(&p->pdev->dev, false); | ||
166 | pm_runtime_put(&p->pdev->dev); | ||
160 | } | 167 | } |
161 | 168 | ||
162 | static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id) | 169 | static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id) |
@@ -208,6 +215,16 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, | |||
208 | } | 215 | } |
209 | } | 216 | } |
210 | 217 | ||
218 | static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced) | ||
219 | { | ||
220 | pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->pdev->dev); | ||
221 | } | ||
222 | |||
223 | static void sh_mtu2_clock_event_resume(struct clock_event_device *ced) | ||
224 | { | ||
225 | pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->pdev->dev); | ||
226 | } | ||
227 | |||
211 | static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, | 228 | static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, |
212 | char *name, unsigned long rating) | 229 | char *name, unsigned long rating) |
213 | { | 230 | { |
@@ -221,6 +238,8 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, | |||
221 | ced->rating = rating; | 238 | ced->rating = rating; |
222 | ced->cpumask = cpumask_of(0); | 239 | ced->cpumask = cpumask_of(0); |
223 | ced->set_mode = sh_mtu2_clock_event_mode; | 240 | ced->set_mode = sh_mtu2_clock_event_mode; |
241 | ced->suspend = sh_mtu2_clock_event_suspend; | ||
242 | ced->resume = sh_mtu2_clock_event_resume; | ||
224 | 243 | ||
225 | dev_info(&p->pdev->dev, "used for clock events\n"); | 244 | dev_info(&p->pdev->dev, "used for clock events\n"); |
226 | clockevents_register_device(ced); | 245 | clockevents_register_device(ced); |
@@ -305,14 +324,17 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
305 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) | 324 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) |
306 | { | 325 | { |
307 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); | 326 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); |
327 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
308 | int ret; | 328 | int ret; |
309 | 329 | ||
310 | if (!is_early_platform_device(pdev)) | 330 | if (!is_early_platform_device(pdev)) { |
311 | pm_genpd_dev_always_on(&pdev->dev, true); | 331 | pm_runtime_set_active(&pdev->dev); |
332 | pm_runtime_enable(&pdev->dev); | ||
333 | } | ||
312 | 334 | ||
313 | if (p) { | 335 | if (p) { |
314 | dev_info(&pdev->dev, "kept as earlytimer\n"); | 336 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
315 | return 0; | 337 | goto out; |
316 | } | 338 | } |
317 | 339 | ||
318 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 340 | p = kmalloc(sizeof(*p), GFP_KERNEL); |
@@ -325,8 +347,19 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev) | |||
325 | if (ret) { | 347 | if (ret) { |
326 | kfree(p); | 348 | kfree(p); |
327 | platform_set_drvdata(pdev, NULL); | 349 | platform_set_drvdata(pdev, NULL); |
350 | pm_runtime_idle(&pdev->dev); | ||
351 | return ret; | ||
328 | } | 352 | } |
329 | return ret; | 353 | if (is_early_platform_device(pdev)) |
354 | return 0; | ||
355 | |||
356 | out: | ||
357 | if (cfg->clockevent_rating) | ||
358 | pm_runtime_irq_safe(&pdev->dev); | ||
359 | else | ||
360 | pm_runtime_idle(&pdev->dev); | ||
361 | |||
362 | return 0; | ||
330 | } | 363 | } |
331 | 364 | ||
332 | static int __devexit sh_mtu2_remove(struct platform_device *pdev) | 365 | static int __devexit sh_mtu2_remove(struct platform_device *pdev) |