aic: Basic AICv2 support

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-11-02 12:36:41 +09:00
parent f824f60f5c
commit dc3806252b
4 changed files with 62 additions and 21 deletions

View file

@ -10,6 +10,38 @@ u64 aic_base;
#define MASK_REG(x) (4 * ((x) >> 5))
#define MASK_BIT(x) BIT((x)&GENMASK(4, 0))
struct aic_regs {
uint64_t reg_size;
uint64_t event;
uint64_t tgt_cpu;
uint64_t sw_set;
uint64_t sw_clr;
uint64_t mask_set;
uint64_t mask_clr;
};
static const struct aic_regs aic1_regs = {
.reg_size = AIC_REG_SIZE,
.event = AIC_EVENT,
.tgt_cpu = AIC_TARGET_CPU,
.sw_set = AIC_SW_SET,
.sw_clr = AIC_SW_CLR,
.mask_set = AIC_MASK_SET,
.mask_clr = AIC_MASK_CLR,
};
static const struct aic_regs aic2_regs = {
.reg_size = AIC2_REG_SIZE,
.event = AIC2_EVENT,
.tgt_cpu = AIC2_TARGET_CPU,
.sw_set = AIC2_SW_SET,
.sw_clr = AIC2_SW_CLR,
.mask_set = AIC2_MASK_SET,
.mask_clr = AIC2_MASK_CLR,
};
static const struct aic_regs *regs;
void aic_init(void)
{
int path[8];
@ -25,13 +57,26 @@ void aic_init(void)
return;
}
printf("AIC registers @ 0x%lx\n", aic_base);
if (adt_is_compatible(adt, node, "aic,1")) {
printf("AIC: Version 1 @ 0x%lx\n", aic_base);
regs = &aic1_regs;
} else if (adt_is_compatible(adt, node, "aic,2")) {
printf("AIC: Version 2 @ 0x%lx\n", aic_base);
regs = &aic2_regs;
} else {
printf("AIC: Error: Unsupported version @ 0x%lx\n", aic_base);
}
}
void aic_set_sw(int irq, bool active)
{
if (active)
write32(aic_base + AIC_SW_SET + MASK_REG(irq), MASK_BIT(irq));
write32(aic_base + regs->sw_set + MASK_REG(irq), MASK_BIT(irq));
else
write32(aic_base + AIC_SW_CLR + MASK_REG(irq), MASK_BIT(irq));
write32(aic_base + regs->sw_clr + MASK_REG(irq), MASK_BIT(irq));
}
uint32_t aic_ack(void)
{
return read32(aic_base + regs->event);
}

View file

@ -9,5 +9,6 @@ extern u64 aic_base;
void aic_init(void);
void aic_set_sw(int irq, bool active);
uint32_t aic_ack(void);
#endif

View file

@ -13,6 +13,15 @@
#define AIC_MASK_SET 0x4100
#define AIC_MASK_CLR 0x4180
#define AIC2_INFO 0x0004
#define AIC2_LATENCY 0x0204
#define AIC2_EVENT 0xc000
#define AIC2_TARGET_CPU 0x2000
#define AIC2_SW_SET 0x6000
#define AIC2_SW_CLR 0x6200
#define AIC2_MASK_SET 0x6400
#define AIC2_MASK_CLR 0x6800
#define AIC_CPU_IPI_SET(cpu) (0x5008 + ((cpu) << 7))
#define AIC_CPU_IPI_CLR(cpu) (0x500c + ((cpu) << 7))
#define AIC_CPU_IPI_MASK_SET(cpu) (0x5024 + ((cpu) << 7))

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: MIT */
#include "exception.h"
#include "aic.h"
#include "cpu_regs.h"
#include "gxf.h"
#include "iodev.h"
@ -283,26 +284,11 @@ void exc_sync(u64 *regs)
void exc_irq(u64 *regs)
{
#ifdef DEBUG_UART_IRQS
u32 ucon, utrstat, uerstat, ufstat;
ucon = read32(0x235200004);
utrstat = read32(0x235200010);
uerstat = read32(0x235200014);
ufstat = read32(0x235200018);
#endif
u32 reason = aic_ack();
printf("Exception: IRQ (from %s)\n", get_exception_source(0));
printf("Exception: IRQ (from %s) type: %d num: %d mpidr: %lx\n", get_exception_source(0),
reason >> 16, reason & 0xffff, mrs(MPIDR_EL1));
u32 reason = read32(0x23b102004);
printf(" type: %d num: %d mpidr: %lx\n", reason >> 16, reason & 0xffff, mrs(MPIDR_EL1));
#ifdef DEBUG_UART_IRQS
printf(" UCON: 0x%x\n", ucon);
printf(" UTRSTAT: 0x%x\n", utrstat);
printf(" UERSTAT: 0x%x\n", uerstat);
printf(" UFSTAT: 0x%x\n", ufstat);
#endif
UNUSED(regs);
// print_regs(regs);
}