Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1984-2008, 2011-2015 Wind River Systems, Inc. |
| 3 | * |
David B. Kinder | ac74d8b | 2017-01-18 17:01:01 -0800 | [diff] [blame] | 4 | * SPDX-License-Identifier: Apache-2.0 |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 5 | */ |
| 6 | |
Anas Nashif | 275ca60 | 2015-12-04 10:09:39 -0500 | [diff] [blame] | 7 | /** |
| 8 | * @file |
| 9 | * @brief LoApicIntr.c - Intel Pentium[234] Local APIC/xAPIC driver |
| 10 | * |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 11 | * This module is a driver for the local APIC/xAPIC (Advanced Programmable |
| 12 | * Interrupt Controller) in P6 (PentiumPro, II, III) family processors |
| 13 | * and P7 (Pentium4) family processors. The local APIC/xAPIC is included |
| 14 | * in selected P6 (PentiumPro, II, III) and P7 (Pentium4) family processors. |
| 15 | * Beginning with the P6 family processors, the presence or absence of an |
| 16 | * on-chip local APIC can be detected using the CPUID instruction. When the |
| 17 | * CPUID instruction is executed, bit 9 of the feature flags returned in the |
| 18 | * EDX register indicates the presence (set) or absence (clear) of an on-chip |
| 19 | * local APIC. |
| 20 | * |
| 21 | * The local APIC performs two main functions for the processor: |
| 22 | * - It processes local external interrupts that the processor receives at its |
| 23 | * interrupt pins and local internal interrupts that software generates. |
| 24 | * - It communicates with an external IO APIC |
| 25 | * chip. The external IO APIC receives external interrupt events from |
| 26 | * peripheral and direct them to the local APIC. The IO APIC is |
| 27 | * part of Intel's system chip set. |
| 28 | * The local APIC controls the dispatching of interrupts (to its associated |
| 29 | * processor) that it receives either locally or from the IO APIC. It provides |
| 30 | * facilities for queuing, nesting and masking of interrupts. It handles the |
| 31 | * interrupt delivery protocol with its local processor and accesses to APIC |
| 32 | * registers. |
| 33 | * A timer on the local APIC allows local generation of interrupts, and |
| 34 | * local interrupt pins permit local reception of processor-specific interrupts. |
| 35 | * The local APIC can be disabled and used in conjunction with a standard 8259A |
| 36 | * style interrupt controller. Disabling the local APIC can be done in hardware |
| 37 | * for the Pentium processors or in software for the P6 and P7 (Pentium4) family |
| 38 | * processors. |
| 39 | * |
| 40 | * The local APIC in the Pentium4 processors (called the xAPIC) is an extension |
| 41 | * of the local APIC found in the P6 family processors. The primary difference |
| 42 | * between the APIC architecture and xAPIC architecture is that with Pentium4 |
| 43 | * processors, the local xAPICs and IO xAPIC communicate with one another |
| 44 | * through the processors system bus; whereas, with the P6 family processors, |
| 45 | * communication between the local APICs and the IO APIC is handled through a |
| 46 | * dedicated 3-wire APIC bus. Also, some of the architectural features of the |
| 47 | * local APIC have been extended and/or modified in the local xAPIC. |
| 48 | * |
| 49 | * This driver contains three routines for use. They are: |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 50 | * z_loapic_init() initializes the Local APIC for the interrupt mode chosen. |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 51 | * _loapic_enable()/disable() enables / disables the Local APIC. |
| 52 | * |
| 53 | * Local APIC is used in the Virtual Wire Mode: delivery mode ExtINT. |
| 54 | * |
| 55 | * Virtual Wire Mode is one of three interrupt modes defined by the MP |
| 56 | * specification. In this mode, interrupts are generated by the 8259A |
| 57 | * equivalent PICs (if present) and delivered to the Boot Strap Processor by |
| 58 | * the local APIC that is programmed to act as a "virtual Wire"; that |
| 59 | * is, the local APIC is logically indistinguishable from a hardware |
| 60 | * connection. This is a uniprocessor compatibility mode. |
| 61 | * |
| 62 | * The local and IO APICs support interrupts in the range of 32 to 255. |
| 63 | * Interrupt priority is implied by its vector, according to the following |
| 64 | * relationship: "priority = vector / 16". |
| 65 | * Here the quotient is rounded down to the nearest integer value to determine |
| 66 | * the priority, with 1 being the lowest and 15 is the highest. Because vectors |
| 67 | * 0 through 31 are reserved for exclusive use by the processor, the priority of |
| 68 | * user defined interrupts range from 2 to 15. A value of 15 in the Interrupt |
| 69 | * Class field of the Task Priority Register (TPR) will mask off all interrupts, |
| 70 | * which require interrupt service. |
| 71 | * The P6 family processor's local APIC includes an in-service entry and a |
| 72 | * holding entry for each priority level. To avoid losing interrupts, software |
| 73 | * should allocate no more than 2 interrupt vectors per priority. The Pentium4 |
| 74 | * processor expands this support of all acceptance of two interrupts per vector |
| 75 | * rather than per priority level. |
Dan Kalowsky | e8563c2 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 76 | * |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 77 | * INCLUDE FILES: loapic.h |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 78 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 79 | |
Flavio Santes | b04cdcd | 2016-12-04 14:59:37 -0600 | [diff] [blame] | 80 | #include <kernel.h> |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 81 | #include <kernel_structs.h> |
Dan Kalowsky | c02dd34 | 2015-05-28 10:56:47 -0700 | [diff] [blame] | 82 | #include <arch/cpu.h> |
Kumar Gala | 7890816 | 2017-04-19 10:32:08 -0500 | [diff] [blame] | 83 | #include <zephyr/types.h> |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 84 | #include <string.h> |
Andrew Boie | a69ea78 | 2016-07-12 11:42:18 -0700 | [diff] [blame] | 85 | #include <misc/__assert.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 86 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 87 | #include <toolchain.h> |
Anas Nashif | 397d29d | 2017-06-17 11:30:47 -0400 | [diff] [blame] | 88 | #include <linker/sections.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 89 | #include <drivers/loapic.h> /* public API declarations */ |
Daniel Leung | 921ee03 | 2015-12-08 11:17:56 -0800 | [diff] [blame] | 90 | #include <init.h> |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 91 | #include <drivers/sysapic.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 92 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 93 | /* IA32_APIC_BASE MSR Bits */ |
| 94 | |
| 95 | #define LOAPIC_BASE_MASK 0xfffff000 /* LO APIC Base Addr mask */ |
| 96 | #define LOAPIC_GLOBAL_ENABLE 0x00000800 /* LO APIC Global Enable */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 97 | |
| 98 | /* Local APIC ID Register Bits */ |
| 99 | |
| 100 | #define LOAPIC_ID_MASK 0x0f000000 /* LO APIC ID mask */ |
| 101 | |
| 102 | /* Local APIC Version Register Bits */ |
| 103 | |
| 104 | #define LOAPIC_VERSION_MASK 0x000000ff /* LO APIC Version mask */ |
| 105 | #define LOAPIC_MAXLVT_MASK 0x00ff0000 /* LO APIC Max LVT mask */ |
| 106 | #define LOAPIC_PENTIUM4 0x00000014 /* LO APIC in Pentium4 */ |
| 107 | #define LOAPIC_LVT_PENTIUM4 5 /* LO APIC LVT - Pentium4 */ |
| 108 | #define LOAPIC_LVT_P6 4 /* LO APIC LVT - P6 */ |
| 109 | #define LOAPIC_LVT_P5 3 /* LO APIC LVT - P5 */ |
| 110 | |
| 111 | /* Local APIC Vector Table Bits */ |
| 112 | |
| 113 | #define LOAPIC_VECTOR 0x000000ff /* vectorNo */ |
| 114 | #define LOAPIC_MODE 0x00000700 /* delivery mode */ |
| 115 | #define LOAPIC_FIXED 0x00000000 /* delivery mode: FIXED */ |
| 116 | #define LOAPIC_SMI 0x00000200 /* delivery mode: SMI */ |
| 117 | #define LOAPIC_NMI 0x00000400 /* delivery mode: NMI */ |
| 118 | #define LOAPIC_EXT 0x00000700 /* delivery mode: ExtINT */ |
| 119 | #define LOAPIC_IDLE 0x00000000 /* delivery status: Idle */ |
| 120 | #define LOAPIC_PEND 0x00001000 /* delivery status: Pend */ |
| 121 | #define LOAPIC_HIGH 0x00000000 /* polarity: High */ |
| 122 | #define LOAPIC_LOW 0x00002000 /* polarity: Low */ |
| 123 | #define LOAPIC_REMOTE 0x00004000 /* remote IRR */ |
| 124 | #define LOAPIC_EDGE 0x00000000 /* trigger mode: Edge */ |
| 125 | #define LOAPIC_LEVEL 0x00008000 /* trigger mode: Level */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 126 | |
| 127 | /* Local APIC Spurious-Interrupt Register Bits */ |
| 128 | |
| 129 | #define LOAPIC_ENABLE 0x100 /* APIC Enabled */ |
| 130 | #define LOAPIC_FOCUS_DISABLE 0x200 /* Focus Processor Checking */ |
| 131 | |
| 132 | /* Local Vector's lock-unlock macro used in loApicIntLock/Unlock */ |
| 133 | |
| 134 | #define LOCKED_TIMER 0x01 |
| 135 | #define LOCKED_PMC 0x02 |
| 136 | #define LOCKED_LINT0 0x04 |
| 137 | #define LOCKED_LINT1 0x08 |
| 138 | #define LOCKED_ERROR 0x10 |
| 139 | #define LOCKED_THERMAL 0x20 |
| 140 | |
| 141 | /* Interrupt Command Register: delivery mode and status */ |
| 142 | |
| 143 | #define MODE_FIXED 0x0 /* delivery mode: Fixed */ |
| 144 | #define MODE_LOWEST 0x1 /* delivery mode: Lowest */ |
| 145 | #define MODE_SMI 0x2 /* delivery mode: SMI */ |
| 146 | #define MODE_NMI 0x4 /* delivery mode: NMI */ |
| 147 | #define MODE_INIT 0x5 /* delivery mode: INIT */ |
| 148 | #define MODE_STARTUP 0x6 /* delivery mode: StartUp */ |
| 149 | #define STATUS_PEND 0x1000 /* delivery status: Pend */ |
| 150 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 151 | /* IMCR related bits */ |
| 152 | |
| 153 | #define IMCR_ADRS 0x22 /* IMCR addr reg */ |
| 154 | #define IMCR_DATA 0x23 /* IMCR data reg */ |
| 155 | #define IMCR_REG_SEL 0x70 /* IMCR reg select */ |
| 156 | #define IMCR_IOAPIC_ON 0x01 /* IMCR IOAPIC route enable */ |
| 157 | #define IMCR_IOAPIC_OFF 0x00 /* IMCR IOAPIC route disable */ |
| 158 | |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 159 | #if CONFIG_LOAPIC_SPURIOUS_VECTOR_ID == -1 |
| 160 | #define LOAPIC_SPURIOUS_VECTOR_ID (CONFIG_IDT_NUM_VECTORS - 1) |
| 161 | #else |
| 162 | #define LOAPIC_SPURIOUS_VECTOR_ID CONFIG_LOAPIC_SPURIOUS_VECTOR_ID |
| 163 | #endif |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 164 | |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 165 | #define LOPIC_SSPND_BITS_PER_IRQ 1 /* Just the one for enable disable*/ |
| 166 | #define LOPIC_SUSPEND_BITS_REQD (ROUND_UP((LOAPIC_IRQ_COUNT * LOPIC_SSPND_BITS_PER_IRQ), 32)) |
| 167 | #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
| 168 | #include <power.h> |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 169 | u32_t loapic_suspend_buf[LOPIC_SUSPEND_BITS_REQD / 32] = {0}; |
| 170 | static u32_t loapic_device_power_state = DEVICE_PM_ACTIVE_STATE; |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 171 | #endif |
| 172 | |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 173 | static ALWAYS_INLINE u32_t LOAPIC_READ(mem_addr_t addr) |
| 174 | { |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 175 | #ifndef CONFIG_JAILHOUSE_X2APIC |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 176 | return sys_read32(CONFIG_LOAPIC_BASE_ADDRESS + addr); |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 177 | #else |
| 178 | return read_x2apic(addr >> 4); |
| 179 | #endif |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | static ALWAYS_INLINE void LOAPIC_WRITE(mem_addr_t addr, u32_t data) |
| 183 | { |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 184 | #ifndef CONFIG_JAILHOUSE_X2APIC |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 185 | sys_write32(data, CONFIG_LOAPIC_BASE_ADDRESS + addr); |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 186 | #else |
| 187 | write_x2apic(addr >> 4, data); |
| 188 | #endif |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 189 | } |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 190 | |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 191 | /** |
| 192 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 193 | * @brief Initialize the Local APIC or xAPIC |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 194 | * |
| 195 | * This routine initializes Local APIC or xAPIC. |
| 196 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 197 | * @return N/A |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 198 | * |
| 199 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 200 | |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 201 | static int loapic_init(struct device *unused) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 202 | { |
Dirk Brandewie | be1b1a4 | 2015-09-15 09:17:38 -0700 | [diff] [blame] | 203 | ARG_UNUSED(unused); |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 204 | s32_t loApicMaxLvt; /* local APIC Max LVT */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 205 | |
| 206 | /* enable the Local APIC */ |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 207 | LOAPIC_WRITE(LOAPIC_SVR, LOAPIC_READ(LOAPIC_SVR) | LOAPIC_ENABLE); |
| 208 | loApicMaxLvt = (LOAPIC_READ(LOAPIC_VER) & LOAPIC_MAXLVT_MASK) >> 16; |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 209 | |
| 210 | /* reset the DFR, TPR, TIMER_CONFIG, and TIMER_ICR */ |
| 211 | |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 212 | /* Jailhouse does not allow writes to DFR in x2APIC mode */ |
| 213 | #ifndef CONFIG_JAILHOUSE_X2APIC |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 214 | LOAPIC_WRITE(LOAPIC_DFR, 0xffffffff); |
Gustavo Lima Chaves | 9bb07ff | 2017-10-11 14:17:12 -0700 | [diff] [blame] | 215 | #endif |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 216 | |
| 217 | LOAPIC_WRITE(LOAPIC_TPR, 0x0); |
| 218 | LOAPIC_WRITE(LOAPIC_TIMER_CONFIG, 0x0); |
| 219 | LOAPIC_WRITE(LOAPIC_TIMER_ICR, 0x0); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 220 | |
| 221 | /* program Local Vector Table for the Virtual Wire Mode */ |
| 222 | |
Gustavo Lima Chaves | 97a8716 | 2017-10-11 14:13:00 -0700 | [diff] [blame] | 223 | /* skip LINT0/LINT1 for Jailhouse guest case, because we won't |
| 224 | * ever be waiting for interrupts on those |
| 225 | */ |
| 226 | #ifndef CONFIG_JAILHOUSE |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 227 | /* set LINT0: extInt, high-polarity, edge-trigger, not-masked */ |
| 228 | |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 229 | LOAPIC_WRITE(LOAPIC_LINT0, (LOAPIC_READ(LOAPIC_LINT0) & |
| 230 | ~(LOAPIC_MODE | LOAPIC_LOW | |
| 231 | LOAPIC_LEVEL | LOAPIC_LVT_MASKED)) | |
| 232 | (LOAPIC_EXT | LOAPIC_HIGH | LOAPIC_EDGE)); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 233 | |
| 234 | /* set LINT1: NMI, high-polarity, edge-trigger, not-masked */ |
| 235 | |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 236 | LOAPIC_WRITE(LOAPIC_LINT1, (LOAPIC_READ(LOAPIC_LINT1) & |
| 237 | ~(LOAPIC_MODE | LOAPIC_LOW | |
| 238 | LOAPIC_LEVEL | LOAPIC_LVT_MASKED)) | |
| 239 | (LOAPIC_NMI | LOAPIC_HIGH | LOAPIC_EDGE)); |
Gustavo Lima Chaves | 97a8716 | 2017-10-11 14:13:00 -0700 | [diff] [blame] | 240 | #endif |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 241 | |
| 242 | /* lock the Local APIC interrupts */ |
| 243 | |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 244 | LOAPIC_WRITE(LOAPIC_TIMER, LOAPIC_LVT_MASKED); |
| 245 | LOAPIC_WRITE(LOAPIC_ERROR, LOAPIC_LVT_MASKED); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 246 | |
Anas Nashif | 4c32258 | 2019-06-04 10:52:23 -0400 | [diff] [blame^] | 247 | if (loApicMaxLvt >= LOAPIC_LVT_P6) { |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 248 | LOAPIC_WRITE(LOAPIC_PMC, LOAPIC_LVT_MASKED); |
Anas Nashif | 4c32258 | 2019-06-04 10:52:23 -0400 | [diff] [blame^] | 249 | } |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 250 | |
Anas Nashif | 4c32258 | 2019-06-04 10:52:23 -0400 | [diff] [blame^] | 251 | if (loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) { |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 252 | LOAPIC_WRITE(LOAPIC_THERMAL, LOAPIC_LVT_MASKED); |
Anas Nashif | 4c32258 | 2019-06-04 10:52:23 -0400 | [diff] [blame^] | 253 | } |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 254 | |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 255 | #if CONFIG_LOAPIC_SPURIOUS_VECTOR |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 256 | LOAPIC_WRITE(LOAPIC_SVR, (LOAPIC_READ(LOAPIC_SVR) & 0xFFFFFF00) | |
| 257 | (LOAPIC_SPURIOUS_VECTOR_ID & 0xFF)); |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 258 | #endif |
| 259 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 260 | /* discard a pending interrupt if any */ |
Andrew Boie | e98ac23 | 2016-08-02 12:05:08 -0700 | [diff] [blame] | 261 | #if CONFIG_EOI_FORWARDING_BUG |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 262 | z_lakemont_eoi(); |
Andrew Boie | e98ac23 | 2016-08-02 12:05:08 -0700 | [diff] [blame] | 263 | #else |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 264 | LOAPIC_WRITE(LOAPIC_EOI, 0); |
Andrew Boie | e98ac23 | 2016-08-02 12:05:08 -0700 | [diff] [blame] | 265 | #endif |
| 266 | |
Dirk Brandewie | be1b1a4 | 2015-09-15 09:17:38 -0700 | [diff] [blame] | 267 | return 0; |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 268 | } |
| 269 | |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 270 | /** |
| 271 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 272 | * @brief Set the vector field in the specified RTE |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 273 | * |
Andrew Boie | 325cae5 | 2016-09-22 11:20:26 -0700 | [diff] [blame] | 274 | * This associates an IRQ with the desired vector in the IDT. |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 275 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 276 | * @return N/A |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 277 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 278 | |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 279 | void z_loapic_int_vec_set(unsigned int irq, /* IRQ number of the interrupt */ |
Peter Mitsis | 2a4a6cf | 2015-07-27 11:02:41 -0400 | [diff] [blame] | 280 | unsigned int vector /* vector to copy into the LVT */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 281 | ) |
| 282 | { |
Flavio Ceolin | 0866d18 | 2018-08-14 17:57:08 -0700 | [diff] [blame] | 283 | unsigned int oldLevel; /* previous interrupt lock level */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 284 | |
| 285 | /* |
| 286 | * The following mappings are used: |
| 287 | * |
| 288 | * IRQ0 -> LOAPIC_TIMER |
| 289 | * IRQ1 -> LOAPIC_THERMAL |
| 290 | * IRQ2 -> LOAPIC_PMC |
| 291 | * IRQ3 -> LOAPIC_LINT0 |
| 292 | * IRQ4 -> LOAPIC_LINT1 |
| 293 | * IRQ5 -> LOAPIC_ERROR |
| 294 | * |
| 295 | * It's assumed that LVTs are spaced by 0x10 bytes |
| 296 | */ |
| 297 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 298 | /* update the 'vector' bits in the LVT */ |
| 299 | |
| 300 | oldLevel = irq_lock(); |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 301 | LOAPIC_WRITE(LOAPIC_TIMER + (irq * 0x10), |
| 302 | (LOAPIC_READ(LOAPIC_TIMER + (irq * 0x10)) & |
| 303 | ~LOAPIC_VECTOR) | vector); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 304 | irq_unlock(oldLevel); |
| 305 | } |
| 306 | |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 307 | /** |
| 308 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 309 | * @brief Enable an individual LOAPIC interrupt (IRQ) |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 310 | * |
Dan Kalowsky | 3a109b1 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 311 | * @param irq the IRQ number of the interrupt |
| 312 | * |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 313 | * This routine clears the interrupt mask bit in the LVT for the specified IRQ |
| 314 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 315 | * @return N/A |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 316 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 317 | |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 318 | void z_loapic_irq_enable(unsigned int irq) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 319 | { |
Flavio Ceolin | 0866d18 | 2018-08-14 17:57:08 -0700 | [diff] [blame] | 320 | unsigned int oldLevel; /* previous interrupt lock level */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 321 | |
| 322 | /* |
| 323 | * See the comments in _LoApicLvtVecSet() regarding IRQ to LVT mappings |
| 324 | * and ths assumption concerning LVT spacing. |
| 325 | */ |
| 326 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 327 | /* clear the mask bit in the LVT */ |
| 328 | |
| 329 | oldLevel = irq_lock(); |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 330 | LOAPIC_WRITE(LOAPIC_TIMER + (irq * 0x10), |
| 331 | LOAPIC_READ(LOAPIC_TIMER + (irq * 0x10)) & |
| 332 | ~LOAPIC_LVT_MASKED); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 333 | irq_unlock(oldLevel); |
| 334 | } |
| 335 | |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 336 | /** |
| 337 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 338 | * @brief Disable an individual LOAPIC interrupt (IRQ) |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 339 | * |
Dan Kalowsky | 3a109b1 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 340 | * @param irq the IRQ number of the interrupt |
| 341 | * |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 342 | * This routine clears the interrupt mask bit in the LVT for the specified IRQ |
| 343 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 344 | * @return N/A |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 345 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 346 | |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 347 | void z_loapic_irq_disable(unsigned int irq) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 348 | { |
Flavio Ceolin | 0866d18 | 2018-08-14 17:57:08 -0700 | [diff] [blame] | 349 | unsigned int oldLevel; /* previous interrupt lock level */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 350 | |
| 351 | /* |
| 352 | * See the comments in _LoApicLvtVecSet() regarding IRQ to LVT mappings |
| 353 | * and ths assumption concerning LVT spacing. |
| 354 | */ |
| 355 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 356 | /* set the mask bit in the LVT */ |
| 357 | |
| 358 | oldLevel = irq_lock(); |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 359 | LOAPIC_WRITE(LOAPIC_TIMER + (irq * 0x10), |
| 360 | LOAPIC_READ(LOAPIC_TIMER + (irq * 0x10)) | |
| 361 | LOAPIC_LVT_MASKED); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 362 | irq_unlock(oldLevel); |
| 363 | } |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 364 | |
| 365 | |
| 366 | /** |
| 367 | * @brief Find the currently executing interrupt vector, if any |
| 368 | * |
| 369 | * This routine finds the vector of the interrupt that is being processed. |
| 370 | * The ISR (In-Service Register) register contain the vectors of the interrupts |
David B. Kinder | 896cf7a | 2017-04-19 10:45:34 -0700 | [diff] [blame] | 371 | * in service. And the higher vector is the identification of the interrupt |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 372 | * being currently processed. |
| 373 | * |
Andrew Boie | a69ea78 | 2016-07-12 11:42:18 -0700 | [diff] [blame] | 374 | * This function must be called with interrupts locked in interrupt context. |
| 375 | * |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 376 | * ISR registers' offsets: |
| 377 | * -------------------- |
| 378 | * | Offset | bits | |
| 379 | * -------------------- |
| 380 | * | 0100H | 0:31 | |
| 381 | * | 0110H | 32:63 | |
| 382 | * | 0120H | 64:95 | |
| 383 | * | 0130H | 96:127 | |
| 384 | * | 0140H | 128:159 | |
| 385 | * | 0150H | 160:191 | |
| 386 | * | 0160H | 192:223 | |
| 387 | * | 0170H | 224:255 | |
| 388 | * -------------------- |
| 389 | * |
Andrew Boie | eec13ca | 2016-09-08 11:01:23 -0700 | [diff] [blame] | 390 | * @return The vector of the interrupt that is currently being processed, or -1 |
| 391 | * if no IRQ is being serviced. |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 392 | */ |
Andrew Boie | e98ac23 | 2016-08-02 12:05:08 -0700 | [diff] [blame] | 393 | int __irq_controller_isr_vector_get(void) |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 394 | { |
Andrew Boie | a69ea78 | 2016-07-12 11:42:18 -0700 | [diff] [blame] | 395 | int pReg, block; |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 396 | |
Andrew Boie | eec13ca | 2016-09-08 11:01:23 -0700 | [diff] [blame] | 397 | /* Block 0 bits never lit up as these are all exception or reserved |
| 398 | * vectors |
| 399 | */ |
| 400 | for (block = 7; likely(block > 0); block--) { |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 401 | pReg = LOAPIC_READ(LOAPIC_ISR + (block * 0x10)); |
Andrew Boie | a69ea78 | 2016-07-12 11:42:18 -0700 | [diff] [blame] | 402 | if (pReg) { |
| 403 | return (block * 32) + (find_msb_set(pReg) - 1); |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 404 | } |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 405 | |
Andrew Boie | a69ea78 | 2016-07-12 11:42:18 -0700 | [diff] [blame] | 406 | } |
Andrew Boie | eec13ca | 2016-09-08 11:01:23 -0700 | [diff] [blame] | 407 | return -1; |
Yonattan Louise | d2108bf | 2015-08-21 19:10:32 -0500 | [diff] [blame] | 408 | } |
Daniel Leung | 921ee03 | 2015-12-08 11:17:56 -0800 | [diff] [blame] | 409 | |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 410 | #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 411 | static int loapic_suspend(struct device *port) |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 412 | { |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 413 | volatile u32_t lvt; /* local vector table entry value */ |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 414 | int loapic_irq; |
| 415 | |
| 416 | ARG_UNUSED(port); |
| 417 | |
Flavio Ceolin | da49f2e | 2018-09-11 19:09:03 -0700 | [diff] [blame] | 418 | (void)memset(loapic_suspend_buf, 0, (LOPIC_SUSPEND_BITS_REQD >> 3)); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 419 | |
| 420 | for (loapic_irq = 0; loapic_irq < LOAPIC_IRQ_COUNT; loapic_irq++) { |
| 421 | |
| 422 | if (_irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]) { |
| 423 | |
| 424 | /* Since vector numbers are already present in RAM/ROM, |
| 425 | * We save only the mask bits here. |
| 426 | */ |
Gustavo Lima Chaves | 1a8e72c | 2017-10-11 14:08:17 -0700 | [diff] [blame] | 427 | lvt = LOAPIC_READ(LOAPIC_TIMER + (loapic_irq * 0x10)); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 428 | |
Patrik Flykt | 24d7143 | 2019-03-26 19:57:45 -0600 | [diff] [blame] | 429 | if ((lvt & LOAPIC_LVT_MASKED) == 0U) { |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 430 | sys_bitfield_set_bit((mem_addr_t)loapic_suspend_buf, |
| 431 | loapic_irq); |
| 432 | } |
| 433 | } |
| 434 | } |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 435 | loapic_device_power_state = DEVICE_PM_SUSPEND_STATE; |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 436 | return 0; |
| 437 | } |
| 438 | |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 439 | int loapic_resume(struct device *port) |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 440 | { |
| 441 | int loapic_irq; |
| 442 | |
| 443 | ARG_UNUSED(port); |
| 444 | |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 445 | /* Assuming all loapic device registers lose their state, the call to |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 446 | * z_loapic_init(), should bring all the registers to a sane state. |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 447 | */ |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 448 | loapic_init(NULL); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 449 | |
| 450 | for (loapic_irq = 0; loapic_irq < LOAPIC_IRQ_COUNT; loapic_irq++) { |
| 451 | |
| 452 | if (_irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]) { |
| 453 | /* Configure vector and enable the required ones*/ |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 454 | z_loapic_int_vec_set(loapic_irq, |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 455 | _irq_to_interrupt_vector[LOAPIC_IRQ_BASE + loapic_irq]); |
| 456 | |
| 457 | if (sys_bitfield_test_bit((mem_addr_t) loapic_suspend_buf, |
| 458 | loapic_irq)) { |
Patrik Flykt | 4344e27 | 2019-03-08 14:19:05 -0700 | [diff] [blame] | 459 | z_loapic_irq_enable(loapic_irq); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 460 | } |
| 461 | } |
| 462 | } |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 463 | loapic_device_power_state = DEVICE_PM_ACTIVE_STATE; |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 464 | |
| 465 | return 0; |
| 466 | } |
| 467 | |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 468 | /* |
| 469 | * Implements the driver control management functionality |
| 470 | * the *context may include IN data or/and OUT data |
| 471 | */ |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 472 | static int loapic_device_ctrl(struct device *port, u32_t ctrl_command, |
Ramakrishna Pallala | e1639b5 | 2019-02-14 09:35:42 +0530 | [diff] [blame] | 473 | void *context, device_pm_cb cb, void *arg) |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 474 | { |
Ramakrishna Pallala | e1639b5 | 2019-02-14 09:35:42 +0530 | [diff] [blame] | 475 | int ret = 0; |
| 476 | |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 477 | if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 478 | if (*((u32_t *)context) == DEVICE_PM_SUSPEND_STATE) { |
Ramakrishna Pallala | e1639b5 | 2019-02-14 09:35:42 +0530 | [diff] [blame] | 479 | ret = loapic_suspend(port); |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 480 | } else if (*((u32_t *)context) == DEVICE_PM_ACTIVE_STATE) { |
Ramakrishna Pallala | e1639b5 | 2019-02-14 09:35:42 +0530 | [diff] [blame] | 481 | ret = loapic_resume(port); |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 482 | } |
| 483 | } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { |
Kumar Gala | ccad5bf | 2017-04-21 10:03:20 -0500 | [diff] [blame] | 484 | *((u32_t *)context) = loapic_device_power_state; |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 485 | } |
| 486 | |
Ramakrishna Pallala | e1639b5 | 2019-02-14 09:35:42 +0530 | [diff] [blame] | 487 | if (cb) { |
| 488 | cb(port, ret, context, arg); |
| 489 | } |
| 490 | |
| 491 | return ret; |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 492 | } |
| 493 | |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 494 | SYS_DEVICE_DEFINE("loapic", loapic_init, loapic_device_ctrl, PRE_KERNEL_1, |
amirkapl | c490219 | 2016-09-11 19:17:19 +0300 | [diff] [blame] | 495 | CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 496 | #else |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 497 | SYS_INIT(loapic_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); |
Jithu Joseph | 09a0c2f | 2016-05-06 21:55:51 -0700 | [diff] [blame] | 498 | #endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ |
| 499 | |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 500 | |
| 501 | #if CONFIG_LOAPIC_SPURIOUS_VECTOR |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 502 | extern void z_loapic_spurious_handler(void); |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 503 | |
Patrik Flykt | 97b3bd1 | 2019-03-12 15:15:42 -0600 | [diff] [blame] | 504 | NANO_CPU_INT_REGISTER(z_loapic_spurious_handler, NANO_SOFT_IRQ, |
Andrew Boie | c25d6c5 | 2015-12-09 14:53:41 -0800 | [diff] [blame] | 505 | LOAPIC_SPURIOUS_VECTOR_ID >> 4, |
| 506 | LOAPIC_SPURIOUS_VECTOR_ID, 0); |
| 507 | #endif |