The RISC-V ACLINT specification is a modular specification and the ACLINT MTIMER device is backward compatible with the M-mode timer functionality of the CLINT device. This patch extends the CLINT timer driver to support both CLINT device and ACLINT MTIMER device. Signed-off-by: Anup Patel <anup.patel@xxxxxxx> Reviewed-by: Bin Meng <bmeng.cn@xxxxxxxxx> --- drivers/clocksource/timer-clint.c | 35 ++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index 3b68ed53fe4a..bf89744cd12a 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -2,8 +2,16 @@ /* * Copyright (C) 2020 Western Digital Corporation or its affiliates. * - * Most of the M-mode (i.e. NoMMU) RISC-V systems usually have a - * CLINT MMIO timer device. + * Most of the M-mode (i.e. NoMMU) RISC-V systems usually have a CLINT + * MMIO device which is a composite device capable of injecting M-mode + * software interrupts and M-mode timer interrupts. + * + * The RISC-V ACLINT specification is modular in nature and defines + * separate devices for M-mode software interrupt (MSWI), M-mode timer + * (MTIMER) and S-mode software interrupt (SSWI). + * + * This is a common timer driver for the CLINT device and the ACLINT + * MTIMER device. */ #define pr_fmt(fmt) "clint: " fmt @@ -21,25 +29,26 @@ #include <linux/smp.h> #include <linux/timex.h> -#ifndef CONFIG_RISCV_M_MODE +#ifdef CONFIG_RISCV_M_MODE #include <asm/clint.h> + +u64 __iomem *clint_time_val; +EXPORT_SYMBOL(clint_time_val); #endif #define CLINT_IPI_OFF 0 #define CLINT_TIMER_CMP_OFF 0x4000 #define CLINT_TIMER_VAL_OFF 0xbff8 +#define ACLINT_MTIMER_CMP_OFF 0x0000 +#define ACLINT_MTIMER_VAL_OFF 0x7ff8 + /* CLINT manages IPI and Timer for RISC-V M-mode */ static u64 __iomem *clint_timer_cmp; 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; -EXPORT_SYMBOL(clint_time_val); -#endif - #ifdef CONFIG_64BIT #define clint_get_cycles() readq_relaxed(clint_timer_val) #else @@ -170,8 +179,13 @@ static int __init clint_timer_init_dt(struct device_node *np) return -ENODEV; } - clint_timer_cmp = base + CLINT_TIMER_CMP_OFF; - clint_timer_val = base + CLINT_TIMER_VAL_OFF; + if (of_device_is_compatible(np, "riscv,aclint-mtimer")) { + clint_timer_cmp = base + ACLINT_MTIMER_CMP_OFF; + clint_timer_val = base + ACLINT_MTIMER_VAL_OFF; + } else { + clint_timer_cmp = base + CLINT_TIMER_CMP_OFF; + clint_timer_val = base + CLINT_TIMER_VAL_OFF; + } clint_timer_freq = riscv_timebase; #ifdef CONFIG_RISCV_M_MODE @@ -219,3 +233,4 @@ static int __init clint_timer_init_dt(struct device_node *np) TIMER_OF_DECLARE(clint_timer, "riscv,clint0", clint_timer_init_dt); TIMER_OF_DECLARE(clint_timer1, "sifive,clint0", clint_timer_init_dt); +TIMER_OF_DECLARE(clint_timer2, "riscv,aclint-mtimer", clint_timer_init_dt); -- 2.25.1