1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2013-7-14      Peng Fan     sep6200 implementation
9  */
10 
11 #include <rtthread.h>
12 #include <rthw.h>
13 #include <sep6200.h>
14 
15 #define MAX_HANDLERS    64
16 
17 
18 #define SEP6200_IRQ_TYPE 0
19 #define SEP6200_FIQ_TYPE 1
20 
21 #define int_enable_all()                      \
22     do {                              \
23         *(volatile unsigned long*)SEP6200_VIC_INT_EN_L = ~0x0;\
24         *(volatile unsigned long*)SEP6200_VIC_INT_EN_H = ~0x0;\
25     }while(0)
26 #define int_disable_all()                    \
27     do {                             \
28         *(volatile unsigned long*)SEP6200_VIC_INT_EN_L = 0x0;\
29         *(volatile unsigned long*)SEP6200_VIC_INT_EN_H = 0x0;\
30     }while(0)
31 #define mask_all_int(int_type)                   \
32     do {                             \
33         if (int_type == SEP6200_IRQ_TYPE){       \
34         *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = 0x1;\
35         } else if (int_type == SEP6200_FIQ_TYPE) {\
36         *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = 0x2;\
37         }\
38     }while(0)
39 #define unmask_all_int(int_type)\
40     do {                             \
41         if (int_type == SEP6200_IRQ_TYPE){       \
42         *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = ~0x1;\
43         } else if (int_type == SEP6200_FIQ_TYPE) {\
44         *(volatile unsigned long*)SEP6200_VIC_INT_MSK_ALL = ~0x2;\
45         }\
46     }while(0)
47 
48 #define SEP6200_INT_SET(intnum)                                     \
49 do{                                                                 \
50     if(intnum < 32)                                                 \
51         *(volatile unsigned long*)SEP6200_VIC_SFT_INT_L |= (1 << intnum); \
52     else                                                            \
53         *(volatile unsigned long*)SEP6200_VIC_SFT_INT_H |= (1 << (intnum - 32));  \
54 }while(0)
55 
56 #define SEP6200_INT_CLR(intnum)   \
57 do{                               \
58     if(intnum < 32)               \
59         *(volatile unsigned long*)SEP6200_VIC_SFT_INT_L &= ~(1 << intnum);\
60     else                          \
61         *(volatile unsigned long*)SEP6200_VIC_SFT_INT_H &= ~(1 << (intnum - 32)); \
62 }while(0)
63 
64 #define SEP6200_INT_ENABLE(intnum)\
65 do{                               \
66     if(intnum < 32)               \
67         *(volatile unsigned long*)SEP6200_VIC_INT_EN_L |= (1 << intnum);  \
68     else                          \
69         *(volatile unsigned long*)SEP6200_VIC_INT_EN_H |= (1 << (intnum - 32));   \
70 }while(0)
71 
72 #define SEP6200_INT_DISABLE(intnum)                                 \
73 do{                                                                 \
74     if(intnum < 32)                                                 \
75         *(volatile unsigned long*)SEP6200_VIC_INT_EN_L &= ~(1 << intnum); \
76     else                                                            \
77         *(volatile unsigned long*)SEP6200_VIC_INT_EN_H &= ~(1 << (intnum - 32));  \
78 }while(0)
79 
80 
81 extern rt_atomic_t rt_interrupt_nest;
82 /* exception and interrupt handler table */
83 struct rt_irq_desc isr_table[MAX_HANDLERS];
84 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
85 rt_uint32_t rt_thread_switch_interrupt_flag;
86 
87 
88 /* --------------------------------------------------------------------
89  *  Interrupt initialization
90  * -------------------------------------------------------------------- */
91 
92 /**
93  * @addtogroup sep6200
94  */
95 /*@{*/
96 
97 void rt_hw_interrupt_mask(int irq);
98 void rt_hw_interrupt_umask(int irq);
99 
sep6200_irq_enable(rt_uint32_t irq)100 rt_inline void sep6200_irq_enable(rt_uint32_t irq)
101 {
102     SEP6200_INT_ENABLE(irq);
103 }
104 
sep6200_irq_disable(rt_uint32_t irq)105 rt_inline void sep6200_irq_disable(rt_uint32_t irq)
106 {
107     SEP6200_INT_DISABLE(irq);
108 }
109 
sep6200_irq_unmask(rt_uint32_t irq)110 rt_inline void sep6200_irq_unmask(rt_uint32_t irq)
111 {
112     SEP6200_INT_ENABLE(irq);
113 }
114 
sep6200_irq_mask(rt_uint32_t irq)115 rt_inline void sep6200_irq_mask(rt_uint32_t irq)
116 {
117     SEP6200_INT_DISABLE(irq);
118 }
rt_hw_interrupt_handle(rt_uint32_t vector)119 rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector)
120 {
121     rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
122     return RT_NULL;
123 }
124 
125 /**
126  * This function will initialize hardware interrupt
127  */
rt_hw_interrupt_init(void)128 void rt_hw_interrupt_init(void)
129 {
130     rt_int32_t i;
131     register rt_uint32_t idx;
132 
133 
134     /* init exceptions table */
135     for(idx=0; idx < MAX_HANDLERS; idx++)
136     {
137         isr_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
138     }
139     int_disable_all();
140     mask_all_int(SEP6200_FIQ_TYPE);
141 
142     //int_enable_all();
143     unmask_all_int(SEP6200_IRQ_TYPE);
144 
145     /* init interrupt nest, and context in thread sp */
146     rt_interrupt_nest = 0;
147     rt_interrupt_from_thread = 0;
148     rt_interrupt_to_thread = 0;
149     rt_thread_switch_interrupt_flag = 0;
150 }
151 
152 
153 
154 /**
155  * This function will mask a interrupt.
156  * @param vector the interrupt number
157  */
rt_hw_interrupt_mask(int irq)158 void rt_hw_interrupt_mask(int irq)
159 {
160     if (irq >= MAX_HANDLERS) {
161         rt_kprintf("Wrong irq num to mask\n");
162     } else {
163         sep6200_irq_mask(irq);
164     }
165 
166 }
167 
168 /**
169  * This function will un-mask a interrupt.
170  * @param vector the interrupt number
171  */
rt_hw_interrupt_umask(int irq)172 void rt_hw_interrupt_umask(int irq)
173 {
174     if (irq >= MAX_HANDLERS) {
175         rt_kprintf("Wrong irq num to unmask\n");
176     } else {
177         sep6200_irq_unmask(irq);
178     }
179 }
180 
181 /**
182  * This function will install a interrupt service routine to a interrupt.
183  * @param vector the interrupt number
184  * @param new_handler the interrupt service routine to be installed
185  * @param old_handler the old interrupt service routine
186  */
rt_hw_interrupt_install(int vector,rt_isr_handler_t handler,void * param,const char * name)187 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
188                                         void *param, const char *name)
189 {
190     rt_isr_handler_t old_handler = RT_NULL;
191 
192     if(vector < MAX_HANDLERS)
193     {
194         old_handler = isr_table[vector].handler;
195 
196         if (handler != RT_NULL)
197         {
198 #ifdef RT_USING_INTERRUPT_INFO
199             rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
200 #endif /* RT_USING_INTERRUPT_INFO */
201             isr_table[vector].handler = handler;
202             isr_table[vector].param = param;
203         }
204     }
205 
206     return old_handler;
207 }
208 
209 /*@}*/
210