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