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