aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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};