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]; |
