1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Nios II C-domain interrupt management code for use with Internal
10 * Interrupt Controller (IIC)
11 */
12
13
14 #include <zephyr/kernel.h>
15 #include <zephyr/kernel_structs.h>
16 #include <zephyr/arch/cpu.h>
17 #include <zephyr/irq.h>
18 #include <zephyr/sw_isr_table.h>
19 #include <ksched.h>
20 #include <kswap.h>
21 #include <zephyr/tracing/tracing.h>
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
24
z_irq_spurious(const void * unused)25 FUNC_NORETURN void z_irq_spurious(const void *unused)
26 {
27 ARG_UNUSED(unused);
28 LOG_ERR("Spurious interrupt detected! ipending: %x",
29 z_nios2_creg_read(NIOS2_CR_IPENDING));
30 z_nios2_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
31 }
32
33
arch_irq_enable(unsigned int irq)34 void arch_irq_enable(unsigned int irq)
35 {
36 uint32_t ienable;
37 unsigned int key;
38
39 key = irq_lock();
40
41 ienable = z_nios2_creg_read(NIOS2_CR_IENABLE);
42 ienable |= BIT(irq);
43 z_nios2_creg_write(NIOS2_CR_IENABLE, ienable);
44
45 irq_unlock(key);
46 };
47
48
49
arch_irq_disable(unsigned int irq)50 void arch_irq_disable(unsigned int irq)
51 {
52 uint32_t ienable;
53 unsigned int key;
54
55 key = irq_lock();
56
57 ienable = z_nios2_creg_read(NIOS2_CR_IENABLE);
58 ienable &= ~BIT(irq);
59 z_nios2_creg_write(NIOS2_CR_IENABLE, ienable);
60
61 irq_unlock(key);
62 };
63
arch_irq_is_enabled(unsigned int irq)64 int arch_irq_is_enabled(unsigned int irq)
65 {
66 uint32_t ienable;
67
68 ienable = z_nios2_creg_read(NIOS2_CR_IENABLE);
69 return ienable & BIT(irq);
70 }
71
72 /**
73 * @brief Interrupt demux function
74 *
75 * Given a bitfield of pending interrupts, execute the appropriate handler
76 *
77 * @param ipending Bitfield of interrupts
78 */
_enter_irq(uint32_t ipending)79 void _enter_irq(uint32_t ipending)
80 {
81 int index;
82
83 _kernel.cpus[0].nested++;
84
85 #ifdef CONFIG_IRQ_OFFLOAD
86 z_irq_do_offload();
87 #endif
88
89 while (ipending) {
90 struct _isr_table_entry *ite;
91
92 #ifdef CONFIG_TRACING_ISR
93 sys_trace_isr_enter();
94 #endif
95
96 index = find_lsb_set(ipending) - 1;
97 ipending &= ~BIT(index);
98
99 ite = &_sw_isr_table[index];
100
101 ite->isr(ite->arg);
102 #ifdef CONFIG_TRACING_ISR
103 sys_trace_isr_exit();
104 #endif
105 }
106
107 _kernel.cpus[0].nested--;
108 #ifdef CONFIG_STACK_SENTINEL
109 z_check_stack_sentinel();
110 #endif
111 }
112
113 #ifdef CONFIG_DYNAMIC_INTERRUPTS
arch_irq_connect_dynamic(unsigned int irq,unsigned int priority,void (* routine)(const void * parameter),const void * parameter,uint32_t flags)114 int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
115 void (*routine)(const void *parameter),
116 const void *parameter, uint32_t flags)
117 {
118 ARG_UNUSED(flags);
119 ARG_UNUSED(priority);
120
121 z_isr_install(irq, routine, parameter);
122 return irq;
123 }
124 #endif /* CONFIG_DYNAMIC_INTERRUPTS */
125