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