This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 5f70307111eeeebd48ae65788dd8112d2d7114c0
Author: Inochi Amaoto <inochi...@outlook.com>
AuthorDate: Sun May 12 20:15:58 2024 +0800

    arch/risc-v: introduce AIA support
    
    Advanced Interrupt Architecture (AIA) introduces flexiable interrupt
    controll for RISC-V. It includes three parts: AIA CSRs, Incoming Message
    Signaled Interrupt Controller (IMSIC) and  Advanced Platform-Level
    Interrupt Controller (APLIC).
    
    Signed-off-by: Inochi Amaoto <inochi...@outlook.com>
---
 arch/risc-v/Kconfig                     |  24 +++
 arch/risc-v/include/csr.h               | 180 ++++++++++++++++++++
 arch/risc-v/include/mode.h              |  12 ++
 arch/risc-v/src/common/CMakeLists.txt   |   8 +
 arch/risc-v/src/common/Make.defs        |   4 +
 arch/risc-v/src/common/riscv_aia.h      | 290 ++++++++++++++++++++++++++++++++
 arch/risc-v/src/common/riscv_aplic.c    |  61 +++++++
 arch/risc-v/src/common/riscv_imsic.c    |  63 +++++++
 arch/risc-v/src/common/riscv_internal.h |  32 ++++
 9 files changed, 674 insertions(+)

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 <nuttx/bits.h>
+#include <arch/csr.h>
+#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)
 

Reply via email to