diff --git a/arch/riscv/Kconfig.isa b/arch/riscv/Kconfig.isa index 722becfb56d55..9a864dcb10d7c 100644 --- a/arch/riscv/Kconfig.isa +++ b/arch/riscv/Kconfig.isa @@ -117,6 +117,15 @@ config RISCV_ISA_EXT_ZICSR The "Zicsr" extension introduces support for the full set of CSR instructions that operate on CSRs registers. +config RISCV_ISA_EXT_SMCSRIND + bool + select RISCV_ISA_EXT_ZICSR + help + (Smcsrind) - Standard Extension for Indirect CSR Access + + The Smcsrind extension provides indirect access to CSRs through + the MISELECT and MIREG registers. + config RISCV_ISA_EXT_ZIFENCEI bool help diff --git a/include/zephyr/arch/riscv/csr.h b/include/zephyr/arch/riscv/csr.h index 70e6e817b630a..6bf999f6e3d27 100644 --- a/include/zephyr/arch/riscv/csr.h +++ b/include/zephyr/arch/riscv/csr.h @@ -233,4 +233,44 @@ : "memory"); \ }) +#ifdef CONFIG_RISCV_ISA_EXT_SMCSRIND + +#define MISELECT 0x350 +#define MIREG 0x351 +#define MIREG2 0x352 +#define MIREG3 0x353 +#define MIREG4 0x355 +#define MIREG5 0x356 +#define MIREG6 0x357 + +static inline unsigned long icsr_read(unsigned int index) +{ + csr_write(MISELECT, index); + return csr_read(MIREG); +} + +static inline void icsr_write(unsigned int index, unsigned long value) +{ + csr_write(MISELECT, index); + csr_write(MIREG, value); +} + +static inline unsigned long icsr_read_set(unsigned int index, unsigned long mask) +{ + unsigned long val = icsr_read(index); + + icsr_write(index, val | mask); + return val; +} + +static inline unsigned long icsr_read_clear(unsigned int index, unsigned long mask) +{ + unsigned long val = icsr_read(index); + + icsr_write(index, val & ~mask); + return val; +} + +#endif /* CONFIG_RISCV_ISA_EXT_SMCSRIND */ + #endif /* CSR_H_ */