mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
clocksource/drivers/arm_arch_timer: Use event stream scaling when available
With FEAT_ECV and the 1GHz counter, it is pretty likely that the event stream divider doesn't fit in the field that holds the divider value (we only have 4 bits to describe counter bits [15:0] Thankfully, FEAT_ECV also provides a scaling mechanism to switch the field to cover counter bits [23:8] instead. Enable this on arm64 when ECV is available (32bit doesn't have any detection infrastructure and is unlikely to be run on an ARMv8.6 system anyway). Signed-off-by: Marc Zyngier <maz@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Mark Rutland <mark.rutland@arm.com> Link: https://lore.kernel.org/r/20220203170502.2694422-1-maz@kernel.org Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
This commit is contained in:
parent
0a3a4b9d2b
commit
8c4b810a87
@ -880,10 +880,19 @@ static void __arch_timer_setup(unsigned type,
|
|||||||
clockevents_config_and_register(clk, arch_timer_rate, 0xf, max_delta);
|
clockevents_config_and_register(clk, arch_timer_rate, 0xf, max_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arch_timer_evtstrm_enable(int divider)
|
static void arch_timer_evtstrm_enable(unsigned int divider)
|
||||||
{
|
{
|
||||||
u32 cntkctl = arch_timer_get_cntkctl();
|
u32 cntkctl = arch_timer_get_cntkctl();
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
/* ECV is likely to require a large divider. Use the EVNTIS flag. */
|
||||||
|
if (cpus_have_const_cap(ARM64_HAS_ECV) && divider > 15) {
|
||||||
|
cntkctl |= ARCH_TIMER_EVT_INTERVAL_SCALE;
|
||||||
|
divider -= 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
divider = min(divider, 15U);
|
||||||
cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
|
cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
|
||||||
/* Set the divider and enable virtual event stream */
|
/* Set the divider and enable virtual event stream */
|
||||||
cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
|
cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
|
||||||
@ -912,7 +921,7 @@ static void arch_timer_configure_evtstream(void)
|
|||||||
lsb++;
|
lsb++;
|
||||||
|
|
||||||
/* enable event stream */
|
/* enable event stream */
|
||||||
arch_timer_evtstrm_enable(max(0, min(lsb, 15)));
|
arch_timer_evtstrm_enable(max(0, lsb));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arch_counter_set_user_access(void)
|
static void arch_counter_set_user_access(void)
|
||||||
|
@ -56,6 +56,7 @@ enum arch_timer_spi_nr {
|
|||||||
#define ARCH_TIMER_EVT_TRIGGER_MASK (0xF << ARCH_TIMER_EVT_TRIGGER_SHIFT)
|
#define ARCH_TIMER_EVT_TRIGGER_MASK (0xF << ARCH_TIMER_EVT_TRIGGER_SHIFT)
|
||||||
#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */
|
#define ARCH_TIMER_USR_VT_ACCESS_EN (1 << 8) /* virtual timer registers */
|
||||||
#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */
|
#define ARCH_TIMER_USR_PT_ACCESS_EN (1 << 9) /* physical timer registers */
|
||||||
|
#define ARCH_TIMER_EVT_INTERVAL_SCALE (1 << 17) /* EVNTIS in the ARMv8 ARM */
|
||||||
|
|
||||||
#define ARCH_TIMER_EVT_STREAM_PERIOD_US 100
|
#define ARCH_TIMER_EVT_STREAM_PERIOD_US 100
|
||||||
#define ARCH_TIMER_EVT_STREAM_FREQ \
|
#define ARCH_TIMER_EVT_STREAM_FREQ \
|
||||||
|
Loading…
Reference in New Issue
Block a user