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

raiden00 pushed a commit to branch releases/12.7
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 1cb81f9a8f96022491c5f92923aecedbcdecd4ab
Author: lipengfei28 <[email protected]>
AuthorDate: Fri Jul 12 16:05:57 2024 +0800

    armv7a pci irq support
    
    Signed-off-by: lipengfei28 <[email protected]>
---
 arch/arm/src/armv7-a/CMakeLists.txt |   4 +
 arch/arm/src/armv7-a/Kconfig        |  11 +++
 arch/arm/src/armv7-a/Make.defs      |   6 +-
 arch/arm/src/armv7-a/arm_gicv2.c    |   4 +
 arch/arm/src/armv7-a/arm_gicv2m.c   | 162 ++++++++++++++++++++++++++++++++++++
 arch/arm/src/armv7-a/gic.h          |  22 +++++
 arch/arm/src/armv7-a/mpcore.h       |   1 +
 arch/arm/src/qemu/chip.h            |   1 +
 drivers/pci/pci_ecam.c              |  77 ++++++++++++++++-
 9 files changed, 283 insertions(+), 5 deletions(-)

diff --git a/arch/arm/src/armv7-a/CMakeLists.txt 
b/arch/arm/src/armv7-a/CMakeLists.txt
index cd390645d1..042be6cffb 100644
--- a/arch/arm/src/armv7-a/CMakeLists.txt
+++ b/arch/arm/src/armv7-a/CMakeLists.txt
@@ -52,6 +52,10 @@ if(CONFIG_ARCH_PERF_EVENTS)
   list(APPEND SRCS arm_perf.c)
 endif()
 
+if(CONFIG_ARMV7A_GICv2M)
+  list(APPEND SRCS arm_gicv2m.c)
+endif()
+
 if(CONFIG_ARMV7A_HAVE_PTM)
   list(APPEND SRCS arm_timer.c)
 endif()
diff --git a/arch/arm/src/armv7-a/Kconfig b/arch/arm/src/armv7-a/Kconfig
index e4e0eca96d..dc8db040e8 100644
--- a/arch/arm/src/armv7-a/Kconfig
+++ b/arch/arm/src/armv7-a/Kconfig
@@ -24,6 +24,17 @@ config ARMV7A_GIC_EOIMODE
                Enable GICC_CTLR.EOImode, this will separates the priority drop 
and interrupt
                deactivation operations.
 
+config ARMV7A_GICV2_LEGACY_IRQ0
+       int "pci legacy irq0 default val"
+       default 35
+       ---help---
+               The qemu pci lagacy irq0 default is 35. -1 mean disable
+
+config ARMV7A_GICv2M
+       bool "gic support msi irq"
+       depends on PCI_MSIX
+       default n
+
 endif # ARMV7A_HAVE_GICv2
 
 config ARMV7A_HAVE_GTM
diff --git a/arch/arm/src/armv7-a/Make.defs b/arch/arm/src/armv7-a/Make.defs
index 331bb62fc1..f757e3d11c 100644
--- a/arch/arm/src/armv7-a/Make.defs
+++ b/arch/arm/src/armv7-a/Make.defs
@@ -47,7 +47,11 @@ CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
 CMN_CSRCS += arm_perf.c cp15_cacheops.c
 
-ifeq ($(CONFIG_ARMV7A_HAVE_PTM), y)
+ifeq ($(CONFIG_ARMV7A_GICv2M),y)
+  CMN_CSRCS += arm_gicv2m.c
+endif
+
+ifeq ($(CONFIG_ARMV7A_HAVE_PTM),y)
   CMN_CSRCS += arm_timer.c
 endif
 
diff --git a/arch/arm/src/armv7-a/arm_gicv2.c b/arch/arm/src/armv7-a/arm_gicv2.c
index 47a132fbc6..f4730ce243 100644
--- a/arch/arm/src/armv7-a/arm_gicv2.c
+++ b/arch/arm/src/armv7-a/arm_gicv2.c
@@ -210,6 +210,10 @@ void arm_gic0_initialize(void)
       putreg32(0x01010101, GIC_ICDIPTR(irq));  /* SPI on CPU0 */
     }
 
+#ifdef CONFIG_ARMV7A_GICv2M
+  gic_v2m_initialize();
+#endif
+
 #ifdef CONFIG_SMP
   /* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
 
diff --git a/arch/arm/src/armv7-a/arm_gicv2m.c 
b/arch/arm/src/armv7-a/arm_gicv2m.c
new file mode 100644
index 0000000000..8d96a5c2cb
--- /dev/null
+++ b/arch/arm/src/armv7-a/arm_gicv2m.c
@@ -0,0 +1,162 @@
+/****************************************************************************
+ * arch/arm/src/armv7-a/arm_gicv2m.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 <errno.h>
+
+#include <nuttx/bits.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/pci/pci.h>
+#include <nuttx/spinlock.h>
+
+#include "arm_internal.h"
+#include "gic.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct gic_v2m_s
+{
+  spinlock_t lock;
+  uint32_t spi_start;
+  uint32_t spi_number;
+  unsigned long *spi_bitmap;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct gic_v2m_s g_v2m =
+{
+  SP_LOCKED
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool is_valid_spi(uint32_t base, uint32_t number)
+{
+  if (base < GIC_IRQ_SPI)
+    {
+      return false;
+    }
+
+  if (number == 0 || base + number > NR_IRQS)
+    {
+      return false;
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int gic_v2m_initialize(void)
+{
+  uint32_t typer;
+
+  typer = getreg32(GIC_V2MTYPER);
+  g_v2m.spi_start = GIC_V2MTYPES_BASE(typer);
+  g_v2m.spi_number = GIC_V2MTYPES_NUMBER(typer);
+
+  if (!is_valid_spi(g_v2m.spi_start, g_v2m.spi_number))
+    {
+      return -EINVAL;
+    }
+
+  g_v2m.spi_bitmap = kmm_zalloc(BITS_TO_LONGS(g_v2m.spi_number));
+  if (g_v2m.spi_bitmap == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  return 0;
+}
+
+int up_alloc_irq_msi(int *num)
+{
+  irqstate_t flags;
+  int offset;
+  int irq;
+  int i;
+
+  flags = spin_lock_irqsave(&g_v2m.lock);
+  offset = bitmap_find_free_region(g_v2m.spi_bitmap, g_v2m.spi_number, *num);
+  spin_unlock_irqrestore(&g_v2m.lock, flags);
+  irq = g_v2m.spi_start + offset;
+  for (i = 0; i < *num; i++)
+    {
+      arm_gic_irq_trigger(i + irq, true);
+    }
+
+  return irq;
+}
+
+void up_release_irq_msi(int *irq, int num)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&g_v2m.lock);
+  bitmap_release_region(g_v2m.spi_bitmap, *irq - g_v2m.spi_start, num);
+  spin_unlock_irqrestore(&g_v2m.lock, flags);
+}
+
+int up_connect_irq(int *irq, int num,
+                   uintptr_t *mar, uint32_t *mdr)
+{
+  *mar = GIC_V2MSETSPI;
+  *mdr = *irq;
+  return 0;
+}
+
+/****************************************************************************
+ * Name: up_get_legacy_irq
+ *
+ * Description:
+ *   Reserve vector for legacy
+ *
+ ****************************************************************************/
+
+int up_get_legacy_irq(uint32_t devfn, uint8_t line, uint8_t pin)
+{
+#if CONFIG_ARMV7A_GICV2_LEGACY_IRQ0 >= 0
+  uint8_t slot;
+  uint8_t tmp;
+
+  UNUSED(line);
+  slot = PCI_SLOT(devfn);
+  tmp = (pin - 1 + slot) % 4;
+  return CONFIG_ARMV7A_GICV2_LEGACY_IRQ0 + tmp;
+#else
+  return -ENOTSUP;
+#endif
+}
diff --git a/arch/arm/src/armv7-a/gic.h b/arch/arm/src/armv7-a/gic.h
index b652dea0a1..ce7cbd0ec6 100644
--- a/arch/arm/src/armv7-a/gic.h
+++ b/arch/arm/src/armv7-a/gic.h
@@ -136,6 +136,11 @@
                                              /* 0x0020-0x003c: Implementation 
defined */
                                              /* 0x0040-0x007c: Reserved */
 
+/* V2M Registers */
+
+#define GIC_V2MTYPER_OFFSET        0x008
+#define GIC_V2MSETSPI_OFFSET       0x040
+
 /* Interrupt Security Registers: 0x0080-0x009c */
 
 #define GIC_ICDISR_OFFSET(n)       (0x0080 + GIC_OFFSET32(n))
@@ -277,6 +282,11 @@
 #define GIC_ICDPIDR(n)             (MPCORE_ICD_VBASE+GIC_ICDPIDR_OFFSET(n))
 #define GIC_ICDCIDR(n)             (MPCORE_ICD_VBASE+GIC_ICDCIDR_OFFSET(n))
 
+/* V2M Registers */
+
+#define GIC_V2MTYPER               (MPCORE_V2M_VBASE + GIC_V2MTYPER_OFFSET)
+#define GIC_V2MSETSPI              (MPCORE_V2M_VBASE + GIC_V2MSETSPI_OFFSET)
+
 /* GIC Register Bit Definitions *********************************************/
 
 /* CPU Interface registers */
@@ -557,6 +567,14 @@
 #  define GIC_ICDSGIR_TGTFILTER_THIS  (2 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* 
Interrupt is sent to requesting CPU only */
                                                                          /* 
Bits 26-31: Reserved */
 
+/* V2M Registers */
+
+#define GIC_V2MTYPES_BASE_SHIFT       16
+#define GIC_V2MTYPES_BASE_MASK        0x3FF
+#define GIC_V2MTYPES_NUMBER_MASK      0x3FF
+#define GIC_V2MTYPES_BASE(x)          (((x) >> GIC_V2MTYPES_BASE_SHIFT) & 
GIC_V2MTYPES_BASE_MASK)
+#define GIC_V2MTYPES_NUMBER(x)        ((x) & GIC_V2MTYPES_NUMBER_MASK)
+
 /* Interrupt IDs ************************************************************/
 
 /* The Global Interrupt Controller (GIC) collects up to 224 interrupt
@@ -886,6 +904,10 @@ void arm_gic_dump(const char *msg, bool all, int irq);
 #  define arm_gic_dump(msg, all, irq)
 #endif
 
+#ifdef CONFIG_ARMV7A_GICv2M
+int gic_v2m_initialize(void);
+#endif
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/arch/arm/src/armv7-a/mpcore.h b/arch/arm/src/armv7-a/mpcore.h
index 404c17dc75..524b9439c5 100644
--- a/arch/arm/src/armv7-a/mpcore.h
+++ b/arch/arm/src/armv7-a/mpcore.h
@@ -73,5 +73,6 @@
 #define MPCORE_GTM_VBASE   (CHIP_MPCORE_VBASE+MPCORE_GTM_OFFSET)
 #define MPCORE_PTM_VBASE   (CHIP_MPCORE_VBASE+MPCORE_PTM_OFFSET)
 #define MPCORE_ICD_VBASE   (CHIP_MPCORE_VBASE+MPCORE_ICD_OFFSET)
+#define MPCORE_V2M_VBASE   (CHIP_MPCORE_VBASE+MPCORE_V2M_OFFSET)
 
 #endif /* __ARCH_ARM_SRC_ARMV7_A_MPCORE_H */
diff --git a/arch/arm/src/qemu/chip.h b/arch/arm/src/qemu/chip.h
index ab2ccc38fa..e3eb6a816e 100644
--- a/arch/arm/src/qemu/chip.h
+++ b/arch/arm/src/qemu/chip.h
@@ -35,6 +35,7 @@
 #define CHIP_MPCORE_VBASE     0x8000000
 #define MPCORE_ICD_OFFSET     0x0000
 #define MPCORE_ICC_OFFSET     0x10000
+#define MPCORE_V2M_OFFSET     0x20000
 
 #define PGTABLE_SIZE          0x00004000
 #define PGTABLE_BASE_PADDR    (CONFIG_RAM_START + CONFIG_RAM_SIZE - 
PGTABLE_SIZE * CONFIG_SMP_NCPUS)
diff --git a/drivers/pci/pci_ecam.c b/drivers/pci/pci_ecam.c
index f238bb4eee..111baa20c4 100644
--- a/drivers/pci/pci_ecam.c
+++ b/drivers/pci/pci_ecam.c
@@ -24,6 +24,7 @@
 
 #include <errno.h>
 
+#include <nuttx/arch.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/lib/math32.h>
 #include <nuttx/pci/pci.h>
@@ -61,6 +62,21 @@ static int pci_ecam_read_io(FAR struct pci_bus_s *bus, 
uintptr_t addr,
 static int pci_ecam_write_io(FAR struct pci_bus_s *bus, uintptr_t addr,
                              int size, uint32_t val);
 
+static int pci_ecam_get_irq(FAR struct pci_bus_s *bus, uint32_t devfn,
+                            uint8_t line, uint8_t pin);
+
+#ifdef CONFIG_PCI_MSIX
+static int pci_ecam_alloc_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                              int num);
+
+static void pci_ecam_release_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                                 int num);
+
+static int pci_ecam_connect_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                                int num, FAR uintptr_t *mar,
+                                FAR uint32_t *mdr);
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -77,10 +93,16 @@ struct pci_ecam_s
 
 static const struct pci_ops_s g_pci_ecam_ops =
 {
-  .read     = pci_ecam_read_config,
-  .write    = pci_ecam_write_config,
-  .read_io  = pci_ecam_read_io,
-  .write_io = pci_ecam_write_io,
+  .read        = pci_ecam_read_config,
+  .write       = pci_ecam_write_config,
+  .read_io     = pci_ecam_read_io,
+  .write_io    = pci_ecam_write_io,
+  .get_irq     = pci_ecam_get_irq,
+#ifdef CONFIG_PCI_MSIX
+  .alloc_irq   = pci_ecam_alloc_irq,
+  .release_irq = pci_ecam_release_irq,
+  .connect_irq = pci_ecam_connect_irq,
+#endif
 };
 
 /****************************************************************************
@@ -368,6 +390,53 @@ static int pci_ecam_write_io(FAR struct pci_bus_s *bus, 
uintptr_t addr,
   return OK;
 }
 
+#ifdef CONFIG_PCI_MSIX
+static int pci_ecam_alloc_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                              int num)
+{
+  *irq = up_alloc_irq_msi(&num);
+  return num;
+}
+
+static void pci_ecam_release_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                                 int num)
+{
+  return up_release_irq_msi(irq, num);
+}
+
+static int pci_ecam_connect_irq(FAR struct pci_bus_s *bus, FAR int *irq,
+                                int num, FAR uintptr_t *mar,
+                                FAR uint32_t *mdr)
+{
+  return up_connect_irq(irq, num, mar, mdr);
+}
+#endif
+
+/****************************************************************************
+ * Name: pci_ecam_get_irq
+ *
+ * Description:
+ *  Get interrupt number associated with a given INTx line.
+ *
+ * Input Parameters:
+ *   bus   - Bus that PCI device resides
+ *   devfn - The pci device and function number
+ *   line  - Activated PCI legacy interrupt line
+ *   pin   - Intx pin number
+ *
+ * Returned Value:
+ *   Return interrupt number associated with a given INTx
+ *
+ ****************************************************************************/
+
+static int pci_ecam_get_irq(FAR struct pci_bus_s *bus, uint32_t devfn,
+                            uint8_t line, uint8_t pin)
+{
+  UNUSED(bus);
+
+  return up_get_legacy_irq(devfn, line, pin);
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/

Reply via email to