Skip to content

Commit

Permalink
Support new version of AIC used by M3
Browse files Browse the repository at this point in the history
Small changes, mostly some offsts are now available in the DT,
and a mask change.

Signed-off-by: Daniel Berlin <[email protected]>
  • Loading branch information
dberlin committed Dec 1, 2023
1 parent 736acde commit bae5247
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
91 changes: 91 additions & 0 deletions src/aic.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,92 @@ static struct aic aic2 = {
},
};

static struct aic aic3 = {
.version = 3,
.regs =
{
.config = AIC2_IRQ_CFG,
},
};

struct aic *aic;

static int aic3_init(int node)
{
int ret = ADT_GETPROP(adt, node, "aic-iack-offset", &aic->regs.event);
if (ret < 0) {
printf("AIC: failed to get property aic-iack-offset\n");
return ret;
}

int cap0_offset;

ret = ADT_GETPROP(adt, node, "cap0-offset", &cap0_offset);
if (ret < 0) {
printf("AIC: failed to get property cap0-offset\n");
}
u32 info1 = read32(aic->base + cap0_offset);
aic->nr_die = FIELD_GET(AIC3_INFO1_LAST_DIE, info1) + 1;
aic->nr_irq = FIELD_GET(AIC3_INFO1_NR_IRQ, info1);

int maxnumirq_offset;
ret = ADT_GETPROP(adt, node, "maxnumirq-offset", &maxnumirq_offset);
if (ret < 0) {
printf("AIC: failed to get property maxnumirq-offset\n");
}

u32 info3 = read32(aic->base + maxnumirq_offset);
aic->max_die = FIELD_GET(AIC3_INFO3_MAX_DIE, info3);
aic->max_irq = FIELD_GET(AIC3_INFO3_MAX_IRQ, info3);

if (aic->nr_die > AIC_MAX_DIES) {
printf("AIC: more dies than supported: %u\n", aic->max_die);
return -1;
}

if (aic->max_irq > AIC_MAX_HW_NUM) {
printf("AIC: more IRQs than supported: %u\n", aic->max_irq);
return -1;
}

const u64 start_off = aic->regs.config;
u64 off = start_off + sizeof(u32) * aic->max_irq; /* IRQ_CFG */

aic->regs.sw_set = off;
off += sizeof(u32) * (aic->max_irq >> 5); /* SW_SET */
aic->regs.sw_clr = off;
off += sizeof(u32) * (aic->max_irq >> 5); /* SW_CLR */
aic->regs.mask_set = off;
off += sizeof(u32) * (aic->max_irq >> 5); /* MASK_SET */
aic->regs.mask_clr = off;
off += sizeof(u32) * (aic->max_irq >> 5); /* MASK_CLR */
off += sizeof(u32) * (aic->max_irq >> 5); /* HW_STATE */

aic->die_stride = off - start_off;
aic->regs.reg_size = aic->regs.event + 4;

printf("AIC: AIC3 with %u/%u dies, %u/%u IRQs, reg_size:%05lx die_stride:%05x\n", aic->nr_die,
aic->max_die, aic->nr_irq, aic->max_irq, aic->regs.reg_size, aic->die_stride);

u32 ext_intr_config_len;
const u8 *ext_intr_config = adt_getprop(adt, node, "aic-ext-intr-cfg", &ext_intr_config_len);

if (ext_intr_config) {
printf("AIC: Configuring %d external interrupts\n", ext_intr_config_len / 3);
for (u32 i = 0; i < ext_intr_config_len; i += 3) {
u8 die = ext_intr_config[i + 1] >> 4;
u16 irq = ext_intr_config[i] | ((ext_intr_config[i + 1] & 0xf) << 8);
u8 target = ext_intr_config[i + 2];
assert(die < aic->nr_die);
assert(irq < aic->nr_irq);
mask32(aic->base + aic->regs.config + die * aic->die_stride + 4 * irq,
AIC3_IRQ_CFG_TARGET, FIELD_PREP(AIC3_IRQ_CFG_TARGET, target));
}
}

return 0;
}

static int aic2_init(int node)
{
int ret = ADT_GETPROP(adt, node, "aic-iack-offset", &aic->regs.event);
Expand Down Expand Up @@ -113,6 +197,8 @@ void aic_init(void)
aic = &aic1;
} else if (adt_is_compatible(adt, node, "aic,2")) {
aic = &aic2;
} else if (adt_is_compatible(adt, node, "aic,3")) {
aic = &aic3;
} else {
printf("AIC: Error: Unsupported version\n");
return;
Expand All @@ -132,6 +218,11 @@ void aic_init(void)
int ret = aic2_init(node);
if (ret < 0)
aic = NULL;
} else if (aic->version == 3) {
printf("AIC: Version 3 @ 0x%lx\n", aic->base);
int ret = aic3_init(node);
if (ret < 0)
aic = NULL;
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/aic_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
#define AIC2_INFO3_MAX_IRQ GENMASK(15, 0)
#define AIC2_INFO3_MAX_DIE GENMASK(27, 24)

#define AIC3_IRQ_CFG_TARGET GENMASK(3, 0)

#define AIC3_INFO1_NR_IRQ GENMASK(15, 0)
#define AIC3_INFO1_LAST_DIE GENMASK(27, 24)

#define AIC3_INFO3_MAX_IRQ GENMASK(15, 0)
#define AIC3_INFO3_MAX_DIE GENMASK(31, 24)

#define AIC_EVENT_DIE GENMASK(31, 24)
#define AIC_EVENT_TYPE GENMASK(23, 16)
#define AIC_EVENT_NUM GENMASK(15, 0)
Expand Down

0 comments on commit bae5247

Please sign in to comment.