diff options
author | Marc Zyngier <Marc.Zyngier@arm.com> | 2012-09-07 13:09:58 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-09-15 16:53:33 -0400 |
commit | a1b2dde70419ae947fd7c9c8fcad7da005dc600e (patch) | |
tree | cf8651233dbb03cd3ce4ad891f4c40aabf2fe8a1 | |
parent | f48b5f12799dbabba4a9c799a9bef0775b2f977d (diff) |
ARM: 7522/1: arch_timers: register a time/cycle counter
Some subsystems (KVM for example) need access to a cycle counter.
In the KVM case, this is used to measure the time delta between
host and guest in order to accurately generate timer events for
the guest.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 7 | ||||
-rw-r--r-- | arch/arm/kernel/arch_timer.c | 25 |
2 files changed, 32 insertions, 0 deletions
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 62e75475e57e..ad9b155c8262 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
@@ -2,11 +2,13 @@ | |||
2 | #define __ASMARM_ARCH_TIMER_H | 2 | #define __ASMARM_ARCH_TIMER_H |
3 | 3 | ||
4 | #include <asm/errno.h> | 4 | #include <asm/errno.h> |
5 | #include <linux/clocksource.h> | ||
5 | 6 | ||
6 | #ifdef CONFIG_ARM_ARCH_TIMER | 7 | #ifdef CONFIG_ARM_ARCH_TIMER |
7 | #define ARCH_HAS_READ_CURRENT_TIMER | 8 | #define ARCH_HAS_READ_CURRENT_TIMER |
8 | int arch_timer_of_register(void); | 9 | int arch_timer_of_register(void); |
9 | int arch_timer_sched_clock_init(void); | 10 | int arch_timer_sched_clock_init(void); |
11 | struct timecounter *arch_timer_get_timecounter(void); | ||
10 | #else | 12 | #else |
11 | static inline int arch_timer_of_register(void) | 13 | static inline int arch_timer_of_register(void) |
12 | { | 14 | { |
@@ -17,6 +19,11 @@ static inline int arch_timer_sched_clock_init(void) | |||
17 | { | 19 | { |
18 | return -ENXIO; | 20 | return -ENXIO; |
19 | } | 21 | } |
22 | |||
23 | static inline struct timecounter *arch_timer_get_timecounter(void) | ||
24 | { | ||
25 | return NULL; | ||
26 | } | ||
20 | #endif | 27 | #endif |
21 | 28 | ||
22 | #endif | 29 | #endif |
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index c4e20b69197a..c04c2a6da470 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c | |||
@@ -333,6 +333,15 @@ int read_current_timer(unsigned long *timer_val) | |||
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) | ||
337 | { | ||
338 | /* | ||
339 | * Always use the physical counter for the clocksource. | ||
340 | * CNTHCTL.PL1PCTEN must be set to 1. | ||
341 | */ | ||
342 | return arch_counter_get_cntpct(); | ||
343 | } | ||
344 | |||
336 | static struct clocksource clocksource_counter = { | 345 | static struct clocksource clocksource_counter = { |
337 | .name = "arch_sys_counter", | 346 | .name = "arch_sys_counter", |
338 | .rating = 400, | 347 | .rating = 400, |
@@ -341,6 +350,18 @@ static struct clocksource clocksource_counter = { | |||
341 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 350 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
342 | }; | 351 | }; |
343 | 352 | ||
353 | static struct cyclecounter cyclecounter = { | ||
354 | .read = arch_counter_read_cc, | ||
355 | .mask = CLOCKSOURCE_MASK(56), | ||
356 | }; | ||
357 | |||
358 | static struct timecounter timecounter; | ||
359 | |||
360 | struct timecounter *arch_timer_get_timecounter(void) | ||
361 | { | ||
362 | return &timecounter; | ||
363 | } | ||
364 | |||
344 | static void __cpuinit arch_timer_stop(struct clock_event_device *clk) | 365 | static void __cpuinit arch_timer_stop(struct clock_event_device *clk) |
345 | { | 366 | { |
346 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", | 367 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", |
@@ -380,6 +401,10 @@ static int __init arch_timer_register(void) | |||
380 | } | 401 | } |
381 | 402 | ||
382 | clocksource_register_hz(&clocksource_counter, arch_timer_rate); | 403 | clocksource_register_hz(&clocksource_counter, arch_timer_rate); |
404 | cyclecounter.mult = clocksource_counter.mult; | ||
405 | cyclecounter.shift = clocksource_counter.shift; | ||
406 | timecounter_init(&timecounter, &cyclecounter, | ||
407 | arch_counter_get_cntpct()); | ||
383 | 408 | ||
384 | if (arch_timer_use_virtual) { | 409 | if (arch_timer_use_virtual) { |
385 | ppi = arch_timer_ppi[VIRT_PPI]; | 410 | ppi = arch_timer_ppi[VIRT_PPI]; |