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 changes from Ingo Molnar:
 "Main changes in this cycle were:

   - Updated full dynticks support.

   - Event stream support for architected (ARM) timers.

   - ARM clocksource driver updates.

   - Move arm64 to using the generic sched_clock framework & resulting
     cleanup in the generic sched_clock code.

   - Misc fixes and cleanups"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (50 commits)
  x86/time: Honor ACPI FADT flag indicating absence of a CMOS RTC
  clocksource: sun4i: remove IRQF_DISABLED
  clocksource: sun4i: Report the minimum tick that we can program
  clocksource: sun4i: Select CLKSRC_MMIO
  clocksource: Provide timekeeping for efm32 SoCs
  clocksource: em_sti: convert to clk_prepare/unprepare
  time: Fix signedness bug in sysfs_get_uname() and its callers
  timekeeping: Fix some trivial typos in comments
  alarmtimer: return EINVAL instead of ENOTSUPP if rtcdev doesn't exist
  clocksource: arch_timer: Do not register arch_sys_counter twice
  timer stats: Add a 'Collection: active/inactive' line to timer usage statistics
  sched_clock: Remove sched_clock_func() hook
  arch_timer: Move to generic sched_clock framework
  clocksource: tcb_clksrc: Remove IRQF_DISABLED
  clocksource: tcb_clksrc: Improve driver robustness
  clocksource: tcb_clksrc: Replace clk_enable/disable with clk_prepare_enable/disable_unprepare
  clocksource: arm_arch_timer: Use clocksource for suspend timekeeping
  clocksource: dw_apb_timer_of: Mark a few more functions as __init
  clocksource: Put nodes passed to CLOCKSOURCE_OF_DECLARE callbacks centrally
  arm: zynq: Enable arm_global_timer
  ...
  • Loading branch information
torvalds committed Nov 12, 2013
2 parents 39cf275 + ee5872b commit 8709382
Show file tree
Hide file tree
Showing 54 changed files with 717 additions and 189 deletions.
23 changes: 23 additions & 0 deletions Documentation/devicetree/bindings/timer/efm32,timer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
* EFM32 timer hardware

The efm32 Giant Gecko SoCs come with four 16 bit timers. Two counters can be
connected to form a 32 bit counter. Each timer has three Compare/Capture
channels and can be used as PWM or Quadrature Decoder. Available clock sources
are the cpu's HFPERCLK (with a 10-bit prescaler) or an external pin.

Required properties:
- compatible : Should be efm32,timer
- reg : Address and length of the register set
- clocks : Should contain a reference to the HFPERCLK

Optional properties:
- interrupts : Reference to the timer interrupt

Example:

timer@40010c00 {
compatible = "efm32,timer";
reg = <0x40010c00 0x400>;
interrupts = <14>;
clocks = <&cmu clk_HFPERCLKTIMER3>;
};
12 changes: 12 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,18 @@ config HAVE_CONTEXT_TRACKING
config HAVE_VIRT_CPU_ACCOUNTING
bool

config HAVE_VIRT_CPU_ACCOUNTING_GEN
bool
default y if 64BIT
help
With VIRT_CPU_ACCOUNTING_GEN, cputime_t becomes 64-bit.
Before enabling this option, arch code must be audited
to ensure there are no races in concurrent read/write of
cputime_t. For example, reading/writing 64-bit cputime_t on
some 32-bit arches may require multiple accesses, so proper
locking is needed to protect against concurrent accesses.


config HAVE_IRQ_TIME_ACCOUNTING
bool
help
Expand Down
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ config ARM
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select IRQ_FORCED_THREADING
select KTIME_SCALAR
select MODULES_USE_ELF_REL
Expand Down
8 changes: 8 additions & 0 deletions arch/arm/boot/dts/zynq-7000.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@
};
};

global_timer: timer@f8f00200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xf8f00200 0x20>;
interrupts = <1 11 0x301>;
interrupt-parent = <&intc>;
clocks = <&clkc 4>;
};

ttc0: ttc0@f8001000 {
interrupt-parent = <&intc>;
interrupts = < 0 10 4 0 11 4 0 12 4 >;
Expand Down
36 changes: 31 additions & 5 deletions arch/arm/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,43 @@ static inline u64 arch_counter_get_cntvct(void)
return cval;
}

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

asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
return cntkctl;
}

/* disable user access to everything */
cntkctl &= ~((3 << 8) | (7 << 0));

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
1 change: 1 addition & 0 deletions arch/arm/include/uapi/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */
#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
#define HWCAP_LPAE (1 << 20)
#define HWCAP_EVTSTRM (1 << 21)

#endif /* _UAPI__ASMARM_HWCAP_H */
14 changes: 0 additions & 14 deletions arch/arm/kernel/arch_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched_clock.h>

#include <asm/delay.h>

Expand All @@ -22,13 +21,6 @@ static unsigned long arch_timer_read_counter_long(void)
return arch_timer_read_counter();
}

static u32 sched_clock_mult __read_mostly;

static unsigned long long notrace arch_timer_sched_clock(void)
{
return arch_timer_read_counter() * sched_clock_mult;
}

static struct delay_timer arch_delay_timer;

static void __init arch_timer_delay_timer_register(void)
Expand All @@ -48,11 +40,5 @@ int __init arch_timer_arch_init(void)

arch_timer_delay_timer_register();

/* Cache the sched_clock multiplier to save a divide in the hot path. */
sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
sched_clock_func = arch_timer_sched_clock;
pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n",
arch_timer_rate / 1000, sched_clock_mult);

return 0;
}
1 change: 1 addition & 0 deletions arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,7 @@ static const char *hwcap_str[] = {
"idivt",
"vfpd32",
"lpae",
"evtstrm",
NULL
};

Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-msm/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ static void __init msm_dt_timer_init(struct device_node *np)
pr_err("Unknown frequency\n");
return;
}
of_node_put(np);

event_base = base + 0x4;
sts_base = base + 0x88;
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-zynq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ config ARCH_ZYNQ
select HAVE_SMP
select SPARSE_IRQ
select CADENCE_TTC_TIMER
select ARM_GLOBAL_TIMER
help
Support for Xilinx Zynq ARM Cortex A9 Platform
1 change: 1 addition & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ config ARM64
select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select HARDIRQS_SW_RESEND
Expand Down
42 changes: 36 additions & 6 deletions arch/arm64/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,49 @@ static inline u32 arch_timer_get_cntfrq(void)
return val;
}

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

/* Disable user access to the timers and the physical counter. */
asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl));
cntkctl &= ~((3 << 8) | (1 << 0));
return cntkctl;
}

/* Enable user access to the virtual counter and frequency. */
cntkctl |= (1 << 1);
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
11 changes: 6 additions & 5 deletions arch/arm64/include/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@
#define COMPAT_HWCAP_IDIVA (1 << 17)
#define COMPAT_HWCAP_IDIVT (1 << 18)
#define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
#define COMPAT_HWCAP_EVTSTRM (1 << 21)

#ifndef __ASSEMBLY__
/*
* This yields a mask that user programs can use to figure out what
* instruction set this cpu supports.
*/
#define ELF_HWCAP (elf_hwcap)
#define COMPAT_ELF_HWCAP (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)

#ifdef CONFIG_COMPAT
#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
extern unsigned int compat_elf_hwcap;
#endif

extern unsigned long elf_hwcap;
#endif
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/uapi/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/
#define HWCAP_FP (1 << 0)
#define HWCAP_ASIMD (1 << 1)
#define HWCAP_EVTSTRM (1 << 2)


#endif /* _UAPI__ASM_HWCAP_H */
11 changes: 11 additions & 0 deletions arch/arm64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ EXPORT_SYMBOL(processor_id);
unsigned long elf_hwcap __read_mostly;
EXPORT_SYMBOL_GPL(elf_hwcap);

#ifdef CONFIG_COMPAT
#define COMPAT_ELF_HWCAP_DEFAULT \
(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
#endif

static const char *cpu_name;
static const char *machine_name;
phys_addr_t __fdt_pointer __initdata;
Expand Down Expand Up @@ -311,6 +321,7 @@ subsys_initcall(topology_init);
static const char *hwcap_str[] = {
"fp",
"asimd",
"evtstrm",
NULL
};

Expand Down
10 changes: 0 additions & 10 deletions arch/arm64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,6 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc);
#endif

static u64 sched_clock_mult __read_mostly;

unsigned long long notrace sched_clock(void)
{
return arch_timer_read_counter() * sched_clock_mult;
}

void __init time_init(void)
{
u32 arch_timer_rate;
Expand All @@ -78,9 +71,6 @@ void __init time_init(void)
if (!arch_timer_rate)
panic("Unable to initialise architected timer.\n");

/* Cache the sched_clock multiplier to save a divide in the hot path. */
sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;

/* Calibrate the delay loop directly */
lpj_fine = arch_timer_rate / HZ;
}
8 changes: 8 additions & 0 deletions arch/x86/kernel/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ static __init int add_rtc_cmos(void)
if (mrst_identify_cpu())
return -ENODEV;

#ifdef CONFIG_ACPI
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
/* This warning can likely go away again in a year or two. */
pr_info("ACPI: not registering RTC platform device\n");
return -ENODEV;
}
#endif

platform_device_register(&rtc_device);
dev_info(&rtc_device.dev,
"registered platform RTC device (no PNP device found)\n");
Expand Down
24 changes: 24 additions & 0 deletions drivers/clocksource/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ config ORION_TIMER
bool

config SUN4I_TIMER
select CLKSRC_MMIO
bool

config VT8500_TIMER
Expand Down Expand Up @@ -71,10 +72,33 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
help
Use the always on PRCMU Timer as sched_clock

config CLKSRC_EFM32
bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
default ARCH_EFM32
help
Support to use the timers of EFM32 SoCs as clock source and clock
event device.

config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF

config ARM_ARCH_TIMER_EVTSTREAM
bool "Support for ARM architected timer event stream generation"
default y if ARM_ARCH_TIMER
help
This option enables support for event stream generation based on
the ARM architected timer. It is used for waking up CPUs executing
the wfe instruction at a frequency represented as a power-of-2
divisor of the clock rate.
The main use of the event stream is wfe-based timeouts of userspace
locking implementations. It might also be useful for imposing timeout
on wfe to safeguard against any programming errors in case an expected
event is not generated.
This must be disabled for hardware validation purposes to detect any
hardware anomalies of missing events.

config ARM_GLOBAL_TIMER
bool
select CLKSRC_OF if OF
Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o
obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o
Expand Down
Loading

0 comments on commit 8709382

Please sign in to comment.