aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clocksource/sh_tmu.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index c1b51d49d106..7d700829bb41 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -33,6 +33,7 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/pm_domain.h> 35#include <linux/pm_domain.h>
36#include <linux/pm_runtime.h>
36 37
37struct sh_tmu_priv { 38struct sh_tmu_priv {
38 void __iomem *mapbase; 39 void __iomem *mapbase;
@@ -43,6 +44,7 @@ struct sh_tmu_priv {
43 unsigned long periodic; 44 unsigned long periodic;
44 struct clock_event_device ced; 45 struct clock_event_device ced;
45 struct clocksource cs; 46 struct clocksource cs;
47 bool cs_enabled;
46}; 48};
47 49
48static DEFINE_RAW_SPINLOCK(sh_tmu_lock); 50static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -204,14 +206,40 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
204 int ret; 206 int ret;
205 207
206 ret = sh_tmu_enable(p); 208 ret = sh_tmu_enable(p);
207 if (!ret) 209 if (!ret) {
208 __clocksource_updatefreq_hz(cs, p->rate); 210 __clocksource_updatefreq_hz(cs, p->rate);
211 p->cs_enabled = true;
212 }
209 return ret; 213 return ret;
210} 214}
211 215
212static void sh_tmu_clocksource_disable(struct clocksource *cs) 216static void sh_tmu_clocksource_disable(struct clocksource *cs)
213{ 217{
214 sh_tmu_disable(cs_to_sh_tmu(cs)); 218 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
219
220 WARN_ON(!p->cs_enabled);
221
222 sh_tmu_disable(p);
223 p->cs_enabled = false;
224}
225
226static void sh_tmu_clocksource_suspend(struct clocksource *cs)
227{
228 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
229
230 if (p->cs_enabled)
231 sh_tmu_disable(p);
232
233 pm_genpd_syscore_poweroff(&p->pdev->dev);
234}
235
236static void sh_tmu_clocksource_resume(struct clocksource *cs)
237{
238 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
239
240 pm_genpd_syscore_poweron(&p->pdev->dev);
241 if (p->cs_enabled)
242 sh_tmu_enable(p);
215} 243}
216 244
217static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, 245static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
@@ -224,6 +252,8 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
224 cs->read = sh_tmu_clocksource_read; 252 cs->read = sh_tmu_clocksource_read;
225 cs->enable = sh_tmu_clocksource_enable; 253 cs->enable = sh_tmu_clocksource_enable;
226 cs->disable = sh_tmu_clocksource_disable; 254 cs->disable = sh_tmu_clocksource_disable;
255 cs->suspend = sh_tmu_clocksource_suspend;
256 cs->resume = sh_tmu_clocksource_resume;
227 cs->mask = CLOCKSOURCE_MASK(32); 257 cs->mask = CLOCKSOURCE_MASK(32);
228 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 258 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
229 259
@@ -301,6 +331,16 @@ static int sh_tmu_clock_event_next(unsigned long delta,
301 return 0; 331 return 0;
302} 332}
303 333
334static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
335{
336 pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->pdev->dev);
337}
338
339static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
340{
341 pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->pdev->dev);
342}
343
304static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, 344static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
305 char *name, unsigned long rating) 345 char *name, unsigned long rating)
306{ 346{
@@ -316,6 +356,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
316 ced->cpumask = cpumask_of(0); 356 ced->cpumask = cpumask_of(0);
317 ced->set_next_event = sh_tmu_clock_event_next; 357 ced->set_next_event = sh_tmu_clock_event_next;
318 ced->set_mode = sh_tmu_clock_event_mode; 358 ced->set_mode = sh_tmu_clock_event_mode;
359 ced->suspend = sh_tmu_clock_event_suspend;
360 ced->resume = sh_tmu_clock_event_resume;
319 361
320 dev_info(&p->pdev->dev, "used for clock events\n"); 362 dev_info(&p->pdev->dev, "used for clock events\n");
321 363
@@ -407,8 +449,12 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
407 struct sh_tmu_priv *p = platform_get_drvdata(pdev); 449 struct sh_tmu_priv *p = platform_get_drvdata(pdev);
408 int ret; 450 int ret;
409 451
410 if (!is_early_platform_device(pdev)) 452 if (!is_early_platform_device(pdev)) {
411 pm_genpd_dev_always_on(&pdev->dev, true); 453 struct sh_timer_config *cfg = pdev->dev.platform_data;
454
455 if (cfg->clocksource_rating || cfg->clockevent_rating)
456 pm_genpd_dev_always_on(&pdev->dev, true);
457 }
412 458
413 if (p) { 459 if (p) {
414 dev_info(&pdev->dev, "kept as earlytimer\n"); 460 dev_info(&pdev->dev, "kept as earlytimer\n");