The RISC-V ACLINT specification is a modular specification and the ACLINT MTIMER device is compatible with the M-mode timer functionality of the CLINT device. This patch extends the CLINT driver to support both CLINT device and ACLINT MTIMER device. Signed-off-by: Anup Patel <anup.patel@xxxxxxx> --- drivers/clocksource/timer-clint.c | 43 +++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index dfdcd94c1fd5..ca329c450810 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -2,8 +2,15 @@ /* * 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 driver for CLINT device and ACLINT MTIMER device. */ #define pr_fmt(fmt) "clint: " fmt @@ -21,14 +28,20 @@ #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 u32 __iomem *clint_ipi_base; static u64 __iomem *clint_timer_cmp; @@ -36,11 +49,6 @@ 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 - static void clint_send_ipi(const struct cpumask *target) { unsigned int cpu; @@ -191,9 +199,15 @@ static int __init clint_timer_init_dt(struct device_node *np) return -ENODEV; } - clint_ipi_base = base + CLINT_IPI_OFF; - 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_ipi_base = NULL; + clint_timer_cmp = base + ACLINT_MTIMER_CMP_OFF; + clint_timer_val = base + ACLINT_MTIMER_VAL_OFF; + } else { + clint_ipi_base = base + CLINT_IPI_OFF; + 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 @@ -230,8 +244,10 @@ static int __init clint_timer_init_dt(struct device_node *np) goto fail_free_irq; } - riscv_set_ipi_ops(&clint_ipi_ops); - clint_clear_ipi(); + if (clint_ipi_base) { + riscv_set_ipi_ops(&clint_ipi_ops); + clint_clear_ipi(); + } return 0; @@ -244,3 +260,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