[PATCH v2] RISC-V: Resurrect the MMIO timer implementation for M-mode systems
Palmer Dabbelt
palmerdabbelt at google.com
Sat Sep 19 23:34:01 EDT 2020
On Sat, 19 Sep 2020 20:31:32 PDT (-0700), Damien Le Moal wrote:
> On Sat, 2020-09-19 at 13:21 -0700, Palmer Dabbelt wrote:
>> The K210 doesn't implement rdtime in M-mode, and since that's where Linux runs
>> in the NOMMU systems that means we can't use rdtime. The K210 is the only
>> system that anyone is currently running NOMMU or M-mode on, so here we're just
>> inlining the timer read directly.
>>
>> This also adds the CLINT driver as an !MMU dependency, as it's currently the
>> only timer driver availiable for these systems and without it we get a build
>> failure for some configurations.
>>
>> Tested-by: Damien Le Moal <damien.lemoal at wdc.com>
>> Signed-off-by: Palmer Dabbelt <palmerdabbelt at google.com>
>
> There is no changelog... What changed from V1 ? Do I need to test again ?
It's just the driver dependency, so allnoconfig and such build. Testing again
shouldn't be necessary, but I guess it never hurts.
>
>> ---
>> arch/riscv/Kconfig | 1 +
>> arch/riscv/include/asm/clint.h | 26 ++++++++++++++++++++++++++
>> arch/riscv/include/asm/timex.h | 27 +++++++++++++++++++++++++++
>> drivers/clocksource/timer-clint.c | 17 +++++++++++++++++
>> 4 files changed, 71 insertions(+)
>> create mode 100644 arch/riscv/include/asm/clint.h
>>
>> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
>> index df18372861d8..7766e1289468 100644
>> --- a/arch/riscv/Kconfig
>> +++ b/arch/riscv/Kconfig
>> @@ -32,6 +32,7 @@ config RISCV
>> select ARCH_WANT_FRAME_POINTERS
>> select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
>> select CLONE_BACKWARDS
>> + select CLINT_TIMER if !MMU
>> select COMMON_CLK
>> select EDAC_SUPPORT
>> select GENERIC_ARCH_TOPOLOGY if SMP
>> diff --git a/arch/riscv/include/asm/clint.h b/arch/riscv/include/asm/clint.h
>> new file mode 100644
>> index 000000000000..0789fd37b40a
>> --- /dev/null
>> +++ b/arch/riscv/include/asm/clint.h
>> @@ -0,0 +1,26 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (C) 2020 Google, Inc
>> + */
>> +
>> +#ifndef _ASM_RISCV_CLINT_H
>> +#define _ASM_RISCV_CLINT_H
>> +
>> +#include <linux/types.h>
>> +#include <asm/mmio.h>
>> +
>> +#ifdef CONFIG_RISCV_M_MODE
>> +/*
>> + * This lives in the CLINT driver, but is accessed directly by timex.h to avoid
>> + * any overhead when accessing the MMIO timer.
>> + *
>> + * The ISA defines mtime as a 64-bit memory-mapped register that increments at
>> + * a constant frequency, but it doesn't define some other constraints we depend
>> + * on (most notably ordering constraints, but also some simpler stuff like the
>> + * memory layout). Thus, this is called "clint_time_val" instead of something
>> + * like "riscv_mtime", to signify that these non-ISA assumptions must hold.
>> + */
>> +extern u64 __iomem *clint_time_val;
>> +#endif
>> +
>> +#endif
>> diff --git a/arch/riscv/include/asm/timex.h b/arch/riscv/include/asm/timex.h
>> index a3fb85d505d4..7f659dda0032 100644
>> --- a/arch/riscv/include/asm/timex.h
>> +++ b/arch/riscv/include/asm/timex.h
>> @@ -10,6 +10,31 @@
>>
>> typedef unsigned long cycles_t;
>>
>> +#ifdef CONFIG_RISCV_M_MODE
>> +
>> +#include <asm/clint.h>
>> +
>> +#ifdef CONFIG_64BIT
>> +static inline cycles_t get_cycles(void)
>> +{
>> + return readq_relaxed(clint_time_val);
>> +}
>> +#else /* !CONFIG_64BIT */
>> +static inline u32 get_cycles(void)
>> +{
>> + return readl_relaxed(((u32 *)clint_time_val));
>> +}
>> +#define get_cycles get_cycles
>> +
>> +static inline u32 get_cycles_hi(void)
>> +{
>> + return readl_relaxed(((u32 *)clint_time_val) + 1);
>> +}
>> +#define get_cycles_hi get_cycles_hi
>> +#endif /* CONFIG_64BIT */
>> +
>> +#else /* CONFIG_RISCV_M_MODE */
>> +
>> static inline cycles_t get_cycles(void)
>> {
>> return csr_read(CSR_TIME);
>> @@ -41,6 +66,8 @@ static inline u64 get_cycles64(void)
>> }
>> #endif /* CONFIG_64BIT */
>>
>> +#endif /* !CONFIG_RISCV_M_MODE */
>> +
>> #define ARCH_HAS_READ_CURRENT_TIMER
>> static inline int read_current_timer(unsigned long *timer_val)
>> {
>> diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c
>> index 8eeafa82c03d..d17367dee02c 100644
>> --- a/drivers/clocksource/timer-clint.c
>> +++ b/drivers/clocksource/timer-clint.c
>> @@ -19,6 +19,11 @@
>> #include <linux/interrupt.h>
>> #include <linux/of_irq.h>
>> #include <linux/smp.h>
>> +#include <linux/timex.h>
>> +
>> +#ifndef CONFIG_RISCV_M_MODE
>> +#include <asm/clint.h>
>> +#endif
>>
>> #define CLINT_IPI_OFF 0
>> #define CLINT_TIMER_CMP_OFF 0x4000
>> @@ -31,6 +36,10 @@ static u64 __iomem *clint_timer_val;
>> static unsigned long clint_timer_freq;
>> static unsigned int clint_timer_irq;
>>
>> +#ifdef CONFIG_RISCV_M_MODE
>> +u64 __iomem *clint_time_val;
>> +#endif
>> +
>> static void clint_send_ipi(const struct cpumask *target)
>> {
>> unsigned int cpu;
>> @@ -184,6 +193,14 @@ static int __init clint_timer_init_dt(struct device_node *np)
>> clint_timer_val = base + CLINT_TIMER_VAL_OFF;
>> clint_timer_freq = riscv_timebase;
>>
>> +#ifdef CONFIG_RISCV_M_MODE
>> + /*
>> + * Yes, that's an odd naming scheme. time_val is public, but hopefully
>> + * will die in favor of something cleaner.
>> + */
>> + clint_time_val = clint_timer_val;
>> +#endif
>> +
>> pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);
>>
>> rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
>
> --
> Damien Le Moal
> Western Digital
More information about the linux-riscv
mailing list