blob: 7ade91d8cc6fa4d723016e1e538e16881092f33c [file] [log] [blame]
Marc Zyngier022c03a2012-01-11 17:25:17 +00001#ifndef __ASMARM_ARCH_TIMER_H
2#define __ASMARM_ARCH_TIMER_H
3
Mark Rutlandec944c92012-11-12 16:18:00 +00004#include <asm/barrier.h>
Will Deacon923df96b2012-07-06 15:46:45 +01005#include <asm/errno.h>
Marc Zyngiera1b2dde2012-09-07 18:09:58 +01006#include <linux/clocksource.h>
Mark Rutland8a4da6e2012-11-12 14:33:44 +00007#include <linux/init.h>
Mark Rutlandec944c92012-11-12 16:18:00 +00008#include <linux/types.h>
Will Deacon923df96b2012-07-06 15:46:45 +01009
Mark Rutland8a4da6e2012-11-12 14:33:44 +000010#include <clocksource/arm_arch_timer.h>
11
Marc Zyngier022c03a2012-01-11 17:25:17 +000012#ifdef CONFIG_ARM_ARCH_TIMER
Marc Zyngier00752422012-01-19 13:53:50 +000013int arch_timer_of_register(void);
Marc Zyngierfb8a99f2012-04-27 13:18:42 +010014int arch_timer_sched_clock_init(void);
Mark Rutlandec944c92012-11-12 16:18:00 +000015
16/*
17 * These register accessors are marked inline so the compiler can
18 * nicely work out which register we want, and chuck away the rest of
19 * the code. At least it does so with a recent GCC (4.6.3).
20 */
21static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
22{
23 if (access == ARCH_TIMER_PHYS_ACCESS) {
24 switch (reg) {
25 case ARCH_TIMER_REG_CTRL:
26 asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
27 break;
28 case ARCH_TIMER_REG_TVAL:
29 asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
30 break;
31 }
32 }
33
34 if (access == ARCH_TIMER_VIRT_ACCESS) {
35 switch (reg) {
36 case ARCH_TIMER_REG_CTRL:
37 asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
38 break;
39 case ARCH_TIMER_REG_TVAL:
40 asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
41 break;
42 }
43 }
Mark Rutland45801042013-01-11 14:32:33 +000044
45 isb();
Mark Rutlandec944c92012-11-12 16:18:00 +000046}
47
48static inline u32 arch_timer_reg_read(const int access, const int reg)
49{
50 u32 val = 0;
51
52 if (access == ARCH_TIMER_PHYS_ACCESS) {
53 switch (reg) {
54 case ARCH_TIMER_REG_CTRL:
55 asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
56 break;
57 case ARCH_TIMER_REG_TVAL:
58 asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
59 break;
60 }
61 }
62
63 if (access == ARCH_TIMER_VIRT_ACCESS) {
64 switch (reg) {
65 case ARCH_TIMER_REG_CTRL:
66 asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
67 break;
68 case ARCH_TIMER_REG_TVAL:
69 asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
70 break;
71 }
72 }
73
74 return val;
75}
76
77static inline u32 arch_timer_get_cntfrq(void)
78{
79 u32 val;
80 asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
81 return val;
82}
83
84static inline u64 arch_counter_get_cntpct(void)
85{
86 u64 cval;
87
Mark Rutland45801042013-01-11 14:32:33 +000088 isb();
Mark Rutlandec944c92012-11-12 16:18:00 +000089 asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
90 return cval;
91}
92
93static inline u64 arch_counter_get_cntvct(void)
94{
95 u64 cval;
96
Mark Rutland45801042013-01-11 14:32:33 +000097 isb();
Mark Rutlandec944c92012-11-12 16:18:00 +000098 asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
99 return cval;
100}
Mark Rutlandb2deabe2012-11-14 10:32:24 +0000101
102static inline void __cpuinit arch_counter_set_user_access(void)
103{
104 u32 cntkctl;
105
106 asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
107
108 /* disable user access to everything */
109 cntkctl &= ~((3 << 8) | (7 << 0));
110
111 asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
112}
Marc Zyngier022c03a2012-01-11 17:25:17 +0000113#else
Marc Zyngier00752422012-01-19 13:53:50 +0000114static inline int arch_timer_of_register(void)
115{
116 return -ENXIO;
117}
118
Marc Zyngier3f61c802011-01-14 15:32:36 +0000119static inline int arch_timer_sched_clock_init(void)
120{
121 return -ENXIO;
122}
Marc Zyngier022c03a2012-01-11 17:25:17 +0000123#endif
124
125#endif