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