diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index d8da0c5d85..17361b7231 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -553,6 +553,30 @@ config ARCH_RV_EXT_SSTC default n depends on ARCH_USE_S_MODE +config ARCH_RV_HAVE_APLIC + bool "Enable RISC-V Advanced Platform-Level Interrupt Controller support" + default n + ---help--- + Instead of PLIC, RISC-V also defines Advanced Platform-Level Interrupt + Controller (APLIC) to provide flexible interrupt control. This device + is not backward compatible with PLIC. + +config ARCH_RV_EXT_AIA + bool "Enable RISC-V SxAIA support" + default n + ---help--- + Advanced Interrupt Architecture defines necessary features that + impact the ISA at a hart. This should not be selected if the + target does not support SxAIA for the operating mode of NuttX. + +if ARCH_RV_EXT_AIA + +config ARCH_RV_HAVE_IMSIC + bool "Enable RISC-V AIA Incoming Message Controller support" + default n + +endif # ARCH_RV_EXT_AIA + choice prompt "Toolchain Selection" default RISCV_TOOLCHAIN_GNU_RV64 diff --git a/arch/risc-v/include/csr.h b/arch/risc-v/include/csr.h index a75d63844d..2350982313 100644 --- a/arch/risc-v/include/csr.h +++ b/arch/risc-v/include/csr.h @@ -390,6 +390,31 @@ #define MISELECT_CLICINTIE 0x1400 /* MIREG2 */ #define MISELECT_CLICINTTRIG 0x1480 /* MIREG */ +/* AIA Machine-Level CSRs */ + +#define CSR_MTOPEI 0x35c /* Machine top external interrupt */ +#define CSR_MTOPI 0xfb0 /* Machine top interrupt */ +#define CSR_MVIEN 0x308 /* Machine virtual interrupt enables */ +#define CSR_MVIP 0x309 /* Machine virtual interrupt-pending bits */ + +/* AIA Machine-Level CSRs (High-Half) */ + +#define CSR_MIDELEGH 0x313 +#define CSR_MIEH 0x314 +#define CSR_MVIENH 0x318 +#define CSR_MVIPH 0x319 +#define CSR_MIPH 0x354 + +/* AIA Supervisor-Level CSRs */ + +#define CSR_STOPEI 0x15c /* Supervisor top external interrupt */ +#define CSR_STOPI 0xdb0 /* Supervisor top interrupt */ + +/* AIA Supervisor-Level CSRs (High-Half) */ + +#define CSR_SIEH 0x114 +#define CSR_SIPH 0x154 + /* In mstatus register */ #define MSTATUS_UIE (0x1 << 0) /* User Interrupt Enable */ @@ -554,6 +579,161 @@ #define COUNTEREN_HPM30 (0x1 << 30) #define COUNTEREN_HPM31 (0x1 << 31) +/* In topi/topei register */ + +#define TOPI_IID_SHIFT 16 +#define TOPI_IPRIO_BITS 8 +#define TOPEI_ID_SHIFT 16 + +/* In iselect register (AIA) */ + +#define ISELECT_IPRIO0 0x30 +#define ISELECT_IPRIO1 0x31 +#define ISELECT_IPRIO2 0x32 +#define ISELECT_IPRIO3 0x33 +#define ISELECT_IPRIO4 0x34 +#define ISELECT_IPRIO5 0x35 +#define ISELECT_IPRIO6 0x36 +#define ISELECT_IPRIO7 0x37 +#define ISELECT_IPRIO8 0x38 +#define ISELECT_IPRIO9 0x39 +#define ISELECT_IPRIO10 0x3a +#define ISELECT_IPRIO11 0x3b +#define ISELECT_IPRIO12 0x3c +#define ISELECT_IPRIO13 0x3d +#define ISELECT_IPRIO14 0x3e +#define ISELECT_IPRIO15 0x3f +#define ISELECT_EIDELIVERY 0x70 +#define ISELECT_EITHRESHOLD 0x72 +#define ISELECT_EIP0 0x80 +#define ISELECT_EIP1 0x81 +#define ISELECT_EIP2 0x82 +#define ISELECT_EIP3 0x83 +#define ISELECT_EIP4 0x84 +#define ISELECT_EIP5 0x85 +#define ISELECT_EIP6 0x86 +#define ISELECT_EIP7 0x87 +#define ISELECT_EIP8 0x88 +#define ISELECT_EIP9 0x89 +#define ISELECT_EIP10 0x8a +#define ISELECT_EIP11 0x8b +#define ISELECT_EIP12 0x8c +#define ISELECT_EIP13 0x8d +#define ISELECT_EIP14 0x8e +#define ISELECT_EIP15 0x8f +#define ISELECT_EIP16 0x90 +#define ISELECT_EIP17 0x91 +#define ISELECT_EIP18 0x92 +#define ISELECT_EIP19 0x93 +#define ISELECT_EIP20 0x94 +#define ISELECT_EIP21 0x95 +#define ISELECT_EIP22 0x96 +#define ISELECT_EIP23 0x97 +#define ISELECT_EIP24 0x98 +#define ISELECT_EIP25 0x99 +#define ISELECT_EIP26 0x9a +#define ISELECT_EIP27 0x9b +#define ISELECT_EIP28 0x9c +#define ISELECT_EIP29 0x9d +#define ISELECT_EIP30 0x9e +#define ISELECT_EIP31 0x9f +#define ISELECT_EIP32 0xa0 +#define ISELECT_EIP33 0xa1 +#define ISELECT_EIP34 0xa2 +#define ISELECT_EIP35 0xa3 +#define ISELECT_EIP36 0xa4 +#define ISELECT_EIP37 0xa5 +#define ISELECT_EIP38 0xa6 +#define ISELECT_EIP39 0xa7 +#define ISELECT_EIP40 0xa8 +#define ISELECT_EIP41 0xa9 +#define ISELECT_EIP42 0xaa +#define ISELECT_EIP43 0xab +#define ISELECT_EIP44 0xac +#define ISELECT_EIP45 0xad +#define ISELECT_EIP46 0xae +#define ISELECT_EIP47 0xaf +#define ISELECT_EIP48 0xb0 +#define ISELECT_EIP49 0xb1 +#define ISELECT_EIP50 0xb2 +#define ISELECT_EIP51 0xb3 +#define ISELECT_EIP52 0xb4 +#define ISELECT_EIP53 0xb5 +#define ISELECT_EIP54 0xb6 +#define ISELECT_EIP55 0xb7 +#define ISELECT_EIP56 0xb8 +#define ISELECT_EIP57 0xb9 +#define ISELECT_EIP58 0xba +#define ISELECT_EIP59 0xbb +#define ISELECT_EIP60 0xbc +#define ISELECT_EIP61 0xbd +#define ISELECT_EIP62 0xbe +#define ISELECT_EIP63 0xbf +#define ISELECT_EIE0 0xc0 +#define ISELECT_EIE1 0xc1 +#define ISELECT_EIE2 0xc2 +#define ISELECT_EIE3 0xc3 +#define ISELECT_EIE4 0xc4 +#define ISELECT_EIE5 0xc5 +#define ISELECT_EIE6 0xc6 +#define ISELECT_EIE7 0xc7 +#define ISELECT_EIE8 0xc8 +#define ISELECT_EIE9 0xc9 +#define ISELECT_EIE10 0xca +#define ISELECT_EIE11 0xcb +#define ISELECT_EIE12 0xcc +#define ISELECT_EIE13 0xcd +#define ISELECT_EIE14 0xce +#define ISELECT_EIE15 0xcf +#define ISELECT_EIE16 0xd0 +#define ISELECT_EIE17 0xd1 +#define ISELECT_EIE18 0xd2 +#define ISELECT_EIE19 0xd3 +#define ISELECT_EIE20 0xd4 +#define ISELECT_EIE21 0xd5 +#define ISELECT_EIE22 0xd6 +#define ISELECT_EIE23 0xd7 +#define ISELECT_EIE24 0xd8 +#define ISELECT_EIE25 0xd9 +#define ISELECT_EIE26 0xda +#define ISELECT_EIE27 0xdb +#define ISELECT_EIE28 0xdc +#define ISELECT_EIE29 0xdd +#define ISELECT_EIE30 0xde +#define ISELECT_EIE31 0xdf +#define ISELECT_EIE32 0xe0 +#define ISELECT_EIE33 0xe1 +#define ISELECT_EIE34 0xe2 +#define ISELECT_EIE35 0xe3 +#define ISELECT_EIE36 0xe4 +#define ISELECT_EIE37 0xe5 +#define ISELECT_EIE38 0xe6 +#define ISELECT_EIE39 0xe7 +#define ISELECT_EIE40 0xe8 +#define ISELECT_EIE41 0xe9 +#define ISELECT_EIE42 0xea +#define ISELECT_EIE43 0xeb +#define ISELECT_EIE44 0xec +#define ISELECT_EIE45 0xed +#define ISELECT_EIE46 0xee +#define ISELECT_EIE47 0xef +#define ISELECT_EIE48 0xf0 +#define ISELECT_EIE49 0xf1 +#define ISELECT_EIE50 0xf2 +#define ISELECT_EIE51 0xf3 +#define ISELECT_EIE52 0xf4 +#define ISELECT_EIE53 0xf5 +#define ISELECT_EIE54 0xf6 +#define ISELECT_EIE55 0xf7 +#define ISELECT_EIE56 0xf8 +#define ISELECT_EIE57 0xf9 +#define ISELECT_EIE58 0xfa +#define ISELECT_EIE59 0xfb +#define ISELECT_EIE60 0xfc +#define ISELECT_EIE61 0xfd +#define ISELECT_EIE62 0xfe +#define ISELECT_EIE63 0xff + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/arch/risc-v/include/mode.h b/arch/risc-v/include/mode.h index 27bff35806..e8f7be5ca8 100644 --- a/arch/risc-v/include/mode.h +++ b/arch/risc-v/include/mode.h @@ -45,6 +45,12 @@ # define CSR_TVAL CSR_STVAL /* Trap value register */ # define CSR_TVEC CSR_STVEC /* Trap vector base addr register */ # define CSR_ENVCFG CSR_SENVCFG /* Env configuration register */ +# define CSR_IEH CSR_SIEH +# define CSR_ISELECT CSR_SISELECT /* Indirect select register */ +# define CSR_IREG CSR_SIREG /* Indirect alias register */ +# define CSR_IPH CSR_SIPH +# define CSR_TOPEI CSR_STOPEI /* Top external interrupt register */ +# define CSR_TOPI CSR_STOPI /* Top interrupt register */ /* In status register */ @@ -88,6 +94,12 @@ # define CSR_TVAL CSR_MTVAL /* Trap value register */ # define CSR_TVEC CSR_MTVEC /* Trap vector base addr register */ # define CSR_ENVCFG CSR_MENVCFG /* Env configuration register */ +# define CSR_IEH CSR_MIEH +# define CSR_ISELECT CSR_MISELECT /* Indirect select register */ +# define CSR_IREG CSR_MIREG /* Indirect alias register */ +# define CSR_IPH CSR_MIPH +# define CSR_TOPEI CSR_MTOPEI /* Top external interrupt register */ +# define CSR_TOPI CSR_MTOPI /* Top interrupt register */ /* In status register */ diff --git a/arch/risc-v/src/common/CMakeLists.txt b/arch/risc-v/src/common/CMakeLists.txt index 092188d49a..b1dd33db88 100644 --- a/arch/risc-v/src/common/CMakeLists.txt +++ b/arch/risc-v/src/common/CMakeLists.txt @@ -88,6 +88,14 @@ if(CONFIG_ARCH_RV_ISA_A) list(APPEND SRCS riscv_testset.S) endif() +if(CONFIG_ARCH_RV_HAVE_APLIC) + list(APPEND SRCS riscv_aplic.c) +endif() + +if(CONFIG_ARCH_RV_HAVE_IMSIC) + list(APPEND SRCS riscv_imsic.c) +endif() + if(CONFIG_RISCV_SEMIHOSTING_HOSTFS) list(APPEND SRCS riscv_semihost.S riscv_hostfs.c) endif() diff --git a/arch/risc-v/src/common/Make.defs b/arch/risc-v/src/common/Make.defs index b3d21641f7..e3c46f6fca 100644 --- a/arch/risc-v/src/common/Make.defs +++ b/arch/risc-v/src/common/Make.defs @@ -91,6 +91,10 @@ ifeq ($(CONFIG_ARCH_RV_ISA_A),y) CMN_ASRCS += riscv_testset.S endif +ifeq ($(CONFIG_ARCH_RV_HAVE_APLIC),y) +CMN_CSRCS += riscv_aia.c +endif + ifeq ($(CONFIG_RISCV_SEMIHOSTING_HOSTFS),y) CMN_ASRCS += riscv_semihost.S CMN_CSRCS += riscv_hostfs.c diff --git a/arch/risc-v/src/common/riscv_aia.h b/arch/risc-v/src/common/riscv_aia.h new file mode 100644 index 0000000000..5cae3e6215 --- /dev/null +++ b/arch/risc-v/src/common/riscv_aia.h @@ -0,0 +1,290 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_aia.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_COMMON_RISCV_AIA_H +#define __ARCH_RISCV_SRC_COMMON_RISCV_AIA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "riscv_internal.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* AIA IMSIC */ + +#define RISCV_IMSIC_MAX_REGS 16 + +#define RISCV_IMSIC_MMIO_PAGE_LE 0x00 +#define RISCV_IMSIC_MMIO_PAGE_BE 0x04 +#define RISCV_IMSIC_MMIO_PAGE_BIT 12 + +#define RISCV_IMSIC_TOPEI_ID_BIT 16 + +#define RISCV_IMSIC_EIP_BITS 32 +#define RISCV_IMSIC_EIE_BITS 32 + +#define RISCV_IMSIC_DISABLE_EIDELIVERY 0 +#define RISCV_IMSIC_ENABLE_EIDELIVERY 1 +#define RISCV_IMSIC_DISABLE_EITHRESHOLD 1 +#define RISCV_IMSIC_ENABLE_EITHRESHOLD 0 + +#define RISCV_IMSIC_IPI_ID 1 + +/* AIA APLIC */ + +#define RISCV_APLIC_MAX_DELEGATE 16 + +#define RISCV_APLIC_MAX_IDC (1UL << 14) +#define RISCV_APLIC_MAX_SOURCE 1024 + +#define RISCV_APLIC_DOMAINCFG 0x0000 +#define RISCV_APLIC_DOMAINCFG_IE (1 << 8) +#define RISCV_APLIC_DOMAINCFG_DM (1 << 2) +#define RISCV_APLIC_DOMAINCFG_BE (1 << 0) + +#define RISCV_APLIC_SOURCECFG_BASE 0x0004 +#define RISCV_APLIC_SOURCECFG_D (1 << 10) +#define RISCV_APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff +#define RISCV_APLIC_SOURCECFG_SM_MASK 0x00000007 +#define RISCV_APLIC_SOURCECFG_SM_INACTIVE 0x0 +#define RISCV_APLIC_SOURCECFG_SM_DETACH 0x1 +#define RISCV_APLIC_SOURCECFG_SM_EDGE_RISE 0x4 +#define RISCV_APLIC_SOURCECFG_SM_EDGE_FALL 0x5 +#define RISCV_APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6 +#define RISCV_APLIC_SOURCECFG_SM_LEVEL_LOW 0x7 + +#define RISCV_APLIC_MMSICFGADDR 0x1bc0 +#define RISCV_APLIC_MMSICFGADDRH 0x1bc4 +#define RISCV_APLIC_SMSICFGADDR 0x1bc8 +#define RISCV_APLIC_SMSICFGADDRH 0x1bcc + +#define RISCV_APLIC_MSICFGADDRH_L (1UL << 31) +#define RISCV_APLIC_MSICFGADDRH_HHXS_SHIFT 24 +#define RISCV_APLIC_MSICFGADDRH_LHXS_SHIFT 20 +#define RISCV_APLIC_MSICFGADDRH_HHXW_SHIFT 16 +#define RISCV_APLIC_MSICFGADDRH_LHXW_SHIFT 12 + +#define RISCV_APLIC_MSICFGADDR_PPN_SHIFT 12 + +#define RISCV_APLIC_SETIP_BASE 0x1c00 +#define RISCV_APLIC_SETIPNUM 0x1cdc + +#define RISCV_APLIC_CLRIP_BASE 0x1d00 +#define RISCV_APLIC_CLRIPNUM 0x1ddc + +#define RISCV_APLIC_SETIE_BASE 0x1e00 +#define RISCV_APLIC_SETIENUM 0x1edc + +#define RISCV_APLIC_CLRIE_BASE 0x1f00 +#define RISCV_APLIC_CLRIENUM 0x1fdc + +#define RISCV_APLIC_SETIPNUM_LE 0x2000 +#define RISCV_APLIC_SETIPNUM_BE 0x2004 + +#define RISCV_APLIC_TARGET_BASE 0x3004 +#define RISCV_APLIC_TARGET_HART_IDX_SHIFT 18 +#define RISCV_APLIC_TARGET_GUEST_IDX_SHIFT 12 + +#define RISCV_APLIC_IDC_BASE 0x4000 +#define RISCV_APLIC_IDC_SIZE 32 + +#define RISCV_APLIC_IDC_IDELIVERY 0x00 + +#define RISCV_APLIC_IDC_IFORCE 0x04 + +#define RISCV_APLIC_IDC_ITHRESHOLD 0x08 + +#define RISCV_APLIC_IDC_TOPI 0x18 +#define RISCV_APLIC_IDC_TOPI_ID_SHIFT 16 + +#define RISCV_APLIC_IDC_CLAIMI 0x1c + +#define RISCV_APLIC_DEFAULT_PRIORITY 1 +#define RISCV_APLIC_DISABLE_IDELIVERY 0 +#define RISCV_APLIC_ENABLE_IDELIVERY 1 +#define RISCV_APLIC_DISABLE_ITHRESHOLD 1 +#define RISCV_APLIC_ENABLE_ITHRESHOLD 0 + +#define RISCV_APLIC_IDC(base, i) \ + ((base) + RISCV_APLIC_IDC_BASE + RISCV_APLIC_IDC_SIZE * (i)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +union aplic_mode_arg_u +{ + struct + { + uint32_t idelivery; + uint32_t ithreshold; + } direct; + + struct + { + uint64_t imsic_ppn; + uint32_t lhxs; + uint32_t lhxw; + uint32_t hhxs; + uint32_t hhxw; + } msi; +}; + +/**************************************************************************** + * Public Function + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* IMSIC */ +#define riscv_imsic_csr_write(reg, val) WRITE_INDIRECT_CSR_REG0(reg, val) +#define riscv_imsic_csr_read(reg, val) READ_INDIRECT_CSR_REG0(reg, val) +#define riscv_imsic_csr_set(reg, val) SET_INDIRECT_CSR_REG0(reg, val) +#define riscv_imsic_csr_clear(reg, val) CLEAR_INDIRECT_CSR_REG0(reg, val) + +void riscv_imsic_local_eix_update(unsigned long base_id, + unsigned long num_id, + bool pend, bool val); + +static inline void riscv_imsic_local_eie_update(unsigned long base_id, + unsigned long num_id, bool val) +{ + return riscv_imsic_local_eix_update(base_id, num_id, false, val); +} + +static inline void riscv_imsic_local_eip_update(unsigned long base_id, + unsigned long num_id, bool val) +{ + return riscv_imsic_local_eix_update(base_id, num_id, true, val); +} + +static inline void riscv_imsic_local_eie_enable(unsigned long base_id) +{ + return riscv_imsic_local_eie_update(base_id, 1, true); +} + +static inline void riscv_imsic_local_eie_disable(unsigned long base_id) +{ + return riscv_imsic_local_eie_update(base_id, 1, false); +} + +void riscv_imsic_send_ipi(int cpu); + +/* APLIC */ + +static inline int riscv_aplic_set_delegate(uintptr_t base, + uint32_t first_irq, + uint32_t last_irq, + uint32_t child_id) +{ + uint32_t j; + uintptr_t sourcecfg_base = base + RISCV_APLIC_SOURCECFG_BASE; + + if (!first_irq || !last_irq) + return 0; + + if (RISCV_APLIC_SOURCECFG_CHILDIDX_MASK < child_id) + return -EINVAL; + + for (j = first_irq; j <= last_irq; j++) + { + putreg32(RISCV_APLIC_SOURCECFG_D | child_id, + sourcecfg_base + (j - 1) * sizeof(uint32_t)); + } + + return 0; +} + +static inline void riscv_aplic_enable_irq(uintptr_t base, uint32_t irq) +{ + putreg32(irq, base + RISCV_APLIC_SETIENUM); +} + +static inline void riscv_aplic_disable_irq(uintptr_t base, uint32_t irq) +{ + putreg32(irq, base + RISCV_APLIC_CLRIENUM); +} + +static inline void riscv_aplic_configure_irq(uintptr_t base, uint32_t irq, + uint32_t mode, uint32_t hartid) +{ + uint32_t val = (hartid << RISCV_APLIC_TARGET_HART_IDX_SHIFT) | irq; + putreg32(mode, base + RISCV_APLIC_SOURCECFG_BASE + + (irq - 1) * sizeof(uint32_t)); + putreg32(val, base + RISCV_APLIC_TARGET_BASE + + (irq - 1) * sizeof(uint32_t)); +} + +static inline void riscv_aplic_disable_irqs(uintptr_t base, + uint32_t num_source) +{ + uint32_t i; + + putreg32(0, base + RISCV_APLIC_DOMAINCFG); + + /* Disable all interrupts */ + + for (i = 0; i < num_source; i += 32) + { + putreg32(-1U, base + RISCV_APLIC_CLRIE_BASE + + (i / 32) * sizeof(uint32_t)); + } +} + +/**************************************************************************** + * Name: riscv_aplic_init + * + * Description: + * Init APLIC to direct mode + * + ****************************************************************************/ + +void riscv_aplic_init(uintptr_t base, + uint32_t idelivery, uint32_t ithreshold); + +/**************************************************************************** + * Name: riscv_aplic_init + * + * Description: + * Init APLIC to msi mode + * + ****************************************************************************/ + +void riscv_aplic_init_msi(uintptr_t base, uint64_t imsic_addr, + uint32_t lhxs, uint32_t lhxw, + uint32_t hhxs, uint32_t hhxw); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_RISCV_SRC_COMMON_RISCV_AIA_H */ diff --git a/arch/risc-v/src/common/riscv_aplic.c b/arch/risc-v/src/common/riscv_aplic.c new file mode 100644 index 0000000000..a5b09386cf --- /dev/null +++ b/arch/risc-v/src/common/riscv_aplic.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_aplic.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "riscv_internal.h" +#include "riscv_aia.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void riscv_aplic_init(uintptr_t base, + uint32_t idelivery, uint32_t ithreshold) +{ + int i; + + for (i = 0; i < CONFIG_SMP_NCPUS; i++) + { + uintptr_t idc_base = RISCV_APLIC_IDC(base, i); + + putreg32(idelivery, idc_base + RISCV_APLIC_IDC_IDELIVERY); + putreg32(0, idc_base + RISCV_APLIC_IDC_IFORCE); + putreg32(ithreshold, idc_base + RISCV_APLIC_IDC_ITHRESHOLD); + } +} + +void riscv_aplic_init_msi(uintptr_t base, uint64_t imsic_addr, + uint32_t lhxs, uint32_t lhxw, + uint32_t hhxs, uint32_t hhxw) +{ + uint32_t tmp; + + tmp = imsic_addr >> RISCV_IMSIC_MMIO_PAGE_BIT; + putreg32(tmp, base + RISCV_APLIC_MMSICFGADDR); + tmp = (uint32_t)(imsic_addr >> 32) | + (lhxw << RISCV_APLIC_MSICFGADDRH_LHXW_SHIFT) | + (lhxs << RISCV_APLIC_MSICFGADDRH_LHXS_SHIFT) | + (hhxw << RISCV_APLIC_MSICFGADDRH_HHXW_SHIFT) | + (hhxs << RISCV_APLIC_MSICFGADDRH_HHXS_SHIFT); + putreg32(tmp, base + RISCV_APLIC_MMSICFGADDRH); +} diff --git a/arch/risc-v/src/common/riscv_imsic.c b/arch/risc-v/src/common/riscv_imsic.c new file mode 100644 index 0000000000..7ea8f52ad8 --- /dev/null +++ b/arch/risc-v/src/common/riscv_imsic.c @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/risc-v/src/common/riscv_imsic.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "riscv_internal.h" +#include "riscv_aia.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void riscv_imsic_local_eix_update(unsigned long base_id, + unsigned long num_id, + bool pend, bool val) +{ + uintptr_t i, isel, ireg; + unsigned long id = base_id; + unsigned long last_id = base_id + num_id; + + while (id < last_id) + { + isel = id / __riscv_xlen; + isel *= __riscv_xlen / RISCV_IMSIC_EIP_BITS; + isel += (pend) ? ISELECT_EIP0 : ISELECT_EIE0; + + ireg = 0; + for (i = id & (__riscv_xlen - 1); + (id < last_id) && (i < __riscv_xlen); i++) + { + ireg |= BIT(i); + id++; + } + + if (val) + { + riscv_imsic_csr_set(isel, ireg); + } + else + { + riscv_imsic_csr_clear(isel, ireg); + } + } +} diff --git a/arch/risc-v/src/common/riscv_internal.h b/arch/risc-v/src/common/riscv_internal.h index 0d590ca7a7..be607bef61 100644 --- a/arch/risc-v/src/common/riscv_internal.h +++ b/arch/risc-v/src/common/riscv_internal.h @@ -197,6 +197,38 @@ static inline void putreg64(uint64_t v, const volatile uintreg_t a) __asm__ __volatile__("csrc " __STR(reg) ", %0" :: "rK"(bits)); \ }) +#define SWAP_CSR(reg, val) \ + ({ \ + uintptr_t regval; \ + __asm__ __volatile__("csrrw %0, " __STR(reg) ", %1" : "=r"(regval) \ + : "rK"(val)); \ + regval; \ + }) + +#define WRITE_INDIRECT_CSR_REG0(reg, val) \ + ({ \ + WRITE_CSR(CSR_ISELECT, reg); \ + WRITE_CSR(CSR_IREG, val); \ + }) + +#define READ_INDIRECT_CSR_REG0(reg, val) \ + ({ \ + WRITE_CSR(CSR_ISELECT, reg); \ + READ_CSR(CSR_IREG, val); \ + }) + +#define SET_INDIRECT_CSR_REG0(reg, val) \ + ({ \ + WRITE_CSR(CSR_ISELECT, reg); \ + SET_CSR(CSR_IREG, val); \ + }) + +#define CLEAR_INDIRECT_CSR_REG0(reg, val) \ + ({ \ + WRITE_CSR(CSR_ISELECT, reg); \ + CLEAR_CSR(CSR_IREG, val); \ + }) + #define riscv_append_pmp_region(a, b, s) \ riscv_config_pmp_region(riscv_next_free_pmp_region(), a, b, s)