/** * * @brief initialize the MVIC IO APIC and local APIC register sets. * * This routine initializes the Quark D2000 Interrupt Controller (MVIC). * This routine replaces the standard Local APIC / IO APIC init routines. * * @returns: N/A */ static int _mvic_init(struct device *unused) { ARG_UNUSED(unused); int i; /* By default mask all interrupt lines */ for (i = 0; i < MVIC_NUM_RTES; i++) { _mvic_rte_set(i, MVIC_IOWIN_MASK); } /* reset the task priority and timer initial count registers */ sys_write32(0, MVIC_TPR); sys_write32(0, MVIC_ICR); /* Initialize and mask the timer interrupt. * Bits 0-3 program the interrupt line number we will use * for the timer interrupt. */ __ASSERT(CONFIG_MVIC_TIMER_IRQ < 16, "Bad irq line %d chosen for timer irq", CONFIG_MVIC_TIMER_IRQ); sys_write32(MVIC_LVTTIMER_MASK | CONFIG_MVIC_TIMER_IRQ, MVIC_LVTTIMER); /* discard a pending interrupt if any */ sys_write32(0, MVIC_EOI); return 0; }
/** * * @brief Programs Rte interrupt line register. * * Always mask interrupt as part of programming like standard IOAPIC * version of this routine. * Vector is fixed by this HW and is unused. * Or in flags for trigger bit. * * @param irq Virtualized IRQ * @param vector Vector Number * @param flags Interrupt flags * * @returns: N/A */ void _ioapic_irq_set(unsigned int irq, unsigned int vector, uint32_t flags) { uint32_t rteValue; /* value to copy into Rte register */ ARG_UNUSED(vector); rteValue = IOAPIC_INT_MASK | flags; _mvic_rte_set(irq, rteValue); }
void __irq_controller_irq_config(unsigned int vector, unsigned int irq, u32_t flags) { ARG_UNUSED(vector); /* Vector argument always ignored. There are no triggering options * for the timer, so nothing to do at all for that case. Other I/O * interrupts need their triggering set */ if (irq != CONFIG_MVIC_TIMER_IRQ) { _mvic_rte_set(irq, MVIC_IOWIN_MASK | flags); } else { __ASSERT(flags == 0, "Timer interrupt cannot have triggering flags set"); } }
/** * * @brief initialize the MVIC IO APIC and local APIC register sets. * * This routine initializes the Quark D2000 Interrupt Controller (MVIC). * This routine replaces the standard Local APIC / IO APIC init routines. * * @returns: N/A */ int _mvic_init(struct device *unused) { ARG_UNUSED(unused); int32_t ix; /* Interrupt line register index */ uint32_t rteValue; /* value to copy into interrupt line register */ /* * The platform must define the CONFIG_IOAPIC_NUM_RTES macro to indicate the number * of redirection table entries supported by the IOAPIC on the board. * * By default mask all interrupt lines and set default sensitivity to edge. * */ rteValue = IOAPIC_EDGE | IOAPIC_INT_MASK; for (ix = 0; ix < CONFIG_IOAPIC_NUM_RTES; ix++) { _mvic_rte_set(ix, rteValue); } /* enable the MVIC Local APIC */ _loapic_enable(); /* reset the TPR, and TIMER_ICR */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TPR) = (int)0x0; *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_ICR) = (int)0x0; /* program Local Vector Table for the Virtual Wire Mode */ /* lock the MVIC timer interrupt, set which IRQ line should be * used for timer interrupts (this is unlike LOAPIC where the * vector is programmed instead). */ __ASSERT_NO_MSG(CONFIG_LOAPIC_TIMER_IRQ <= 15); *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER) = LOAPIC_LVT_MASKED | CONFIG_LOAPIC_TIMER_IRQ; /* discard a pending interrupt if any */ *(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI) = 0; return 0; }
/** * * @brief modify interrupt line register. * * @param irq INTIN number * @param value value to be written * @param mask of bits to be modified * * @returns N/A */ static void _mvic_rte_update(unsigned int irq, uint32_t value, uint32_t mask) { _mvic_rte_set(irq, (_mvic_rte_get(irq) & ~mask) | (value & mask)); }