aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2012-11-14 04:50:19 -0500
committerMark Rutland <mark.rutland@arm.com>2013-01-31 10:51:06 -0500
commitb8e243431fa11f542a0fd94e939543bcb7d236ee (patch)
tree12dc92819adc89656a74e08d137d9e1bb88c4a6a /arch
parentef01c1d1483d214357f183949bc6173f29906a87 (diff)
arm: arch_timer: standardise counter reading
We're currently inconsistent with respect to our accesses to the physical and virtual counters, mixing and matching the two. This patch introduces and uses a function pointer for accessing the correct counter based on whether we're using physical or virtual interrupts. All current accesses to the counter accessors are redirected through it. When the driver is moved out to drivers/clocksource, there's the possibility that code called before the timer code is initialised will attempt to call arch_timer_read_counter (e.g. sched_clock for AArch64). To avoid having to have to check whether the timer has been initialised either in arch_timer_read_counter or one of it's callers, a default implementation is assigned that simply returns 0. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/arch_timer.c58
1 files changed, 22 insertions, 36 deletions
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 498c29ffbd39..eb78f43cf290 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -272,51 +272,37 @@ static int arch_timer_available(void)
272 return 0; 272 return 0;
273} 273}
274 274
275static u32 notrace arch_counter_get_cntpct32(void) 275/*
276 * Some external users of arch_timer_read_counter (e.g. sched_clock) may try to
277 * call it before it has been initialised. Rather than incur a performance
278 * penalty checking for initialisation, provide a default implementation that
279 * won't lead to time appearing to jump backwards.
280 */
281static u64 arch_timer_read_zero(void)
276{ 282{
277 cycle_t cnt = arch_counter_get_cntpct(); 283 return 0;
278
279 /*
280 * The sched_clock infrastructure only knows about counters
281 * with at most 32bits. Forget about the upper 24 bits for the
282 * time being...
283 */
284 return (u32)cnt;
285} 284}
286 285
287static u32 notrace arch_counter_get_cntvct32(void) 286u64 (*arch_timer_read_counter)(void) = arch_timer_read_zero;
288{
289 cycle_t cnt = arch_counter_get_cntvct();
290 287
291 /* 288static u32 arch_timer_read_counter32(void)
292 * The sched_clock infrastructure only knows about counters 289{
293 * with at most 32bits. Forget about the upper 24 bits for the 290 return arch_timer_read_counter();
294 * time being...
295 */
296 return (u32)cnt;
297} 291}
298 292
299static cycle_t arch_counter_read(struct clocksource *cs) 293static cycle_t arch_counter_read(struct clocksource *cs)
300{ 294{
301 /* 295 return arch_timer_read_counter();
302 * Always use the physical counter for the clocksource.
303 * CNTHCTL.PL1PCTEN must be set to 1.
304 */
305 return arch_counter_get_cntpct();
306} 296}
307 297
308static unsigned long arch_timer_read_current_timer(void) 298static unsigned long arch_timer_read_current_timer(void)
309{ 299{
310 return arch_counter_get_cntpct(); 300 return arch_timer_read_counter();
311} 301}
312 302
313static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) 303static cycle_t arch_counter_read_cc(const struct cyclecounter *cc)
314{ 304{
315 /* 305 return arch_timer_read_counter();
316 * Always use the physical counter for the clocksource.
317 * CNTHCTL.PL1PCTEN must be set to 1.
318 */
319 return arch_counter_get_cntpct();
320} 306}
321 307
322static struct clocksource clocksource_counter = { 308static struct clocksource clocksource_counter = {
@@ -484,23 +470,23 @@ int __init arch_timer_of_register(void)
484 } 470 }
485 } 471 }
486 472
473 if (arch_timer_use_virtual)
474 arch_timer_read_counter = arch_counter_get_cntvct;
475 else
476 arch_timer_read_counter = arch_counter_get_cntpct;
477
487 return arch_timer_register(); 478 return arch_timer_register();
488} 479}
489 480
490int __init arch_timer_sched_clock_init(void) 481int __init arch_timer_sched_clock_init(void)
491{ 482{
492 u32 (*cnt32)(void);
493 int err; 483 int err;
494 484
495 err = arch_timer_available(); 485 err = arch_timer_available();
496 if (err) 486 if (err)
497 return err; 487 return err;
498 488
499 if (arch_timer_use_virtual) 489 setup_sched_clock(arch_timer_read_counter32,
500 cnt32 = arch_counter_get_cntvct32; 490 32, arch_timer_rate);
501 else
502 cnt32 = arch_counter_get_cntpct32;
503
504 setup_sched_clock(cnt32, 32, arch_timer_rate);
505 return 0; 491 return 0;
506} 492}