You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.5 KiB
132 lines
3.5 KiB
/* |
|
* Copyright (c) 2016 Cadence Design Systems, Inc. |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/types.h> |
|
#include <stdio.h> |
|
#include <zephyr/arch/xtensa/irq.h> |
|
#include <zephyr/sys/__assert.h> |
|
|
|
#include <kernel_arch_func.h> |
|
|
|
#include <xtensa_internal.h> |
|
|
|
#include <zephyr/logging/log.h> |
|
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); |
|
|
|
/** |
|
* @internal |
|
* |
|
* @brief Set an interrupt's priority |
|
* |
|
* The priority is verified if ASSERT_ON is enabled. |
|
* |
|
* The priority is verified if ASSERT_ON is enabled. The maximum number of |
|
* priority levels is a little complex, as there are some hardware priority |
|
* levels which are reserved: three for various types of exceptions, and |
|
* possibly one additional to support zero latency interrupts. |
|
* |
|
* Valid values are from 1 to 6. Interrupts of priority 1 are not masked when |
|
* interrupts are locked system-wide, so care must be taken when using them. |
|
* ISR installed with priority 0 interrupts cannot make kernel calls. |
|
*/ |
|
void z_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) |
|
{ |
|
__ASSERT(prio < XCHAL_EXCM_LEVEL + 1, |
|
"invalid priority %d! values must be less than %d\n", |
|
prio, XCHAL_EXCM_LEVEL + 1); |
|
/* TODO: Write code to set priority if this is ever possible on |
|
* Xtensa |
|
*/ |
|
} |
|
|
|
#ifdef CONFIG_DYNAMIC_INTERRUPTS |
|
#ifndef CONFIG_MULTI_LEVEL_INTERRUPTS |
|
int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, |
|
void (*routine)(const void *parameter), |
|
const void *parameter, uint32_t flags) |
|
{ |
|
ARG_UNUSED(flags); |
|
ARG_UNUSED(priority); |
|
|
|
z_isr_install(irq, routine, parameter); |
|
return irq; |
|
} |
|
#else /* !CONFIG_MULTI_LEVEL_INTERRUPTS */ |
|
int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, |
|
void (*routine)(const void *parameter), |
|
const void *parameter, uint32_t flags) |
|
{ |
|
return z_soc_irq_connect_dynamic(irq, priority, routine, parameter, |
|
flags); |
|
} |
|
#endif /* !CONFIG_MULTI_LEVEL_INTERRUPTS */ |
|
#endif /* CONFIG_DYNAMIC_INTERRUPTS */ |
|
|
|
void z_irq_spurious(const void *arg) |
|
{ |
|
int irqs, ie; |
|
|
|
ARG_UNUSED(arg); |
|
|
|
__asm__ volatile("rsr.interrupt %0" : "=r"(irqs)); |
|
__asm__ volatile("rsr.intenable %0" : "=r"(ie)); |
|
LOG_ERR(" ** Spurious INTERRUPT(s) %p, INTENABLE = %p", |
|
(void *)irqs, (void *)ie); |
|
|
|
#if XCHAL_NUM_INTERRUPTS > 32 |
|
__asm__ volatile("rsr.interrupt1 %0" : "=r"(irqs)); |
|
__asm__ volatile("rsr.intenable1 %0" : "=r"(ie)); |
|
LOG_ERR(" ** Spurious INTERRUPT1(s) %p, INTENABLE1 = %p", |
|
(void *)irqs, (void *)ie); |
|
#endif |
|
|
|
#if XCHAL_NUM_INTERRUPTS > 64 |
|
__asm__ volatile("rsr.interrupt2 %0" : "=r"(irqs)); |
|
__asm__ volatile("rsr.intenable2 %0" : "=r"(ie)); |
|
LOG_ERR(" ** Spurious INTERRUPT2(s) %p, INTENABLE2 = %p", |
|
(void *)irqs, (void *)ie); |
|
#endif |
|
|
|
#if XCHAL_NUM_INTERRUPTS > 96 |
|
__asm__ volatile("rsr.interrupt3 %0" : "=r"(irqs)); |
|
__asm__ volatile("rsr.intenable3 %0" : "=r"(ie)); |
|
LOG_ERR(" ** Spurious INTERRUPT3(s) %p, INTENABLE3 = %p", |
|
(void *)irqs, (void *)ie); |
|
#endif |
|
|
|
xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); |
|
} |
|
|
|
int xtensa_irq_is_enabled(unsigned int irq) |
|
{ |
|
uint32_t ie; |
|
|
|
#if XCHAL_NUM_INTERRUPTS > 32 |
|
switch (irq >> 5) { |
|
case 0: |
|
__asm__ volatile("rsr.intenable %0" : "=r"(ie)); |
|
break; |
|
case 1: |
|
__asm__ volatile("rsr.intenable1 %0" : "=r"(ie)); |
|
break; |
|
#if XCHAL_NUM_INTERRUPTS > 64 |
|
case 2: |
|
__asm__ volatile("rsr.intenable2 %0" : "=r"(ie)); |
|
break; |
|
#endif |
|
#if XCHAL_NUM_INTERRUPTS > 96 |
|
case 3: |
|
__asm__ volatile("rsr.intenable3 %0" : "=r"(ie)); |
|
break; |
|
#endif |
|
default: |
|
break; |
|
} |
|
#else |
|
__asm__ volatile("rsr.intenable %0" : "=r"(ie)); |
|
#endif |
|
|
|
return (ie & (1 << (irq & 31U))) != 0U; |
|
}
|
|
|