1 /*
2  * Copyright (c) 2013-2015, Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief  system module for variants with LOAPIC
10  *
11  */
12 
13 #include <zephyr/sys/__assert.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/arch/cpu.h>
16 #include <zephyr/drivers/interrupt_controller/ioapic.h>
17 #include <zephyr/drivers/interrupt_controller/loapic.h>
18 #include <zephyr/drivers/interrupt_controller/sysapic.h>
19 #include <zephyr/irq.h>
20 #include <zephyr/linker/sections.h>
21 
22 #define IS_IOAPIC_IRQ(irq)  ((irq) < z_loapic_irq_base())
23 #define HARDWARE_IRQ_LIMIT ((z_loapic_irq_base() + LOAPIC_IRQ_COUNT) - 1)
24 
25 /**
26  * @brief Program interrupt controller
27  *
28  * This routine programs the interrupt controller with the given vector
29  * based on the given IRQ parameter.
30  *
31  * Drivers call this routine instead of IRQ_CONNECT() when interrupts are
32  * configured statically.
33  *
34  * The Galileo board virtualizes IRQs as follows:
35  *
36  * - The first z_ioapic_num_rtes() IRQs are provided by the IOAPIC so the
37  *     IOAPIC is programmed for these IRQs
38  * - The remaining IRQs are provided by the LOAPIC and hence the LOAPIC is
39  *     programmed.
40  *
41  * @param vector the vector number
42  * @param irq the virtualized IRQ
43  * @param flags interrupt flags
44  */
45 __boot_func
z_irq_controller_irq_config(unsigned int vector,unsigned int irq,uint32_t flags)46 void z_irq_controller_irq_config(unsigned int vector, unsigned int irq,
47 				 uint32_t flags)
48 {
49 	__ASSERT(irq <= HARDWARE_IRQ_LIMIT, "invalid irq line");
50 
51 	if (IS_IOAPIC_IRQ(irq)) {
52 		z_ioapic_irq_set(irq, vector, flags);
53 	} else {
54 		z_loapic_int_vec_set(irq - z_loapic_irq_base(), vector);
55 	}
56 }
57 
58 /**
59  * @brief Enable an individual interrupt (IRQ)
60  *
61  * The public interface for enabling/disabling a specific IRQ for the IA-32
62  * architecture is defined as follows in include/arch/x86/arch.h
63  *
64  *   extern void  irq_enable  (unsigned int irq);
65  *   extern void  irq_disable (unsigned int irq);
66  *
67  * The irq_enable() routine is provided by the interrupt controller driver due
68  * to the IRQ virtualization that is performed by this platform.  See the
69  * comments in _interrupt_vector_allocate() for more information regarding IRQ
70  * virtualization.
71  */
72 __pinned_func
arch_irq_enable(unsigned int irq)73 void arch_irq_enable(unsigned int irq)
74 {
75 	if (IS_IOAPIC_IRQ(irq)) {
76 		z_ioapic_irq_enable(irq);
77 	} else {
78 		z_loapic_irq_enable(irq - z_loapic_irq_base());
79 	}
80 }
81 
82 /**
83  * @brief Disable an individual interrupt (IRQ)
84  *
85  * The irq_disable() routine is provided by the interrupt controller driver due
86  * to the IRQ virtualization that is performed by this platform.  See the
87  * comments in _interrupt_vector_allocate() for more information regarding IRQ
88  * virtualization.
89  */
90 __pinned_func
arch_irq_disable(unsigned int irq)91 void arch_irq_disable(unsigned int irq)
92 {
93 	if (IS_IOAPIC_IRQ(irq)) {
94 		z_ioapic_irq_disable(irq);
95 	} else {
96 		z_loapic_irq_disable(irq - z_loapic_irq_base());
97 	}
98 }
99