zephyr/drivers/interrupt_controller/intc_system_apic.c

99 lines
2.7 KiB
C
Raw Permalink Normal View History

/*
* Copyright (c) 2013-2015, Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief system module for variants with LOAPIC
*
*/
#include <zephyr/sys/__assert.h>
#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/drivers/interrupt_controller/ioapic.h>
#include <zephyr/drivers/interrupt_controller/loapic.h>
#include <zephyr/drivers/interrupt_controller/sysapic.h>
#include <zephyr/irq.h>
#include <zephyr/linker/sections.h>
#define IS_IOAPIC_IRQ(irq) ((irq) < z_loapic_irq_base())
#define HARDWARE_IRQ_LIMIT ((z_loapic_irq_base() + LOAPIC_IRQ_COUNT) - 1)
/**
* @brief Program interrupt controller
*
* This routine programs the interrupt controller with the given vector
* based on the given IRQ parameter.
*
* Drivers call this routine instead of IRQ_CONNECT() when interrupts are
* configured statically.
*
* The Galileo board virtualizes IRQs as follows:
*
* - The first z_ioapic_num_rtes() IRQs are provided by the IOAPIC so the
* IOAPIC is programmed for these IRQs
* - The remaining IRQs are provided by the LOAPIC and hence the LOAPIC is
* programmed.
*
* @param vector the vector number
* @param irq the virtualized IRQ
* @param flags interrupt flags
*/
__boot_func
void z_irq_controller_irq_config(unsigned int vector, unsigned int irq,
uint32_t flags)
{
__ASSERT(irq <= HARDWARE_IRQ_LIMIT, "invalid irq line");
x86: declare internal API for interrupt controllers Originally, x86 just supported APIC. Then later support for the Mint Valley Interrupt Controller was added. This controller is mostly similar to the APIC with some differences, but was integrated in a somewhat hacked-up fashion. Now we define irq_controller.h, which is a layer of abstraction between the core arch code and the interrupt controller implementation. Contents of the API: - Controllers with a fixed irq-to-vector mapping define _IRQ_CONTROLLER_VECTOR_MAPPING(irq) to obtain a compile-time map between the two. - _irq_controller_program() notifies the interrupt controller what vector will be used for a particular IRQ along with triggering flags - _irq_controller_isr_vector_get() reports the vector number of the IRQ currently being serviced - In assembly language domain, _irq_controller_eoi implements EOI handling. - Since triggering options can vary, some common defines for triggering IRQ_TRIGGER_EDGE, IRQ_TRIGGER_LEVEL, IRQ_POLARITY_HIGH, IRQ_POLARITY_LOW introduced. Specific changes made: - New Kconfig X86_FIXED_IRQ_MAPPING for those interrupt controllers that have a fixed relationship between IRQ lines and IDT vectors. - MVIC driver rewritten per the HAS instead of the tortuous methods used to get it to behave like LOAPIC. We are no longer writing values to reserved registers. Additional assertions added. - Some cleanup in the loapic_timer driver to make the MVIC differences clearer. - Unused APIs removed, or folded into calling code when used just once. - MVIC doesn't bother to write a -1 to the intList priority field since it gets ignored anyway Issue: ZEP-48 Change-Id: I071a477ea68c36e00c3d0653ce74b3583454154d Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2016-08-02 21:05:08 +02:00
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_set(irq, vector, flags);
} else {
z_loapic_int_vec_set(irq - z_loapic_irq_base(), vector);
}
}
/**
* @brief Enable an individual interrupt (IRQ)
*
* The public interface for enabling/disabling a specific IRQ for the IA-32
* architecture is defined as follows in include/arch/x86/arch.h
*
* extern void irq_enable (unsigned int irq);
* extern void irq_disable (unsigned int irq);
*
* The irq_enable() routine is provided by the interrupt controller driver due
* to the IRQ virtualization that is performed by this platform. See the
x86: declare internal API for interrupt controllers Originally, x86 just supported APIC. Then later support for the Mint Valley Interrupt Controller was added. This controller is mostly similar to the APIC with some differences, but was integrated in a somewhat hacked-up fashion. Now we define irq_controller.h, which is a layer of abstraction between the core arch code and the interrupt controller implementation. Contents of the API: - Controllers with a fixed irq-to-vector mapping define _IRQ_CONTROLLER_VECTOR_MAPPING(irq) to obtain a compile-time map between the two. - _irq_controller_program() notifies the interrupt controller what vector will be used for a particular IRQ along with triggering flags - _irq_controller_isr_vector_get() reports the vector number of the IRQ currently being serviced - In assembly language domain, _irq_controller_eoi implements EOI handling. - Since triggering options can vary, some common defines for triggering IRQ_TRIGGER_EDGE, IRQ_TRIGGER_LEVEL, IRQ_POLARITY_HIGH, IRQ_POLARITY_LOW introduced. Specific changes made: - New Kconfig X86_FIXED_IRQ_MAPPING for those interrupt controllers that have a fixed relationship between IRQ lines and IDT vectors. - MVIC driver rewritten per the HAS instead of the tortuous methods used to get it to behave like LOAPIC. We are no longer writing values to reserved registers. Additional assertions added. - Some cleanup in the loapic_timer driver to make the MVIC differences clearer. - Unused APIs removed, or folded into calling code when used just once. - MVIC doesn't bother to write a -1 to the intList priority field since it gets ignored anyway Issue: ZEP-48 Change-Id: I071a477ea68c36e00c3d0653ce74b3583454154d Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2016-08-02 21:05:08 +02:00
* comments in _interrupt_vector_allocate() for more information regarding IRQ
* virtualization.
*/
__pinned_func
void arch_irq_enable(unsigned int irq)
{
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_enable(irq);
} else {
z_loapic_irq_enable(irq - z_loapic_irq_base());
}
}
/**
* @brief Disable an individual interrupt (IRQ)
*
* The irq_disable() routine is provided by the interrupt controller driver due
* to the IRQ virtualization that is performed by this platform. See the
x86: declare internal API for interrupt controllers Originally, x86 just supported APIC. Then later support for the Mint Valley Interrupt Controller was added. This controller is mostly similar to the APIC with some differences, but was integrated in a somewhat hacked-up fashion. Now we define irq_controller.h, which is a layer of abstraction between the core arch code and the interrupt controller implementation. Contents of the API: - Controllers with a fixed irq-to-vector mapping define _IRQ_CONTROLLER_VECTOR_MAPPING(irq) to obtain a compile-time map between the two. - _irq_controller_program() notifies the interrupt controller what vector will be used for a particular IRQ along with triggering flags - _irq_controller_isr_vector_get() reports the vector number of the IRQ currently being serviced - In assembly language domain, _irq_controller_eoi implements EOI handling. - Since triggering options can vary, some common defines for triggering IRQ_TRIGGER_EDGE, IRQ_TRIGGER_LEVEL, IRQ_POLARITY_HIGH, IRQ_POLARITY_LOW introduced. Specific changes made: - New Kconfig X86_FIXED_IRQ_MAPPING for those interrupt controllers that have a fixed relationship between IRQ lines and IDT vectors. - MVIC driver rewritten per the HAS instead of the tortuous methods used to get it to behave like LOAPIC. We are no longer writing values to reserved registers. Additional assertions added. - Some cleanup in the loapic_timer driver to make the MVIC differences clearer. - Unused APIs removed, or folded into calling code when used just once. - MVIC doesn't bother to write a -1 to the intList priority field since it gets ignored anyway Issue: ZEP-48 Change-Id: I071a477ea68c36e00c3d0653ce74b3583454154d Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2016-08-02 21:05:08 +02:00
* comments in _interrupt_vector_allocate() for more information regarding IRQ
* virtualization.
*/
__pinned_func
void arch_irq_disable(unsigned int irq)
{
if (IS_IOAPIC_IRQ(irq)) {
z_ioapic_irq_disable(irq);
} else {
z_loapic_irq_disable(irq - z_loapic_irq_base());
}
}