forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch adds support for the ARM generic timers with A64 instructions for accessing the timer registers. It uses the physical counter as the clock source and the virtual counter as sched_clock. The timer frequency can be specified via DT or read from the CNTFRQ_EL0 register. The physical counter is also accessible from user space allowing fast gettimeofday() implementation. Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Catalin Marinas <[email protected]> Acked-by: Tony Lindgren <[email protected]> Acked-by: Nicolas Pitre <[email protected]> Acked-by: Olof Johansson <[email protected]> Acked-by: Santosh Shilimkar <[email protected]> Acked-by: Arnd Bergmann <[email protected]>
- Loading branch information
Showing
7 changed files
with
453 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* arch/arm64/include/asm/arm_generic.h | ||
* | ||
* Copyright (C) 2012 ARM Ltd. | ||
* Author: Marc Zyngier <[email protected]> | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
#ifndef __ASM_ARM_GENERIC_H | ||
#define __ASM_ARM_GENERIC_H | ||
|
||
#include <linux/clocksource.h> | ||
|
||
#define ARCH_TIMER_CTRL_ENABLE (1 << 0) | ||
#define ARCH_TIMER_CTRL_IMASK (1 << 1) | ||
#define ARCH_TIMER_CTRL_ISTATUS (1 << 2) | ||
|
||
#define ARCH_TIMER_REG_CTRL 0 | ||
#define ARCH_TIMER_REG_FREQ 1 | ||
#define ARCH_TIMER_REG_TVAL 2 | ||
|
||
static inline void arch_timer_reg_write(int reg, u32 val) | ||
{ | ||
switch (reg) { | ||
case ARCH_TIMER_REG_CTRL: | ||
asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); | ||
break; | ||
case ARCH_TIMER_REG_TVAL: | ||
asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); | ||
break; | ||
default: | ||
BUILD_BUG(); | ||
} | ||
|
||
isb(); | ||
} | ||
|
||
static inline u32 arch_timer_reg_read(int reg) | ||
{ | ||
u32 val; | ||
|
||
switch (reg) { | ||
case ARCH_TIMER_REG_CTRL: | ||
asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val)); | ||
break; | ||
case ARCH_TIMER_REG_FREQ: | ||
asm volatile("mrs %0, cntfrq_el0" : "=r" (val)); | ||
break; | ||
case ARCH_TIMER_REG_TVAL: | ||
asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); | ||
break; | ||
default: | ||
BUILD_BUG(); | ||
} | ||
|
||
return val; | ||
} | ||
|
||
static inline void __cpuinit arch_counter_enable_user_access(void) | ||
{ | ||
u32 cntkctl; | ||
|
||
/* Disable user access to the timers and the virtual counter. */ | ||
asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); | ||
cntkctl &= ~((3 << 8) | (1 << 1)); | ||
|
||
/* Enable user access to the physical counter and frequency. */ | ||
cntkctl |= 1; | ||
asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); | ||
} | ||
|
||
static inline cycle_t arch_counter_get_cntpct(void) | ||
{ | ||
cycle_t cval; | ||
|
||
asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); | ||
|
||
return cval; | ||
} | ||
|
||
static inline cycle_t arch_counter_get_cntvct(void) | ||
{ | ||
cycle_t cval; | ||
|
||
asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); | ||
|
||
return cval; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
#ifndef __ASM_TIMEX_H | ||
#define __ASM_TIMEX_H | ||
|
||
/* | ||
* Use the current timer as a cycle counter since this is what we use for | ||
* the delay loop. | ||
*/ | ||
#define get_cycles() ({ cycles_t c; read_current_timer(&c); c; }) | ||
|
||
#include <asm-generic/timex.h> | ||
|
||
#define ARCH_HAS_READ_CURRENT_TIMER | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Based on arch/arm/kernel/time.c | ||
* | ||
* Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
* Modifications for ARM (C) 1994-2001 Russell King | ||
* Copyright (C) 2012 ARM Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include <linux/export.h> | ||
#include <linux/kernel.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/time.h> | ||
#include <linux/init.h> | ||
#include <linux/sched.h> | ||
#include <linux/smp.h> | ||
#include <linux/timex.h> | ||
#include <linux/errno.h> | ||
#include <linux/profile.h> | ||
#include <linux/syscore_ops.h> | ||
#include <linux/timer.h> | ||
#include <linux/irq.h> | ||
|
||
#include <clocksource/arm_generic.h> | ||
|
||
#include <asm/thread_info.h> | ||
#include <asm/stacktrace.h> | ||
|
||
#ifdef CONFIG_SMP | ||
unsigned long profile_pc(struct pt_regs *regs) | ||
{ | ||
struct stackframe frame; | ||
|
||
if (!in_lock_functions(regs->pc)) | ||
return regs->pc; | ||
|
||
frame.fp = regs->regs[29]; | ||
frame.sp = regs->sp; | ||
frame.pc = regs->pc; | ||
do { | ||
int ret = unwind_frame(&frame); | ||
if (ret < 0) | ||
return 0; | ||
} while (in_lock_functions(frame.pc)); | ||
|
||
return frame.pc; | ||
} | ||
EXPORT_SYMBOL(profile_pc); | ||
#endif | ||
|
||
void __init time_init(void) | ||
{ | ||
arm_generic_timer_init(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.