1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2013-07-06 Bernard first version 9 * 2014-04-03 Grissiom port to VMM 10 */ 11 12 #include <rthw.h> 13 #include <rtthread.h> 14 #include "realview.h" 15 #include "gic.h" 16 17 #ifdef RT_USING_VMM 18 #include <vmm.h> 19 #endif 20 21 #define MAX_HANDLERS NR_IRQS_PBA8 22 23 extern volatile rt_uint8_t rt_interrupt_nest; 24 25 /* exception and interrupt handler table */ 26 struct rt_irq_desc isr_table[MAX_HANDLERS]; 27 28 /* Those varibles will be accessed in ISR, so we need to share them. */ 29 rt_uint32_t rt_interrupt_from_thread SECTION(".bss.share.int"); 30 rt_uint32_t rt_interrupt_to_thread SECTION(".bss.share.int"); 31 rt_uint32_t rt_thread_switch_interrupt_flag SECTION(".bss.share.int"); 32 33 const unsigned int VECTOR_BASE = 0x00; 34 extern void rt_cpu_vector_set_base(unsigned int addr); 35 extern int system_vectors; 36 37 static void rt_hw_vector_init(void) 38 { 39 #ifndef RT_USING_VMM 40 unsigned int *dest = (unsigned int *)VECTOR_BASE; 41 unsigned int *src = (unsigned int *)&system_vectors; 42 43 rt_memcpy(dest, src, 16 * 4); 44 rt_cpu_vector_set_base(VECTOR_BASE); 45 #endif 46 } 47 48 /** 49 * This function will initialize hardware interrupt 50 */ 51 void rt_hw_interrupt_init(void) 52 { 53 rt_uint32_t gic_cpu_base; 54 rt_uint32_t gic_dist_base; 55 56 /* initialize vector table */ 57 rt_hw_vector_init(); 58 59 /* initialize exceptions table */ 60 rt_memset(isr_table, 0x00, sizeof(isr_table)); 61 62 /* initialize ARM GIC */ 63 #ifdef RT_USING_VMM 64 gic_dist_base = vmm_find_iomap("GIC_DIST"); 65 gic_cpu_base = vmm_find_iomap("GIC_CPU"); 66 #else 67 gic_dist_base = REALVIEW_GIC_DIST_BASE; 68 gic_cpu_base = REALVIEW_GIC_CPU_BASE; 69 #endif 70 arm_gic_dist_init(0, gic_dist_base, 0); 71 arm_gic_cpu_init(0, gic_cpu_base); 72 /*arm_gic_dump_type(0);*/ 73 74 /* init interrupt nest, and context in thread sp */ 75 rt_interrupt_nest = 0; 76 rt_interrupt_from_thread = 0; 77 rt_interrupt_to_thread = 0; 78 rt_thread_switch_interrupt_flag = 0; 79 } 80 81 /** 82 * This function will mask a interrupt. 83 * @param vector the interrupt number 84 */ 85 void rt_hw_interrupt_mask(int vector) 86 { 87 arm_gic_mask(0, vector); 88 } 89 90 /** 91 * This function will un-mask a interrupt. 92 * @param vector the interrupt number 93 */ 94 void rt_hw_interrupt_umask(int vector) 95 { 96 arm_gic_umask(0, vector); 97 } 98 99 /** 100 * This function will install a interrupt service routine to a interrupt. 101 * @param vector the interrupt number 102 * @param new_handler the interrupt service routine to be installed 103 * @param old_handler the old interrupt service routine 104 */ 105 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, 106 void *param, const char *name) 107 { 108 rt_isr_handler_t old_handler = RT_NULL; 109 110 if (vector < MAX_HANDLERS) 111 { 112 old_handler = isr_table[vector].handler; 113 114 if (handler != RT_NULL) 115 { 116 #ifdef RT_USING_INTERRUPT_INFO 117 rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); 118 #endif /* RT_USING_INTERRUPT_INFO */ 119 isr_table[vector].handler = handler; 120 isr_table[vector].param = param; 121 } 122 } 123 124 return old_handler; 125 } 126 127 /** 128 * Trigger a software IRQ 129 * 130 * Since we are running in single core, the target CPU are always CPU0. 131 */ 132 void rt_hw_interrupt_trigger(int vector) 133 { 134 arm_gic_trigger(0, 1, vector); 135 } 136 137 void rt_hw_interrupt_clear(int vector) 138 { 139 arm_gic_clear_sgi(0, 1, vector); 140 } 141