On 8/16/25 12:24, Vivian Wang wrote: > On 8/16/25 00:14, Anup Patel wrote: >> In RISC-V, there is no CSR read/write instruction which takes CSR >> number via register so add common csr_read_num() and csr_write_num() >> functions which allow accessing certain CSRs by passing CSR number >> as parameter. These common functions will be first used by the >> ACPI CPPC driver and RISC-V PMU driver. >> >> Signed-off-by: Anup Patel <apatel@xxxxxxxxxxxxxxxx> >> --- >> arch/riscv/include/asm/csr.h | 3 + >> arch/riscv/kernel/Makefile | 1 + >> arch/riscv/kernel/csr.c | 177 +++++++++++++++++++++++++++++++++++ >> drivers/acpi/riscv/cppc.c | 17 ++-- >> drivers/perf/riscv_pmu.c | 43 +-------- >> 5 files changed, 189 insertions(+), 52 deletions(-) >> create mode 100644 arch/riscv/kernel/csr.c >> >> diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h >> index 6fed42e37705..1540626b3540 100644 >> --- a/arch/riscv/include/asm/csr.h >> +++ b/arch/riscv/include/asm/csr.h >> @@ -575,6 +575,9 @@ >> : "memory"); \ >> }) >> >> +extern unsigned long csr_read_num(unsigned long csr_num, int *out_err); >> +extern void csr_write_num(unsigned long csr_num, unsigned long val, int *out_err); >> + >> #endif /* __ASSEMBLY__ */ >> >> #endif /* _ASM_RISCV_CSR_H */ >> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile >> index c7b542573407..0a75e20bde18 100644 >> --- a/arch/riscv/kernel/Makefile >> +++ b/arch/riscv/kernel/Makefile >> @@ -50,6 +50,7 @@ obj-y += soc.o >> obj-$(CONFIG_RISCV_ALTERNATIVE) += alternative.o >> obj-y += cpu.o >> obj-y += cpufeature.o >> +obj-y += csr.o >> obj-y += entry.o >> obj-y += irq.o >> obj-y += process.o >> diff --git a/arch/riscv/kernel/csr.c b/arch/riscv/kernel/csr.c >> new file mode 100644 >> index 000000000000..f7de45bb597c >> --- /dev/null >> +++ b/arch/riscv/kernel/csr.c >> @@ -0,0 +1,177 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (c) 2025 Ventana Micro Systems Inc. >> + */ >> + >> +#define pr_fmt(fmt) "riscv: " fmt >> +#include <linux/err.h> >> +#include <linux/export.h> >> +#include <linux/printk.h> >> +#include <linux/types.h> >> +#include <asm/csr.h> >> + >> +#define CSR_CUSTOM0_U_RW_BASE 0x800 >> +#define CSR_CUSTOM0_U_RW_COUNT 0x100 >> + >> +#define CSR_CUSTOM1_U_RO_BASE 0xCC0 >> +#define CSR_CUSTOM1_U_RO_COUNT 0x040 >> + >> +#define CSR_CUSTOM2_S_RW_BASE 0x5C0 >> +#define CSR_CUSTOM2_S_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM3_S_RW_BASE 0x9C0 >> +#define CSR_CUSTOM3_S_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM4_S_RO_BASE 0xDC0 >> +#define CSR_CUSTOM4_S_RO_COUNT 0x040 >> + >> +#define CSR_CUSTOM5_HS_RW_BASE 0x6C0 >> +#define CSR_CUSTOM5_HS_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM6_HS_RW_BASE 0xAC0 >> +#define CSR_CUSTOM6_HS_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM7_HS_RO_BASE 0xEC0 >> +#define CSR_CUSTOM7_HS_RO_COUNT 0x040 >> + >> +#define CSR_CUSTOM8_M_RW_BASE 0x7C0 >> +#define CSR_CUSTOM8_M_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM9_M_RW_BASE 0xBC0 >> +#define CSR_CUSTOM9_M_RW_COUNT 0x040 >> + >> +#define CSR_CUSTOM10_M_RO_BASE 0xFC0 >> +#define CSR_CUSTOM10_M_RO_COUNT 0x040 >> + >> +unsigned long csr_read_num(unsigned long csr_num, int *out_err) >> +{ >> +#define switchcase_csr_read(__csr_num) \ >> + case (__csr_num): \ >> + return csr_read(__csr_num) >> +#define switchcase_csr_read_2(__csr_num) \ >> + switchcase_csr_read(__csr_num + 0); \ >> + switchcase_csr_read(__csr_num + 1) >> +#define switchcase_csr_read_4(__csr_num) \ >> + switchcase_csr_read_2(__csr_num + 0); \ >> + switchcase_csr_read_2(__csr_num + 2) >> +#define switchcase_csr_read_8(__csr_num) \ >> + switchcase_csr_read_4(__csr_num + 0); \ >> + switchcase_csr_read_4(__csr_num + 4) >> +#define switchcase_csr_read_16(__csr_num) \ >> + switchcase_csr_read_8(__csr_num + 0); \ >> + switchcase_csr_read_8(__csr_num + 8) >> +#define switchcase_csr_read_32(__csr_num) \ >> + switchcase_csr_read_16(__csr_num + 0); \ >> + switchcase_csr_read_16(__csr_num + 16) >> +#define switchcase_csr_read_64(__csr_num) \ >> + switchcase_csr_read_32(__csr_num + 0); \ >> + switchcase_csr_read_32(__csr_num + 32) >> +#define switchcase_csr_read_128(__csr_num) \ >> + switchcase_csr_read_64(__csr_num + 0); \ >> + switchcase_csr_read_64(__csr_num + 64) >> +#define switchcase_csr_read_256(__csr_num) \ >> + switchcase_csr_read_128(__csr_num + 0); \ >> + switchcase_csr_read_128(__csr_num + 128) >> + > That's... a bit horrendous. > > Since we know that each inner case is quite simple, can we just do our > own jump table for that? Each case can be one csrr/csrw and one jal > (possibly pad to 8 bytes), and we can just jump to > label + (csr_num - range_start) * 8. See bottom of this message for an > untested prototype. > > Vivian "dramforever" Wang > > UNTESTED prototype: I want to make it clear by the way that I *don't* think the details are right with this code. Please do fix stuff like macro parameter parens and formatting if *anyone* is trying to use this code. Vivian "dramforever" Wang > #define CSR_CYCLE 0xc00 > #define CSR_CYCLEH 0xc80 > > /* Force expand argument if macro */ > #define str(_x) #_x > > unsigned long csr_read_num(long csr_num) > { > > [...]