drivers/interrupt_controller/mvic.c: remove MVIC interrupt controller

The Quark D2000 is the only x86 with an MVIC, and since support for
it has been dropped, the interrupt controller is orphaned. Removed.

Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
Charles E. Youse 2019-06-23 19:19:48 +00:00 committed by Anas Nashif
commit 3dc7c7a6ea
16 changed files with 5 additions and 435 deletions

View file

@ -230,7 +230,6 @@
/include/drivers/modem/ @mike-scott /include/drivers/modem/ @mike-scott
/include/drivers/ioapic.h @andrewboie /include/drivers/ioapic.h @andrewboie
/include/drivers/loapic.h @andrewboie /include/drivers/loapic.h @andrewboie
/include/drivers/mvic.h @andrewboie
/include/drivers/pcie/ @gnuless /include/drivers/pcie/ @gnuless
/include/drivers/serial/uart_ns16550.h @gnuless /include/drivers/serial/uart_ns16550.h @gnuless
/include/dt-bindings/clock/kinetis_scg.h @henrikbrixandersen /include/dt-bindings/clock/kinetis_scg.h @henrikbrixandersen

View file

@ -345,27 +345,19 @@ config X86_KERNEL_OOPS
config X86_KERNEL_OOPS_VECTOR config X86_KERNEL_OOPS_VECTOR
int "IDT vector to use for kernel oops" int "IDT vector to use for kernel oops"
default 62 if MVIC default 33
default 33 if !MVIC
range 32 255 range 32 255
depends on X86_KERNEL_OOPS depends on X86_KERNEL_OOPS
help help
Specify the IDT vector to use for the kernel oops exception handler. Specify the IDT vector to use for the kernel oops exception handler.
The default should be fine for most arches, but on systems like MVIC
where there is a fixed IRQ-to-vector mapping another value may be
needed to avoid collision.
config IRQ_OFFLOAD_VECTOR config IRQ_OFFLOAD_VECTOR
int "IDT vector to use for IRQ offload" int "IDT vector to use for IRQ offload"
default 63 if MVIC default 32
default 32 if !MVIC
range 32 255 range 32 255
depends on IRQ_OFFLOAD depends on IRQ_OFFLOAD
help help
Specify the IDT vector to use for the IRQ offload interrupt handler. Specify the IDT vector to use for the IRQ offload interrupt handler.
The default should be fine for most arches, but on systems like MVIC
where there is a fixed IRQ-to-vector mapping another value may be
needed to avoid collision.
config X86_DYNAMIC_IRQ_STUBS config X86_DYNAMIC_IRQ_STUBS
int "Number of dynamic interrupt stubs" int "Number of dynamic interrupt stubs"

View file

@ -249,10 +249,6 @@ static void idt_vector_install(int vector, void *irq_handler)
key = irq_lock(); key = irq_lock();
z_init_irq_gate(&z_x86_idt.entries[vector], CODE_SEG, z_init_irq_gate(&z_x86_idt.entries[vector], CODE_SEG,
(u32_t)irq_handler, 0); (u32_t)irq_handler, 0);
#ifdef CONFIG_MVIC
/* MVIC requires IDT be reloaded if the entries table is ever changed */
z_set_idt(&z_x86_idt);
#endif
irq_unlock(key); irq_unlock(key);
} }

View file

@ -320,10 +320,7 @@ There can be significant differences between the interrupt controllers and the
interrupt concepts across architectures. interrupt concepts across architectures.
For example, x86 has the concept of an :abbr:`IDT (Interrupt Descriptor Table)` For example, x86 has the concept of an :abbr:`IDT (Interrupt Descriptor Table)`
and different interrupt controllers. Although modern systems mostly and different interrupt controllers. The position of an interrupt in the IDT
standardized on the :abbr:`APIC (Advanced Programmable Interrupt Controller)`,
some small Quark-based systems use the :abbr:`MVIC (Micro-controller Vectored
Interrupt Controller)`. Also, the position of an interrupt in the IDT
determines its priority. determines its priority.
On the other hand, the ARM Cortex-M has the :abbr:`NVIC (Nested Vectored On the other hand, the ARM Cortex-M has the :abbr:`NVIC (Nested Vectored

View file

@ -389,10 +389,6 @@ scheme, interrupts of priority level 0 will be placed in vectors 32-47, level 1
configures an interrupt it will look for a free vector in the appropriate range configures an interrupt it will look for a free vector in the appropriate range
for the requested priority level and set the handler there. for the requested priority level and set the handler there.
There are some APIC variants (such as MVIC) where priorities cannot be set
by the user and the position in the vector table does correspond to the
IRQ line. Systems like this will enable CONFIG_X86_FIXED_IRQ_MAPPING.
On x86 when an interrupt or exception vector is executed by the CPU, there is On x86 when an interrupt or exception vector is executed by the CPU, there is
no foolproof way to determine which vector was fired, so a software ISR table no foolproof way to determine which vector was fired, so a software ISR table
indexed by IRQ line is not used. Instead, the :c:macro:`IRQ_CONNECT` call indexed by IRQ line is not used. Instead, the :c:macro:`IRQ_CONNECT` call

View file

@ -4,7 +4,6 @@ zephyr_sources_ifdef(CONFIG_ARCV2_INTERRUPT_UNIT arcv2_irq_unit.c)
zephyr_sources_ifdef(CONFIG_IOAPIC ioapic_intr.c) zephyr_sources_ifdef(CONFIG_IOAPIC ioapic_intr.c)
zephyr_sources_ifdef(CONFIG_LOAPIC loapic_intr.c system_apic.c) zephyr_sources_ifdef(CONFIG_LOAPIC loapic_intr.c system_apic.c)
zephyr_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR loapic_spurious.S) zephyr_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR loapic_spurious.S)
zephyr_sources_ifdef(CONFIG_MVIC mvic.c)
zephyr_sources_ifdef(CONFIG_PLIC plic.c) zephyr_sources_ifdef(CONFIG_PLIC plic.c)
zephyr_sources_ifdef(CONFIG_SHARED_IRQ shared_irq.c) zephyr_sources_ifdef(CONFIG_SHARED_IRQ shared_irq.c)
zephyr_sources_ifdef(CONFIG_EXTI_STM32 exti_stm32.c) zephyr_sources_ifdef(CONFIG_EXTI_STM32 exti_stm32.c)

View file

@ -84,27 +84,6 @@ config IOAPIC_MASK_RTE
endif #LOAPIC endif #LOAPIC
config MVIC
bool "Intel Quark D2000 Interrupt Controller (MVIC)"
depends on X86
select X86_FIXED_IRQ_MAPPING
help
The MVIC (Intel Quark microcontroller D2000 Interrupt Controller) is
configured by default to support 32 external interrupt lines. Unlike the
traditional IA LAPIC/IOAPIC, the interrupt vectors in MVIC are fixed and
not programmable. In addition, the priorities of these interrupt
lines are also fixed.
config MVIC_TIMER_IRQ
int "IRQ line to use for timer interrupt"
range 0 15
default 10
depends on MVIC
help
Specify the IRQ line to use for the timer interrupt. This should be
an IRQ line unused by any hardware. If nested interrupts are enabled,
higher interrupt lines have priority.
config ARCV2_INTERRUPT_UNIT config ARCV2_INTERRUPT_UNIT
bool "ARCv2 Interrupt Unit" bool "ARCv2 Interrupt Unit"
default y default y

View file

@ -1,225 +0,0 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Quark D2000 Interrupt Controller (MVIC)
*
* This module is based on the standard Local APIC and IO APIC source modules.
* This modules combines these modules into one source module that exports the
* same APIs defined by the Local APIC and IO APIC header modules. These
* routine have been adapted for the Quark D2000 Interrupt Controller which has
* a cutdown implementation of the Local APIC & IO APIC register sets.
*
* The MVIC (Quark D2000 Interrupt Controller) is configured by default
* to support 32 external interrupt lines.
* Unlike the traditional IA LAPIC/IOAPIC, the interrupt vectors in MVIC are fixed
* and not programmable.
* The larger the vector number, the higher the priority of the interrupt.
* Higher priority interrupts preempt lower priority interrupts.
* Lower priority interrupts do not preempt higher priority interrupts.
* The MVIC holds the lower priority interrupts pending until the interrupt
* service routine for the higher priority interrupt writes to the End of
* Interrupt (EOI) register.
* After an EOI write, the MVIC asserts the next highest pending interrupt.
*
* INCLUDE FILES: ioapic.h loapic.h
*
*/
/* includes */
#include <kernel.h>
#include <arch/cpu.h>
#include <misc/__assert.h>
#include <misc/util.h>
#include <init.h>
#include <arch/x86/irq_controller.h>
#include <inttypes.h>
static inline u32_t compute_ioregsel(unsigned int irq)
{
unsigned int low_nibble;
unsigned int high_nibble;
__ASSERT(irq < MVIC_NUM_RTES, "invalid irq line %d", irq);
low_nibble = ((irq & MVIC_LOW_NIBBLE_MASK) << 0x1);
high_nibble = ((irq & MVIC_HIGH_NIBBLE_MASK) << 0x2);
return low_nibble | high_nibble;
}
/**
*
* @brief write to 32 bit MVIC IO APIC register
*
* @param irq INTIN number
* @param value value to be written
*
* @returns N/A
*/
static void mvic_rte_set(unsigned int irq, u32_t value)
{
unsigned int key; /* interrupt lock level */
u32_t regsel;
__ASSERT(!(value & ~MVIC_IOWIN_SUPPORTED_BITS_MASK),
"invalid IRQ flags %" PRIx32 " for irq %d", value, irq);
regsel = compute_ioregsel(irq);
/* lock interrupts to ensure indirect addressing works "atomically" */
key = irq_lock();
sys_write32(regsel, MVIC_IOREGSEL);
sys_write32(value, MVIC_IOWIN);
irq_unlock(key);
}
/**
*
* @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, u32_t value, u32_t mask)
{
unsigned int key;
u32_t regsel, old_value, updated_value;
__ASSERT(!(value & ~MVIC_IOWIN_SUPPORTED_BITS_MASK),
"invalid IRQ flags %" PRIx32 " for irq %d", value, irq);
regsel = compute_ioregsel(irq);
key = irq_lock();
sys_write32(regsel, MVIC_IOREGSEL);
old_value = sys_read32(MVIC_IOWIN);
updated_value = (old_value & ~mask) | (value & mask);
sys_write32(updated_value, MVIC_IOWIN);
irq_unlock(key);
}
/**
*
* @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;
}
SYS_INIT(mvic_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
void z_arch_irq_enable(unsigned int irq)
{
if (irq == CONFIG_MVIC_TIMER_IRQ) {
sys_write32(sys_read32(MVIC_LVTTIMER) & ~MVIC_LVTTIMER_MASK,
MVIC_LVTTIMER);
} else {
mvic_rte_update(irq, 0, MVIC_IOWIN_MASK);
}
}
void z_arch_irq_disable(unsigned int irq)
{
if (irq == CONFIG_MVIC_TIMER_IRQ) {
sys_write32(sys_read32(MVIC_LVTTIMER) | MVIC_LVTTIMER_MASK,
MVIC_LVTTIMER);
} else {
mvic_rte_update(irq, MVIC_IOWIN_MASK, MVIC_IOWIN_MASK);
}
}
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 == 0U,
"Timer interrupt cannot have triggering flags set");
}
}
/**
* @brief Find the currently executing interrupt vector, if any
*
* This routine finds the vector of the interrupt that is being processed.
* The ISR (In-Service Register) register contain the vectors of the interrupts
* in service. And the higher vector is the identification of the interrupt
* being currently processed.
*
* MVIC ISR registers' offsets:
* --------------------
* | Offset | bits |
* --------------------
* | 0110H | 32:63 |
* --------------------
*
* @return The vector of the interrupt that is currently being processed, or
* -1 if this can't be determined
*/
int __irq_controller_isr_vector_get(void)
{
/* In-service register value */
int isr;
isr = sys_read32(MVIC_ISR);
if (unlikely(!isr)) {
return -1;
}
return 32 + (find_msb_set(isr) - 1);
}

View file

@ -6,7 +6,7 @@
#include <errno.h> #include <errno.h>
#include <device.h> #include <device.h>
#if defined(CONFIG_IOAPIC) || defined(CONFIG_MVIC) #if defined(CONFIG_IOAPIC)
#include <ioapic.h> #include <ioapic.h>
#endif #endif
#include <uart.h> #include <uart.h>

View file

@ -44,7 +44,7 @@ endif #HPET_TIMER
menuconfig LOAPIC_TIMER menuconfig LOAPIC_TIMER
bool "LOAPIC timer" bool "LOAPIC timer"
depends on (LOAPIC || MVIC) && X86 depends on LOAPIC && X86
help help
This option selects LOAPIC timer as a system timer. This option selects LOAPIC timer as a system timer.

View file

@ -110,10 +110,8 @@ static unsigned char timer_mode = TIMER_MODE_PERIODIC;
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT #ifdef CONFIG_DEVICE_POWER_MANAGEMENT
static u32_t loapic_timer_device_power_state; static u32_t loapic_timer_device_power_state;
static u32_t reg_timer_save; static u32_t reg_timer_save;
#ifndef CONFIG_MVIC
static u32_t reg_timer_cfg_save; static u32_t reg_timer_cfg_save;
#endif #endif
#endif
/** /**
* *
@ -125,13 +123,8 @@ static u32_t reg_timer_cfg_save;
*/ */
static inline void periodic_mode_set(void) static inline void periodic_mode_set(void)
{ {
#ifdef CONFIG_MVIC
sys_write32(sys_read32(MVIC_LVTTIMER) | LOAPIC_TIMER_PERIODIC,
MVIC_LVTTIMER);
#else
x86_write_loapic(LOAPIC_TIMER, x86_write_loapic(LOAPIC_TIMER,
x86_read_loapic(LOAPIC_TIMER) | LOAPIC_TIMER_PERIODIC); x86_read_loapic(LOAPIC_TIMER) | LOAPIC_TIMER_PERIODIC);
#endif
} }
@ -147,11 +140,7 @@ static inline void periodic_mode_set(void)
*/ */
static inline void initial_count_register_set(u32_t count) static inline void initial_count_register_set(u32_t count)
{ {
#ifdef CONFIG_MVIC
sys_write32(count, MVIC_ICR);
#else
x86_write_loapic(LOAPIC_TIMER_ICR, count); x86_write_loapic(LOAPIC_TIMER_ICR, count);
#endif
} }
#if defined(CONFIG_TICKLESS_IDLE) #if defined(CONFIG_TICKLESS_IDLE)
@ -165,13 +154,8 @@ static inline void initial_count_register_set(u32_t count)
*/ */
static inline void one_shot_mode_set(void) static inline void one_shot_mode_set(void)
{ {
#ifdef CONFIG_MVIC
sys_write32(sys_read32(MVIC_LVTTIMER) & ~LOAPIC_TIMER_PERIODIC,
MVIC_LVTTIMER);
#else
x86_write_loapic(LOAPIC_TIMER, x86_write_loapic(LOAPIC_TIMER,
x86_read_loapic(LOAPIC_TIMER) & ~LOAPIC_TIMER_PERIODIC); x86_read_loapic(LOAPIC_TIMER) & ~LOAPIC_TIMER_PERIODIC);
#endif
} }
#endif /* CONFIG_TICKLESS_IDLE */ #endif /* CONFIG_TICKLESS_IDLE */
@ -188,11 +172,7 @@ static inline void one_shot_mode_set(void)
*/ */
static inline u32_t current_count_register_get(void) static inline u32_t current_count_register_get(void)
{ {
#ifdef CONFIG_MVIC
return sys_read32(MVIC_CCR);
#else
return x86_read_loapic(LOAPIC_TIMER_CCR); return x86_read_loapic(LOAPIC_TIMER_CCR);
#endif
} }
#endif #endif
@ -207,11 +187,7 @@ static inline u32_t current_count_register_get(void)
*/ */
static inline u32_t initial_count_register_get(void) static inline u32_t initial_count_register_get(void)
{ {
#ifdef CONFIG_MVIC
return sys_read32(MVIC_ICR);
#else
return x86_read_loapic(LOAPIC_TIMER_ICR); return x86_read_loapic(LOAPIC_TIMER_ICR);
#endif
} }
#endif /* CONFIG_TICKLESS_IDLE */ #endif /* CONFIG_TICKLESS_IDLE */
@ -603,11 +579,9 @@ int z_clock_driver_init(struct device *device)
tickless_idle_init(); tickless_idle_init();
#ifndef CONFIG_MVIC
x86_write_loapic(LOAPIC_TIMER_CONFIG, x86_write_loapic(LOAPIC_TIMER_CONFIG,
(x86_read_loapic(LOAPIC_TIMER_CONFIG) & ~0xf) (x86_read_loapic(LOAPIC_TIMER_CONFIG) & ~0xf)
| LOAPIC_TIMER_DIVBY_1); | LOAPIC_TIMER_DIVBY_1);
#endif
#ifdef CONFIG_TICKLESS_KERNEL #ifdef CONFIG_TICKLESS_KERNEL
one_shot_mode_set(); one_shot_mode_set();
@ -619,14 +593,9 @@ int z_clock_driver_init(struct device *device)
loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE; loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE;
#endif #endif
#ifdef CONFIG_MVIC
IRQ_CONNECT(CONFIG_MVIC_TIMER_IRQ, -1, timer_int_handler, 0, 0);
irq_enable(CONFIG_MVIC_TIMER_IRQ);
#else
IRQ_CONNECT(CONFIG_LOAPIC_TIMER_IRQ, CONFIG_LOAPIC_TIMER_IRQ_PRIORITY, IRQ_CONNECT(CONFIG_LOAPIC_TIMER_IRQ, CONFIG_LOAPIC_TIMER_IRQ_PRIORITY,
timer_int_handler, 0, 0); timer_int_handler, 0, 0);
irq_enable(CONFIG_LOAPIC_TIMER_IRQ); irq_enable(CONFIG_LOAPIC_TIMER_IRQ);
#endif
return 0; return 0;
} }
@ -636,13 +605,8 @@ static int sys_clock_suspend(struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
#ifdef CONFIG_MVIC
reg_timer_save = sys_read32(MVIC_LVTTIMER);
#else
reg_timer_save = x86_read_loapic(LOAPIC_TIMER); reg_timer_save = x86_read_loapic(LOAPIC_TIMER);
reg_timer_cfg_save = x86_read_loapic(LOAPIC_TIMER_CONFIG); reg_timer_cfg_save = x86_read_loapic(LOAPIC_TIMER_CONFIG);
#endif
loapic_timer_device_power_state = DEVICE_PM_SUSPEND_STATE; loapic_timer_device_power_state = DEVICE_PM_SUSPEND_STATE;
return 0; return 0;
@ -652,12 +616,8 @@ static int sys_clock_resume(struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
#ifdef CONFIG_MVIC
sys_write32(reg_timer_save, MVIC_LVTTIMER);
#else
x86_write_loapic(LOAPIC_TIMER, reg_timer_save); x86_write_loapic(LOAPIC_TIMER, reg_timer_save);
x86_write_loapic(LOAPIC_TIMER_CONFIG, reg_timer_cfg_save); x86_write_loapic(LOAPIC_TIMER_CONFIG, reg_timer_cfg_save);
#endif
/* /*
* It is difficult to accurately know the time spent in DS. * It is difficult to accurately know the time spent in DS.
@ -758,11 +718,7 @@ void sys_clock_disable(void)
key = irq_lock(); key = irq_lock();
#ifdef CONFIG_MVIC
irq_disable(MVIC_TIMER_IRQ);
#else
irq_disable(CONFIG_LOAPIC_TIMER_IRQ); irq_disable(CONFIG_LOAPIC_TIMER_IRQ);
#endif
initial_count_register_set(0); initial_count_register_set(0);
irq_unlock(key); irq_unlock(key);

View file

@ -1,27 +0,0 @@
title: Intel Quark D2000 Interrupt Controller
version: 0.1
description: >
This binding describes the Intel Quark D2000 Interrupt
Controller
inherits:
!include base.yaml
properties:
compatible:
constraint: "intel,mvic"
reg:
category: required
intel,num-irq-priority-bits:
category: required
type: int
description: number of bits of IRQ priorities
generation: define
"#cells":
- irq
- sense

View file

@ -163,9 +163,6 @@ typedef struct s_isrList {
* out the right vector to use based on our priority scheme. Groups of 16 * out the right vector to use based on our priority scheme. Groups of 16
* vectors starting at 32 correspond to each priority level. * vectors starting at 32 correspond to each priority level.
* *
* On MVIC, the mapping is fixed; the vector to use is just the irq line
* number plus 0x20. The priority argument supplied by the user is discarded.
*
* These macros are only intended to be used by IRQ_CONNECT() macro. * These macros are only intended to be used by IRQ_CONNECT() macro.
*/ */
#if CONFIG_X86_FIXED_IRQ_MAPPING #if CONFIG_X86_FIXED_IRQ_MAPPING

View file

@ -7,21 +7,12 @@
/** /**
* @file * @file
* @brief Abstraction layer for x86 interrupt controllers * @brief Abstraction layer for x86 interrupt controllers
*
* Most x86 just support APIC. However we are starting to see design
* variants such as MVIC or APICs with reduced feature sets. This
* interface provides a layer of abstraction between the core arch code
* and the interrupt controller implementation for x86
*/ */
#ifndef ZEPHYR_INCLUDE_ARCH_X86_IRQ_CONTROLLER_H_ #ifndef ZEPHYR_INCLUDE_ARCH_X86_IRQ_CONTROLLER_H_
#define ZEPHYR_INCLUDE_ARCH_X86_IRQ_CONTROLLER_H_ #define ZEPHYR_INCLUDE_ARCH_X86_IRQ_CONTROLLER_H_
#ifdef CONFIG_MVIC
#include <drivers/mvic.h>
#else
#include <drivers/sysapic.h> #include <drivers/sysapic.h>
#endif
/* Triggering flags abstraction layer. /* Triggering flags abstraction layer.
* If a particular set of triggers is not supported, leave undefined * If a particular set of triggers is not supported, leave undefined

View file

@ -1,75 +0,0 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_MVIC_H_
#define ZEPHYR_INCLUDE_DRIVERS_MVIC_H_
#include <arch/cpu.h>
/* Register defines. A lot of similarities to APIC, but not quite the same */
#define MVIC_TPR 0xFEE00080 /* Task priority register */
#define MVIC_PPR 0xFEE000A0 /* Process priority register */
#define MVIC_EOI 0xFEE000B0 /* End-of-interrupt register */
#define MVIC_SIVR 0xFEE000F0 /* Spurious interrupt vector register */
#define MVIC_ISR 0xFEE00110 /* In-service register */
#define MVIC_IRR 0xFEE00210 /* Interrupt request register */
#define MVIC_LVTTIMER 0xFEE00320 /* Local vector table timer register */
#define MVIC_ICR 0xFEE00380 /* Timer initial count register */
#define MVIC_CCR 0xFEE00390 /* Timer current count register */
#define MVIC_IOREGSEL 0xFEC00000 /* Register select (index) */
#define MVIC_IOWIN 0xFEC00010 /* Register windows (data) */
/* MVIC_LVTTIMER bits */
#define MVIC_LVTTIMER_MASK BIT(16)
#define MVIC_LVTTIMER_PERIODIC BIT(17)
/* MVIC_IOWIN bits */
#define MVIC_IOWIN_TRIGGER_LEVEL BIT(15)
#define MVIC_IOWIN_TRIGGER_EDGE 0
#define MVIC_IOWIN_MASK BIT(16)
#define MVIC_IOWIN_SUPPORTED_BITS_MASK (MVIC_IOWIN_MASK | \
MVIC_IOWIN_TRIGGER_LEVEL)
/* MVIC IOREGSEL register usage defines */
#define MVIC_LOW_NIBBLE_MASK 0x07
#define MVIC_HIGH_NIBBLE_MASK 0x18
#define MVIC_NUM_RTES 32
#define _IRQ_TRIGGER_EDGE MVIC_IOWIN_TRIGGER_EDGE
#define _IRQ_TRIGGER_LEVEL MVIC_IOWIN_TRIGGER_LEVEL
/* MVIC does not support IRQ_POLARITY_HIGH or IRQ_POLARITY_LOW,
* leave undefined
*/
#ifndef _ASMLANGUAGE
#include <zephyr/types.h>
/* Implementation of irq_controller.h interface */
#define __IRQ_CONTROLLER_VECTOR_MAPPING(irq) ((irq) + 32)
void __irq_controller_irq_config(unsigned int vector, unsigned int irq,
u32_t flags);
int __irq_controller_isr_vector_get(void);
static inline void __irq_controller_eoi(void)
{
*(volatile int *)(MVIC_EOI) = 0;
}
#else /* _ASMLANGUAGE */
.macro __irq_controller_eoi_macro
xorl %eax, %eax /* zeroes eax */
movl %eax, MVIC_EOI /* tell MVIC the IRQ is handled */
.endm
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_MVIC_H_ */

View file

@ -50,12 +50,7 @@
#if defined(CONFIG_HPET_TIMER) #if defined(CONFIG_HPET_TIMER)
#define TICK_IRQ CONFIG_HPET_TIMER_IRQ #define TICK_IRQ CONFIG_HPET_TIMER_IRQ
#elif defined(CONFIG_LOAPIC_TIMER) #elif defined(CONFIG_LOAPIC_TIMER)
#if defined(CONFIG_LOAPIC)
#define TICK_IRQ CONFIG_LOAPIC_TIMER_IRQ #define TICK_IRQ CONFIG_LOAPIC_TIMER_IRQ
#else
/* MVIC case */
#define TICK_IRQ CONFIG_MVIC_TIMER_IRQ
#endif
#elif defined(CONFIG_XTENSA) #elif defined(CONFIG_XTENSA)
#define TICK_IRQ UTIL_CAT(XCHAL_TIMER, \ #define TICK_IRQ UTIL_CAT(XCHAL_TIMER, \
UTIL_CAT(CONFIG_XTENSA_TIMER_ID, _INTERRUPT)) UTIL_CAT(CONFIG_XTENSA_TIMER_ID, _INTERRUPT))