armv7a pci irq support
Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
parent
3b1870028c
commit
1cb81f9a8f
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
162
arch/arm/src/armv7-a/arm_gicv2m.c
Normal file
162
arch/arm/src/armv7-a/arm_gicv2m.c
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user