aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-09 06:35:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-09 06:35:05 -0400
commit47137c6ba1bcde30215795f9594cea770946456b (patch)
tree3a7a04e6ecffcb188b6708ccdc3f02b70f07d7c4 /drivers/clocksource
parentafa3536be88b435a057cb727b48fd3d760a497d2 (diff)
parent867f667fb9c6734e06cc24e96fc7f06a7e772084 (diff)
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner: "Nothing really exciting this time: - a few fixlets in the NOHZ code - a new ARM SoC timer abomination. One should expect that we have enough of them already, but they insist on inventing new ones. - the usual bunch of ARM SoC timer updates. That feels like herding cats" * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: clocksource: arm_arch_timer: Consolidate arch_timer_evtstrm_enable clocksource: arm_arch_timer: Enable counter access for 32-bit ARM clocksource: arm_arch_timer: Change clocksource name if CP15 unavailable clocksource: sirf: Disable counter before re-setting it clocksource: cadence_ttc: Add support for 32bit mode clocksource: tcb_clksrc: Sanitize IRQ request clocksource: arm_arch_timer: Discard unavailable timers correctly clocksource: vf_pit_timer: Support shutdown mode ARM: meson6: clocksource: Add Meson6 timer support ARM: meson: documentation: Add timer documentation clocksource: sh_tmu: Document r8a7779 binding clocksource: sh_mtu2: Document r7s72100 binding clocksource: sh_cmt: Document SoC specific bindings timerfd: Remove an always true check nohz: Avoid tick's double reprogramming in highres mode nohz: Fix spurious periodic tick behaviour in low-res dynticks mode
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig3
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/arm_arch_timer.c64
-rw-r--r--drivers/clocksource/cadence_ttc_timer.c15
-rw-r--r--drivers/clocksource/meson6_timer.c167
-rw-r--r--drivers/clocksource/timer-marco.c5
-rw-r--r--drivers/clocksource/vf_pit_timer.c4
7 files changed, 247 insertions, 12 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 82a2ebe41e27..90420600e1eb 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -30,6 +30,9 @@ config ARMADA_370_XP_TIMER
30 bool 30 bool
31 select CLKSRC_OF 31 select CLKSRC_OF
32 32
33config MESON6_TIMER
34 bool
35
33config ORION_TIMER 36config ORION_TIMER
34 select CLKSRC_OF 37 select CLKSRC_OF
35 select CLKSRC_MMIO 38 select CLKSRC_MMIO
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index e566f6c7ded4..756f6f10efa0 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
26obj-$(CONFIG_ARCH_U300) += timer-u300.o 26obj-$(CONFIG_ARCH_U300) += timer-u300.o
27obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o 27obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
28obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o 28obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o
29obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o
29obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o 30obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
30obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o 31obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
31obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o 32obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5163ec13429d..2133f9d59d06 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -299,6 +299,21 @@ static void __arch_timer_setup(unsigned type,
299 clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); 299 clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
300} 300}
301 301
302static void arch_timer_evtstrm_enable(int divider)
303{
304 u32 cntkctl = arch_timer_get_cntkctl();
305
306 cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
307 /* Set the divider and enable virtual event stream */
308 cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
309 | ARCH_TIMER_VIRT_EVT_EN;
310 arch_timer_set_cntkctl(cntkctl);
311 elf_hwcap |= HWCAP_EVTSTRM;
312#ifdef CONFIG_COMPAT
313 compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
314#endif
315}
316
302static void arch_timer_configure_evtstream(void) 317static void arch_timer_configure_evtstream(void)
303{ 318{
304 int evt_stream_div, pos; 319 int evt_stream_div, pos;
@@ -312,6 +327,23 @@ static void arch_timer_configure_evtstream(void)
312 arch_timer_evtstrm_enable(min(pos, 15)); 327 arch_timer_evtstrm_enable(min(pos, 15));
313} 328}
314 329
330static void arch_counter_set_user_access(void)
331{
332 u32 cntkctl = arch_timer_get_cntkctl();
333
334 /* Disable user access to the timers and the physical counter */
335 /* Also disable virtual event stream */
336 cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
337 | ARCH_TIMER_USR_VT_ACCESS_EN
338 | ARCH_TIMER_VIRT_EVT_EN
339 | ARCH_TIMER_USR_PCT_ACCESS_EN);
340
341 /* Enable user access to the virtual counter */
342 cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
343
344 arch_timer_set_cntkctl(cntkctl);
345}
346
315static int arch_timer_setup(struct clock_event_device *clk) 347static int arch_timer_setup(struct clock_event_device *clk)
316{ 348{
317 __arch_timer_setup(ARCH_CP15_TIMER, clk); 349 __arch_timer_setup(ARCH_CP15_TIMER, clk);
@@ -429,11 +461,19 @@ static void __init arch_counter_register(unsigned type)
429 u64 start_count; 461 u64 start_count;
430 462
431 /* Register the CP15 based counter if we have one */ 463 /* Register the CP15 based counter if we have one */
432 if (type & ARCH_CP15_TIMER) 464 if (type & ARCH_CP15_TIMER) {
433 arch_timer_read_counter = arch_counter_get_cntvct; 465 arch_timer_read_counter = arch_counter_get_cntvct;
434 else 466 } else {
435 arch_timer_read_counter = arch_counter_get_cntvct_mem; 467 arch_timer_read_counter = arch_counter_get_cntvct_mem;
436 468
469 /* If the clocksource name is "arch_sys_counter" the
470 * VDSO will attempt to read the CP15-based counter.
471 * Ensure this does not happen when CP15-based
472 * counter is not available.
473 */
474 clocksource_counter.name = "arch_mem_counter";
475 }
476
437 start_count = arch_timer_read_counter(); 477 start_count = arch_timer_read_counter();
438 clocksource_register_hz(&clocksource_counter, arch_timer_rate); 478 clocksource_register_hz(&clocksource_counter, arch_timer_rate);
439 cyclecounter.mult = clocksource_counter.mult; 479 cyclecounter.mult = clocksource_counter.mult;
@@ -616,17 +656,29 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
616 {}, 656 {},
617}; 657};
618 658
659static bool __init
660arch_timer_probed(int type, const struct of_device_id *matches)
661{
662 struct device_node *dn;
663 bool probed = false;
664
665 dn = of_find_matching_node(NULL, matches);
666 if (dn && of_device_is_available(dn) && (arch_timers_present & type))
667 probed = true;
668 of_node_put(dn);
669
670 return probed;
671}
672
619static void __init arch_timer_common_init(void) 673static void __init arch_timer_common_init(void)
620{ 674{
621 unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; 675 unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER;
622 676
623 /* Wait until both nodes are probed if we have two timers */ 677 /* Wait until both nodes are probed if we have two timers */
624 if ((arch_timers_present & mask) != mask) { 678 if ((arch_timers_present & mask) != mask) {
625 if (of_find_matching_node(NULL, arch_timer_mem_of_match) && 679 if (!arch_timer_probed(ARCH_MEM_TIMER, arch_timer_mem_of_match))
626 !(arch_timers_present & ARCH_MEM_TIMER))
627 return; 680 return;
628 if (of_find_matching_node(NULL, arch_timer_of_match) && 681 if (!arch_timer_probed(ARCH_CP15_TIMER, arch_timer_of_match))
629 !(arch_timers_present & ARCH_CP15_TIMER))
630 return; 682 return;
631 } 683 }
632 684
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index 7a08811df9aa..510c8a1d37b3 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -25,7 +25,7 @@
25#include <linux/sched_clock.h> 25#include <linux/sched_clock.h>
26 26
27/* 27/*
28 * This driver configures the 2 16-bit count-up timers as follows: 28 * This driver configures the 2 16/32-bit count-up timers as follows:
29 * 29 *
30 * T1: Timer 1, clocksource for generic timekeeping 30 * T1: Timer 1, clocksource for generic timekeeping
31 * T2: Timer 2, clockevent source for hrtimers 31 * T2: Timer 2, clockevent source for hrtimers
@@ -321,7 +321,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
321 return NOTIFY_DONE; 321 return NOTIFY_DONE;
322} 322}
323 323
324static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) 324static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base,
325 u32 timer_width)
325{ 326{
326 struct ttc_timer_clocksource *ttccs; 327 struct ttc_timer_clocksource *ttccs;
327 int err; 328 int err;
@@ -351,7 +352,7 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
351 ttccs->cs.name = "ttc_clocksource"; 352 ttccs->cs.name = "ttc_clocksource";
352 ttccs->cs.rating = 200; 353 ttccs->cs.rating = 200;
353 ttccs->cs.read = __ttc_clocksource_read; 354 ttccs->cs.read = __ttc_clocksource_read;
354 ttccs->cs.mask = CLOCKSOURCE_MASK(16); 355 ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width);
355 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; 356 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
356 357
357 /* 358 /*
@@ -372,7 +373,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
372 } 373 }
373 374
374 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; 375 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
375 sched_clock_register(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE); 376 sched_clock_register(ttc_sched_clock_read, timer_width,
377 ttccs->ttc.freq / PRESCALE);
376} 378}
377 379
378static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, 380static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
@@ -467,6 +469,7 @@ static void __init ttc_timer_init(struct device_node *timer)
467 struct clk *clk_cs, *clk_ce; 469 struct clk *clk_cs, *clk_ce;
468 static int initialized; 470 static int initialized;
469 int clksel; 471 int clksel;
472 u32 timer_width = 16;
470 473
471 if (initialized) 474 if (initialized)
472 return; 475 return;
@@ -490,6 +493,8 @@ static void __init ttc_timer_init(struct device_node *timer)
490 BUG(); 493 BUG();
491 } 494 }
492 495
496 of_property_read_u32(timer, "timer-width", &timer_width);
497
493 clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); 498 clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET);
494 clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); 499 clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK);
495 clk_cs = of_clk_get(timer, clksel); 500 clk_cs = of_clk_get(timer, clksel);
@@ -506,7 +511,7 @@ static void __init ttc_timer_init(struct device_node *timer)
506 BUG(); 511 BUG();
507 } 512 }
508 513
509 ttc_setup_clocksource(clk_cs, timer_baseaddr); 514 ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
510 ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); 515 ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
511 516
512 pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); 517 pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq);
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c
new file mode 100644
index 000000000000..5c15cba41dca
--- /dev/null
+++ b/drivers/clocksource/meson6_timer.c
@@ -0,0 +1,167 @@
1/*
2 * Amlogic Meson6 SoCs timer handling.
3 *
4 * Copyright (C) 2014 Carlo Caione <carlo@caione.org>
5 *
6 * Based on code from Amlogic, Inc
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/interrupt.h>
16#include <linux/irq.h>
17#include <linux/irqreturn.h>
18#include <linux/sched_clock.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22
23#define CED_ID 0
24#define CSD_ID 4
25
26#define TIMER_ISA_MUX 0
27#define TIMER_ISA_VAL(t) (((t) + 1) << 2)
28
29#define TIMER_INPUT_BIT(t) (2 * (t))
30#define TIMER_ENABLE_BIT(t) (16 + (t))
31#define TIMER_PERIODIC_BIT(t) (12 + (t))
32
33#define TIMER_CED_INPUT_MASK (3UL << TIMER_INPUT_BIT(CED_ID))
34#define TIMER_CSD_INPUT_MASK (7UL << TIMER_INPUT_BIT(CSD_ID))
35
36#define TIMER_CED_UNIT_1US 0
37#define TIMER_CSD_UNIT_1US 1
38
39static void __iomem *timer_base;
40
41static u64 notrace meson6_timer_sched_read(void)
42{
43 return (u64)readl(timer_base + TIMER_ISA_VAL(CSD_ID));
44}
45
46static void meson6_clkevt_time_stop(unsigned char timer)
47{
48 u32 val = readl(timer_base + TIMER_ISA_MUX);
49
50 writel(val & ~TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX);
51}
52
53static void meson6_clkevt_time_setup(unsigned char timer, unsigned long delay)
54{
55 writel(delay, timer_base + TIMER_ISA_VAL(timer));
56}
57
58static void meson6_clkevt_time_start(unsigned char timer, bool periodic)
59{
60 u32 val = readl(timer_base + TIMER_ISA_MUX);
61
62 if (periodic)
63 val |= TIMER_PERIODIC_BIT(timer);
64 else
65 val &= ~TIMER_PERIODIC_BIT(timer);
66
67 writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX);
68}
69
70static void meson6_clkevt_mode(enum clock_event_mode mode,
71 struct clock_event_device *clk)
72{
73 switch (mode) {
74 case CLOCK_EVT_MODE_PERIODIC:
75 meson6_clkevt_time_stop(CED_ID);
76 meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC/HZ - 1);
77 meson6_clkevt_time_start(CED_ID, true);
78 break;
79 case CLOCK_EVT_MODE_ONESHOT:
80 meson6_clkevt_time_stop(CED_ID);
81 meson6_clkevt_time_start(CED_ID, false);
82 break;
83 case CLOCK_EVT_MODE_UNUSED:
84 case CLOCK_EVT_MODE_SHUTDOWN:
85 default:
86 meson6_clkevt_time_stop(CED_ID);
87 break;
88 }
89}
90
91static int meson6_clkevt_next_event(unsigned long evt,
92 struct clock_event_device *unused)
93{
94 meson6_clkevt_time_stop(CED_ID);
95 meson6_clkevt_time_setup(CED_ID, evt);
96 meson6_clkevt_time_start(CED_ID, false);
97
98 return 0;
99}
100
101static struct clock_event_device meson6_clockevent = {
102 .name = "meson6_tick",
103 .rating = 400,
104 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
105 .set_mode = meson6_clkevt_mode,
106 .set_next_event = meson6_clkevt_next_event,
107};
108
109static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id)
110{
111 struct clock_event_device *evt = (struct clock_event_device *)dev_id;
112
113 evt->event_handler(evt);
114
115 return IRQ_HANDLED;
116}
117
118static struct irqaction meson6_timer_irq = {
119 .name = "meson6_timer",
120 .flags = IRQF_TIMER | IRQF_IRQPOLL,
121 .handler = meson6_timer_interrupt,
122 .dev_id = &meson6_clockevent,
123};
124
125static void __init meson6_timer_init(struct device_node *node)
126{
127 u32 val;
128 int ret, irq;
129
130 timer_base = of_io_request_and_map(node, 0, "meson6-timer");
131 if (IS_ERR(timer_base))
132 panic("Can't map registers");
133
134 irq = irq_of_parse_and_map(node, 0);
135 if (irq <= 0)
136 panic("Can't parse IRQ");
137
138 /* Set 1us for timer E */
139 val = readl(timer_base + TIMER_ISA_MUX);
140 val &= ~TIMER_CSD_INPUT_MASK;
141 val |= TIMER_CSD_UNIT_1US << TIMER_INPUT_BIT(CSD_ID);
142 writel(val, timer_base + TIMER_ISA_MUX);
143
144 sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC);
145 clocksource_mmio_init(timer_base + TIMER_ISA_VAL(CSD_ID), node->name,
146 1000 * 1000, 300, 32, clocksource_mmio_readl_up);
147
148 /* Timer A base 1us */
149 val &= ~TIMER_CED_INPUT_MASK;
150 val |= TIMER_CED_UNIT_1US << TIMER_INPUT_BIT(CED_ID);
151 writel(val, timer_base + TIMER_ISA_MUX);
152
153 /* Stop the timer A */
154 meson6_clkevt_time_stop(CED_ID);
155
156 ret = setup_irq(irq, &meson6_timer_irq);
157 if (ret)
158 pr_warn("failed to setup irq %d\n", irq);
159
160 meson6_clockevent.cpumask = cpu_possible_mask;
161 meson6_clockevent.irq = irq;
162
163 clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC,
164 1, 0xfffe);
165}
166CLOCKSOURCE_OF_DECLARE(meson6, "amlogic,meson6-timer",
167 meson6_timer_init);
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index 330e93064692..caf7a2030461 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -63,7 +63,7 @@ static inline void sirfsoc_timer_count_disable(int idx)
63/* enable count and interrupt */ 63/* enable count and interrupt */
64static inline void sirfsoc_timer_count_enable(int idx) 64static inline void sirfsoc_timer_count_enable(int idx)
65{ 65{
66 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7, 66 writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x3,
67 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx); 67 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
68} 68}
69 69
@@ -103,6 +103,9 @@ static int sirfsoc_timer_set_next_event(unsigned long delta,
103{ 103{
104 int cpu = smp_processor_id(); 104 int cpu = smp_processor_id();
105 105
106 /* disable timer first, then modify the related registers */
107 sirfsoc_timer_count_disable(cpu);
108
106 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 + 109 writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
107 4 * cpu); 110 4 * cpu);
108 writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 + 111 writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index a918bc481c52..b45ac6229b57 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -93,6 +93,10 @@ static void pit_set_mode(enum clock_event_mode mode,
93 case CLOCK_EVT_MODE_PERIODIC: 93 case CLOCK_EVT_MODE_PERIODIC:
94 pit_set_next_event(cycle_per_jiffy, evt); 94 pit_set_next_event(cycle_per_jiffy, evt);
95 break; 95 break;
96 case CLOCK_EVT_MODE_SHUTDOWN:
97 case CLOCK_EVT_MODE_UNUSED:
98 pit_timer_disable();
99 break;
96 default: 100 default:
97 break; 101 break;
98 } 102 }