xref: /nrf52832-nimble/rt-thread/libcpu/mips/x1000/interrupt.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * File      : cpu_intc.c
3  * This file is part of RT-Thread RTOS
4  * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Change Logs:
21  * Date           Author       Notes
22  * 2016/09/07     Urey         the first version
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 #include <rtthread.h>
29 #include <rthw.h>
30 #include <board.h>
31 
32 #include "../common/mips.h"
33 
34 #define INTERRUPTS_MAX	64
35 
36 extern rt_uint32_t rt_interrupt_nest;
37 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
38 rt_uint32_t rt_thread_switch_interrupt_flag;
39 
40 static struct rt_irq_desc isr_table[INTERRUPTS_MAX];
41 
42 static void rt_hw_interrupt_handler(int vector, void *param)
43 {
44     rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
45 }
46 
47 void rt_hw_interrupt_init(void)
48 {
49     rt_int32_t idx;
50 
51 	clear_c0_status(0xff04); /* clear ERL */
52 	set_c0_status(0x0400);   /* set IP2 */
53 
54 
55     rt_memset(isr_table, 0x00, sizeof(isr_table));
56     for (idx = 0; idx < INTERRUPTS_MAX; idx ++)
57     {
58         isr_table[idx].handler = rt_hw_interrupt_handler;
59     }
60 
61     /* init interrupt nest, and context in thread sp */
62     rt_interrupt_nest               = 0;
63     rt_interrupt_from_thread        = 0;
64     rt_interrupt_to_thread          = 0;
65     rt_thread_switch_interrupt_flag = 0;
66 
67 	/* enable cpu interrupt mask */
68 	set_c0_status(IE_IRQ0 | IE_IRQ1);
69 }
70 
71 void rt_hw_interrupt_mask(int vector)
72 {
73     /* mask interrupt */
74     __intc_mask_irq(vector);
75 }
76 
77 void rt_hw_interrupt_umask(int vector)
78 {
79     __intc_unmask_irq(vector);
80 }
81 
82 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
83         void *param, const char *name)
84 {
85     rt_isr_handler_t old_handler = RT_NULL;
86 
87     if(vector < INTERRUPTS_MAX)
88     {
89         old_handler = isr_table[vector].handler;
90 
91 #ifdef RT_USING_INTERRUPT_INFO
92         rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
93 #endif /* RT_USING_INTERRUPT_INFO */
94         isr_table[vector].handler = handler;
95         isr_table[vector].param = param;
96     }
97 
98     return old_handler;
99 }
100 
101 rt_inline int fls(int x)
102 {
103     __asm__("clz %0, %1" : "=r" (x) : "r" (x));
104 
105     return 32 - x;
106 }
107 
108 void rt_interrupt_dispatch(void *ptreg)
109 {
110     void *param;
111     rt_isr_handler_t irq_func;
112 
113     int irq = 0, group;
114     rt_uint32_t intc_ipr0 = 0, intc_ipr1 = 0, vpu_pending = 0;
115 
116     rt_uint32_t c0_status, c0_cause;
117     rt_uint32_t pending_im;
118 
119     /* check os timer */
120     c0_status = read_c0_status();
121     c0_cause = read_c0_cause();
122 
123 	pending_im = (c0_cause & ST0_IM) & (c0_status & ST0_IM);
124 
125     if (pending_im & CAUSEF_IP3)
126     {
127 		extern void rt_hw_ost_handler(void);
128         rt_hw_ost_handler();
129         return;
130     }
131     if (pending_im & CAUSEF_IP2)
132     {
133         intc_ipr0 = REG_INTC_IPR(0);
134         intc_ipr1 = REG_INTC_IPR(1);
135 
136         if (intc_ipr0)
137         {
138             irq = fls(intc_ipr0) - 1;
139             intc_ipr0 &= ~(1<<irq);
140         }
141         else if(intc_ipr1)
142         {
143             irq = fls(intc_ipr1) - 1;
144             intc_ipr1 &= ~(1<<irq);
145             irq += 32;
146         }
147         else
148         {
149         	//VPU
150         }
151 
152         if (irq >= INTERRUPTS_MAX)
153             rt_kprintf("max interrupt, irq=%d\n", irq);
154 
155         /* do interrupt */
156         irq_func = isr_table[irq].handler;
157         param = isr_table[irq].param;
158         (*irq_func)(irq, param);
159 
160 #ifdef RT_USING_INTERRUPT_INFO
161         isr_table[irq].counter++;
162 #endif /* RT_USING_INTERRUPT_INFO */
163 
164         /* ack interrupt */
165         __intc_ack_irq(irq);
166     }
167 
168     if (pending_im & CAUSEF_IP0)
169         rt_kprintf("CAUSEF_IP0\n");
170     if (pending_im & CAUSEF_IP1)
171         rt_kprintf("CAUSEF_IP1\n");
172     if (pending_im & CAUSEF_IP4)
173         rt_kprintf("CAUSEF_IP4\n");
174     if (pending_im & CAUSEF_IP5)
175         rt_kprintf("CAUSEF_IP5\n");
176     if (pending_im & CAUSEF_IP6)
177         rt_kprintf("CAUSEF_IP6\n");
178     if (pending_im & CAUSEF_IP7)
179         rt_kprintf("CAUSEF_IP7\n");
180 }
181 
182 #ifdef RT_USING_INTERRUPT_INFO
183 #include <finsh.h>
184 int list_irqs(void)
185 {
186     int index;
187 
188     rt_kprintf("interrupt list:\n");
189     rt_kprintf("----------------\n");
190     rt_kprintf("name     counter\n");
191     for (index = 0; index < INTERRUPTS_MAX; index ++)
192     {
193         if (isr_table[index].handler != rt_hw_interrupt_handler)
194         {
195             rt_kprintf("%-*.*s %d\n", RT_NAME_MAX, RT_NAME_MAX, isr_table[index].name, isr_table[index].counter);
196         }
197     }
198 
199     return 0;
200 }
201 MSH_CMD_EXPORT(list_irqs, list interrupt counter);
202 #endif
203 
204 unsigned int spin_lock_irqsave(void)
205 {
206 	register unsigned int t;
207 	t = read_c0_status();
208 	write_c0_status((t & (~1)));
209 	return (t);
210 }
211 
212 void spin_unlock_irqrestore(unsigned int val)
213 {
214 	write_c0_status(val);
215 }
216