aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 14:34:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 14:34:26 -0500
commit6c6461435611e1d4843516f2d55e8316c009112e (patch)
tree2285f7ef3257dcb30342f931430ad755fc5d299b /drivers/clocksource
parenta0fa1dd3cdbccec9597fe53b6177a9aa6e20f2f8 (diff)
parent00e2bcd6d35f59fce7fa0e76e24d08f74c6a8506 (diff)
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer changes from Ingo Molnar: - ARM clocksource/clockevent improvements and fixes - generic timekeeping updates: TAI fixes/improvements, cleanups - Posix cpu timer cleanups and improvements - dynticks updates: full dynticks bugfixes, optimizations and cleanups * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (46 commits) clocksource: Timer-sun5i: Switch to sched_clock_register() timekeeping: Remove comment that's mostly out of date rtc-cmos: Add an alarm disable quirk timekeeper: fix comment typo for tk_setup_internals() timekeeping: Fix missing timekeeping_update in suspend path timekeeping: Fix CLOCK_TAI timer/nanosleep delays tick/timekeeping: Call update_wall_time outside the jiffies lock timekeeping: Avoid possible deadlock from clock_was_set_delayed timekeeping: Fix potential lost pv notification of time change timekeeping: Fix lost updates to tai adjustment clocksource: sh_cmt: Add clk_prepare/unprepare support clocksource: bcm_kona_timer: Remove unused bcm_timer_ids clocksource: vt8500: Remove deprecated IRQF_DISABLED clocksource: tegra: Remove deprecated IRQF_DISABLED clocksource: misc drivers: Remove deprecated IRQF_DISABLED clocksource: sh_mtu2: Remove unnecessary platform_set_drvdata() clocksource: sh_tmu: Remove unnecessary platform_set_drvdata() clocksource: armada-370-xp: Enable timer divider only when needed clocksource: clksrc-of: Warn if no clock sources are found clocksource: orion: Switch to sched_clock_register() ...
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_global_timer.c4
-rw-r--r--drivers/clocksource/bcm_kona_timer.c6
-rw-r--r--drivers/clocksource/cadence_ttc_timer.c7
-rw-r--r--drivers/clocksource/clksrc-of.c4
-rw-r--r--drivers/clocksource/cs5535-clockevt.c2
-rw-r--r--drivers/clocksource/dw_apb_timer.c3
-rw-r--r--drivers/clocksource/nomadik-mtu.c2
-rw-r--r--drivers/clocksource/samsung_pwm_timer.c2
-rw-r--r--drivers/clocksource/sh_cmt.c23
-rw-r--r--drivers/clocksource/sh_mtu2.c4
-rw-r--r--drivers/clocksource/sh_tmu.c4
-rw-r--r--drivers/clocksource/sun4i_timer.c11
-rw-r--r--drivers/clocksource/tegra20_timer.c2
-rw-r--r--drivers/clocksource/time-armada-370-xp.c18
-rw-r--r--drivers/clocksource/time-orion.c4
-rw-r--r--drivers/clocksource/timer-sun5i.c192
-rw-r--r--drivers/clocksource/vt8500_timer.c2
19 files changed, 248 insertions, 47 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 634c4d6dd45a..cd6950fd8caf 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -37,6 +37,10 @@ config SUN4I_TIMER
37 select CLKSRC_MMIO 37 select CLKSRC_MMIO
38 bool 38 bool
39 39
40config SUN5I_HSTIMER
41 select CLKSRC_MMIO
42 bool
43
40config VT8500_TIMER 44config VT8500_TIMER
41 bool 45 bool
42 46
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 33621efb9148..358358d87b6d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o
22obj-$(CONFIG_ARCH_MXS) += mxs_timer.o 22obj-$(CONFIG_ARCH_MXS) += mxs_timer.o
23obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o 23obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
24obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o 24obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
25obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o
25obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o 26obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
26obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o 27obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
27obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o 28obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index c639b1a9e996..0fc31d029e52 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -202,7 +202,7 @@ static struct clocksource gt_clocksource = {
202}; 202};
203 203
204#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK 204#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
205static u32 notrace gt_sched_clock_read(void) 205static u64 notrace gt_sched_clock_read(void)
206{ 206{
207 return gt_counter_read(); 207 return gt_counter_read();
208} 208}
@@ -217,7 +217,7 @@ static void __init gt_clocksource_init(void)
217 writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); 217 writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
218 218
219#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK 219#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
220 setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate); 220 sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate);
221#endif 221#endif
222 clocksource_register_hz(&gt_clocksource, gt_clk_rate); 222 clocksource_register_hz(&gt_clocksource, gt_clk_rate);
223} 223}
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
index 0d7d8c3ed6b2..5176e761166b 100644
--- a/drivers/clocksource/bcm_kona_timer.c
+++ b/drivers/clocksource/bcm_kona_timer.c
@@ -98,12 +98,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw)
98 return; 98 return;
99} 99}
100 100
101static const struct of_device_id bcm_timer_ids[] __initconst = {
102 {.compatible = "brcm,kona-timer"},
103 {.compatible = "bcm,kona-timer"}, /* deprecated name */
104 {},
105};
106
107static void __init kona_timers_init(struct device_node *node) 101static void __init kona_timers_init(struct device_node *node)
108{ 102{
109 u32 freq; 103 u32 freq;
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index a92350b55d32..63f176de0d02 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -160,7 +160,7 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs)
160 TTC_COUNT_VAL_OFFSET); 160 TTC_COUNT_VAL_OFFSET);
161} 161}
162 162
163static u32 notrace ttc_sched_clock_read(void) 163static u64 notrace ttc_sched_clock_read(void)
164{ 164{
165 return __raw_readl(ttc_sched_clock_val_reg); 165 return __raw_readl(ttc_sched_clock_val_reg);
166} 166}
@@ -308,7 +308,7 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
308 } 308 }
309 309
310 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; 310 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
311 setup_sched_clock(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE); 311 sched_clock_register(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE);
312} 312}
313 313
314static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, 314static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
@@ -393,8 +393,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
393 __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); 393 __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET);
394 394
395 err = request_irq(irq, ttc_clock_event_interrupt, 395 err = request_irq(irq, ttc_clock_event_interrupt,
396 IRQF_DISABLED | IRQF_TIMER, 396 IRQF_TIMER, ttcce->ce.name, ttcce);
397 ttcce->ce.name, ttcce);
398 if (WARN_ON(err)) { 397 if (WARN_ON(err)) {
399 kfree(ttcce); 398 kfree(ttcce);
400 return; 399 return;
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
index b9ddd9e3a2f5..ae2e4278c42a 100644
--- a/drivers/clocksource/clksrc-of.c
+++ b/drivers/clocksource/clksrc-of.c
@@ -28,6 +28,7 @@ void __init clocksource_of_init(void)
28 struct device_node *np; 28 struct device_node *np;
29 const struct of_device_id *match; 29 const struct of_device_id *match;
30 clocksource_of_init_fn init_func; 30 clocksource_of_init_fn init_func;
31 unsigned clocksources = 0;
31 32
32 for_each_matching_node_and_match(np, __clksrc_of_table, &match) { 33 for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
33 if (!of_device_is_available(np)) 34 if (!of_device_is_available(np))
@@ -35,5 +36,8 @@ void __init clocksource_of_init(void)
35 36
36 init_func = match->data; 37 init_func = match->data;
37 init_func(np); 38 init_func(np);
39 clocksources++;
38 } 40 }
41 if (!clocksources)
42 pr_crit("%s: no matching clocksources found\n", __func__);
39} 43}
diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c
index ea210482dd20..db2105290898 100644
--- a/drivers/clocksource/cs5535-clockevt.c
+++ b/drivers/clocksource/cs5535-clockevt.c
@@ -131,7 +131,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
131 131
132static struct irqaction mfgptirq = { 132static struct irqaction mfgptirq = {
133 .handler = mfgpt_tick, 133 .handler = mfgpt_tick,
134 .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, 134 .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED,
135 .name = DRV_NAME, 135 .name = DRV_NAME,
136}; 136};
137 137
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index e54ca1062d8e..f3656a6b0382 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -243,8 +243,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
243 dw_ced->irqaction.dev_id = &dw_ced->ced; 243 dw_ced->irqaction.dev_id = &dw_ced->ced;
244 dw_ced->irqaction.irq = irq; 244 dw_ced->irqaction.irq = irq;
245 dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | 245 dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL |
246 IRQF_NOBALANCING | 246 IRQF_NOBALANCING;
247 IRQF_DISABLED;
248 247
249 dw_ced->eoi = apbt_eoi; 248 dw_ced->eoi = apbt_eoi;
250 err = setup_irq(irq, &dw_ced->irqaction); 249 err = setup_irq(irq, &dw_ced->irqaction);
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index ed7b73b508e0..152a3f3875ee 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -187,7 +187,7 @@ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
187 187
188static struct irqaction nmdk_timer_irq = { 188static struct irqaction nmdk_timer_irq = {
189 .name = "Nomadik Timer Tick", 189 .name = "Nomadik Timer Tick",
190 .flags = IRQF_DISABLED | IRQF_TIMER, 190 .flags = IRQF_TIMER,
191 .handler = nmdk_timer_interrupt, 191 .handler = nmdk_timer_interrupt,
192 .dev_id = &nmdk_clkevt, 192 .dev_id = &nmdk_clkevt,
193}; 193};
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index 85082e8d3052..5645cfc90c41 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -264,7 +264,7 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
264 264
265static struct irqaction samsung_clock_event_irq = { 265static struct irqaction samsung_clock_event_irq = {
266 .name = "samsung_time_irq", 266 .name = "samsung_time_irq",
267 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 267 .flags = IRQF_TIMER | IRQF_IRQPOLL,
268 .handler = samsung_clock_event_isr, 268 .handler = samsung_clock_event_isr,
269 .dev_id = &time_event_device, 269 .dev_id = &time_event_device,
270}; 270};
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 0965e9848b3d..0b1836a6c539 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -634,12 +634,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
634 634
635static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) 635static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
636{ 636{
637 pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev); 637 struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
638
639 pm_genpd_syscore_poweroff(&p->pdev->dev);
640 clk_unprepare(p->clk);
638} 641}
639 642
640static void sh_cmt_clock_event_resume(struct clock_event_device *ced) 643static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
641{ 644{
642 pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev); 645 struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
646
647 clk_prepare(p->clk);
648 pm_genpd_syscore_poweron(&p->pdev->dev);
643} 649}
644 650
645static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, 651static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
@@ -726,8 +732,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
726 p->irqaction.name = dev_name(&p->pdev->dev); 732 p->irqaction.name = dev_name(&p->pdev->dev);
727 p->irqaction.handler = sh_cmt_interrupt; 733 p->irqaction.handler = sh_cmt_interrupt;
728 p->irqaction.dev_id = p; 734 p->irqaction.dev_id = p;
729 p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 735 p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
730 IRQF_IRQPOLL | IRQF_NOBALANCING;
731 736
732 /* get hold of clock */ 737 /* get hold of clock */
733 p->clk = clk_get(&p->pdev->dev, "cmt_fck"); 738 p->clk = clk_get(&p->pdev->dev, "cmt_fck");
@@ -737,6 +742,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
737 goto err2; 742 goto err2;
738 } 743 }
739 744
745 ret = clk_prepare(p->clk);
746 if (ret < 0)
747 goto err3;
748
740 if (res2 && (resource_size(res2) == 4)) { 749 if (res2 && (resource_size(res2) == 4)) {
741 /* assume both CMSTR and CMCSR to be 32-bit */ 750 /* assume both CMSTR and CMCSR to be 32-bit */
742 p->read_control = sh_cmt_read32; 751 p->read_control = sh_cmt_read32;
@@ -773,19 +782,21 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
773 cfg->clocksource_rating); 782 cfg->clocksource_rating);
774 if (ret) { 783 if (ret) {
775 dev_err(&p->pdev->dev, "registration failed\n"); 784 dev_err(&p->pdev->dev, "registration failed\n");
776 goto err3; 785 goto err4;
777 } 786 }
778 p->cs_enabled = false; 787 p->cs_enabled = false;
779 788
780 ret = setup_irq(irq, &p->irqaction); 789 ret = setup_irq(irq, &p->irqaction);
781 if (ret) { 790 if (ret) {
782 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); 791 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
783 goto err3; 792 goto err4;
784 } 793 }
785 794
786 platform_set_drvdata(pdev, p); 795 platform_set_drvdata(pdev, p);
787 796
788 return 0; 797 return 0;
798err4:
799 clk_unprepare(p->clk);
789err3: 800err3:
790 clk_put(p->clk); 801 clk_put(p->clk);
791err2: 802err2:
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 3cf12834681e..e30d76e0a6fa 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -302,8 +302,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
302 p->irqaction.handler = sh_mtu2_interrupt; 302 p->irqaction.handler = sh_mtu2_interrupt;
303 p->irqaction.dev_id = p; 303 p->irqaction.dev_id = p;
304 p->irqaction.irq = irq; 304 p->irqaction.irq = irq;
305 p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 305 p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
306 IRQF_IRQPOLL | IRQF_NOBALANCING;
307 306
308 /* get hold of clock */ 307 /* get hold of clock */
309 p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); 308 p->clk = clk_get(&p->pdev->dev, "mtu2_fck");
@@ -358,7 +357,6 @@ static int sh_mtu2_probe(struct platform_device *pdev)
358 ret = sh_mtu2_setup(p, pdev); 357 ret = sh_mtu2_setup(p, pdev);
359 if (ret) { 358 if (ret) {
360 kfree(p); 359 kfree(p);
361 platform_set_drvdata(pdev, NULL);
362 pm_runtime_idle(&pdev->dev); 360 pm_runtime_idle(&pdev->dev);
363 return ret; 361 return ret;
364 } 362 }
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 63557cda0a7d..ecd7b60bfdfa 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -462,8 +462,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
462 p->irqaction.handler = sh_tmu_interrupt; 462 p->irqaction.handler = sh_tmu_interrupt;
463 p->irqaction.dev_id = p; 463 p->irqaction.dev_id = p;
464 p->irqaction.irq = irq; 464 p->irqaction.irq = irq;
465 p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 465 p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
466 IRQF_IRQPOLL | IRQF_NOBALANCING;
467 466
468 /* get hold of clock */ 467 /* get hold of clock */
469 p->clk = clk_get(&p->pdev->dev, "tmu_fck"); 468 p->clk = clk_get(&p->pdev->dev, "tmu_fck");
@@ -523,7 +522,6 @@ static int sh_tmu_probe(struct platform_device *pdev)
523 ret = sh_tmu_setup(p, pdev); 522 ret = sh_tmu_setup(p, pdev);
524 if (ret) { 523 if (ret) {
525 kfree(p); 524 kfree(p);
526 platform_set_drvdata(pdev, NULL);
527 pm_runtime_idle(&pdev->dev); 525 pm_runtime_idle(&pdev->dev);
528 return ret; 526 return ret;
529 } 527 }
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index a4f6119aafd8..bf497afba9ad 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -114,7 +114,7 @@ static int sun4i_clkevt_next_event(unsigned long evt,
114 114
115static struct clock_event_device sun4i_clockevent = { 115static struct clock_event_device sun4i_clockevent = {
116 .name = "sun4i_tick", 116 .name = "sun4i_tick",
117 .rating = 300, 117 .rating = 350,
118 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 118 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
119 .set_mode = sun4i_clkevt_mode, 119 .set_mode = sun4i_clkevt_mode,
120 .set_next_event = sun4i_clkevt_next_event, 120 .set_next_event = sun4i_clkevt_next_event,
@@ -138,7 +138,7 @@ static struct irqaction sun4i_timer_irq = {
138 .dev_id = &sun4i_clockevent, 138 .dev_id = &sun4i_clockevent,
139}; 139};
140 140
141static u32 sun4i_timer_sched_read(void) 141static u64 notrace sun4i_timer_sched_read(void)
142{ 142{
143 return ~readl(timer_base + TIMER_CNTVAL_REG(1)); 143 return ~readl(timer_base + TIMER_CNTVAL_REG(1));
144} 144}
@@ -170,9 +170,9 @@ static void __init sun4i_timer_init(struct device_node *node)
170 TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), 170 TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
171 timer_base + TIMER_CTL_REG(1)); 171 timer_base + TIMER_CTL_REG(1));
172 172
173 setup_sched_clock(sun4i_timer_sched_read, 32, rate); 173 sched_clock_register(sun4i_timer_sched_read, 32, rate);
174 clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, 174 clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
175 rate, 300, 32, clocksource_mmio_readl_down); 175 rate, 350, 32, clocksource_mmio_readl_down);
176 176
177 ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 177 ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
178 178
@@ -190,7 +190,8 @@ static void __init sun4i_timer_init(struct device_node *node)
190 val = readl(timer_base + TIMER_IRQ_EN_REG); 190 val = readl(timer_base + TIMER_IRQ_EN_REG);
191 writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); 191 writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
192 192
193 sun4i_clockevent.cpumask = cpumask_of(0); 193 sun4i_clockevent.cpumask = cpu_possible_mask;
194 sun4i_clockevent.irq = irq;
194 195
195 clockevents_config_and_register(&sun4i_clockevent, rate, 196 clockevents_config_and_register(&sun4i_clockevent, rate,
196 TIMER_SYNC_TICKS, 0xffffffff); 197 TIMER_SYNC_TICKS, 0xffffffff);
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index 642849256d82..d1869f02051c 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -149,7 +149,7 @@ static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
149 149
150static struct irqaction tegra_timer_irq = { 150static struct irqaction tegra_timer_irq = {
151 .name = "timer0", 151 .name = "timer0",
152 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, 152 .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH,
153 .handler = tegra_timer_interrupt, 153 .handler = tegra_timer_interrupt,
154 .dev_id = &tegra_clockevent, 154 .dev_id = &tegra_clockevent,
155}; 155};
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 4e7f6802e840..ee8691b89944 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -76,6 +76,7 @@
76static void __iomem *timer_base, *local_base; 76static void __iomem *timer_base, *local_base;
77static unsigned int timer_clk; 77static unsigned int timer_clk;
78static bool timer25Mhz = true; 78static bool timer25Mhz = true;
79static u32 enable_mask;
79 80
80/* 81/*
81 * Number of timer ticks per jiffy. 82 * Number of timer ticks per jiffy.
@@ -121,8 +122,7 @@ armada_370_xp_clkevt_next_event(unsigned long delta,
121 /* 122 /*
122 * Enable the timer. 123 * Enable the timer.
123 */ 124 */
124 local_timer_ctrl_clrset(TIMER0_RELOAD_EN, 125 local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask);
125 TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT));
126 return 0; 126 return 0;
127} 127}
128 128
@@ -141,9 +141,7 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
141 /* 141 /*
142 * Enable timer. 142 * Enable timer.
143 */ 143 */
144 local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | 144 local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
145 TIMER0_EN |
146 TIMER0_DIV(TIMER_DIVIDER_SHIFT));
147 } else { 145 } else {
148 /* 146 /*
149 * Disable timer. 147 * Disable timer.
@@ -240,10 +238,13 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
240 WARN_ON(!timer_base); 238 WARN_ON(!timer_base);
241 local_base = of_iomap(np, 1); 239 local_base = of_iomap(np, 1);
242 240
243 if (timer25Mhz) 241 if (timer25Mhz) {
244 set = TIMER0_25MHZ; 242 set = TIMER0_25MHZ;
245 else 243 enable_mask = TIMER0_EN;
244 } else {
246 clr = TIMER0_25MHZ; 245 clr = TIMER0_25MHZ;
246 enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT);
247 }
247 timer_ctrl_clrset(clr, set); 248 timer_ctrl_clrset(clr, set);
248 local_timer_ctrl_clrset(clr, set); 249 local_timer_ctrl_clrset(clr, set);
249 250
@@ -262,8 +263,7 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
262 writel(0xffffffff, timer_base + TIMER0_VAL_OFF); 263 writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
263 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); 264 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
264 265
265 timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN | 266 timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
266 TIMER0_DIV(TIMER_DIVIDER_SHIFT));
267 267
268 /* 268 /*
269 * Set scale and timer for sched_clock. 269 * Set scale and timer for sched_clock.
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
index 9c7f018a67ca..20066222f3f2 100644
--- a/drivers/clocksource/time-orion.c
+++ b/drivers/clocksource/time-orion.c
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(orion_timer_ctrl_clrset);
53/* 53/*
54 * Free-running clocksource handling. 54 * Free-running clocksource handling.
55 */ 55 */
56static u32 notrace orion_read_sched_clock(void) 56static u64 notrace orion_read_sched_clock(void)
57{ 57{
58 return ~readl(timer_base + TIMER0_VAL); 58 return ~readl(timer_base + TIMER0_VAL);
59} 59}
@@ -135,7 +135,7 @@ static void __init orion_timer_init(struct device_node *np)
135 clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", 135 clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource",
136 clk_get_rate(clk), 300, 32, 136 clk_get_rate(clk), 300, 32,
137 clocksource_mmio_readl_down); 137 clocksource_mmio_readl_down);
138 setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk)); 138 sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk));
139 139
140 /* setup timer1 as clockevent timer */ 140 /* setup timer1 as clockevent timer */
141 if (setup_irq(irq, &orion_clkevt_irq)) 141 if (setup_irq(irq, &orion_clkevt_irq))
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
new file mode 100644
index 000000000000..deebcd6469fc
--- /dev/null
+++ b/drivers/clocksource/timer-sun5i.c
@@ -0,0 +1,192 @@
1/*
2 * Allwinner SoCs hstimer driver.
3 *
4 * Copyright (C) 2013 Maxime Ripard
5 *
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/clk.h>
14#include <linux/clockchips.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18#include <linux/irqreturn.h>
19#include <linux/sched_clock.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/of_irq.h>
23
24#define TIMER_IRQ_EN_REG 0x00
25#define TIMER_IRQ_EN(val) BIT(val)
26#define TIMER_IRQ_ST_REG 0x04
27#define TIMER_CTL_REG(val) (0x20 * (val) + 0x10)
28#define TIMER_CTL_ENABLE BIT(0)
29#define TIMER_CTL_RELOAD BIT(1)
30#define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4)
31#define TIMER_CTL_ONESHOT BIT(7)
32#define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14)
33#define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18)
34#define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c)
35#define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20)
36
37#define TIMER_SYNC_TICKS 3
38
39static void __iomem *timer_base;
40static u32 ticks_per_jiffy;
41
42/*
43 * When we disable a timer, we need to wait at least for 2 cycles of
44 * the timer source clock. We will use for that the clocksource timer
45 * that is already setup and runs at the same frequency than the other
46 * timers, and we never will be disabled.
47 */
48static void sun5i_clkevt_sync(void)
49{
50 u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1));
51
52 while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
53 cpu_relax();
54}
55
56static void sun5i_clkevt_time_stop(u8 timer)
57{
58 u32 val = readl(timer_base + TIMER_CTL_REG(timer));
59 writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
60
61 sun5i_clkevt_sync();
62}
63
64static void sun5i_clkevt_time_setup(u8 timer, u32 delay)
65{
66 writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer));
67}
68
69static void sun5i_clkevt_time_start(u8 timer, bool periodic)
70{
71 u32 val = readl(timer_base + TIMER_CTL_REG(timer));
72
73 if (periodic)
74 val &= ~TIMER_CTL_ONESHOT;
75 else
76 val |= TIMER_CTL_ONESHOT;
77
78 writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
79 timer_base + TIMER_CTL_REG(timer));
80}
81
82static void sun5i_clkevt_mode(enum clock_event_mode mode,
83 struct clock_event_device *clk)
84{
85 switch (mode) {
86 case CLOCK_EVT_MODE_PERIODIC:
87 sun5i_clkevt_time_stop(0);
88 sun5i_clkevt_time_setup(0, ticks_per_jiffy);
89 sun5i_clkevt_time_start(0, true);
90 break;
91 case CLOCK_EVT_MODE_ONESHOT:
92 sun5i_clkevt_time_stop(0);
93 sun5i_clkevt_time_start(0, false);
94 break;
95 case CLOCK_EVT_MODE_UNUSED:
96 case CLOCK_EVT_MODE_SHUTDOWN:
97 default:
98 sun5i_clkevt_time_stop(0);
99 break;
100 }
101}
102
103static int sun5i_clkevt_next_event(unsigned long evt,
104 struct clock_event_device *unused)
105{
106 sun5i_clkevt_time_stop(0);
107 sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
108 sun5i_clkevt_time_start(0, false);
109
110 return 0;
111}
112
113static struct clock_event_device sun5i_clockevent = {
114 .name = "sun5i_tick",
115 .rating = 340,
116 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
117 .set_mode = sun5i_clkevt_mode,
118 .set_next_event = sun5i_clkevt_next_event,
119};
120
121
122static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
123{
124 struct clock_event_device *evt = (struct clock_event_device *)dev_id;
125
126 writel(0x1, timer_base + TIMER_IRQ_ST_REG);
127 evt->event_handler(evt);
128
129 return IRQ_HANDLED;
130}
131
132static struct irqaction sun5i_timer_irq = {
133 .name = "sun5i_timer0",
134 .flags = IRQF_TIMER | IRQF_IRQPOLL,
135 .handler = sun5i_timer_interrupt,
136 .dev_id = &sun5i_clockevent,
137};
138
139static u64 sun5i_timer_sched_read(void)
140{
141 return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1));
142}
143
144static void __init sun5i_timer_init(struct device_node *node)
145{
146 unsigned long rate;
147 struct clk *clk;
148 int ret, irq;
149 u32 val;
150
151 timer_base = of_iomap(node, 0);
152 if (!timer_base)
153 panic("Can't map registers");
154
155 irq = irq_of_parse_and_map(node, 0);
156 if (irq <= 0)
157 panic("Can't parse IRQ");
158
159 clk = of_clk_get(node, 0);
160 if (IS_ERR(clk))
161 panic("Can't get timer clock");
162 clk_prepare_enable(clk);
163 rate = clk_get_rate(clk);
164
165 writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
166 writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
167 timer_base + TIMER_CTL_REG(1));
168
169 sched_clock_register(sun5i_timer_sched_read, 32, rate);
170 clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name,
171 rate, 340, 32, clocksource_mmio_readl_down);
172
173 ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
174
175 ret = setup_irq(irq, &sun5i_timer_irq);
176 if (ret)
177 pr_warn("failed to setup irq %d\n", irq);
178
179 /* Enable timer0 interrupt */
180 val = readl(timer_base + TIMER_IRQ_EN_REG);
181 writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
182
183 sun5i_clockevent.cpumask = cpu_possible_mask;
184 sun5i_clockevent.irq = irq;
185
186 clockevents_config_and_register(&sun5i_clockevent, rate,
187 TIMER_SYNC_TICKS, 0xffffffff);
188}
189CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
190 sun5i_timer_init);
191CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
192 sun5i_timer_init);
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index ad3c0e83a779..1098ed3b9b89 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -124,7 +124,7 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
124 124
125static struct irqaction irq = { 125static struct irqaction irq = {
126 .name = "vt8500_timer", 126 .name = "vt8500_timer",
127 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 127 .flags = IRQF_TIMER | IRQF_IRQPOLL,
128 .handler = vt8500_timer_interrupt, 128 .handler = vt8500_timer_interrupt,
129 .dev_id = &clockevent, 129 .dev_id = &clockevent,
130}; 130};