1 /*
2  * Copyright (c) 2016 Cadence Design Systems, Inc.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/types.h>
7 #include <stdio.h>
8 #include <zephyr/arch/xtensa/irq.h>
9 #include <zephyr/sys/__assert.h>
10 
11 #include <kernel_arch_func.h>
12 
13 #include <xtensa_internal.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
17 
18 /**
19  * @internal
20  *
21  * @brief Set an interrupt's priority
22  *
23  * The priority is verified if ASSERT_ON is enabled.
24  *
25  * The priority is verified if ASSERT_ON is enabled. The maximum number of
26  * priority levels is a little complex, as there are some hardware priority
27  * levels which are reserved: three for various types of exceptions, and
28  * possibly one additional to support zero latency interrupts.
29  *
30  * Valid values are from 1 to 6. Interrupts of priority 1 are not masked when
31  * interrupts are locked system-wide, so care must be taken when using them.
32  * ISR installed with priority 0 interrupts cannot make kernel calls.
33  */
z_irq_priority_set(unsigned int irq,unsigned int prio,uint32_t flags)34 void z_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
35 {
36 	__ASSERT(prio < XCHAL_EXCM_LEVEL + 1,
37 		 "invalid priority %d! values must be less than %d\n",
38 		 prio, XCHAL_EXCM_LEVEL + 1);
39 	/* TODO: Write code to set priority if this is ever possible on
40 	 * Xtensa
41 	 */
42 }
43 
44 #ifdef CONFIG_DYNAMIC_INTERRUPTS
45 #ifndef CONFIG_MULTI_LEVEL_INTERRUPTS
z_arch_irq_connect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)46 int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
47 			       void (*routine)(const void *parameter),
48 			       const void *parameter, uint32_t flags)
49 {
50 	ARG_UNUSED(flags);
51 	ARG_UNUSED(priority);
52 
53 	z_isr_install(irq, routine, parameter);
54 	return irq;
55 }
56 #else /* !CONFIG_MULTI_LEVEL_INTERRUPTS */
z_arch_irq_connect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)57 int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
58 			       void (*routine)(const void *parameter),
59 			       const void *parameter, uint32_t flags)
60 {
61 	return z_soc_irq_connect_dynamic(irq, priority, routine, parameter,
62 					 flags);
63 }
64 #endif /* !CONFIG_MULTI_LEVEL_INTERRUPTS */
65 #endif /* CONFIG_DYNAMIC_INTERRUPTS */
66 
z_irq_spurious(const void * arg)67 void z_irq_spurious(const void *arg)
68 {
69 	int irqs, ie;
70 
71 	ARG_UNUSED(arg);
72 
73 	__asm__ volatile("rsr.interrupt %0" : "=r"(irqs));
74 	__asm__ volatile("rsr.intenable %0" : "=r"(ie));
75 	LOG_ERR(" ** Spurious INTERRUPT(s) %p, INTENABLE = %p",
76 		(void *)irqs, (void *)ie);
77 	xtensa_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
78 }
79 
xtensa_irq_is_enabled(unsigned int irq)80 int xtensa_irq_is_enabled(unsigned int irq)
81 {
82 	uint32_t ie;
83 
84 	__asm__ volatile("rsr.intenable %0" : "=r"(ie));
85 
86 	return (ie & (1 << irq)) != 0U;
87 }
88