Skip to content

Commit

Permalink
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Oct 9, 2014
2 parents afa3536 + 867f667 commit 47137c6
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 80 deletions.
15 changes: 15 additions & 0 deletions Documentation/devicetree/bindings/timer/amlogic,meson6-timer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Amlogic Meson6 SoCs Timer Controller

Required properties:

- compatible : should be "amlogic,meson6-timer"
- reg : Specifies base physical address and size of the registers.
- interrupts : The interrupt of the first timer

Example:

timer@c1109940 {
compatible = "amlogic,meson6-timer";
reg = <0xc1109940 0x14>;
interrupts = <0 10 1>;
};
44 changes: 38 additions & 6 deletions Documentation/devicetree/bindings/timer/renesas,cmt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,47 @@ datasheets.

Required Properties:

- compatible: must contain one of the following.
- "renesas,cmt-32" for the 32-bit CMT
- compatible: must contain one or more of the following:
- "renesas,cmt-32-r8a7740" for the r8a7740 32-bit CMT
(CMT0)
- "renesas,cmt-32-sh7372" for the sh7372 32-bit CMT
(CMT0)
- "renesas,cmt-32-sh73a0" for the sh73a0 32-bit CMT
(CMT0)
- "renesas,cmt-32" for all 32-bit CMT without fast clock support
(CMT0 on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
This is a fallback for the above renesas,cmt-32-* entries.

- "renesas,cmt-32-fast-r8a7740" for the r8a7740 32-bit CMT with fast
clock support (CMT[234])
- "renesas,cmt-32-fast-sh7372" for the sh7372 32-bit CMT with fast
clock support (CMT[234])
- "renesas,cmt-32-fast-sh73a0" for the sh73A0 32-bit CMT with fast
clock support (CMT[234])
- "renesas,cmt-32-fast" for all 32-bit CMT with fast clock support
(CMT[234] on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-48" for the 48-bit CMT
This is a fallback for the above renesas,cmt-32-fast-* entries.

- "renesas,cmt-48-sh7372" for the sh7372 48-bit CMT
(CMT1)
- "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT
(CMT1)
- "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT
(CMT1)
- "renesas,cmt-48" for all non-second generation 48-bit CMT
(CMT1 on sh7372, sh73a0 and r8a7740)
- "renesas,cmt-48-gen2" for the second generation 48-bit CMT
This is a fallback for the above renesas,cmt-48-* entries.

- "renesas,cmt-48-r8a73a4" for the r8a73a4 48-bit CMT
(CMT[01])
- "renesas,cmt-48-r8a7790" for the r8a7790 48-bit CMT
(CMT[01])
- "renesas,cmt-48-r8a7791" for the r8a7791 48-bit CMT
(CMT[01])
- "renesas,cmt-48-gen2" for all second generation 48-bit CMT
(CMT[01] on r8a73a4, r8a7790 and r8a7791)
This is a fallback for the renesas,cmt-48-r8a73a4,
renesas,cmt-48-r8a7790 and renesas,cmt-48-r8a7791 entries.

- reg: base address and length of the registers block for the timer module.
- interrupts: interrupt-specifier for the timer, one per channel.
Expand All @@ -36,7 +68,7 @@ Example: R8A7790 (R-Car H2) CMT0 node
them channels 0 and 1 in the documentation.

cmt0: timer@ffca0000 {
compatible = "renesas,cmt-48-gen2";
compatible = "renesas,cmt-48-r8a7790", "renesas,cmt-48-gen2";
reg = <0 0xffca0000 0 0x1004>;
interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
<0 142 IRQ_TYPE_LEVEL_HIGH>;
Expand Down
7 changes: 5 additions & 2 deletions Documentation/devicetree/bindings/timer/renesas,mtu2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ are independent. The MTU2 hardware supports five channels indexed from 0 to 4.

Required Properties:

- compatible: must contain "renesas,mtu2"
- compatible: must be one or more of the following:
- "renesas,mtu2-r7s72100" for the r7s72100 MTU2
- "renesas,mtu2" for any MTU2
This is a fallback for the above renesas,mtu2-* entries

- reg: base address and length of the registers block for the timer module.

Expand All @@ -26,7 +29,7 @@ Required Properties:
Example: R7S72100 (RZ/A1H) MTU2 node

mtu2: timer@fcff0000 {
compatible = "renesas,mtu2";
compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
reg = <0xfcff0000 0x400>;
interrupts = <0 139 IRQ_TYPE_LEVEL_HIGH>,
<0 146 IRQ_TYPE_LEVEL_HIGH>,
Expand Down
7 changes: 5 additions & 2 deletions Documentation/devicetree/bindings/timer/renesas,tmu.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ are independent. The TMU hardware supports up to three channels.

Required Properties:

- compatible: must contain "renesas,tmu"
- compatible: must contain one or more of the following:
- "renesas,tmu-r8a7779" for the r8a7779 TMU
- "renesas,tmu" for any TMU.
This is a fallback for the above renesas,tmu-* entries

- reg: base address and length of the registers block for the timer module.

Expand All @@ -27,7 +30,7 @@ Optional Properties:
Example: R8A7779 (R-Car H1) TMU0 node

tmu0: timer@ffd80000 {
compatible = "renesas,tmu";
compatible = "renesas,tmu-r8a7779", "renesas,tmu";
reg = <0xffd80000 0x30>;
interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
<0 33 IRQ_TYPE_LEVEL_HIGH>,
Expand Down
25 changes: 0 additions & 25 deletions arch/arm/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,31 +99,6 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
}

static inline void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();

/* Disable user access to both physical/virtual counters/timers */
/* Also disable virtual event stream */
cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
| ARCH_TIMER_USR_VT_ACCESS_EN
| ARCH_TIMER_VIRT_EVT_EN
| ARCH_TIMER_USR_VCT_ACCESS_EN
| ARCH_TIMER_USR_PCT_ACCESS_EN);
arch_timer_set_cntkctl(cntkctl);
}

static inline void arch_timer_evtstrm_enable(int divider)
{
u32 cntkctl = arch_timer_get_cntkctl();
cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
/* Set the divider and enable virtual event stream */
cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
| ARCH_TIMER_VIRT_EVT_EN;
arch_timer_set_cntkctl(cntkctl);
elf_hwcap |= HWCAP_EVTSTRM;
}

#endif

#endif
31 changes: 0 additions & 31 deletions arch/arm64/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,37 +104,6 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl));
}

static inline void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();

/* Disable user access to the timers and the physical counter */
/* Also disable virtual event stream */
cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
| ARCH_TIMER_USR_VT_ACCESS_EN
| ARCH_TIMER_VIRT_EVT_EN
| ARCH_TIMER_USR_PCT_ACCESS_EN);

/* Enable user access to the virtual counter */
cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;

arch_timer_set_cntkctl(cntkctl);
}

static inline void arch_timer_evtstrm_enable(int divider)
{
u32 cntkctl = arch_timer_get_cntkctl();
cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
/* Set the divider and enable virtual event stream */
cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
| ARCH_TIMER_VIRT_EVT_EN;
arch_timer_set_cntkctl(cntkctl);
elf_hwcap |= HWCAP_EVTSTRM;
#ifdef CONFIG_COMPAT
compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
#endif
}

static inline u64 arch_counter_get_cntvct(void)
{
u64 cval;
Expand Down
3 changes: 3 additions & 0 deletions drivers/clocksource/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ config ARMADA_370_XP_TIMER
bool
select CLKSRC_OF

config MESON6_TIMER
bool

config ORION_TIMER
select CLKSRC_OF
select CLKSRC_MMIO
Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
obj-$(CONFIG_ARCH_U300) += timer-u300.o
obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o
obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o
obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
Expand Down
64 changes: 58 additions & 6 deletions drivers/clocksource/arm_arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,21 @@ static void __arch_timer_setup(unsigned type,
clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
}

static void arch_timer_evtstrm_enable(int divider)
{
u32 cntkctl = arch_timer_get_cntkctl();

cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
/* Set the divider and enable virtual event stream */
cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
| ARCH_TIMER_VIRT_EVT_EN;
arch_timer_set_cntkctl(cntkctl);
elf_hwcap |= HWCAP_EVTSTRM;
#ifdef CONFIG_COMPAT
compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
#endif
}

static void arch_timer_configure_evtstream(void)
{
int evt_stream_div, pos;
Expand All @@ -312,6 +327,23 @@ static void arch_timer_configure_evtstream(void)
arch_timer_evtstrm_enable(min(pos, 15));
}

static void arch_counter_set_user_access(void)
{
u32 cntkctl = arch_timer_get_cntkctl();

/* Disable user access to the timers and the physical counter */
/* Also disable virtual event stream */
cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
| ARCH_TIMER_USR_VT_ACCESS_EN
| ARCH_TIMER_VIRT_EVT_EN
| ARCH_TIMER_USR_PCT_ACCESS_EN);

/* Enable user access to the virtual counter */
cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;

arch_timer_set_cntkctl(cntkctl);
}

static int arch_timer_setup(struct clock_event_device *clk)
{
__arch_timer_setup(ARCH_CP15_TIMER, clk);
Expand Down Expand Up @@ -429,11 +461,19 @@ static void __init arch_counter_register(unsigned type)
u64 start_count;

/* Register the CP15 based counter if we have one */
if (type & ARCH_CP15_TIMER)
if (type & ARCH_CP15_TIMER) {
arch_timer_read_counter = arch_counter_get_cntvct;
else
} else {
arch_timer_read_counter = arch_counter_get_cntvct_mem;

/* If the clocksource name is "arch_sys_counter" the
* VDSO will attempt to read the CP15-based counter.
* Ensure this does not happen when CP15-based
* counter is not available.
*/
clocksource_counter.name = "arch_mem_counter";
}

start_count = arch_timer_read_counter();
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
cyclecounter.mult = clocksource_counter.mult;
Expand Down Expand Up @@ -616,17 +656,29 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
{},
};

static bool __init
arch_timer_probed(int type, const struct of_device_id *matches)
{
struct device_node *dn;
bool probed = false;

dn = of_find_matching_node(NULL, matches);
if (dn && of_device_is_available(dn) && (arch_timers_present & type))
probed = true;
of_node_put(dn);

return probed;
}

static void __init arch_timer_common_init(void)
{
unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER;

/* Wait until both nodes are probed if we have two timers */
if ((arch_timers_present & mask) != mask) {
if (of_find_matching_node(NULL, arch_timer_mem_of_match) &&
!(arch_timers_present & ARCH_MEM_TIMER))
if (!arch_timer_probed(ARCH_MEM_TIMER, arch_timer_mem_of_match))
return;
if (of_find_matching_node(NULL, arch_timer_of_match) &&
!(arch_timers_present & ARCH_CP15_TIMER))
if (!arch_timer_probed(ARCH_CP15_TIMER, arch_timer_of_match))
return;
}

Expand Down
15 changes: 10 additions & 5 deletions drivers/clocksource/cadence_ttc_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <linux/sched_clock.h>

/*
* This driver configures the 2 16-bit count-up timers as follows:
* This driver configures the 2 16/32-bit count-up timers as follows:
*
* T1: Timer 1, clocksource for generic timekeeping
* T2: Timer 2, clockevent source for hrtimers
Expand Down Expand Up @@ -321,7 +321,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
return NOTIFY_DONE;
}

static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base,
u32 timer_width)
{
struct ttc_timer_clocksource *ttccs;
int err;
Expand Down Expand Up @@ -351,7 +352,7 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
ttccs->cs.name = "ttc_clocksource";
ttccs->cs.rating = 200;
ttccs->cs.read = __ttc_clocksource_read;
ttccs->cs.mask = CLOCKSOURCE_MASK(16);
ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width);
ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;

/*
Expand All @@ -372,7 +373,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
}

ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
sched_clock_register(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE);
sched_clock_register(ttc_sched_clock_read, timer_width,
ttccs->ttc.freq / PRESCALE);
}

static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
Expand Down Expand Up @@ -467,6 +469,7 @@ static void __init ttc_timer_init(struct device_node *timer)
struct clk *clk_cs, *clk_ce;
static int initialized;
int clksel;
u32 timer_width = 16;

if (initialized)
return;
Expand All @@ -490,6 +493,8 @@ static void __init ttc_timer_init(struct device_node *timer)
BUG();
}

of_property_read_u32(timer, "timer-width", &timer_width);

clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET);
clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK);
clk_cs = of_clk_get(timer, clksel);
Expand All @@ -506,7 +511,7 @@ static void __init ttc_timer_init(struct device_node *timer)
BUG();
}

ttc_setup_clocksource(clk_cs, timer_baseaddr);
ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);

pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq);
Expand Down
Loading

0 comments on commit 47137c6

Please sign in to comment.