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

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


The following commit(s) were added to refs/heads/master by this push:
     new 37a0445ddb armv8-r/gicv3: support fiq
37a0445ddb is described below

commit 37a0445ddbe280ccc9f11c68de2db1120531d150
Author: Jinliang Li <[email protected]>
AuthorDate: Thu Nov 14 00:01:02 2024 +0800

    armv8-r/gicv3: support fiq
    
    1. support fiq decoding and dispatch
    2. replace CONFIG_ARMV8R_DECODEFIQ with CONFIG_ARCH_HIPRI_INTERRUPT
    
    Signed-off-by: Jinliang Li <[email protected]>
---
 arch/arm/Kconfig                        |   3 +-
 arch/arm/include/armv8-r/cp15.h         |   3 +
 arch/arm/include/armv8-r/irq.h          |   4 +-
 arch/arm/src/armv8-r/CMakeLists.txt     |   4 +
 arch/arm/src/armv8-r/Kconfig            |  12 ---
 arch/arm/src/armv8-r/Make.defs          |   4 +
 arch/arm/src/armv8-r/arm_dofiq.c        |  61 +++++++++++++++
 arch/arm/src/armv8-r/arm_gic.h          |   5 ++
 arch/arm/src/armv8-r/arm_gicv3.c        | 134 ++++++++++++++++++++++++++++++--
 arch/arm/src/armv8-r/arm_initialstate.c |   6 +-
 arch/arm/src/armv8-r/arm_vectors.S      |  12 +--
 11 files changed, 218 insertions(+), 30 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 51adc49fc8..6b105bad09 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -90,7 +90,8 @@ config ARCH_CHIP_FVP_ARMV8R_AARCH32
        select ARCH_CORTEXR52
        select ARCH_HAVE_LOWVECTORS
        select ARCH_HAVE_FETCHADD
-       select ARMV8R_HAVE_DECODEFIQ
+       select ARCH_HAVE_IRQPRIO
+       select ARCH_HAVE_HIPRI_INTERRUPT
        select ARCH_HAVE_FPU
        ---help---
                ARM FVP virt platform (ARMv8r)
diff --git a/arch/arm/include/armv8-r/cp15.h b/arch/arm/include/armv8-r/cp15.h
index 7ad3fa4250..5865f242f0 100644
--- a/arch/arm/include/armv8-r/cp15.h
+++ b/arch/arm/include/armv8-r/cp15.h
@@ -170,10 +170,13 @@
 #define CP15_DCIALLU(r)       _CP15(0, r, c15, c5, 0)     /* Invalidate data 
cache */
 
 #define CP15_ICC_PMR(r)       _CP15(0, r, c4,  c6,  0)    /* ICC_PMR */
+#define CP15_ICC_IAR0(r)      _CP15(0, r, c12, c8,  0)    /* ICC_IAR0 */
 #define CP15_ICC_IAR1(r)      _CP15(0, r, c12, c12, 0)    /* ICC_IAR1 */
+#define CP15_ICC_EOIR0(r)     _CP15(0, r, c12, c8,  1)    /* ICC_EOIR0 */
 #define CP15_ICC_EOIR1(r)     _CP15(0, r, c12, c12, 1)    /* ICC_EOIR1 */
 #define CP15_ICC_SRE(r)       _CP15(0, r, c12, c12, 5)    /* ICC_SRE */
 #define CP15_ICC_HSRE(r)      _CP15(4, r, c12,  c9, 5)    /* ICC_HSRE */
+#define CP15_ICC_IGRPEN0(r)   _CP15(0, r, c12, c12, 6)    /* ICC_IGRPEN0 */
 #define CP15_ICC_IGRPEN1(r)   _CP15(0, r, c12, c12, 7)    /* ICC_IGRPEN1 */
 #define CP15_ICC_SGI1R(lo,hi) _CP15_64(0, lo, hi, c12)    /* ICC_SGI1R */
 
diff --git a/arch/arm/include/armv8-r/irq.h b/arch/arm/include/armv8-r/irq.h
index a142b4bfbb..30de6ca2a9 100644
--- a/arch/arm/include/armv8-r/irq.h
+++ b/arch/arm/include/armv8-r/irq.h
@@ -365,7 +365,7 @@ noinstrument_function static inline irqstate_t 
up_irq_save(void)
     (
       "\tmrs    %0, cpsr\n"
       "\tcpsid  i\n"
-#if defined(CONFIG_ARMV8R_DECODEFIQ)
+#if defined(CONFIG_ARCH_HIPRI_INTERRUPT)
       "\tcpsid  f\n"
 #endif
       : "=r" (cpsr)
@@ -386,7 +386,7 @@ static inline irqstate_t up_irq_enable(void)
     (
       "\tmrs    %0, cpsr\n"
       "\tcpsie  i\n"
-#if defined(CONFIG_ARMV8R_DECODEFIQ)
+#if defined(CONFIG_ARCH_HIPRI_INTERRUPT)
       "\tcpsie  f\n"
 #endif
       : "=r" (cpsr)
diff --git a/arch/arm/src/armv8-r/CMakeLists.txt 
b/arch/arm/src/armv8-r/CMakeLists.txt
index 79a08e37f8..a32ef6c04e 100644
--- a/arch/arm/src/armv8-r/CMakeLists.txt
+++ b/arch/arm/src/armv8-r/CMakeLists.txt
@@ -51,4 +51,8 @@ if(CONFIG_ARCH_FPU)
   list(APPEND SRCS arm_fpucmp.c arm_fpuconfig.S)
 endif()
 
+if(CONFIG_ARCH_HIPRI_INTERRUPT)
+  list(APPEND SRCS arm_dofiq.c)
+endif()
+
 target_sources(arch PRIVATE ${SRCS})
diff --git a/arch/arm/src/armv8-r/Kconfig b/arch/arm/src/armv8-r/Kconfig
index 8dc77ec88a..e232b07f87 100644
--- a/arch/arm/src/armv8-r/Kconfig
+++ b/arch/arm/src/armv8-r/Kconfig
@@ -43,18 +43,6 @@ config ARMV8R_MEMINIT
                the memory initialization first, then explicitly call
                arm_data_initialize().
 
-config ARMV8R_HAVE_DECODEFIQ
-       bool
-       default n
-
-config ARMV8R_DECODEFIQ
-       bool "FIQ Handler"
-       default n
-       depends on ARMV8R_HAVE_DECODEFIQ
-       ---help---
-               Select this option if your platform supports the function
-               arm_decodefiq().
-
 config ARMV8R_ALIGNMENT_TRAP
        bool "Enable Alignment Check at __start"
        default n
diff --git a/arch/arm/src/armv8-r/Make.defs b/arch/arm/src/armv8-r/Make.defs
index 2e994acd62..31de2d98f8 100644
--- a/arch/arm/src/armv8-r/Make.defs
+++ b/arch/arm/src/armv8-r/Make.defs
@@ -52,3 +52,7 @@ endif
 ifeq ($(CONFIG_ARMV8R_L2CC_PL310),y)
   CMN_CSRCS += arm_l2cc_pl310.c
 endif
+
+ifeq ($(CONFIG_ARCH_HIPRI_INTERRUPT),y)
+  CMN_CSRCS += arm_dofiq.c
+endif
diff --git a/arch/arm/src/armv8-r/arm_dofiq.c b/arch/arm/src/armv8-r/arm_dofiq.c
new file mode 100644
index 0000000000..5bc5ec009f
--- /dev/null
+++ b/arch/arm/src/armv8-r/arm_dofiq.c
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * arch/arm/src/armv8-r/arm_dofiq.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 <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/board.h>
+#include <arch/board/board.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm_dofiq
+ *
+ * Description:
+ *   Receives the decoded GIC interrupt information and dispatches control
+ *   to the attached fiq handler. It is not allowed to call OS functions
+ *   within a FIQ handler.
+ *
+ ****************************************************************************/
+
+uint32_t *arm_dofiq(int fiq, uint32_t *regs)
+{
+  board_autoled_on(LED_INIRQ);
+
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+  PANIC();
+#else
+  irq_dispatch(fiq, regs);
+#endif
+
+  board_autoled_off(LED_INIRQ);
+  return regs;
+}
diff --git a/arch/arm/src/armv8-r/arm_gic.h b/arch/arm/src/armv8-r/arm_gic.h
index 6aee95dff5..743ccbb61b 100644
--- a/arch/arm/src/armv8-r/arm_gic.h
+++ b/arch/arm/src/armv8-r/arm_gic.h
@@ -328,6 +328,11 @@ bool arm_gic_irq_is_enabled(unsigned int intid);
 int  arm_gic_initialize(void);
 void arm_gic_irq_set_priority(unsigned int intid, unsigned int prio,
                                 uint32_t flags);
+
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+void arm_gic_set_group(unsigned int intid, unsigned int group);
+#endif
+
 int arm_gic_irq_trigger(unsigned int intid, uint32_t flags);
 
 int arm_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);
diff --git a/arch/arm/src/armv8-r/arm_gicv3.c b/arch/arm/src/armv8-r/arm_gicv3.c
index 1cd20ee972..af3ec11a98 100644
--- a/arch/arm/src/armv8-r/arm_gicv3.c
+++ b/arch/arm/src/armv8-r/arm_gicv3.c
@@ -279,6 +279,68 @@ bool arm_gic_irq_is_enabled(unsigned int intid)
   return (val & mask) != 0;
 }
 
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+void arm_gic_set_group(unsigned int intid, unsigned int group)
+{
+  uint32_t mask = BIT(intid & (GIC_NUM_INTR_PER_REG - 1));
+  uint32_t idx  = intid / GIC_NUM_INTR_PER_REG;
+  unsigned long base = GET_DIST_BASE(intid);
+  uint32_t igroupr_val;
+  uint32_t igroupmodr_val;
+
+  igroupr_val = getreg32(IGROUPR(base, idx));
+  igroupmodr_val = getreg32(IGROUPMODR(base, idx));
+  if (group == 0)
+    {
+      igroupr_val &= ~mask;
+      igroupmodr_val &= ~mask;
+    }
+  else
+    {
+      igroupr_val |= mask;
+      igroupmodr_val |= mask;
+    }
+
+  putreg32(igroupr_val, IGROUPR(base, idx));
+  putreg32(igroupmodr_val, IGROUPMODR(base, idx));
+}
+
+static unsigned int arm_gic_get_active_group0(void)
+{
+  int intid;
+
+  /* (Pending -> Active / AP) or (AP -> AP)
+   * Read a Group 0 INTID on an interrupt acknowledge.
+   */
+
+  intid = CP15_GET(ICC_IAR0);
+
+  return intid;
+}
+
+static void arm_gic_eoi_group0(unsigned int intid)
+{
+  /* Interrupt request deassertion from peripheral to GIC happens
+   * by clearing interrupt condition by a write to the peripheral
+   * register. It is desired that the write transfer is complete
+   * before the core tries to change GIC state from 'AP/Active' to
+   * a new state on seeing 'EOI write'.
+   * Since ICC interface writes are not ordered against Device
+   * memory writes, a barrier is required to ensure the ordering.
+   * The dsb will also ensure *completion* of previous writes with
+   * DEVICE nGnRnE attribute.
+   */
+
+  ARM_DSB();
+
+  /* (AP -> Pending) Or (Active -> Inactive) or (AP to AP) nested case
+   * Write a Group 0 interrupt completion
+   */
+
+  CP15_SET(ICC_EOIR0, intid);
+}
+#endif
+
 unsigned int arm_gic_get_active(void)
 {
   int intid;
@@ -458,6 +520,12 @@ static void gicv3_cpuif_init(void)
 
   CP15_SET(ICC_PMR, GIC_IDLE_PRIO);
 
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+  /* Allow group0 interrupts */
+
+  CP15_SET(ICC_IGRPEN0, 1);
+#endif
+
   /* Allow group1 interrupts */
 
   CP15_SET(ICC_IGRPEN1, 1);
@@ -560,14 +628,23 @@ static void gicv3_dist_init(void)
    * BIT(1), we can reuse them.
    */
 
-  putreg32(BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1NS),
-                 GICD_CTLR);
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+  putreg32(BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1NS) |
+           BIT(GICD_CTLR_ENABLE_G0), GICD_CTLR);
+#else
+  putreg32(BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1NS), GICD_CTLR);
+#endif /* CONFIG_ARCH_HIPRI_INTERRUPT */
 
 #else
   /* Enable distributor with ARE */
 
-  putreg32(BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS),
-           GICD_CTLR);
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+  putreg32(BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS) |
+           BIT(GICD_CTLR_ENABLE_G0), GICD_CTLR);
+#else
+  putreg32(BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS), GICD_CTLR);
+#endif /* CONFIG_ARCH_HIPRI_INTERRUPT */
+
 #endif
 
 #ifdef CONFIG_SMP
@@ -676,11 +753,56 @@ void up_trigger_irq(int irq, cpu_set_t cpuset)
     }
 }
 
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+/***************************************************************************
+ * Name: arm_decodefiq
+ *
+ * Description:
+ *   This function is called from the FIQ vector handler in arm_vectors.S.
+ *   At this point, the interrupt has been taken and the registers have
+ *   been saved on the stack.  This function simply needs to determine the
+ *   the irq number of the interrupt and then to call arm_dofiq to dispatch
+ *   the interrupt.
+ *
+ *  Input Parameters:
+ *   regs - A pointer to the register save area on the stack.
+ ***************************************************************************/
+
+uint32_t *arm_decodefiq(uint32_t *regs)
+{
+  int fiq;
+
+  /* Read the Group0 interrupt acknowledge register
+   * and get the interrupt ID
+   */
+
+  fiq = arm_gic_get_active_group0();
+
+  /* Ignore spurions FIQs.  ICCIAR will report 1023 if there is no pending
+   * interrupt.
+   */
+
+  DEBUGASSERT(fiq < NR_IRQS || fiq == 1023);
+  if (fiq < NR_IRQS)
+    {
+      /* Dispatch the fiq interrupt */
+
+      regs = arm_dofiq(fiq, regs);
+    }
+
+  /* Write to Group0 the end-of-interrupt register */
+
+  arm_gic_eoi_group0(fiq);
+
+  return regs;
+}
+#endif
+
 /***************************************************************************
- * Name: arm64_decodeirq
+ * Name: arm_decodeirq
  *
  * Description:
- *   This function is called from the IRQ vector handler in arm64_vectors.S.
+ *   This function is called from the IRQ vector handler in arm_vectors.S.
  *   At this point, the interrupt has been taken and the registers have
  *   been saved on the stack.  This function simply needs to determine the
  *   the irq number of the interrupt and then to call arm_doirq to dispatch
diff --git a/arch/arm/src/armv8-r/arm_initialstate.c 
b/arch/arm/src/armv8-r/arm_initialstate.c
index 079eba403d..71f9b4f130 100644
--- a/arch/arm/src/armv8-r/arm_initialstate.c
+++ b/arch/arm/src/armv8-r/arm_initialstate.c
@@ -131,13 +131,13 @@ void up_initial_state(struct tcb_s *tcb)
   cpsr |= (PSR_I_BIT | PSR_F_BIT);
 
 #else /* CONFIG_SUPPRESS_INTERRUPTS */
-  /* Leave IRQs enabled (Also FIQs if CONFIG_ARMV8R_DECODEFIQ is selected) */
+  /* Leave IRQs enabled (Also FIQs if CONFIG_ARCH_HIPRI_INTERRUPT is selected) 
*/
 
-#ifndef CONFIG_ARMV8R_DECODEFIQ
+#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
 
   cpsr |= PSR_F_BIT;
 
-#endif /* !CONFIG_ARMV8R_DECODEFIQ */
+#endif /* !CONFIG_ARCH_HIPRI_INTERRUPT */
 
 #ifdef CONFIG_ARM_THUMB
   cpsr |= PSR_T_BIT;
diff --git a/arch/arm/src/armv8-r/arm_vectors.S 
b/arch/arm/src/armv8-r/arm_vectors.S
index 4c2d051da3..891bf904d2 100644
--- a/arch/arm/src/armv8-r/arm_vectors.S
+++ b/arch/arm/src/armv8-r/arm_vectors.S
@@ -163,7 +163,7 @@ arm_vectorirq:
 
        /* Switch to SYS mode */
 
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
        cpsid           if, #PSR_MODE_SYS
 #else
        cpsid           i, #PSR_MODE_SYS
@@ -273,7 +273,7 @@ arm_vectorsvc:
 
        /* Switch to SYS mode */
 
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
        cpsid           if, #PSR_MODE_SYS
 #else
        cpsid           i, #PSR_MODE_SYS
@@ -384,7 +384,7 @@ arm_vectordata:
 
        /* Switch to SYS mode */
 
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
        cpsid           if, #PSR_MODE_SYS
 #else
        cpsid           i, #PSR_MODE_SYS
@@ -625,14 +625,14 @@ arm_vectorundefinsn:
  *
  ****************************************************************************/
 
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
        .globl  arm_decodefiq
 #endif
        .globl  arm_vectorfiq
        .type   arm_vectorfiq, %function
 
 arm_vectorfiq:
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
 
        /* Save the LR and SPSR onto the SYS mode stack before switch. */
 
@@ -754,7 +754,7 @@ g_intstacktop:
  *  Name: g_fiqstackalloc/g_fiqstacktop
  ****************************************************************************/
 
-#ifdef CONFIG_ARMV8R_DECODEFIQ
+#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
        .globl  g_fiqstackalloc
        .type   g_fiqstackalloc, object
        .globl  g_fiqstacktop

Reply via email to