diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 14:34:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 14:34:26 -0500 |
commit | 6c6461435611e1d4843516f2d55e8316c009112e (patch) | |
tree | 2285f7ef3257dcb30342f931430ad755fc5d299b /drivers/clocksource | |
parent | a0fa1dd3cdbccec9597fe53b6177a9aa6e20f2f8 (diff) | |
parent | 00e2bcd6d35f59fce7fa0e76e24d08f74c6a8506 (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/Kconfig | 4 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/arm_global_timer.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/bcm_kona_timer.c | 6 | ||||
-rw-r--r-- | drivers/clocksource/cadence_ttc_timer.c | 7 | ||||
-rw-r--r-- | drivers/clocksource/clksrc-of.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/cs5535-clockevt.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/dw_apb_timer.c | 3 | ||||
-rw-r--r-- | drivers/clocksource/nomadik-mtu.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/samsung_pwm_timer.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 23 | ||||
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/sh_tmu.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/sun4i_timer.c | 11 | ||||
-rw-r--r-- | drivers/clocksource/tegra20_timer.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/time-armada-370-xp.c | 18 | ||||
-rw-r--r-- | drivers/clocksource/time-orion.c | 4 | ||||
-rw-r--r-- | drivers/clocksource/timer-sun5i.c | 192 | ||||
-rw-r--r-- | drivers/clocksource/vt8500_timer.c | 2 |
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 | ||
40 | config SUN5I_HSTIMER | ||
41 | select CLKSRC_MMIO | ||
42 | bool | ||
43 | |||
40 | config VT8500_TIMER | 44 | config 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 | |||
22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o | 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | 23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o |
24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
25 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o | ||
25 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 26 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
26 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 27 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
27 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o | 28 | obj-$(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 |
205 | static u32 notrace gt_sched_clock_read(void) | 205 | static 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(>_clocksource, gt_clk_rate); | 222 | clocksource_register_hz(>_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 | ||
101 | static const struct of_device_id bcm_timer_ids[] __initconst = { | ||
102 | {.compatible = "brcm,kona-timer"}, | ||
103 | {.compatible = "bcm,kona-timer"}, /* deprecated name */ | ||
104 | {}, | ||
105 | }; | ||
106 | |||
107 | static void __init kona_timers_init(struct device_node *node) | 101 | static 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 | ||
163 | static u32 notrace ttc_sched_clock_read(void) | 163 | static 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 | ||
314 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | 314 | static 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 | ||
132 | static struct irqaction mfgptirq = { | 132 | static 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 | ||
188 | static struct irqaction nmdk_timer_irq = { | 188 | static 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 | ||
265 | static struct irqaction samsung_clock_event_irq = { | 265 | static 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 | ||
635 | static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) | 635 | static 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 | ||
640 | static void sh_cmt_clock_event_resume(struct clock_event_device *ced) | 643 | static 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 | ||
645 | static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, | 651 | static 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; |
798 | err4: | ||
799 | clk_unprepare(p->clk); | ||
789 | err3: | 800 | err3: |
790 | clk_put(p->clk); | 801 | clk_put(p->clk); |
791 | err2: | 802 | err2: |
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 | ||
115 | static struct clock_event_device sun4i_clockevent = { | 115 | static 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 | ||
141 | static u32 sun4i_timer_sched_read(void) | 141 | static 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 | ||
150 | static struct irqaction tegra_timer_irq = { | 150 | static 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 @@ | |||
76 | static void __iomem *timer_base, *local_base; | 76 | static void __iomem *timer_base, *local_base; |
77 | static unsigned int timer_clk; | 77 | static unsigned int timer_clk; |
78 | static bool timer25Mhz = true; | 78 | static bool timer25Mhz = true; |
79 | static 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 | */ |
56 | static u32 notrace orion_read_sched_clock(void) | 56 | static 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 | |||
39 | static void __iomem *timer_base; | ||
40 | static 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 | */ | ||
48 | static 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 | |||
56 | static 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 | |||
64 | static void sun5i_clkevt_time_setup(u8 timer, u32 delay) | ||
65 | { | ||
66 | writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer)); | ||
67 | } | ||
68 | |||
69 | static 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 | |||
82 | static 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 | |||
103 | static 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 | |||
113 | static 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 | |||
122 | static 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 | |||
132 | static 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 | |||
139 | static u64 sun5i_timer_sched_read(void) | ||
140 | { | ||
141 | return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1)); | ||
142 | } | ||
143 | |||
144 | static 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 | } | ||
189 | CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", | ||
190 | sun5i_timer_init); | ||
191 | CLOCKSOURCE_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 | ||
125 | static struct irqaction irq = { | 125 | static 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 | }; |