1 /*
2 * Copyright (c) 2006-2020, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-04-05 bigmagic Initial version
9 */
10
11 /**
12 * @addtogroup ls2k
13 */
14
15 /*@{*/
16
17 #include <rtthread.h>
18 #include <rthw.h>
19 #include <exception.h>
20 #include <drivers/dev_pin.h>
21 #include "ls2k1000.h"
22 #include "interrupt.h"
23
24 static struct rt_irq_desc irq_handle_table[MAX_INTR];
25
rt_hw_interrupt_handler(int vector,void * param)26 static void rt_hw_interrupt_handler(int vector, void *param)
27 {
28 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
29 }
30
liointc_init(void)31 static void liointc_init(void)
32 {
33 int i;
34 /* Router for LIOINTC0, to Core 0, INT0 (CPU IP2) */
35 for (i = 0; i < 32; i ++)
36 {
37 HWREG8(LIOINTC0_BASE + i) = LIOINTC_COREx_INTy(0, 0);
38 }
39
40 /* Router for LIOINTC1, to Core 0, INT1 (CPU IP3) */
41 for (i = 0; i < 32; i ++)
42 {
43 HWREG8(LIOINTC1_BASE + i) = LIOINTC_COREx_INTy(0, 1);
44 }
45
46 /* Disable all IRQs */
47 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_DISABLE) = 0xffffffff;
48 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_DISABLE) = 0xffffffff;
49
50 /* Set all IRQs to low level triggered (Default?) */
51 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) = 0x0;
52 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) = 0x0;
53
54 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) = 0x0;
55 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) = 0x0;
56 }
57
58 //set irq mode
liointc_set_irq_mode(int irq,int mode)59 void liointc_set_irq_mode(int irq, int mode)
60 {
61 if (irq < 32)
62 {
63 if (mode == PIN_IRQ_MODE_RISING)
64 {
65 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq));
66 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
67 }
68 else if (mode == PIN_IRQ_MODE_FALLING)
69 {
70 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
71 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
72 }
73 else if (mode == PIN_IRQ_MODE_HIGH_LEVEL)
74 {
75 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
76 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq));
77 }
78 else if (mode == PIN_IRQ_MODE_LOW_LEVEL)
79 {
80 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq));
81 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq));
82 }
83 else
84 {
85 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq));
86 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq));
87 }
88 }
89 else
90 {
91 if (mode == PIN_IRQ_MODE_RISING)
92 {
93 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq - 32));
94 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
95 }
96 else if (mode == PIN_IRQ_MODE_FALLING)
97 {
98 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
99 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
100 }
101 else if (mode == PIN_IRQ_MODE_HIGH_LEVEL)
102 {
103 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
104 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq - 32));
105 }
106 else if (mode == PIN_IRQ_MODE_LOW_LEVEL)
107 {
108 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x0 << (irq - 32));
109 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x0 << (irq - 32));
110 }
111 else
112 {
113 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_POL) |= (0x1 << (irq - 32));
114 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_EDGE) |= (0x1 << (irq - 32));
115 }
116 }
117 }
118
liointc_isr(rt_ubase_t reg_base,rt_ubase_t isr_base,int irq_base)119 static void liointc_isr(rt_ubase_t reg_base, rt_ubase_t isr_base,
120 int irq_base)
121 {
122 rt_uint32_t isr, tmp;
123 int intx;
124 /* Mask to clear ISR */
125 isr = HWREG32(isr_base);
126
127 tmp = isr;
128 /* Handle each of them */
129 while (tmp)
130 {
131 rt_isr_handler_t irq_func;
132 void *param;
133 int irq;
134
135 intx = __rt_ffs(isr) - 1;
136 tmp &= ~(1 << intx);
137
138 irq = intx + irq_base;
139
140 irq_func = irq_handle_table[irq].handler;
141 param = irq_handle_table[irq].param;
142 irq_func(irq, param);
143 #ifdef RT_USING_INTERRUPT_INFO
144 irq_handle_table[irq].counter++;
145 #endif
146 }
147
148 /* Enable them again */
149 HWREG32(reg_base + LIOINTC_REG_INTC_ENABLE) = isr;
150 }
151
152 /**
153 * This function will initialize hardware interrupt
154 */
rt_hw_interrupt_init(void)155 void rt_hw_interrupt_init(void)
156 {
157 rt_uint32_t idx;
158
159 rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table));
160 for (idx = 0; idx < MAX_INTR; idx ++)
161 {
162 irq_handle_table[idx].handler = rt_hw_interrupt_handler;
163 }
164
165 liointc_init();
166 }
167
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)168 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
169 void *param, const char *name)
170 {
171 rt_isr_handler_t old_handler = RT_NULL;
172
173 if (vector >= 0 && vector < MAX_INTR)
174 {
175 old_handler = irq_handle_table[vector].handler;
176
177 #ifdef RT_USING_INTERRUPT_INFO
178 rt_strncpy(irq_handle_table[vector].name, name, RT_NAME_MAX);
179 #endif /* RT_USING_INTERRUPT_INFO */
180 irq_handle_table[vector].handler = handler;
181 irq_handle_table[vector].param = param;
182 }
183
184 if (vector <= 32)
185 {
186 mips_unmask_cpu_irq(2);
187 }
188 else
189 {
190 mips_unmask_cpu_irq(3);
191 }
192
193 return old_handler;
194 }
195
rt_do_mips_cpu_irq(rt_uint32_t ip)196 void rt_do_mips_cpu_irq(rt_uint32_t ip)
197 {
198 void *param;
199 rt_isr_handler_t irq_func;
200 if (ip == 7)
201 {
202 rt_hw_timer_handler();
203 }
204 else if (ip == 2)
205 {
206 liointc_isr(LIOINTC0_BASE, CORE0_INTISR0, LIOINTC0_IRQBASE);
207 }
208 else if (ip == 3)
209 {
210 liointc_isr(LIOINTC1_BASE, CORE0_INTISR1, LIOINTC1_IRQBASE);
211 }
212 }
213
rt_hw_interrupt_umask(int irq)214 void rt_hw_interrupt_umask(int irq)
215 {
216 if (irq < LIOINTC0_IRQBASE + 32)
217 {
218 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_ENABLE) = (1 << irq);
219 }
220 else if (irq < LIOINTC1_IRQBASE + 32)
221 {
222 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_ENABLE) = (1 << (irq - 32));
223 }
224 }
225
rt_hw_interrupt_mask(int irq)226 void rt_hw_interrupt_mask(int irq)
227 {
228 if (irq < LIOINTC0_IRQBASE + 32)
229 {
230 HWREG32(LIOINTC0_BASE + LIOINTC_REG_INTC_DISABLE) = (1 << irq);
231 }
232 else if (irq < LIOINTC1_IRQBASE + 32)
233 {
234 HWREG32(LIOINTC1_BASE + LIOINTC_REG_INTC_DISABLE) = (1 << (irq - 32));
235 }
236 }
237 /*@}*/
238