Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1aee5d7a authored by Mark Rutland's avatar Mark Rutland
Browse files

arm64: move from arm_generic to arm_arch_timer



The arch_timer driver supports a superset of the functionality of the
arm_generic driver, and is not tied to a particular arch.

This patch moves arm64 to use the arch_timer driver, gaining additional
functionality in doing so, and removes the (now unused) arm_generic
driver. Timer-related hooks specific to arm64 are moved into
arch/arm64/kernel/time.c.

Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Acked-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
parent 1dac0dd7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ config ARM64
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
	select ARM_AMBA
	select ARM_ARCH_TIMER
	select CLONE_BACKWARDS
	select COMMON_CLK
	select GENERIC_CLOCKEVENTS
+133 −0
Original line number Diff line number Diff line
/*
 * arch/arm64/include/asm/arm_generic.h
 * arch/arm64/include/asm/arch_timer.h
 *
 * Copyright (C) 2012 ARM Ltd.
 * Author: Marc Zyngier <marc.zyngier@arm.com>
@@ -16,21 +16,19 @@
 * 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
#ifndef __ASM_ARCH_TIMER_H
#define __ASM_ARCH_TIMER_H

#include <linux/clocksource.h>
#include <asm/barrier.h>

#define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
#define ARCH_TIMER_CTRL_IMASK		(1 << 1)
#define ARCH_TIMER_CTRL_ISTATUS		(1 << 2)
#include <linux/init.h>
#include <linux/types.h>

#define ARCH_TIMER_REG_CTRL		0
#define ARCH_TIMER_REG_FREQ		1
#define ARCH_TIMER_REG_TVAL		2
#include <clocksource/arm_arch_timer.h>

static inline void arch_timer_reg_write(int reg, u32 val)
static inline void arch_timer_reg_write(int access, int reg, u32 val)
{
	if (access == ARCH_TIMER_PHYS_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("msr cntp_ctl_el0,  %0" : : "r" (val));
@@ -41,32 +39,65 @@ static inline void arch_timer_reg_write(int reg, u32 val)
		default:
			BUILD_BUG();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("msr cntv_ctl_el0,  %0" : : "r" (val));
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("msr cntv_tval_el0, %0" : : "r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else {
		BUILD_BUG();
	}

	isb();
}

static inline u32 arch_timer_reg_read(int reg)
static inline u32 arch_timer_reg_read(int access, int reg)
{
	u32 val;

	if (access == ARCH_TIMER_PHYS_ACCESS) {
		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();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("mrs %0,  cntv_ctl_el0" : "=r" (val));
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else {
		BUILD_BUG();
	}

	return val;
}

static inline u32 arch_timer_get_cntfrq(void)
{
	u32 val;
	asm volatile("mrs %0,   cntfrq_el0" : "=r" (val));
	return val;
}

static inline void __cpuinit arch_counter_enable_user_access(void)
static inline void __cpuinit arch_counter_set_user_access(void)
{
	u32 cntkctl;

@@ -79,9 +110,9 @@ static inline void __cpuinit arch_counter_enable_user_access(void)
	asm volatile("msr	cntkctl_el1, %0" : : "r" (cntkctl));
}

static inline cycle_t arch_counter_get_cntpct(void)
static inline u64 arch_counter_get_cntpct(void)
{
	cycle_t cval;
	u64 cval;

	isb();
	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
@@ -89,9 +120,9 @@ static inline cycle_t arch_counter_get_cntpct(void)
	return cval;
}

static inline cycle_t arch_counter_get_cntvct(void)
static inline u64 arch_counter_get_cntvct(void)
{
	cycle_t cval;
	u64 cval;

	isb();
	asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+27 −2
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@
#include <linux/syscore_ops.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/delay.h>

#include <clocksource/arm_generic.h>
#include <clocksource/arm_arch_timer.h>

#include <asm/thread_info.h>
#include <asm/stacktrace.h>
@@ -59,7 +60,31 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc);
#endif

static u64 sched_clock_mult __read_mostly;

unsigned long long notrace sched_clock(void)
{
	return arch_timer_read_counter() * sched_clock_mult;
}

int read_current_timer(unsigned long *timer_value)
{
	*timer_value = arch_timer_read_counter();
	return 0;
}

void __init time_init(void)
{
	arm_generic_timer_init();
	u32 arch_timer_rate;

	if (arch_timer_init())
		panic("Unable to initialise architected timer.\n");

	arch_timer_rate = arch_timer_get_rate();

	/* Cache the sched_clock multiplier to save a divide in the hot path. */
	sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;

	/* Calibrate the delay loop directly */
	lpj_fine = arch_timer_rate / HZ;
}
+0 −5
Original line number Diff line number Diff line
@@ -54,10 +54,5 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
	help
	  Use the always on PRCMU Timer as sched_clock

config CLKSRC_ARM_GENERIC
	def_bool y if ARM64
	help
	  This option enables support for the ARM generic timer.

config ARM_ARCH_TIMER
	bool
+0 −1
Original line number Diff line number Diff line
@@ -17,5 +17,4 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o

obj-$(CONFIG_CLKSRC_ARM_GENERIC)	+= arm_generic.o
obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
Loading