Commit a69483ee authored by Will Deacon's avatar Will Deacon
Browse files

Merge branch 'for-next/8.6-timers' into for-next/core

* for-next/8.6-timers:
  arm64: Add HWCAP for self-synchronising virtual counter
  arm64: Add handling of CNTVCTSS traps
  arm64: Add CNT{P,V}CTSS_EL0 alternatives to cnt{p,v}ct_el0
  arm64: Add a capability for FEAT_ECV
  clocksource/drivers/arch_arm_timer: Move workaround synchronisation around
  clocksource/drivers/arm_arch_timer: Fix masking for high freq counters
  clocksource/drivers/arm_arch_timer: Drop unnecessary ISB on CVAL programming
  clocksource/drivers/arm_arch_timer: Remove any trace of the TVAL programming interface
  clocksource/drivers/arm_arch_timer: Work around broken CVAL implementations
  clocksource/drivers/arm_arch_timer: Advertise 56bit timer to the core code
  clocksource/drivers/arm_arch_timer: Move MMIO timer programming over to CVAL
  clocksource/drivers/arm_arch_timer: Fix MMIO base address vs callback ordering issue
  clocksource/drivers/arm_arch_timer: Move drop _tval from erratum function names
  clocksource/drivers/arm_arch_timer: Move system register timer programming over to CVAL
  clocksource/drivers/arm_arch_timer: Extend write side of timer register accessors to u64
  clocksource/drivers/arm_arch_timer: Drop CNT*_TVAL read accessors
  clocksource/arm_arch_timer: Add build-time guards for unhandled register accesses
parents 5816b3e6 fee29f00
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -235,7 +235,15 @@ infrastructure:
     | DPB                          | [3-0]   |    y    |
     +------------------------------+---------+---------+

  6) ID_AA64MMFR2_EL1 - Memory model feature register 2
  6) ID_AA64MMFR0_EL1 - Memory model feature register 0

     +------------------------------+---------+---------+
     | Name                         |  bits   | visible |
     +------------------------------+---------+---------+
     | ECV                          | [63-60] |    y    |
     +------------------------------+---------+---------+

  7) ID_AA64MMFR2_EL1 - Memory model feature register 2

     +------------------------------+---------+---------+
     | Name                         |  bits   | visible |
@@ -243,7 +251,7 @@ infrastructure:
     | AT                           | [35-32] |    y    |
     +------------------------------+---------+---------+

  7) ID_AA64ZFR0_EL1 - SVE feature ID register 0
  8) ID_AA64ZFR0_EL1 - SVE feature ID register 0

     +------------------------------+---------+---------+
     | Name                         |  bits   | visible |
+4 −0
Original line number Diff line number Diff line
@@ -247,6 +247,10 @@ HWCAP2_MTE
    Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0010, as described
    by Documentation/arm64/memory-tagging-extension.rst.

HWCAP2_ECV

    Functionality implied by ID_AA64MMFR0_EL1.ECV == 0b0001.

4. Unused AT_HWCAP bits
-----------------------

+22 −15
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <asm/hwcap.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/types.h>

#include <clocksource/arm_arch_timer.h>
@@ -24,29 +25,35 @@ int arch_timer_arch_init(void);
 * the code. At least it does so with a recent GCC (4.6.3).
 */
static __always_inline
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
{
	if (access == ARCH_TIMER_PHYS_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" ((u32)val));
			isb();
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
		case ARCH_TIMER_REG_CVAL:
			asm volatile("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" ((u32)val));
			isb();
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
		case ARCH_TIMER_REG_CVAL:
			asm volatile("mcrr p15, 3, %Q0, %R0, c14" : : "r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else {
		BUILD_BUG();
	}

	isb();
}

static __always_inline
@@ -59,19 +66,19 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
		case ARCH_TIMER_REG_CTRL:
			asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
			break;
		case ARCH_TIMER_REG_TVAL:
			asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
			break;
		default:
			BUILD_BUG();
		}
	} else {
		BUILD_BUG();
	}

	return val;
+44 −34
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@
	({								\
		const struct arch_timer_erratum_workaround *__wa;	\
		__wa = __this_cpu_read(timer_unstable_counter_workaround); \
		(__wa && __wa->h) ? __wa->h : arch_timer_##h;		\
		(__wa && __wa->h) ? ({ isb(); __wa->h;}) : arch_timer_##h; \
	})

#else
@@ -52,8 +52,6 @@ struct arch_timer_erratum_workaround {
	enum arch_timer_erratum_match_type match_type;
	const void *id;
	const char *desc;
	u32 (*read_cntp_tval_el0)(void);
	u32 (*read_cntv_tval_el0)(void);
	u64 (*read_cntpct_el0)(void);
	u64 (*read_cntvct_el0)(void);
	int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
@@ -64,25 +62,28 @@ struct arch_timer_erratum_workaround {
DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
		timer_unstable_counter_workaround);

/* inline sysreg accessors that make erratum_handler() work */
static inline notrace u32 arch_timer_read_cntp_tval_el0(void)
static inline notrace u64 arch_timer_read_cntpct_el0(void)
{
	return read_sysreg(cntp_tval_el0);
}
	u64 cnt;

static inline notrace u32 arch_timer_read_cntv_tval_el0(void)
{
	return read_sysreg(cntv_tval_el0);
}
	asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0",
				 "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0),
				 ARM64_HAS_ECV)
		     : "=r" (cnt));

static inline notrace u64 arch_timer_read_cntpct_el0(void)
{
	return read_sysreg(cntpct_el0);
	return cnt;
}

static inline notrace u64 arch_timer_read_cntvct_el0(void)
{
	return read_sysreg(cntvct_el0);
	u64 cnt;

	asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0",
				 "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0),
				 ARM64_HAS_ECV)
		     : "=r" (cnt));

	return cnt;
}

#define arch_timer_reg_read_stable(reg)					\
@@ -102,51 +103,58 @@ static inline notrace u64 arch_timer_read_cntvct_el0(void)
 * the code.
 */
static __always_inline
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
{
	if (access == ARCH_TIMER_PHYS_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			write_sysreg(val, cntp_ctl_el0);
			isb();
			break;
		case ARCH_TIMER_REG_TVAL:
			write_sysreg(val, cntp_tval_el0);
		case ARCH_TIMER_REG_CVAL:
			write_sysreg(val, cntp_cval_el0);
			break;
		default:
			BUILD_BUG();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			write_sysreg(val, cntv_ctl_el0);
			isb();
			break;
		case ARCH_TIMER_REG_TVAL:
			write_sysreg(val, cntv_tval_el0);
		case ARCH_TIMER_REG_CVAL:
			write_sysreg(val, cntv_cval_el0);
			break;
		default:
			BUILD_BUG();
		}
	} else {
		BUILD_BUG();
	}

	isb();
}

static __always_inline
u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
u64 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
{
	if (access == ARCH_TIMER_PHYS_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			return read_sysreg(cntp_ctl_el0);
		case ARCH_TIMER_REG_TVAL:
			return arch_timer_reg_read_stable(cntp_tval_el0);
		default:
			BUILD_BUG();
		}
	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
		switch (reg) {
		case ARCH_TIMER_REG_CTRL:
			return read_sysreg(cntv_ctl_el0);
		case ARCH_TIMER_REG_TVAL:
			return arch_timer_reg_read_stable(cntv_tval_el0);
		default:
			BUILD_BUG();
		}
	}

	BUG();
	BUILD_BUG();
	unreachable();
}

static inline u32 arch_timer_get_cntfrq(void)
@@ -169,7 +177,6 @@ static __always_inline u64 __arch_counter_get_cntpct_stable(void)
{
	u64 cnt;

	isb();
	cnt = arch_timer_reg_read_stable(cntpct_el0);
	arch_counter_enforce_ordering(cnt);
	return cnt;
@@ -179,8 +186,10 @@ static __always_inline u64 __arch_counter_get_cntpct(void)
{
	u64 cnt;

	isb();
	cnt = read_sysreg(cntpct_el0);
	asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0",
				 "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0),
				 ARM64_HAS_ECV)
		     : "=r" (cnt));
	arch_counter_enforce_ordering(cnt);
	return cnt;
}
@@ -189,7 +198,6 @@ static __always_inline u64 __arch_counter_get_cntvct_stable(void)
{
	u64 cnt;

	isb();
	cnt = arch_timer_reg_read_stable(cntvct_el0);
	arch_counter_enforce_ordering(cnt);
	return cnt;
@@ -199,8 +207,10 @@ static __always_inline u64 __arch_counter_get_cntvct(void)
{
	u64 cnt;

	isb();
	cnt = read_sysreg(cntvct_el0);
	asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0",
				 "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0),
				 ARM64_HAS_ECV)
		     : "=r" (cnt));
	arch_counter_enforce_ordering(cnt);
	return cnt;
}
+6 −0
Original line number Diff line number Diff line
@@ -227,6 +227,9 @@
#define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
					 ESR_ELx_SYS64_ISS_DIR_READ)

#define ESR_ELx_SYS64_ISS_SYS_CNTVCTSS	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 6, 14, 0) | \
					 ESR_ELx_SYS64_ISS_DIR_READ)

#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \
					 ESR_ELx_SYS64_ISS_DIR_READ)

@@ -317,6 +320,9 @@
#define ESR_ELx_CP15_64_ISS_SYS_CNTVCT	(ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
					 ESR_ELx_CP15_64_ISS_DIR_READ)

#define ESR_ELx_CP15_64_ISS_SYS_CNTVCTSS (ESR_ELx_CP15_64_ISS_SYS_VAL(9, 14) | \
					 ESR_ELx_CP15_64_ISS_DIR_READ)

#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ	(ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) |\
					 ESR_ELx_CP15_32_ISS_DIR_READ)

Loading