[DRIVER/PIC] Add ARM GICv2/v3 V2M, ITS support.

Fix some code style and init for V2M, ITS.

V2M is the PCI MSI/MSI-X for GICv2.
ITS is the PCI MSI/MSI-X for GICv3/v4.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
GuEe-GUI authored and Rbb666 committed 2024-09-19 21:14:42 +08:00
1 parent 94e49755af
commit 3d503e931b
8 files changed
+2157 -54

No files matched your search

+21 -1
View File
@@ -1,6 +1,7 @@
menuconfig RT_USING_PIC
bool "Using Programmable Interrupt Controller (PIC)"
select RT_USING_BITMAP
select RT_USING_ADT
select RT_USING_ADT_BITMAP
depends on RT_USING_DM
default n
@@ -22,12 +23,31 @@ config RT_PIC_ARM_GIC
select RT_USING_OFW
default n
config RT_PIC_ARM_GIC_V2M
bool "ARM GIC V2M" if RT_PIC_ARM_GIC && RT_PCI_MSI
depends on RT_USING_OFW
default n
config RT_PIC_ARM_GIC_V3
bool "ARM GICv3"
depends on RT_USING_PIC
select RT_USING_OFW
default n
config RT_PIC_ARM_GIC_V3_ITS
bool "ARM GICv3 ITS (Interrupt Translation Service)" if RT_PIC_ARM_GIC_V3 && RT_PCI_MSI
depends on RT_USING_OFW
select RT_USING_ADT_REF
default n
config RT_PIC_ARM_GIC_V3_ITS_IRQ_MAX
int "IRQ maximum used"
depends on RT_PIC_ARM_GIC_V3_ITS
default 127 if ARCH_CPU_64BIT
default 63
help
Recommended to be based on the bit length (full bits) of maximum usage.
config RT_PIC_ARM_GIC_MAX_NR
int
depends on RT_USING_PIC
+6
View File
@@ -16,9 +16,15 @@ if GetDepend(['RT_PIC_ARM_GIC']) or GetDepend(['RT_PIC_ARM_GIC_V3']):
if GetDepend(['RT_PIC_ARM_GIC']):
src += ['pic-gicv2.c']
if GetDepend(['RT_PIC_ARM_GIC_V2M']):
src += ['pic-gicv2m.c']
if GetDepend(['RT_PIC_ARM_GIC_V3']):
src += ['pic-gicv3.c']
if GetDepend(['RT_PIC_ARM_GIC_V3_ITS']):
src += ['pic-gicv3-its.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
+7 -3
View File
@@ -8,10 +8,14 @@
* 2023-01-30 GuEe-GUI first version
*/
#ifndef __IRQ_GIC_COMMON_H__
#define __IRQ_GIC_COMMON_H__
#ifndef __PIC_GIC_COMMON_H__
#define __PIC_GIC_COMMON_H__
#include <rtdef.h>
#ifdef RT_PCI_MSI
#include <drivers/pci_msi.h>
#endif
#include <drivers/ofw.h>
#define GIC_SGI_NR 16
@@ -52,4 +56,4 @@ rt_err_t gicv2m_ofw_probe(struct rt_ofw_node *ic_np, const struct rt_ofw_node_id
rt_err_t gicv3_its_ofw_probe(struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *id);
#endif
#endif /* __IRQ_GIC_COMMON_H__ */
#endif /* __PIC_GIC_COMMON_H__ */
+2
View File
@@ -128,6 +128,8 @@ static void gicv2_cpu_init(struct gicv2 *gic)
#ifdef ARCH_SUPPORT_HYP
_gicv2_eoi_mode_ns = RT_TRUE;
#else
_gicv2_eoi_mode_ns = !!rt_ofw_bootargs_select("pic.gicv2_eoimode", 0);
#endif
if (_gicv2_eoi_mode_ns)
+378
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+25 -7
View File
@@ -266,20 +266,25 @@ static void gicv3_dist_init(void)
HWREG64(base + GICD_IROUTERnE + i * 8) = affinity;
}
if (GICD_TYPER_NUM_LPIS(_gic.gicd_typer))
if (GICD_TYPER_NUM_LPIS(_gic.gicd_typer) > 1)
{
/* Max LPI = 8192 + Math.pow(2, num_LPIs + 1) - 1 */
rt_size_t num_lpis = (1 << (GICD_TYPER_NUM_LPIS(_gic.gicd_typer) + 1)) + 1;
rt_size_t num_lpis = 1UL << (GICD_TYPER_NUM_LPIS(_gic.gicd_typer) + 1);
_gic.lpi_nr = rt_min_t(int, num_lpis, 1 << GICD_TYPER_ID_BITS(_gic.gicd_typer));
_gic.lpi_nr = rt_min_t(int, num_lpis, 1UL << GICD_TYPER_ID_BITS(_gic.gicd_typer));
}
else
{
_gic.lpi_nr = 1 << GICD_TYPER_ID_BITS(_gic.gicd_typer);
_gic.lpi_nr = 1UL << GICD_TYPER_ID_BITS(_gic.gicd_typer);
}
/* SPI + eSPI + LPIs */
_gic.irq_nr = _gic.line_nr - 32 + _gic.espi_nr + _gic.lpi_nr;
_gic.irq_nr = _gic.line_nr - 32 + _gic.espi_nr;
#ifdef RT_PIC_ARM_GIC_V3_ITS
/* ITS will allocate the same number of lpi PIRQs */
_gic.lpi_nr = rt_min_t(rt_size_t, RT_PIC_ARM_GIC_V3_ITS_IRQ_MAX, _gic.lpi_nr);
_gic.irq_nr += _gic.lpi_nr;
#endif
}
static void gicv3_redist_enable(rt_bool_t enable)
@@ -389,6 +394,8 @@ static void gicv3_cpu_init(void)
int cpu_id = rt_hw_cpu_id();
#ifdef ARCH_SUPPORT_HYP
_gicv3_eoi_mode_ns = RT_TRUE;
#else
_gicv3_eoi_mode_ns = !!rt_ofw_bootargs_select("pic.gicv3_eoimode", 0);
#endif
base = gicv3_percpu_redist_sgi_base();
@@ -700,6 +707,7 @@ static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
if (pirq && hwirq >= GIC_SGI_NR)
{
pirq->mode = mode;
pirq->priority = GICD_INT_DEF_PRI;
switch (gicv3_hwirq_type(hwirq))
{
@@ -708,7 +716,6 @@ static int gicv3_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
break;
case SPI_TYPE:
case ESPI_TYPE:
pirq->priority = GICD_INT_DEF_PRI;
RT_IRQ_AFFINITY_SET(pirq->affinity, _init_cpu_id);
default:
break;
@@ -823,7 +830,18 @@ static rt_bool_t gicv3_handler(void *data)
}
else
{
pirq = rt_pic_find_irq(&gic->parent, hwirq - GIC_SGI_NR);
int irq_index;
if (hwirq < 8192)
{
irq_index = hwirq - GIC_SGI_NR;
}
else
{
irq_index = gic->irq_nr - gic->lpi_nr + hwirq - 8192;
}
pirq = rt_pic_find_irq(&gic->parent, irq_index);
}
gicv3_irq_ack(pirq);
File diff suppressed because it is too large. Load diff