Skip to content

Commit

Permalink
interrupt_controller: intc_dw_ace_v1x: fix multi-level IRQs
Browse files Browse the repository at this point in the history
Zephyr encodes multi-level interrupts in a certain way, and
the driver is not utilizing the encoding correctly. So fix
it.

Signed-off-by: Daniel Leung <[email protected]>
  • Loading branch information
dcpleung authored and fabiobaltieri committed Sep 29, 2022
1 parent cc74b3b commit 4bbd3c7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 13 deletions.
35 changes: 24 additions & 11 deletions drivers/interrupt_controller/intc_dw_ace_v1x.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,43 +54,55 @@
* enabled always.
*/

#define IS_DW(irq) ((irq) >= XCHAL_NUM_INTERRUPTS)
static inline bool is_dw_irq(uint32_t irq)
{
if (((irq & XTENSA_IRQ_NUM_MASK) == ACE_INTC_IRQ)
&& ((irq & ~XTENSA_IRQ_NUM_MASK) != 0)) {
return true;
}

return false;
}

void dw_ace_v1x_irq_enable(const struct device *dev, uint32_t irq)
{
ARG_UNUSED(dev);

if (IS_DW(irq)) {
if (is_dw_irq(irq)) {
for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
ACE_INTC[i].inten |= BIT(MTL_IRQ_FROM_ZEPHYR(irq));
ACE_INTC[i].intmask &= ~BIT(MTL_IRQ_FROM_ZEPHYR(irq));
}
} else {
z_xtensa_irq_enable(irq);
} else if ((irq & ~XTENSA_IRQ_NUM_MASK) == 0U) {
z_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq));
}
}

void dw_ace_v1x_irq_disable(const struct device *dev, uint32_t irq)
{
ARG_UNUSED(dev);

if (IS_DW(irq)) {
if (is_dw_irq(irq)) {
for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
ACE_INTC[i].inten &= ~BIT(MTL_IRQ_FROM_ZEPHYR(irq));
ACE_INTC[i].intmask |= BIT(MTL_IRQ_FROM_ZEPHYR(irq));
}
} else {
z_xtensa_irq_disable(irq);
} else if ((irq & ~XTENSA_IRQ_NUM_MASK) == 0U) {
z_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
}
}

int dw_ace_v1x_irq_is_enabled(const struct device *dev, unsigned int irq)
{
ARG_UNUSED(dev);

if (IS_DW(irq)) {
if (is_dw_irq(irq)) {
return ACE_INTC[0].inten & BIT(MTL_IRQ_FROM_ZEPHYR(irq));
} else {
return z_xtensa_irq_is_enabled(irq);
} else if ((irq & ~XTENSA_IRQ_NUM_MASK) == 0U) {
return z_xtensa_irq_is_enabled(XTENSA_IRQ_NUMBER(irq));
}

return false;
}

#ifdef CONFIG_DYNAMIC_INTERRUPTS
Expand All @@ -116,7 +128,8 @@ static void dwint_isr(const void *arg)

while (fs) {
uint32_t bit = find_lsb_set(fs) - 1;
struct _isr_table_entry *ent = &_sw_isr_table[MTL_IRQ_TO_ZEPHYR(bit)];
uint32_t offset = CONFIG_2ND_LVL_ISR_TBL_OFFSET + bit;
struct _isr_table_entry *ent = &_sw_isr_table[offset];

fs &= ~BIT(bit);
ent->isr(ent->arg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,14 @@ struct mtl_dint {
#define MTL_DINT ((volatile struct mtl_dint *)DXHIPCIE_REG)

/* Convert between IRQ_CONNECT() numbers and MTL_INTL_* interrupts */
#define MTL_IRQ_TO_ZEPHYR(n) (XCHAL_NUM_INTERRUPTS + (n))
#define MTL_IRQ_FROM_ZEPHYR(n) ((n) - XCHAL_NUM_INTERRUPTS)
#define ACE_IRQ_NUM_SHIFT 8
#define ACE_IRQ_NUM_MASK 0xFFU

#define MTL_IRQ_FROM_ZEPHYR(_irq) \
(((_irq >> ACE_IRQ_NUM_SHIFT) & ACE_IRQ_NUM_MASK) - 1)

#define MTL_IRQ_TO_ZEPHYR(_irq) \
((((_irq + 1) & ACE_IRQ_NUM_MASK) << ACE_IRQ_NUM_SHIFT) + ACE_INTC_IRQ)

/* MTL also has per-core instantiations of a Synopsys interrupt
* controller. These inputs (with the same indices as MTL_INTL_*
Expand Down

0 comments on commit 4bbd3c7

Please sign in to comment.