#include <config.h>
#include <arch/machine/gic_pl390.h>
#define TARGET_CPU_ALLINT(CPU) ( \
( ((CPU)&0xff)<<0u ) |\
( ((CPU)&0xff)<<8u ) |\
( ((CPU)&0xff)<<16u ) |\
( ((CPU)&0xff)<<24u ) \
)
#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(BIT(0))
#define IRQ_SET_ALL 0xffffffff;
#define GICD_SGIR_SGIINTID_SHIFT 0
#define GICD_SGIR_CPUTARGETLIST_SHIFT 16
#define GICD_SGIR_TARGETLISTFILTER_SHIFT 24
#ifndef GIC_PL390_DISTRIBUTOR_PPTR
#error GIC_PL390_DISTRIBUTOR_PPTR must be defined for virtual memory access to the gic distributer
#else
volatile struct gic_dist_map * const gic_dist =
(volatile struct gic_dist_map*)(GIC_PL390_DISTRIBUTOR_PPTR);
#endif
#ifndef GIC_PL390_CONTROLLER_PPTR
#error GIC_PL390_CONTROLLER_PPTR must be defined for virtual memory access to the gic cpu interface
#else
volatile struct gic_cpu_iface_map * const gic_cpuiface =
(volatile struct gic_cpu_iface_map*)(GIC_PL390_CONTROLLER_PPTR);
#endif
static inline void
set_irq_active(irq_t irq)
{
int word = irq >> 5;
int bit = irq & 0x1f;
gic_dist->active[word] = BIT(bit);
}
uint32_t active_irq[CONFIG_MAX_NUM_NODES] = {IRQ_NONE};
BOOT_CODE static void
dist_init(void)
{
word_t i;
int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1);
gic_dist->enable = 0;
for (i = 0; i < nirqs; i += 32) {
gic_dist->enable_clr[i >> 5] = IRQ_SET_ALL;
gic_dist->pending_clr[i >> 5] = IRQ_SET_ALL;
}
for (i = 32; i < nirqs; i += 4) {
if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
gic_dist->priority[i >> 2] = 0x80808080;
} else {
gic_dist->priority[i >> 2] = 0;
}
}
for (i = 0; i < nirqs; i += 4) {
gic_dist->targets[i >> 2] = TARGET_CPU0_ALLINT;
}
for (i = 64; i < nirqs; i += 32) {
gic_dist->config[i >> 5] = 0x55555555;
}
for (i = 0; i < nirqs; i += 32) {
if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
gic_dist->security[i >> 5] = 0xffffffff;
} else {
gic_dist->security[i >> 5] = 0;
}
}
gic_dist->enable = 1;
}
BOOT_CODE static void
cpu_iface_init(void)
{
uint32_t i;
gic_dist->enable_clr[0] = IRQ_SET_ALL;
gic_dist->pending_clr[0] = IRQ_SET_ALL;
if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) {
gic_dist->security[0] = 0xffffffff;
gic_dist->priority[0] = 0x80808080;
} else {
gic_dist->security[0] = 0;
gic_dist->priority[0] = 0x0;
}
for (i = 0; i < 16; i += 4) {
gic_dist->sgi_pending_clr[i >> 2] = IRQ_SET_ALL;
}
gic_cpuiface->icontrol = 0;
gic_cpuiface->pri_msk_c = 0x000000f0;
gic_cpuiface->pb_c = 0x00000003;
i = gic_cpuiface->int_ack;
while ((i & IRQ_MASK) != IRQ_NONE) {
gic_cpuiface->eoi = i;
i = gic_cpuiface->int_ack;
}
gic_cpuiface->icontrol = 1;
}
BOOT_CODE void
initIRQController(void)
{
dist_init();
}
BOOT_CODE void cpu_initLocalIRQController(void)
{
cpu_iface_init();
}
#if CONFIG_MAX_NUM_NODES > 1
void ipiBroadcast(irq_t irq, bool_t includeSelfCPU)
{
gic_dist->sgi_control = (!includeSelfCPU << GICD_SGIR_TARGETLISTFILTER_SHIFT) | (irq << GICD_SGIR_SGIINTID_SHIFT);
}
void ipi_send_target(irq_t irq, word_t cpuTargetList)
{
gic_dist->sgi_control = (cpuTargetList << GICD_SGIR_CPUTARGETLIST_SHIFT) | (irq << GICD_SGIR_SGIINTID_SHIFT);
}
#endif