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 <kernel.h>
15 #include <kernel_structs.h>
16 #include <arch/cpu.h>
17 #include <irq.h>
18 #include <sw_isr_table.h>
19 #include <ksched.h>
20 #include <kswap.h>
21 #include <tracing/tracing.h>
22 #include <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