aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-01-12 11:28:52 -0500
committerIngo Molnar <mingo@kernel.org>2014-01-14 08:33:29 -0500
commit1b3f82876006bd4172ca7696aa367baf96ec7c15 (patch)
treeb9c6058bc773cab95db1daf457bbf56ad6a47bbe
parentd05d24a984f8e14086771a158083dbe6facb769e (diff)
parent98aefbe72ec6015f90fe045ed16c5cf755da283d (diff)
Merge branch 'clockevents/3.14' of git://git.linaro.org/people/daniel.lezcano/linux into timers/core
Pull clocksource/clockevent updates from Daniel Lezcano: * Axel Lin removed an unused structure defining the ids for the bcm kona driver. * Ezequiel Garcia enabled the timer divider only when the 25MHz timer is not used for the armada 370 XP. * Jingoo Han removed a pointless platform data initialization for the sh_mtu and sh_mtu2. * Laurent Pinchart added the clk_prepare/clk_unprepare for sh_cmt. * Linus Walleij added a useful warning in clk_of when no clocks are found while the old behavior was to silently hang at boot time. * Maxime Ripard added the high speed timer drivers for the Allwinner SoCs (A10, A13, A20). He increased the rating, shared the irq across all available cpus and fixed the clockevent's irq initialization for the sun4i. * Michael Opdenacker removed the usage of the IRQF_DISABLED for the all the timers driver located in drivers/clocksource. * Stephen Boyd switched to sched_clock_register for the arm_global_timer, cadence_ttc, sun4i and orion timers. Conflicts: drivers/clocksource/clksrc-of.c Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt22
-rw-r--r--arch/arm/boot/dts/sun5i-a10s.dtsi7
-rw-r--r--arch/arm/boot/dts/sun5i-a13.dtsi7
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi10
-rw-r--r--arch/arm/mach-sunxi/Kconfig1
-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
24 files changed, 295 insertions, 47 deletions
diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
new file mode 100644
index 000000000000..7c26154b8bbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
@@ -0,0 +1,22 @@
1Allwinner SoCs High Speed Timer Controller
2
3Required properties:
4
5- compatible : should be "allwinner,sun5i-a13-hstimer" or
6 "allwinner,sun7i-a20-hstimer"
7- reg : Specifies base physical address and size of the registers.
8- interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i
9 one)
10- clocks: phandle to the source clock (usually the AHB clock)
11
12Example:
13
14timer@01c60000 {
15 compatible = "allwinner,sun7i-a20-hstimer";
16 reg = <0x01c60000 0x1000>;
17 interrupts = <0 51 1>,
18 <0 52 1>,
19 <0 53 1>,
20 <0 54 1>;
21 clocks = <&ahb1_gates 19>;
22};
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 52476742a104..e674c94c7206 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -332,5 +332,12 @@
332 clock-frequency = <100000>; 332 clock-frequency = <100000>;
333 status = "disabled"; 333 status = "disabled";
334 }; 334 };
335
336 timer@01c60000 {
337 compatible = "allwinner,sun5i-a13-hstimer";
338 reg = <0x01c60000 0x1000>;
339 interrupts = <82>, <83>;
340 clocks = <&ahb_gates 28>;
341 };
335 }; 342 };
336}; 343};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index ce8ef2a45be0..1ccd75d37f49 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -273,5 +273,12 @@
273 clock-frequency = <100000>; 273 clock-frequency = <100000>;
274 status = "disabled"; 274 status = "disabled";
275 }; 275 };
276
277 timer@01c60000 {
278 compatible = "allwinner,sun5i-a13-hstimer";
279 reg = <0x01c60000 0x1000>;
280 interrupts = <82>, <83>;
281 clocks = <&ahb_gates 28>;
282 };
276 }; 283 };
277}; 284};
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 367611a0730b..0135039eff96 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -395,6 +395,16 @@
395 status = "disabled"; 395 status = "disabled";
396 }; 396 };
397 397
398 hstimer@01c60000 {
399 compatible = "allwinner,sun7i-a20-hstimer";
400 reg = <0x01c60000 0x1000>;
401 interrupts = <0 81 1>,
402 <0 82 1>,
403 <0 83 1>,
404 <0 84 1>;
405 clocks = <&ahb_gates 28>;
406 };
407
398 gic: interrupt-controller@01c81000 { 408 gic: interrupt-controller@01c81000 {
399 compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; 409 compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
400 reg = <0x01c81000 0x1000>, 410 reg = <0x01c81000 0x1000>,
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index c9e72c89066a..bce0d4277f71 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -12,3 +12,4 @@ config ARCH_SUNXI
12 select PINCTRL_SUNXI 12 select PINCTRL_SUNXI
13 select SPARSE_IRQ 13 select SPARSE_IRQ
14 select SUN4I_TIMER 14 select SUN4I_TIMER
15 select SUN5I_HSTIMER
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 b2bb3a4bc205..8c7382bf260c 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -158,7 +158,7 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs)
158 TTC_COUNT_VAL_OFFSET); 158 TTC_COUNT_VAL_OFFSET);
159} 159}
160 160
161static u32 notrace ttc_sched_clock_read(void) 161static u64 notrace ttc_sched_clock_read(void)
162{ 162{
163 return __raw_readl(ttc_sched_clock_val_reg); 163 return __raw_readl(ttc_sched_clock_val_reg);
164} 164}
@@ -306,7 +306,7 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
306 } 306 }
307 307
308 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; 308 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
309 setup_sched_clock(ttc_sched_clock_read, 16, 309 sched_clock_register(ttc_sched_clock_read, 16,
310 clk_get_rate(ttccs->ttc.clk) / PRESCALE); 310 clk_get_rate(ttccs->ttc.clk) / PRESCALE);
311} 311}
312 312
@@ -388,8 +388,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
388 __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); 388 __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET);
389 389
390 err = request_irq(irq, ttc_clock_event_interrupt, 390 err = request_irq(irq, ttc_clock_event_interrupt,
391 IRQF_DISABLED | IRQF_TIMER, 391 IRQF_TIMER, ttcce->ce.name, ttcce);
392 ttcce->ce.name, ttcce);
393 if (WARN_ON(err)) { 392 if (WARN_ON(err)) {
394 kfree(ttcce); 393 kfree(ttcce);
395 return; 394 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..bddc52233d2a
--- /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 u32 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 setup_sched_clock(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};