xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1b/interrupt.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * File      : interrupt.c
3*10465441SEvalZero  * This file is part of RT-Thread RTOS
4*10465441SEvalZero  * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
5*10465441SEvalZero  *
6*10465441SEvalZero  * The license and distribution terms for this file may be
7*10465441SEvalZero  * found in the file LICENSE in this distribution or at
8*10465441SEvalZero  * http://www.rt-thread.org/license/LICENSE
9*10465441SEvalZero  *
10*10465441SEvalZero  * Change Logs:
11*10465441SEvalZero  * Date           Author       Notes
12*10465441SEvalZero  * 2010-10-15     Bernard      first version
13*10465441SEvalZero  * 2010-10-15     lgnq         modified for LS1B
14*10465441SEvalZero  * 2013-03-29     aozima       Modify the interrupt interface implementations.
15*10465441SEvalZero  */
16*10465441SEvalZero 
17*10465441SEvalZero #include <rtthread.h>
18*10465441SEvalZero #include <rthw.h>
19*10465441SEvalZero #include "ls1b.h"
20*10465441SEvalZero 
21*10465441SEvalZero #define MAX_INTR 32
22*10465441SEvalZero 
23*10465441SEvalZero extern rt_uint32_t rt_interrupt_nest;
24*10465441SEvalZero rt_uint32_t rt_interrupt_from_thread;
25*10465441SEvalZero rt_uint32_t rt_interrupt_to_thread;
26*10465441SEvalZero rt_uint32_t rt_thread_switch_interrupt_flag;
27*10465441SEvalZero 
28*10465441SEvalZero static struct rt_irq_desc irq_handle_table[MAX_INTR];
29*10465441SEvalZero void rt_interrupt_dispatch(void *ptreg);
30*10465441SEvalZero void rt_hw_timer_handler();
31*10465441SEvalZero 
32*10465441SEvalZero static struct ls1b_intc_regs volatile *ls1b_hw0_icregs
33*10465441SEvalZero = (struct ls1b_intc_regs volatile *)(LS1B_INTREG_BASE);
34*10465441SEvalZero 
35*10465441SEvalZero /**
36*10465441SEvalZero  * @addtogroup Loongson LS1B
37*10465441SEvalZero  */
38*10465441SEvalZero 
39*10465441SEvalZero /*@{*/
40*10465441SEvalZero 
rt_hw_interrupt_handler(int vector,void * param)41*10465441SEvalZero static void rt_hw_interrupt_handler(int vector, void *param)
42*10465441SEvalZero {
43*10465441SEvalZero     rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
44*10465441SEvalZero }
45*10465441SEvalZero 
46*10465441SEvalZero /**
47*10465441SEvalZero  * This function will initialize hardware interrupt
48*10465441SEvalZero  */
rt_hw_interrupt_init(void)49*10465441SEvalZero void rt_hw_interrupt_init(void)
50*10465441SEvalZero {
51*10465441SEvalZero     rt_int32_t idx;
52*10465441SEvalZero 
53*10465441SEvalZero     /* pci active low */
54*10465441SEvalZero     ls1b_hw0_icregs->int_pol = -1;	   //must be done here 20110802 lgnq
55*10465441SEvalZero     /* make all interrupts level triggered */
56*10465441SEvalZero     (ls1b_hw0_icregs+0)->int_edge = 0x0000e000;
57*10465441SEvalZero     /* mask all interrupts */
58*10465441SEvalZero     (ls1b_hw0_icregs+0)->int_clr = 0xffffffff;
59*10465441SEvalZero 
60*10465441SEvalZero     rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table));
61*10465441SEvalZero     for (idx = 0; idx < MAX_INTR; idx ++)
62*10465441SEvalZero     {
63*10465441SEvalZero         irq_handle_table[idx].handler = rt_hw_interrupt_handler;
64*10465441SEvalZero     }
65*10465441SEvalZero 
66*10465441SEvalZero     /* init interrupt nest, and context in thread sp */
67*10465441SEvalZero     rt_interrupt_nest = 0;
68*10465441SEvalZero     rt_interrupt_from_thread = 0;
69*10465441SEvalZero     rt_interrupt_to_thread = 0;
70*10465441SEvalZero     rt_thread_switch_interrupt_flag = 0;
71*10465441SEvalZero }
72*10465441SEvalZero 
73*10465441SEvalZero /**
74*10465441SEvalZero  * This function will mask a interrupt.
75*10465441SEvalZero  * @param vector the interrupt number
76*10465441SEvalZero  */
rt_hw_interrupt_mask(int vector)77*10465441SEvalZero void rt_hw_interrupt_mask(int vector)
78*10465441SEvalZero {
79*10465441SEvalZero     /* mask interrupt */
80*10465441SEvalZero     (ls1b_hw0_icregs+(vector>>5))->int_en &= ~(1 << (vector&0x1f));
81*10465441SEvalZero }
82*10465441SEvalZero 
83*10465441SEvalZero /**
84*10465441SEvalZero  * This function will un-mask a interrupt.
85*10465441SEvalZero  * @param vector the interrupt number
86*10465441SEvalZero  */
rt_hw_interrupt_umask(int vector)87*10465441SEvalZero void rt_hw_interrupt_umask(int vector)
88*10465441SEvalZero {
89*10465441SEvalZero     (ls1b_hw0_icregs+(vector>>5))->int_en |= (1 << (vector&0x1f));
90*10465441SEvalZero }
91*10465441SEvalZero 
92*10465441SEvalZero /**
93*10465441SEvalZero  * This function will install a interrupt service routine to a interrupt.
94*10465441SEvalZero  * @param vector the interrupt number
95*10465441SEvalZero  * @param new_handler the interrupt service routine to be installed
96*10465441SEvalZero  * @param old_handler the old interrupt service routine
97*10465441SEvalZero  */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)98*10465441SEvalZero rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
99*10465441SEvalZero                                          void *param, const char *name)
100*10465441SEvalZero {
101*10465441SEvalZero     rt_isr_handler_t old_handler = RT_NULL;
102*10465441SEvalZero 
103*10465441SEvalZero     if (vector >= 0 && vector < MAX_INTR)
104*10465441SEvalZero     {
105*10465441SEvalZero         old_handler = irq_handle_table[vector].handler;
106*10465441SEvalZero 
107*10465441SEvalZero #ifdef RT_USING_INTERRUPT_INFO
108*10465441SEvalZero         rt_strncpy(irq_handle_table[vector].name, name, RT_NAME_MAX);
109*10465441SEvalZero #endif /* RT_USING_INTERRUPT_INFO */
110*10465441SEvalZero         irq_handle_table[vector].handler = handler;
111*10465441SEvalZero         irq_handle_table[vector].param = param;
112*10465441SEvalZero     }
113*10465441SEvalZero 
114*10465441SEvalZero     return old_handler;
115*10465441SEvalZero }
116*10465441SEvalZero 
rt_interrupt_dispatch(void * ptreg)117*10465441SEvalZero void rt_interrupt_dispatch(void *ptreg)
118*10465441SEvalZero {
119*10465441SEvalZero     int irq;
120*10465441SEvalZero     void *param;
121*10465441SEvalZero     rt_isr_handler_t irq_func;
122*10465441SEvalZero     static rt_uint32_t status = 0;
123*10465441SEvalZero     rt_uint32_t c0_status;
124*10465441SEvalZero     rt_uint32_t c0_cause;
125*10465441SEvalZero     volatile rt_uint32_t cause_im;
126*10465441SEvalZero     volatile rt_uint32_t status_im;
127*10465441SEvalZero     rt_uint32_t pending_im;
128*10465441SEvalZero 
129*10465441SEvalZero     /* check os timer */
130*10465441SEvalZero     c0_status = read_c0_status();
131*10465441SEvalZero     c0_cause = read_c0_cause();
132*10465441SEvalZero 
133*10465441SEvalZero     cause_im = c0_cause & ST0_IM;
134*10465441SEvalZero     status_im = c0_status & ST0_IM;
135*10465441SEvalZero     pending_im = cause_im & status_im;
136*10465441SEvalZero 
137*10465441SEvalZero     if (pending_im & CAUSEF_IP7)
138*10465441SEvalZero     {
139*10465441SEvalZero         rt_hw_timer_handler();
140*10465441SEvalZero     }
141*10465441SEvalZero 
142*10465441SEvalZero     if (pending_im & CAUSEF_IP2)
143*10465441SEvalZero     {
144*10465441SEvalZero         /* the hardware interrupt */
145*10465441SEvalZero         status = ls1b_hw0_icregs->int_isr;
146*10465441SEvalZero         if (!status)
147*10465441SEvalZero             return;
148*10465441SEvalZero 
149*10465441SEvalZero         for (irq = MAX_INTR; irq > 0; --irq)
150*10465441SEvalZero         {
151*10465441SEvalZero             if ((status & (1 << irq)))
152*10465441SEvalZero             {
153*10465441SEvalZero                 status &= ~(1 << irq);
154*10465441SEvalZero 
155*10465441SEvalZero                 irq_func = irq_handle_table[irq].handler;
156*10465441SEvalZero                 param = irq_handle_table[irq].param;
157*10465441SEvalZero 
158*10465441SEvalZero                 /* do interrupt */
159*10465441SEvalZero                 irq_func(irq, param);
160*10465441SEvalZero 
161*10465441SEvalZero #ifdef RT_USING_INTERRUPT_INFO
162*10465441SEvalZero                 irq_handle_table[irq].counter++;
163*10465441SEvalZero #endif /* RT_USING_INTERRUPT_INFO */
164*10465441SEvalZero 
165*10465441SEvalZero                 /* ack interrupt */
166*10465441SEvalZero                 ls1b_hw0_icregs->int_clr |= (1 << irq);
167*10465441SEvalZero             }
168*10465441SEvalZero         }
169*10465441SEvalZero     }
170*10465441SEvalZero     else if (pending_im & CAUSEF_IP3)
171*10465441SEvalZero     {
172*10465441SEvalZero         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
173*10465441SEvalZero     }
174*10465441SEvalZero     else if (pending_im & CAUSEF_IP4)
175*10465441SEvalZero     {
176*10465441SEvalZero         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
177*10465441SEvalZero     }
178*10465441SEvalZero     else if (pending_im & CAUSEF_IP5)
179*10465441SEvalZero     {
180*10465441SEvalZero         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
181*10465441SEvalZero     }
182*10465441SEvalZero     else if (pending_im & CAUSEF_IP6)
183*10465441SEvalZero     {
184*10465441SEvalZero         rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__);
185*10465441SEvalZero     }
186*10465441SEvalZero }
187*10465441SEvalZero 
188*10465441SEvalZero /*@}*/
189