armv7a pci irq support

Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
lipengfei28 2024-07-12 16:05:57 +08:00 committed by Mateusz Szafoni
parent 3b1870028c
commit 1cb81f9a8f
9 changed files with 283 additions and 5 deletions

View File

@ -52,6 +52,10 @@ if(CONFIG_ARCH_PERF_EVENTS)
list(APPEND SRCS arm_perf.c) list(APPEND SRCS arm_perf.c)
endif() endif()
if(CONFIG_ARMV7A_GICv2M)
list(APPEND SRCS arm_gicv2m.c)
endif()
if(CONFIG_ARMV7A_HAVE_PTM) if(CONFIG_ARMV7A_HAVE_PTM)
list(APPEND SRCS arm_timer.c) list(APPEND SRCS arm_timer.c)
endif() endif()

View File

@ -24,6 +24,17 @@ config ARMV7A_GIC_EOIMODE
Enable GICC_CTLR.EOImode, this will separates the priority drop and interrupt Enable GICC_CTLR.EOImode, this will separates the priority drop and interrupt
deactivation operations. 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 endif # ARMV7A_HAVE_GICv2
config ARMV7A_HAVE_GTM config ARMV7A_HAVE_GTM

View File

@ -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_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
CMN_CSRCS += arm_perf.c cp15_cacheops.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 CMN_CSRCS += arm_timer.c
endif endif

View File

@ -210,6 +210,10 @@ void arm_gic0_initialize(void)
putreg32(0x01010101, GIC_ICDIPTR(irq)); /* SPI on CPU0 */ putreg32(0x01010101, GIC_ICDIPTR(irq)); /* SPI on CPU0 */
} }
#ifdef CONFIG_ARMV7A_GICv2M
gic_v2m_initialize();
#endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */ /* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */

View File

@ -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
}

View File

@ -136,6 +136,11 @@
/* 0x0020-0x003c: Implementation defined */ /* 0x0020-0x003c: Implementation defined */
/* 0x0040-0x007c: Reserved */ /* 0x0040-0x007c: Reserved */
/* V2M Registers */
#define GIC_V2MTYPER_OFFSET 0x008
#define GIC_V2MSETSPI_OFFSET 0x040
/* Interrupt Security Registers: 0x0080-0x009c */ /* Interrupt Security Registers: 0x0080-0x009c */
#define GIC_ICDISR_OFFSET(n) (0x0080 + GIC_OFFSET32(n)) #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_ICDPIDR(n) (MPCORE_ICD_VBASE+GIC_ICDPIDR_OFFSET(n))
#define GIC_ICDCIDR(n) (MPCORE_ICD_VBASE+GIC_ICDCIDR_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 *********************************************/ /* GIC Register Bit Definitions *********************************************/
/* CPU Interface registers */ /* CPU Interface registers */
@ -557,6 +567,14 @@
# define GIC_ICDSGIR_TGTFILTER_THIS (2 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt is sent to requesting CPU only */ # define GIC_ICDSGIR_TGTFILTER_THIS (2 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt is sent to requesting CPU only */
/* Bits 26-31: Reserved */ /* 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 ************************************************************/ /* Interrupt IDs ************************************************************/
/* The Global Interrupt Controller (GIC) collects up to 224 interrupt /* 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) # define arm_gic_dump(msg, all, irq)
#endif #endif
#ifdef CONFIG_ARMV7A_GICv2M
int gic_v2m_initialize(void);
#endif
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -73,5 +73,6 @@
#define MPCORE_GTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_GTM_OFFSET) #define MPCORE_GTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_GTM_OFFSET)
#define MPCORE_PTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_PTM_OFFSET) #define MPCORE_PTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_PTM_OFFSET)
#define MPCORE_ICD_VBASE (CHIP_MPCORE_VBASE+MPCORE_ICD_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 */ #endif /* __ARCH_ARM_SRC_ARMV7_A_MPCORE_H */

View File

@ -35,6 +35,7 @@
#define CHIP_MPCORE_VBASE 0x8000000 #define CHIP_MPCORE_VBASE 0x8000000
#define MPCORE_ICD_OFFSET 0x0000 #define MPCORE_ICD_OFFSET 0x0000
#define MPCORE_ICC_OFFSET 0x10000 #define MPCORE_ICC_OFFSET 0x10000
#define MPCORE_V2M_OFFSET 0x20000
#define PGTABLE_SIZE 0x00004000 #define PGTABLE_SIZE 0x00004000
#define PGTABLE_BASE_PADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - PGTABLE_SIZE * CONFIG_SMP_NCPUS) #define PGTABLE_BASE_PADDR (CONFIG_RAM_START + CONFIG_RAM_SIZE - PGTABLE_SIZE * CONFIG_SMP_NCPUS)

View File

@ -24,6 +24,7 @@
#include <errno.h> #include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/lib/math32.h> #include <nuttx/lib/math32.h>
#include <nuttx/pci/pci.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, static int pci_ecam_write_io(FAR struct pci_bus_s *bus, uintptr_t addr,
int size, uint32_t val); 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 * Private Types
****************************************************************************/ ****************************************************************************/
@ -77,10 +93,16 @@ struct pci_ecam_s
static const struct pci_ops_s g_pci_ecam_ops = static const struct pci_ops_s g_pci_ecam_ops =
{ {
.read = pci_ecam_read_config, .read = pci_ecam_read_config,
.write = pci_ecam_write_config, .write = pci_ecam_write_config,
.read_io = pci_ecam_read_io, .read_io = pci_ecam_read_io,
.write_io = pci_ecam_write_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; 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 * Public Functions
****************************************************************************/ ****************************************************************************/