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