xref: /nrf52832-nimble/rt-thread/libcpu/mips/loongson_1c/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  * 2015-07-06     chinesebear modified for loongson 1c
16*10465441SEvalZero  */
17*10465441SEvalZero 
18*10465441SEvalZero #include <rtthread.h>
19*10465441SEvalZero #include <rthw.h>
20*10465441SEvalZero #include "ls1c.h"
21*10465441SEvalZero #include "ls1c_public.h"
22*10465441SEvalZero 
23*10465441SEvalZero 
24*10465441SEvalZero #define MAX_INTR            (LS1C_NR_IRQS)
25*10465441SEvalZero 
26*10465441SEvalZero extern rt_uint32_t rt_interrupt_nest;
27*10465441SEvalZero rt_uint32_t rt_interrupt_from_thread;
28*10465441SEvalZero rt_uint32_t rt_interrupt_to_thread;
29*10465441SEvalZero rt_uint32_t rt_thread_switch_interrupt_flag;
30*10465441SEvalZero 
31*10465441SEvalZero static struct rt_irq_desc irq_handle_table[MAX_INTR];
32*10465441SEvalZero void rt_interrupt_dispatch(void *ptreg);
33*10465441SEvalZero void rt_hw_timer_handler();
34*10465441SEvalZero 
35*10465441SEvalZero static struct ls1c_intc_regs volatile *ls1c_hw0_icregs
36*10465441SEvalZero = (struct ls1c_intc_regs volatile *)(LS1C_INTREG_BASE);
37*10465441SEvalZero 
38*10465441SEvalZero /**
39*10465441SEvalZero  * @addtogroup Loongson LS1B
40*10465441SEvalZero  */
41*10465441SEvalZero 
42*10465441SEvalZero /*@{*/
43*10465441SEvalZero 
rt_hw_interrupt_handler(int vector,void * param)44*10465441SEvalZero static void rt_hw_interrupt_handler(int vector, void *param)
45*10465441SEvalZero {
46*10465441SEvalZero     rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
47*10465441SEvalZero }
48*10465441SEvalZero 
49*10465441SEvalZero /**
50*10465441SEvalZero  * This function will initialize hardware interrupt
51*10465441SEvalZero  */
rt_hw_interrupt_init(void)52*10465441SEvalZero void rt_hw_interrupt_init(void)
53*10465441SEvalZero {
54*10465441SEvalZero     rt_int32_t idx;
55*10465441SEvalZero     rt_int32_t i;
56*10465441SEvalZero     rt_uint32_t c0_status = 0;
57*10465441SEvalZero 
58*10465441SEvalZero     // ����Э������0��״̬�Ĵ���SR��IM7-2�������ж�
59*10465441SEvalZero     c0_status = read_c0_status();
60*10465441SEvalZero     c0_status |= 0xFC00;
61*10465441SEvalZero     write_c0_status(c0_status);
62*10465441SEvalZero 
63*10465441SEvalZero     // ��о1c���жϷ�Ϊ����
64*10465441SEvalZero     for (i=0; i<5; i++)
65*10465441SEvalZero     {
66*10465441SEvalZero         /* disable */
67*10465441SEvalZero         (ls1c_hw0_icregs+i)->int_en = 0x0;
68*10465441SEvalZero         /* pci active low */
69*10465441SEvalZero         (ls1c_hw0_icregs+i)->int_pol = -1;	   //must be done here 20110802 lgnq
70*10465441SEvalZero         /* make all interrupts level triggered */
71*10465441SEvalZero         (ls1c_hw0_icregs+i)->int_edge = 0x00000000;
72*10465441SEvalZero         /* mask all interrupts */
73*10465441SEvalZero         (ls1c_hw0_icregs+i)->int_clr = 0xffffffff;
74*10465441SEvalZero     }
75*10465441SEvalZero 
76*10465441SEvalZero     rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table));
77*10465441SEvalZero     for (idx = 0; idx < MAX_INTR; idx ++)
78*10465441SEvalZero     {
79*10465441SEvalZero         irq_handle_table[idx].handler = rt_hw_interrupt_handler;
80*10465441SEvalZero     }
81*10465441SEvalZero 
82*10465441SEvalZero     /* init interrupt nest, and context in thread sp */
83*10465441SEvalZero     rt_interrupt_nest = 0;
84*10465441SEvalZero     rt_interrupt_from_thread = 0;
85*10465441SEvalZero     rt_interrupt_to_thread = 0;
86*10465441SEvalZero     rt_thread_switch_interrupt_flag = 0;
87*10465441SEvalZero }
88*10465441SEvalZero 
89*10465441SEvalZero /**
90*10465441SEvalZero  * This function will mask a interrupt.
91*10465441SEvalZero  * @param vector the interrupt number
92*10465441SEvalZero  */
rt_hw_interrupt_mask(int vector)93*10465441SEvalZero void rt_hw_interrupt_mask(int vector)
94*10465441SEvalZero {
95*10465441SEvalZero     /* mask interrupt */
96*10465441SEvalZero     (ls1c_hw0_icregs+(vector>>5))->int_en &= ~(1 << (vector&0x1f));
97*10465441SEvalZero }
98*10465441SEvalZero 
99*10465441SEvalZero /**
100*10465441SEvalZero  * This function will un-mask a interrupt.
101*10465441SEvalZero  * @param vector the interrupt number
102*10465441SEvalZero  */
rt_hw_interrupt_umask(int vector)103*10465441SEvalZero void rt_hw_interrupt_umask(int vector)
104*10465441SEvalZero {
105*10465441SEvalZero     (ls1c_hw0_icregs+(vector>>5))->int_en |= (1 << (vector&0x1f));
106*10465441SEvalZero }
107*10465441SEvalZero 
108*10465441SEvalZero /**
109*10465441SEvalZero  * This function will install a interrupt service routine to a interrupt.
110*10465441SEvalZero  * @param vector the interrupt number
111*10465441SEvalZero  * @param new_handler the interrupt service routine to be installed
112*10465441SEvalZero  * @param old_handler the old interrupt service routine
113*10465441SEvalZero  */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)114*10465441SEvalZero rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
115*10465441SEvalZero                                          void *param, const char *name)
116*10465441SEvalZero {
117*10465441SEvalZero     rt_isr_handler_t old_handler = RT_NULL;
118*10465441SEvalZero 
119*10465441SEvalZero     if (vector >= 0 && vector < MAX_INTR)
120*10465441SEvalZero     {
121*10465441SEvalZero         old_handler = irq_handle_table[vector].handler;
122*10465441SEvalZero 
123*10465441SEvalZero #ifdef RT_USING_INTERRUPT_INFO
124*10465441SEvalZero         rt_strncpy(irq_handle_table[vector].name, name, RT_NAME_MAX);
125*10465441SEvalZero #endif /* RT_USING_INTERRUPT_INFO */
126*10465441SEvalZero         irq_handle_table[vector].handler = handler;
127*10465441SEvalZero         irq_handle_table[vector].param = param;
128*10465441SEvalZero     }
129*10465441SEvalZero 
130*10465441SEvalZero     return old_handler;
131*10465441SEvalZero }
132*10465441SEvalZero 
133*10465441SEvalZero 
134*10465441SEvalZero /**
135*10465441SEvalZero  * ִ���жϴ�����
136*10465441SEvalZero  * @IRQn �жϺ�
137*10465441SEvalZero  */
ls1c_do_IRQ(int IRQn)138*10465441SEvalZero void ls1c_do_IRQ(int IRQn)
139*10465441SEvalZero {
140*10465441SEvalZero     rt_isr_handler_t irq_func;
141*10465441SEvalZero     void *param;
142*10465441SEvalZero 
143*10465441SEvalZero     // �ҵ��жϴ�����
144*10465441SEvalZero     irq_func = irq_handle_table[IRQn].handler;
145*10465441SEvalZero     param    = irq_handle_table[IRQn].param;
146*10465441SEvalZero 
147*10465441SEvalZero     // ִ���жϴ�����
148*10465441SEvalZero     irq_func(IRQn, param);
149*10465441SEvalZero 
150*10465441SEvalZero #ifdef RT_USING_INTERRUPT_INFO
151*10465441SEvalZero     irq_handle_table[IRQn].counter++;
152*10465441SEvalZero #endif
153*10465441SEvalZero 
154*10465441SEvalZero     return ;
155*10465441SEvalZero }
156*10465441SEvalZero 
157*10465441SEvalZero 
ls1c_irq_dispatch(int n)158*10465441SEvalZero void ls1c_irq_dispatch(int n)
159*10465441SEvalZero {
160*10465441SEvalZero     rt_uint32_t intstatus, irq;
161*10465441SEvalZero 
162*10465441SEvalZero     /* Receive interrupt signal, compute the irq */
163*10465441SEvalZero     intstatus = (ls1c_hw0_icregs+n)->int_isr & (ls1c_hw0_icregs+n)->int_en;
164*10465441SEvalZero     if (0 == intstatus)
165*10465441SEvalZero         return ;
166*10465441SEvalZero 
167*10465441SEvalZero     // ִ���жϴ�����
168*10465441SEvalZero     irq = ls1c_ffs(intstatus) - 1;
169*10465441SEvalZero     ls1c_do_IRQ((n<<5) + irq);
170*10465441SEvalZero 
171*10465441SEvalZero     /* ack interrupt */
172*10465441SEvalZero     (ls1c_hw0_icregs+n)->int_clr |= (1 << irq);
173*10465441SEvalZero 
174*10465441SEvalZero     return ;
175*10465441SEvalZero }
176*10465441SEvalZero 
177*10465441SEvalZero 
rt_interrupt_dispatch(void * ptreg)178*10465441SEvalZero void rt_interrupt_dispatch(void *ptreg)
179*10465441SEvalZero {
180*10465441SEvalZero     int irq;
181*10465441SEvalZero     void *param;
182*10465441SEvalZero     rt_isr_handler_t irq_func;
183*10465441SEvalZero     static rt_uint32_t status = 0;
184*10465441SEvalZero     rt_uint32_t c0_status;
185*10465441SEvalZero     rt_uint32_t c0_cause;
186*10465441SEvalZero     volatile rt_uint32_t cause_im;
187*10465441SEvalZero     volatile rt_uint32_t status_im;
188*10465441SEvalZero     rt_uint32_t pending_im;
189*10465441SEvalZero 
190*10465441SEvalZero     /* check os timer */
191*10465441SEvalZero     c0_status = read_c0_status();
192*10465441SEvalZero     c0_cause = read_c0_cause();
193*10465441SEvalZero 
194*10465441SEvalZero     cause_im = c0_cause & ST0_IM;
195*10465441SEvalZero     status_im = c0_status & ST0_IM;
196*10465441SEvalZero     pending_im = cause_im & status_im;
197*10465441SEvalZero 
198*10465441SEvalZero     if (pending_im & CAUSEF_IP7)
199*10465441SEvalZero     {
200*10465441SEvalZero         rt_hw_timer_handler();
201*10465441SEvalZero     }
202*10465441SEvalZero     else if (pending_im & CAUSEF_IP2)
203*10465441SEvalZero     {
204*10465441SEvalZero         ls1c_irq_dispatch(0);
205*10465441SEvalZero     }
206*10465441SEvalZero     else if (pending_im & CAUSEF_IP3)
207*10465441SEvalZero     {
208*10465441SEvalZero         ls1c_irq_dispatch(1);
209*10465441SEvalZero     }
210*10465441SEvalZero     else if (pending_im & CAUSEF_IP4)
211*10465441SEvalZero     {
212*10465441SEvalZero         ls1c_irq_dispatch(2);
213*10465441SEvalZero     }
214*10465441SEvalZero     else if (pending_im & CAUSEF_IP5)
215*10465441SEvalZero     {
216*10465441SEvalZero         ls1c_irq_dispatch(3);
217*10465441SEvalZero     }
218*10465441SEvalZero     else if (pending_im & CAUSEF_IP6)
219*10465441SEvalZero     {
220*10465441SEvalZero         ls1c_irq_dispatch(4);
221*10465441SEvalZero     }
222*10465441SEvalZero }
223*10465441SEvalZero 
224*10465441SEvalZero /*@}*/
225*10465441SEvalZero 
226*10465441SEvalZero 
227