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