diff options
author | Olof Johansson <olof@lixom.net> | 2013-02-11 09:04:35 -0800 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-02-11 09:04:44 -0800 |
commit | 37a42fca282cb37c14d997ca9299bdc6617815bb (patch) | |
tree | 787d3142e42a8e723e5707767cc585b47c416561 /arch/arm/include | |
parent | 3ddc0e1a7fd2fc222a6c87654af1cf059acdd1ec (diff) | |
parent | 9e02e394c7d7fdc2570a73fb7fc6da3c79f6db2a (diff) |
Merge branch 'for-arm-soc/arch-timers' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into next/virt
From Will Deacon:
This set of changes moves the arch-timer driver out from arch/arm/ and
into drivers/clocksource and unifies the new driver with the arm64 copy.
* 'for-arm-soc/arch-timers' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux:
ARM: arch_timers: switch to physical timers if HYP mode is available
Documentation: Add ARMv8 to arch_timer devicetree
arm64: move from arm_generic to arm_arch_timer
arm64: arm_generic: prevent reading stale time
arm: arch_timer: move core to drivers/clocksource
arm: arch_timer: add arch_counter_set_user_access
arm: arch_timer: divorce from local_timer api
arm: arch_timer: add isbs to register accessors
arm: arch_timer: factor out register accessors
arm: arch_timer: split cntfrq accessor
arm: arch_timer: standardise counter reading
arm: arch_timer: use u64/u32 for register data
arm: arch_timer: remove redundant available check
arm: arch_timer: balance device_node refcounting
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 109 |
1 files changed, 103 insertions, 6 deletions
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index d40229d9a1c..7ade91d8cc6 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -1,13 +1,115 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H +#include <asm/barrier.h> #include <asm/errno.h> #include <linux/clocksource.h> +#include <linux/init.h> +#include <linux/types.h> + +#include <clocksource/arm_arch_timer.h> #ifdef CONFIG_ARM_ARCH_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); -struct timecounter *arch_timer_get_timecounter(void); + +/* + * These register accessors are marked inline so the compiler can + * nicely work out which register we want, and chuck away the rest of + * the code. At least it does so with a recent GCC (4.6.3). + */ +static inline void arch_timer_reg_write(const int access, const int reg, u32 val) +{ + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); + break; + } + } + + isb(); +} + +static inline u32 arch_timer_reg_read(const int access, const int reg) +{ + u32 val = 0; + + if (access == ARCH_TIMER_PHYS_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); + break; + } + } + + if (access == ARCH_TIMER_VIRT_ACCESS) { + switch (reg) { + case ARCH_TIMER_REG_CTRL: + asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); + break; + case ARCH_TIMER_REG_TVAL: + asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); + break; + } + } + + return val; +} + +static inline u32 arch_timer_get_cntfrq(void) +{ + u32 val; + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); + return val; +} + +static inline u64 arch_counter_get_cntpct(void) +{ + u64 cval; + + isb(); + asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); + return cval; +} + +static inline u64 arch_counter_get_cntvct(void) +{ + u64 cval; + + isb(); + asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); + return cval; +} + +static inline void __cpuinit arch_counter_set_user_access(void) +{ + u32 cntkctl; + + asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); + + /* disable user access to everything */ + cntkctl &= ~((3 << 8) | (7 << 0)); + + asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); +} #else static inline int arch_timer_of_register(void) { @@ -18,11 +120,6 @@ static inline int arch_timer_sched_clock_init(void) { return -ENXIO; } - -static inline struct timecounter *arch_timer_get_timecounter(void) -{ - return NULL; -} #endif #endif |