blob: db0fdc4cc9cc21e55674a22b03108d9c398f8613 [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 Rutlandec944c92012-11-12 16:18:00 +00007#include <linux/types.h>
Will Deacon923df96b2012-07-06 15:46:45 +01008
Marc Zyngier022c03a2012-01-11 17:25:17 +00009#ifdef CONFIG_ARM_ARCH_TIMER
Marc Zyngier00752422012-01-19 13:53:50 +000010int arch_timer_of_register(void);
Marc Zyngierfb8a99f2012-04-27 13:18:42 +010011int arch_timer_sched_clock_init(void);
Marc Zyngiera1b2dde2012-09-07 18:09:58 +010012struct timecounter *arch_timer_get_timecounter(void);
Mark Rutlandec944c92012-11-12 16:18:00 +000013
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 */
29static 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
54static 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
83static 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
90static 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
98static 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}
Marc Zyngier022c03a2012-01-11 17:25:17 +0000105#else
Marc Zyngier00752422012-01-19 13:53:50 +0000106static inline int arch_timer_of_register(void)
107{
108 return -ENXIO;
109}
110
Marc Zyngier3f61c802011-01-14 15:32:36 +0000111static inline int arch_timer_sched_clock_init(void)
112{
113 return -ENXIO;
114}
Marc Zyngiera1b2dde2012-09-07 18:09:58 +0100115
116static inline struct timecounter *arch_timer_get_timecounter(void)
117{
118 return NULL;
119}
Marc Zyngier022c03a2012-01-11 17:25:17 +0000120#endif
121
122#endif