diff options
| -rw-r--r-- | arch/arm/include/asm/arch_timer.h | 94 | ||||
| -rw-r--r-- | arch/arm/kernel/arch_timer.c | 92 |
2 files changed, 94 insertions, 92 deletions
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index d40229d9a1c9..db0fdc4cc9cc 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
| @@ -1,13 +1,107 @@ | |||
| 1 | #ifndef __ASMARM_ARCH_TIMER_H | 1 | #ifndef __ASMARM_ARCH_TIMER_H |
| 2 | #define __ASMARM_ARCH_TIMER_H | 2 | #define __ASMARM_ARCH_TIMER_H |
| 3 | 3 | ||
| 4 | #include <asm/barrier.h> | ||
| 4 | #include <asm/errno.h> | 5 | #include <asm/errno.h> |
| 5 | #include <linux/clocksource.h> | 6 | #include <linux/clocksource.h> |
| 7 | #include <linux/types.h> | ||
| 6 | 8 | ||
| 7 | #ifdef CONFIG_ARM_ARCH_TIMER | 9 | #ifdef CONFIG_ARM_ARCH_TIMER |
| 8 | int arch_timer_of_register(void); | 10 | int arch_timer_of_register(void); |
| 9 | int arch_timer_sched_clock_init(void); | 11 | int arch_timer_sched_clock_init(void); |
| 10 | struct timecounter *arch_timer_get_timecounter(void); | 12 | struct timecounter *arch_timer_get_timecounter(void); |
| 13 | |||
| 14 | #define ARCH_TIMER_CTRL_ENABLE (1 << 0) | ||
| 15 | #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) | ||
| 16 | #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) | ||
| 17 | |||
| 18 | #define ARCH_TIMER_REG_CTRL 0 | ||
| 19 | #define ARCH_TIMER_REG_TVAL 1 | ||
| 20 | |||
| 21 | #define ARCH_TIMER_PHYS_ACCESS 0 | ||
| 22 | #define ARCH_TIMER_VIRT_ACCESS 1 | ||
| 23 | |||
| 24 | /* | ||
| 25 | * These register accessors are marked inline so the compiler can | ||
| 26 | * nicely work out which register we want, and chuck away the rest of | ||
| 27 | * the code. At least it does so with a recent GCC (4.6.3). | ||
| 28 | */ | ||
| 29 | static inline void arch_timer_reg_write(const int access, const int reg, u32 val) | ||
| 30 | { | ||
| 31 | if (access == ARCH_TIMER_PHYS_ACCESS) { | ||
| 32 | switch (reg) { | ||
| 33 | case ARCH_TIMER_REG_CTRL: | ||
| 34 | asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); | ||
| 35 | break; | ||
| 36 | case ARCH_TIMER_REG_TVAL: | ||
| 37 | asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); | ||
| 38 | break; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
| 43 | switch (reg) { | ||
| 44 | case ARCH_TIMER_REG_CTRL: | ||
| 45 | asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); | ||
| 46 | break; | ||
| 47 | case ARCH_TIMER_REG_TVAL: | ||
| 48 | asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); | ||
| 49 | break; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline u32 arch_timer_reg_read(const int access, const int reg) | ||
| 55 | { | ||
| 56 | u32 val = 0; | ||
| 57 | |||
| 58 | if (access == ARCH_TIMER_PHYS_ACCESS) { | ||
| 59 | switch (reg) { | ||
| 60 | case ARCH_TIMER_REG_CTRL: | ||
| 61 | asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); | ||
| 62 | break; | ||
| 63 | case ARCH_TIMER_REG_TVAL: | ||
| 64 | asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
| 70 | switch (reg) { | ||
| 71 | case ARCH_TIMER_REG_CTRL: | ||
| 72 | asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); | ||
| 73 | break; | ||
| 74 | case ARCH_TIMER_REG_TVAL: | ||
| 75 | asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | return val; | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline u32 arch_timer_get_cntfrq(void) | ||
| 84 | { | ||
| 85 | u32 val; | ||
| 86 | asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); | ||
| 87 | return val; | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline u64 arch_counter_get_cntpct(void) | ||
| 91 | { | ||
| 92 | u64 cval; | ||
| 93 | |||
| 94 | asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); | ||
| 95 | return cval; | ||
| 96 | } | ||
| 97 | |||
| 98 | static inline u64 arch_counter_get_cntvct(void) | ||
| 99 | { | ||
| 100 | u64 cval; | ||
| 101 | |||
| 102 | asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); | ||
| 103 | return cval; | ||
| 104 | } | ||
| 11 | #else | 105 | #else |
| 12 | static inline int arch_timer_of_register(void) | 106 | static inline int arch_timer_of_register(void) |
| 13 | { | 107 | { |
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index f31c9ee18af2..e973cc0eaad1 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c | |||
| @@ -46,98 +46,6 @@ static bool arch_timer_use_virtual = true; | |||
| 46 | * Architected system timer support. | 46 | * Architected system timer support. |
| 47 | */ | 47 | */ |
| 48 | 48 | ||
| 49 | #define ARCH_TIMER_CTRL_ENABLE (1 << 0) | ||
| 50 | #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) | ||
| 51 | #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) | ||
| 52 | |||
| 53 | #define ARCH_TIMER_REG_CTRL 0 | ||
| 54 | #define ARCH_TIMER_REG_TVAL 1 | ||
| 55 | |||
| 56 | #define ARCH_TIMER_PHYS_ACCESS 0 | ||
| 57 | #define ARCH_TIMER_VIRT_ACCESS 1 | ||
| 58 | |||
| 59 | /* | ||
| 60 | * These register accessors are marked inline so the compiler can | ||
| 61 | * nicely work out which register we want, and chuck away the rest of | ||
| 62 | * the code. At least it does so with a recent GCC (4.6.3). | ||
| 63 | */ | ||
| 64 | static inline void arch_timer_reg_write(const int access, const int reg, u32 val) | ||
| 65 | { | ||
| 66 | if (access == ARCH_TIMER_PHYS_ACCESS) { | ||
| 67 | switch (reg) { | ||
| 68 | case ARCH_TIMER_REG_CTRL: | ||
| 69 | asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); | ||
| 70 | break; | ||
| 71 | case ARCH_TIMER_REG_TVAL: | ||
| 72 | asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
| 78 | switch (reg) { | ||
| 79 | case ARCH_TIMER_REG_CTRL: | ||
| 80 | asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); | ||
| 81 | break; | ||
| 82 | case ARCH_TIMER_REG_TVAL: | ||
| 83 | asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | isb(); | ||
| 89 | } | ||
| 90 | |||
| 91 | static inline u32 arch_timer_reg_read(const int access, const int reg) | ||
| 92 | { | ||
| 93 | u32 val = 0; | ||
| 94 | |||
| 95 | if (access == ARCH_TIMER_PHYS_ACCESS) { | ||
| 96 | switch (reg) { | ||
| 97 | case ARCH_TIMER_REG_CTRL: | ||
| 98 | asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); | ||
| 99 | break; | ||
| 100 | case ARCH_TIMER_REG_TVAL: | ||
| 101 | asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
| 107 | switch (reg) { | ||
| 108 | case ARCH_TIMER_REG_CTRL: | ||
| 109 | asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); | ||
| 110 | break; | ||
| 111 | case ARCH_TIMER_REG_TVAL: | ||
| 112 | asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | return val; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline u32 arch_timer_get_cntfrq(void) | ||
| 121 | { | ||
| 122 | u32 val; | ||
| 123 | asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); | ||
| 124 | return val; | ||
| 125 | } | ||
| 126 | |||
| 127 | static inline u64 arch_counter_get_cntpct(void) | ||
| 128 | { | ||
| 129 | u64 cval; | ||
| 130 | asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); | ||
| 131 | return cval; | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline u64 arch_counter_get_cntvct(void) | ||
| 135 | { | ||
| 136 | u64 cval; | ||
| 137 | asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); | ||
| 138 | return cval; | ||
| 139 | } | ||
| 140 | |||
| 141 | static irqreturn_t inline timer_handler(const int access, | 49 | static irqreturn_t inline timer_handler(const int access, |
| 142 | struct clock_event_device *evt) | 50 | struct clock_event_device *evt) |
| 143 | { | 51 | { |
