forked from RT-Thread/rt-thread
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PIC: Add ARM GICv2/v3, and V2M, ITS support.
GIC (Generic Interrupt Controller) is the ARMv7/v8 PIC. V2M is the PCI MSI/MSI-X for GICv2. ITS is the PCI MSI/MSI-X for GICv3/v4. Signed-off-by: GuEe-GUI <[email protected]>
- Loading branch information
Showing
11 changed files
with
4,441 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Copyright (c) 2006-2022, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef __DT_BINDINGS_SIZE_H__ | ||
#define __DT_BINDINGS_SIZE_H__ | ||
|
||
#define SIZE_KB 1024 | ||
#define SIZE_MB (1024 * SIZE_KB) | ||
#define SIZE_GB (1024 * SIZE_MB) | ||
|
||
#define SIZE_ALIGN(size, align) (((size) + (align) - 1) & ~((align) - 1)) | ||
#define SIZE_ALIGN_DOWN(size, align) ((size) & ~((align) - 1)) | ||
|
||
#endif /* __DT_BINDINGS_SIZE_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/* | ||
* Copyright (c) 2006-2023, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2023-01-30 GuEe-GUI first version | ||
*/ | ||
|
||
#include <rthw.h> | ||
#include <rtthread.h> | ||
|
||
#define DBG_TAG "pic.gic*" | ||
#define DBG_LVL DBG_INFO | ||
#include <rtdbg.h> | ||
|
||
#include <drivers/pic.h> | ||
|
||
#include "pic-gicv2.h" | ||
#include "pic-gic-common.h" | ||
|
||
void gic_common_init_quirk_ofw(const struct rt_ofw_node *ic_np, const struct gic_quirk *quirks, void *data) | ||
{ | ||
for (; quirks->desc; ++quirks) | ||
{ | ||
if (!quirks->compatible || !rt_ofw_node_is_compatible(ic_np, quirks->compatible)) | ||
{ | ||
continue; | ||
} | ||
|
||
RT_ASSERT(quirks->init != RT_NULL); | ||
|
||
if (!quirks->init(data)) | ||
{ | ||
LOG_I("Enable workaround for %s", quirks->desc); | ||
} | ||
} | ||
} | ||
|
||
void gic_common_init_quirk_hw(rt_uint32_t iidr, const struct gic_quirk *quirks, void *data) | ||
{ | ||
for (; quirks->desc; ++quirks) | ||
{ | ||
if (quirks->compatible) | ||
{ | ||
continue; | ||
} | ||
|
||
if (quirks->iidr == (iidr & quirks->iidr_mask)) | ||
{ | ||
RT_ASSERT(quirks->init != RT_NULL); | ||
|
||
if (!quirks->init(data)) | ||
{ | ||
LOG_I("Enable workaround for %s", quirks->desc); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void gic_common_sgi_config(void *base, void *data, int irq_base) | ||
{ | ||
#ifdef RT_USING_SMP | ||
if (irq_base < 2) | ||
{ | ||
struct rt_pic_irq *pirq; | ||
|
||
#define DECLARE_GIC_IPI(ipi, hwirq) \ | ||
rt_pic_config_ipi(data, ipi, hwirq); \ | ||
pirq = rt_pic_find_ipi(data, ipi); \ | ||
pirq->mode = RT_IRQ_MODE_EDGE_RISING; \ | ||
|
||
DECLARE_GIC_IPI(RT_SCHEDULE_IPI, 0); | ||
DECLARE_GIC_IPI(RT_STOP_IPI, 1); | ||
|
||
#undef DECLARE_GIC_IPI | ||
} | ||
#endif /* RT_USING_SMP */ | ||
} | ||
|
||
rt_err_t gic_common_configure_irq(void *base, int irq, rt_uint32_t mode, void (*sync_access)(void *), void *data) | ||
{ | ||
rt_err_t err = RT_EOK; | ||
rt_ubase_t level; | ||
rt_uint32_t val, oldval; | ||
rt_uint32_t confoff = (irq / 16) * 4; | ||
rt_uint32_t confmask = 0x2 << ((irq % 16) * 2); | ||
static struct rt_spinlock ic_lock = { 0 }; | ||
|
||
level = rt_spin_lock_irqsave(&ic_lock); | ||
|
||
val = oldval = HWREG32(base + confoff); | ||
|
||
if (mode & RT_IRQ_MODE_LEVEL_MASK) | ||
{ | ||
/* Level-sensitive */ | ||
val &= ~confmask; | ||
} | ||
else if (mode & RT_IRQ_MODE_EDGE_BOTH) | ||
{ | ||
/* Edge-triggered */ | ||
val |= confmask; | ||
} | ||
|
||
if (val != oldval) | ||
{ | ||
HWREG32(base + confoff) = val; | ||
|
||
if (HWREG32(base + confoff) != val) | ||
{ | ||
err = -RT_EINVAL; | ||
} | ||
if (sync_access) | ||
{ | ||
sync_access(data); | ||
} | ||
} | ||
|
||
rt_spin_unlock_irqrestore(&ic_lock, level); | ||
|
||
return err; | ||
} | ||
|
||
void gic_common_dist_config(void *base, int max_irqs, void (*sync_access)(void *), void *data) | ||
{ | ||
rt_uint32_t i; | ||
|
||
/* Set all global interrupts to be level triggered, active low. */ | ||
for (i = 32; i < max_irqs; i += 16) | ||
{ | ||
HWREG32(base + GIC_DIST_CONFIG + i / 4) = GICD_INT_ACTLOW_LVLTRIG; | ||
} | ||
|
||
/* Set priority on all global interrupts. */ | ||
for (i = 32; i < max_irqs; i += 4) | ||
{ | ||
HWREG32(base + GIC_DIST_PRI + i * 4 / 4) = GICD_INT_DEF_PRI_X4; | ||
} | ||
|
||
/* Disable all SPIs. */ | ||
for (i = 32; i < max_irqs; i += 32) | ||
{ | ||
HWREG32(base + GIC_DIST_ACTIVE_CLEAR + i / 8) = GICD_INT_EN_CLR_X32; | ||
HWREG32(base + GIC_DIST_ENABLE_CLEAR + i / 8) = GICD_INT_EN_CLR_X32; | ||
} | ||
|
||
if (sync_access) | ||
{ | ||
sync_access(data); | ||
} | ||
} | ||
|
||
void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void *data) | ||
{ | ||
rt_uint32_t i; | ||
|
||
/* Disable all SGIs, PPIs. */ | ||
for (i = 0; i < nr; i += 32) | ||
{ | ||
HWREG32(base + GIC_DIST_ACTIVE_CLEAR + i / 8) = GICD_INT_EN_CLR_X32; | ||
HWREG32(base + GIC_DIST_ENABLE_CLEAR + i / 8) = GICD_INT_EN_CLR_X32; | ||
} | ||
|
||
/* Set priority on all PPI and SGI. */ | ||
for (i = 0; i < nr; i += 4) | ||
{ | ||
HWREG32(base + GIC_DIST_PRI + i * 4 / 4) = GICD_INT_DEF_PRI_X4; | ||
} | ||
|
||
if (sync_access) | ||
{ | ||
sync_access(data); | ||
} | ||
} | ||
|
||
void gic_fill_ppi_affinity(bitmap_t *affinity) | ||
{ | ||
for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid) | ||
{ | ||
RT_IRQ_AFFINITY_SET(affinity, cpuid); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (c) 2006-2023, RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2023-01-30 GuEe-GUI first version | ||
*/ | ||
|
||
#ifndef __IRQ_GIC_COMMON_H__ | ||
#define __IRQ_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 | ||
|
||
#define GICD_INT_DEF_PRI 0xa0U | ||
#define GICD_INT_DEF_PRI_X4 \ | ||
( \ | ||
(GICD_INT_DEF_PRI << 24) | \ | ||
(GICD_INT_DEF_PRI << 16) | \ | ||
(GICD_INT_DEF_PRI << 8) | \ | ||
GICD_INT_DEF_PRI \ | ||
) | ||
|
||
struct gic_quirk | ||
{ | ||
const char *desc; | ||
const char *compatible; | ||
rt_err_t (*init)(void *data); | ||
|
||
rt_uint32_t iidr; | ||
rt_uint32_t iidr_mask; | ||
}; | ||
|
||
void gic_common_init_quirk_ofw(const struct rt_ofw_node *ic_np, const struct gic_quirk *quirks, void *data); | ||
void gic_common_init_quirk_hw(rt_uint32_t iidr, const struct gic_quirk *quirks, void *data); | ||
|
||
void gic_common_sgi_config(void *base, void *data, int irq_base); | ||
rt_err_t gic_common_configure_irq(void *base, int irq, rt_uint32_t mode, void (*sync_access)(void *), void *data); | ||
void gic_common_dist_config(void *base, int max_irqs, void (*sync_access)(void *), void *data); | ||
void gic_common_cpu_config(void *base, int nr, void (*sync_access)(void *), void *data); | ||
|
||
void gic_fill_ppi_affinity(bitmap_t *affinity); | ||
|
||
#ifdef RT_PIC_ARM_GIC_V2M | ||
rt_err_t gicv2m_ofw_probe(struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *id); | ||
#endif | ||
#ifdef RT_PIC_ARM_GIC_V3_ITS | ||
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__ */ |
Oops, something went wrong.