aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 21:32:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 21:32:35 -0400
commit16642a2e7be23bbda013fc32d8f6c68982eab603 (patch)
tree346ae485f485f6901e5d8150f0d34d178a7dd448 /drivers/clocksource
parent51562cba98939da0a1d10fe7c25359b77a069033 (diff)
parentb9142167a2bb979b58b98ffcd928a311b55cbd9f (diff)
Merge tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael J Wysocki: - Improved system suspend/resume and runtime PM handling for the SH TMU, CMT and MTU2 clock event devices (also used by ARM/shmobile). - Generic PM domains framework extensions related to cpuidle support and domain objects lookup using names. - ARM/shmobile power management updates including improved support for the SH7372's A4S power domain containing the CPU core. - cpufreq changes related to AMD CPUs support from Matthew Garrett, Andre Przywara and Borislav Petkov. - cpu0 cpufreq driver from Shawn Guo. - cpufreq governor fixes related to the relaxing of limit from Michal Pecio. - OMAP cpufreq updates from Axel Lin and Richard Zhao. - cpuidle ladder governor fixes related to the disabling of states from Carsten Emde and me. - Runtime PM core updates related to the interactions with the system suspend core from Alan Stern and Kevin Hilman. - Wakeup sources modification allowing more helper functions to be called from interrupt context from John Stultz and additional diagnostic code from Todd Poynor. - System suspend error code path fix from Feng Hong. Fixed up conflicts in cpufreq/powernow-k8 that stemmed from the workqueue fixes conflicting fairly badly with the removal of support for hardware P-state chips. The changes were independent but somewhat intertwined. * tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits) Revert "PM QoS: Use spinlock in the per-device PM QoS constraints code" PM / Runtime: let rpm_resume() succeed if RPM_ACTIVE, even when disabled, v2 cpuidle: rename function name "__cpuidle_register_driver", v2 cpufreq: OMAP: Check IS_ERR() instead of NULL for omap_device_get_by_hwmod_name cpuidle: remove some empty lines PM: Prevent runtime suspend during system resume PM QoS: Use spinlock in the per-device PM QoS constraints code PM / Sleep: use resume event when call dpm_resume_early cpuidle / ACPI : move cpuidle_device field out of the acpi_processor_power structure ACPI / processor: remove pointless variable initialization ACPI / processor: remove unused function parameter cpufreq: OMAP: remove loops_per_jiffy recalculate for smp sections: fix section conflicts in drivers/cpufreq cpufreq: conservative: update frequency when limits are relaxed cpufreq / ondemand: update frequency when limits are relaxed properly __init-annotate pm_sysrq_init() cpufreq: Add a generic cpufreq-cpu0 driver PM / OPP: Initialize OPP table from device tree ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp cpufreq: Remove support for hardware P-state chips from powernow-k8 ...
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/sh_cmt.c71
-rw-r--r--drivers/clocksource/sh_mtu2.c41
-rw-r--r--drivers/clocksource/sh_tmu.c112
3 files changed, 204 insertions, 20 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 98b06baafcc6..a5f7829f2799 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.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_cmt_priv { 38struct sh_cmt_priv {
38 void __iomem *mapbase; 39 void __iomem *mapbase;
@@ -52,6 +53,7 @@ struct sh_cmt_priv {
52 struct clock_event_device ced; 53 struct clock_event_device ced;
53 struct clocksource cs; 54 struct clocksource cs;
54 unsigned long total_cycles; 55 unsigned long total_cycles;
56 bool cs_enabled;
55}; 57};
56 58
57static DEFINE_RAW_SPINLOCK(sh_cmt_lock); 59static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
@@ -155,6 +157,9 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
155{ 157{
156 int k, ret; 158 int k, ret;
157 159
160 pm_runtime_get_sync(&p->pdev->dev);
161 dev_pm_syscore_device(&p->pdev->dev, true);
162
158 /* enable clock */ 163 /* enable clock */
159 ret = clk_enable(p->clk); 164 ret = clk_enable(p->clk);
160 if (ret) { 165 if (ret) {
@@ -221,6 +226,9 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
221 226
222 /* stop clock */ 227 /* stop clock */
223 clk_disable(p->clk); 228 clk_disable(p->clk);
229
230 dev_pm_syscore_device(&p->pdev->dev, false);
231 pm_runtime_put(&p->pdev->dev);
224} 232}
225 233
226/* private flags */ 234/* private flags */
@@ -451,22 +459,42 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs)
451 int ret; 459 int ret;
452 struct sh_cmt_priv *p = cs_to_sh_cmt(cs); 460 struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
453 461
462 WARN_ON(p->cs_enabled);
463
454 p->total_cycles = 0; 464 p->total_cycles = 0;
455 465
456 ret = sh_cmt_start(p, FLAG_CLOCKSOURCE); 466 ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
457 if (!ret) 467 if (!ret) {
458 __clocksource_updatefreq_hz(cs, p->rate); 468 __clocksource_updatefreq_hz(cs, p->rate);
469 p->cs_enabled = true;
470 }
459 return ret; 471 return ret;
460} 472}
461 473
462static void sh_cmt_clocksource_disable(struct clocksource *cs) 474static void sh_cmt_clocksource_disable(struct clocksource *cs)
463{ 475{
464 sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE); 476 struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
477
478 WARN_ON(!p->cs_enabled);
479
480 sh_cmt_stop(p, FLAG_CLOCKSOURCE);
481 p->cs_enabled = false;
482}
483
484static void sh_cmt_clocksource_suspend(struct clocksource *cs)
485{
486 struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
487
488 sh_cmt_stop(p, FLAG_CLOCKSOURCE);
489 pm_genpd_syscore_poweroff(&p->pdev->dev);
465} 490}
466 491
467static void sh_cmt_clocksource_resume(struct clocksource *cs) 492static void sh_cmt_clocksource_resume(struct clocksource *cs)
468{ 493{
469 sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE); 494 struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
495
496 pm_genpd_syscore_poweron(&p->pdev->dev);
497 sh_cmt_start(p, FLAG_CLOCKSOURCE);
470} 498}
471 499
472static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, 500static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
@@ -479,7 +507,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
479 cs->read = sh_cmt_clocksource_read; 507 cs->read = sh_cmt_clocksource_read;
480 cs->enable = sh_cmt_clocksource_enable; 508 cs->enable = sh_cmt_clocksource_enable;
481 cs->disable = sh_cmt_clocksource_disable; 509 cs->disable = sh_cmt_clocksource_disable;
482 cs->suspend = sh_cmt_clocksource_disable; 510 cs->suspend = sh_cmt_clocksource_suspend;
483 cs->resume = sh_cmt_clocksource_resume; 511 cs->resume = sh_cmt_clocksource_resume;
484 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); 512 cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
485 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 513 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
@@ -562,6 +590,16 @@ static int sh_cmt_clock_event_next(unsigned long delta,
562 return 0; 590 return 0;
563} 591}
564 592
593static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
594{
595 pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev);
596}
597
598static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
599{
600 pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev);
601}
602
565static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, 603static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
566 char *name, unsigned long rating) 604 char *name, unsigned long rating)
567{ 605{
@@ -576,6 +614,8 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
576 ced->cpumask = cpumask_of(0); 614 ced->cpumask = cpumask_of(0);
577 ced->set_next_event = sh_cmt_clock_event_next; 615 ced->set_next_event = sh_cmt_clock_event_next;
578 ced->set_mode = sh_cmt_clock_event_mode; 616 ced->set_mode = sh_cmt_clock_event_mode;
617 ced->suspend = sh_cmt_clock_event_suspend;
618 ced->resume = sh_cmt_clock_event_resume;
579 619
580 dev_info(&p->pdev->dev, "used for clock events\n"); 620 dev_info(&p->pdev->dev, "used for clock events\n");
581 clockevents_register_device(ced); 621 clockevents_register_device(ced);
@@ -670,6 +710,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
670 dev_err(&p->pdev->dev, "registration failed\n"); 710 dev_err(&p->pdev->dev, "registration failed\n");
671 goto err1; 711 goto err1;
672 } 712 }
713 p->cs_enabled = false;
673 714
674 ret = setup_irq(irq, &p->irqaction); 715 ret = setup_irq(irq, &p->irqaction);
675 if (ret) { 716 if (ret) {
@@ -688,14 +729,17 @@ err0:
688static int __devinit sh_cmt_probe(struct platform_device *pdev) 729static int __devinit sh_cmt_probe(struct platform_device *pdev)
689{ 730{
690 struct sh_cmt_priv *p = platform_get_drvdata(pdev); 731 struct sh_cmt_priv *p = platform_get_drvdata(pdev);
732 struct sh_timer_config *cfg = pdev->dev.platform_data;
691 int ret; 733 int ret;
692 734
693 if (!is_early_platform_device(pdev)) 735 if (!is_early_platform_device(pdev)) {
694 pm_genpd_dev_always_on(&pdev->dev, true); 736 pm_runtime_set_active(&pdev->dev);
737 pm_runtime_enable(&pdev->dev);
738 }
695 739
696 if (p) { 740 if (p) {
697 dev_info(&pdev->dev, "kept as earlytimer\n"); 741 dev_info(&pdev->dev, "kept as earlytimer\n");
698 return 0; 742 goto out;
699 } 743 }
700 744
701 p = kmalloc(sizeof(*p), GFP_KERNEL); 745 p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -708,8 +752,19 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
708 if (ret) { 752 if (ret) {
709 kfree(p); 753 kfree(p);
710 platform_set_drvdata(pdev, NULL); 754 platform_set_drvdata(pdev, NULL);
755 pm_runtime_idle(&pdev->dev);
756 return ret;
711 } 757 }
712 return ret; 758 if (is_early_platform_device(pdev))
759 return 0;
760
761 out:
762 if (cfg->clockevent_rating || cfg->clocksource_rating)
763 pm_runtime_irq_safe(&pdev->dev);
764 else
765 pm_runtime_idle(&pdev->dev);
766
767 return 0;
713} 768}
714 769
715static int __devexit sh_cmt_remove(struct platform_device *pdev) 770static int __devexit sh_cmt_remove(struct platform_device *pdev)
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
36struct sh_mtu2_priv { 37struct 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
162static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id) 169static 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
218static 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
223static 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
211static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, 228static 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)
305static int __devinit sh_mtu2_probe(struct platform_device *pdev) 324static 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
332static int __devexit sh_mtu2_remove(struct platform_device *pdev) 365static int __devexit sh_mtu2_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index c1b51d49d106..0cc4add88279 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,8 @@ 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;
48 unsigned int enable_count;
46}; 49};
47 50
48static DEFINE_RAW_SPINLOCK(sh_tmu_lock); 51static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -107,7 +110,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
107 raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); 110 raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
108} 111}
109 112
110static int sh_tmu_enable(struct sh_tmu_priv *p) 113static int __sh_tmu_enable(struct sh_tmu_priv *p)
111{ 114{
112 int ret; 115 int ret;
113 116
@@ -135,7 +138,18 @@ static int sh_tmu_enable(struct sh_tmu_priv *p)
135 return 0; 138 return 0;
136} 139}
137 140
138static void sh_tmu_disable(struct sh_tmu_priv *p) 141static int sh_tmu_enable(struct sh_tmu_priv *p)
142{
143 if (p->enable_count++ > 0)
144 return 0;
145
146 pm_runtime_get_sync(&p->pdev->dev);
147 dev_pm_syscore_device(&p->pdev->dev, true);
148
149 return __sh_tmu_enable(p);
150}
151
152static void __sh_tmu_disable(struct sh_tmu_priv *p)
139{ 153{
140 /* disable channel */ 154 /* disable channel */
141 sh_tmu_start_stop_ch(p, 0); 155 sh_tmu_start_stop_ch(p, 0);
@@ -147,6 +161,20 @@ static void sh_tmu_disable(struct sh_tmu_priv *p)
147 clk_disable(p->clk); 161 clk_disable(p->clk);
148} 162}
149 163
164static void sh_tmu_disable(struct sh_tmu_priv *p)
165{
166 if (WARN_ON(p->enable_count == 0))
167 return;
168
169 if (--p->enable_count > 0)
170 return;
171
172 __sh_tmu_disable(p);
173
174 dev_pm_syscore_device(&p->pdev->dev, false);
175 pm_runtime_put(&p->pdev->dev);
176}
177
150static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, 178static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
151 int periodic) 179 int periodic)
152{ 180{
@@ -203,15 +231,53 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
203 struct sh_tmu_priv *p = cs_to_sh_tmu(cs); 231 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
204 int ret; 232 int ret;
205 233
234 if (WARN_ON(p->cs_enabled))
235 return 0;
236
206 ret = sh_tmu_enable(p); 237 ret = sh_tmu_enable(p);
207 if (!ret) 238 if (!ret) {
208 __clocksource_updatefreq_hz(cs, p->rate); 239 __clocksource_updatefreq_hz(cs, p->rate);
240 p->cs_enabled = true;
241 }
242
209 return ret; 243 return ret;
210} 244}
211 245
212static void sh_tmu_clocksource_disable(struct clocksource *cs) 246static void sh_tmu_clocksource_disable(struct clocksource *cs)
213{ 247{
214 sh_tmu_disable(cs_to_sh_tmu(cs)); 248 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
249
250 if (WARN_ON(!p->cs_enabled))
251 return;
252
253 sh_tmu_disable(p);
254 p->cs_enabled = false;
255}
256
257static void sh_tmu_clocksource_suspend(struct clocksource *cs)
258{
259 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
260
261 if (!p->cs_enabled)
262 return;
263
264 if (--p->enable_count == 0) {
265 __sh_tmu_disable(p);
266 pm_genpd_syscore_poweroff(&p->pdev->dev);
267 }
268}
269
270static void sh_tmu_clocksource_resume(struct clocksource *cs)
271{
272 struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
273
274 if (!p->cs_enabled)
275 return;
276
277 if (p->enable_count++ == 0) {
278 pm_genpd_syscore_poweron(&p->pdev->dev);
279 __sh_tmu_enable(p);
280 }
215} 281}
216 282
217static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, 283static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
@@ -224,6 +290,8 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
224 cs->read = sh_tmu_clocksource_read; 290 cs->read = sh_tmu_clocksource_read;
225 cs->enable = sh_tmu_clocksource_enable; 291 cs->enable = sh_tmu_clocksource_enable;
226 cs->disable = sh_tmu_clocksource_disable; 292 cs->disable = sh_tmu_clocksource_disable;
293 cs->suspend = sh_tmu_clocksource_suspend;
294 cs->resume = sh_tmu_clocksource_resume;
227 cs->mask = CLOCKSOURCE_MASK(32); 295 cs->mask = CLOCKSOURCE_MASK(32);
228 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 296 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
229 297
@@ -301,6 +369,16 @@ static int sh_tmu_clock_event_next(unsigned long delta,
301 return 0; 369 return 0;
302} 370}
303 371
372static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
373{
374 pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->pdev->dev);
375}
376
377static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
378{
379 pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->pdev->dev);
380}
381
304static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, 382static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
305 char *name, unsigned long rating) 383 char *name, unsigned long rating)
306{ 384{
@@ -316,6 +394,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
316 ced->cpumask = cpumask_of(0); 394 ced->cpumask = cpumask_of(0);
317 ced->set_next_event = sh_tmu_clock_event_next; 395 ced->set_next_event = sh_tmu_clock_event_next;
318 ced->set_mode = sh_tmu_clock_event_mode; 396 ced->set_mode = sh_tmu_clock_event_mode;
397 ced->suspend = sh_tmu_clock_event_suspend;
398 ced->resume = sh_tmu_clock_event_resume;
319 399
320 dev_info(&p->pdev->dev, "used for clock events\n"); 400 dev_info(&p->pdev->dev, "used for clock events\n");
321 401
@@ -392,6 +472,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
392 ret = PTR_ERR(p->clk); 472 ret = PTR_ERR(p->clk);
393 goto err1; 473 goto err1;
394 } 474 }
475 p->cs_enabled = false;
476 p->enable_count = 0;
395 477
396 return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), 478 return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
397 cfg->clockevent_rating, 479 cfg->clockevent_rating,
@@ -405,14 +487,17 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
405static int __devinit sh_tmu_probe(struct platform_device *pdev) 487static int __devinit sh_tmu_probe(struct platform_device *pdev)
406{ 488{
407 struct sh_tmu_priv *p = platform_get_drvdata(pdev); 489 struct sh_tmu_priv *p = platform_get_drvdata(pdev);
490 struct sh_timer_config *cfg = pdev->dev.platform_data;
408 int ret; 491 int ret;
409 492
410 if (!is_early_platform_device(pdev)) 493 if (!is_early_platform_device(pdev)) {
411 pm_genpd_dev_always_on(&pdev->dev, true); 494 pm_runtime_set_active(&pdev->dev);
495 pm_runtime_enable(&pdev->dev);
496 }
412 497
413 if (p) { 498 if (p) {
414 dev_info(&pdev->dev, "kept as earlytimer\n"); 499 dev_info(&pdev->dev, "kept as earlytimer\n");
415 return 0; 500 goto out;
416 } 501 }
417 502
418 p = kmalloc(sizeof(*p), GFP_KERNEL); 503 p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -425,8 +510,19 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
425 if (ret) { 510 if (ret) {
426 kfree(p); 511 kfree(p);
427 platform_set_drvdata(pdev, NULL); 512 platform_set_drvdata(pdev, NULL);
513 pm_runtime_idle(&pdev->dev);
514 return ret;
428 } 515 }
429 return ret; 516 if (is_early_platform_device(pdev))
517 return 0;
518
519 out:
520 if (cfg->clockevent_rating || cfg->clocksource_rating)
521 pm_runtime_irq_safe(&pdev->dev);
522 else
523 pm_runtime_idle(&pdev->dev);
524
525 return 0;
430} 526}
431 527
432static int __devexit sh_tmu_remove(struct platform_device *pdev) 528static int __devexit sh_tmu_remove(struct platform_device *pdev)