1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <common/bk_include.h>
16 #include <common/bk_compiler.h>
17 #include <os/mem.h>
18 #include "bk_arm_arch.h"
19 #include "arch_interrupt.h"
20 #include "icu_driver.h"
21 #include "interrupt_base.h"
22 #include "interrupt.h"
23 #include "arch_interrupt.h"
24 #include <driver/int_types.h>
25 #include <driver/int.h>
26 #include <common/bk_assert.h>
27
28 #define ICU_RETURN_ON_INVALID_DEVS(dev) do {\
29 if ((dev) >= INT_SRC_NONE) {\
30 return BK_ERR_INT_DEVICE_NONE;\
31 }\
32 } while(0)
33
34 const icu_int_map_t icu_int_map_table[] = ICU_DEV_MAP;
35
36 #if CONFIG_ARCH_RISCV
bk_int_isr_register(icu_int_src_t src,int_group_isr_t isr_callback,void * arg)37 bk_err_t bk_int_isr_register(icu_int_src_t src, int_group_isr_t isr_callback, void*arg)
38 {
39 ICU_RETURN_ON_INVALID_DEVS(src);
40
41 // icu_int_map_t icu_int_map_table[] = ICU_DEV_MAP;
42 const icu_int_map_t *icu_int_map = &icu_int_map_table[src];
43
44 uint8_t int_num = icu_int_map->int_bit;
45
46 arch_interrupt_unregister_int(int_num);
47 arch_interrupt_register_int(int_num,isr_callback);
48
49 return 0;
50 }
interrupt_init(void)51 void interrupt_init(void)
52 {
53 soc_isr_init();
54 }
55
interrupt_deinit(void)56 void interrupt_deinit(void)
57 {
58 soc_isr_deinit();
59 }
60
bk_int_set_priority(icu_int_src_t int_src,uint32_t int_priority)61 bk_err_t bk_int_set_priority(icu_int_src_t int_src, uint32_t int_priority)
62 {
63 const icu_int_map_t *icu_int_map = &icu_int_map_table[int_src];
64 uint8_t int_num = icu_int_map->int_bit;
65
66 arch_interrupt_set_priority(int_num, int_priority);
67
68 return BK_OK;
69 }
70
bk_int_isr_unregister(icu_int_src_t src)71 bk_err_t bk_int_isr_unregister(icu_int_src_t src)
72 {
73 ICU_RETURN_ON_INVALID_DEVS(src);
74
75 const icu_int_map_t *icu_int_map = &icu_int_map_table[src];
76
77 uint8_t int_num = icu_int_map->int_bit;
78
79 arch_interrupt_unregister_int(int_num);
80
81 return BK_OK;
82 }
83 #else
84
85 static uint32_t s_isr_mask[MAX_INT_GROUP_NUM] = {0};
86 static isr_list_t s_int_lists[MAX_INT_GROUP_NUM];
87 static int_mac_ps_callback_t s_int_mac_ps_callback = NULL;
88
89 #if CONFIG_INT_STATIS
90 int_statis_t g_int_statis_num = {0};
91 #endif
92
int_isr_del(icu_int_src_t src)93 static isr_t* int_isr_del(icu_int_src_t src)
94 {
95
96 LIST_HEADER_T *pos, *next;
97
98 isr_t *cur_ptr;
99 isr_list_t *int_list;
100
101 // icu_int_map_t icu_int_map_table[] = ICU_DEV_MAP;
102 if (src >= ARRAY_SIZE(icu_int_map_table)) {
103 ICU_LOGW("int_isr_del, int_src(%d) is out of icu_int_map_table range\r\n", src);
104 return NULL;
105 }
106 const icu_int_map_t *icu_int_map = &icu_int_map_table[src];
107
108 uint32_t int_num = icu_int_map->int_bit;
109 uint32_t group_id = icu_int_map->group;
110
111 int_list = &s_int_lists[group_id];
112
113 ICU_LOGD("delete:src: %d pri=tem_ptr->pri, int_num = %d\r\n", src, int_num);
114 GLOBAL_INT_DECLARATION();
115
116 GLOBAL_INT_DISABLE();
117 if (list_empty(&int_list->isr)) {
118 GLOBAL_INT_RESTORE();
119 return NULL;
120 }
121
122 list_for_each_safe(pos, next, &int_list->isr) {
123 cur_ptr = list_entry(pos, isr_t, list);
124
125 if (int_num == cur_ptr->int_num) {
126 ICU_LOGD("delete:src: %d pri=tem_ptr->pri, int_num = %d\r\n", src, int_num);
127 list_del(&cur_ptr->list);
128 GLOBAL_INT_RESTORE();
129 return cur_ptr;
130 }
131 }
132
133 GLOBAL_INT_RESTORE();
134
135 return NULL;
136 }
137
bk_int_isr_unregister(icu_int_src_t src)138 bk_err_t bk_int_isr_unregister(icu_int_src_t src)
139 {
140 ICU_RETURN_ON_INVALID_DEVS(src);
141 isr_t *cur_isr = int_isr_del(src);
142 if (cur_isr) {
143 os_free(cur_isr);
144 cur_isr = NULL;
145 }
146 return BK_OK;
147 }
148
int_isr_add(isr_t * new_isr,int group_id)149 bk_err_t int_isr_add(isr_t *new_isr, int group_id)
150 {
151 LIST_HEADER_T *pos, *next;
152 isr_t *cur_ptr;
153 isr_list_t *int_list;
154
155 int_list = &s_int_lists[group_id];
156
157 GLOBAL_INT_DECLARATION();
158 GLOBAL_INT_DISABLE();
159 if (list_empty(&int_list->isr)) {
160 list_add_head(&new_isr->list, &int_list->isr);
161 goto int_isr_add_exit;
162 }
163
164 /* Insert the ISR to the function list, this list is sorted by priority number */
165 list_for_each_safe(pos, next, &int_list->isr) {
166 cur_ptr = list_entry(pos, isr_t, list);
167
168 ICU_LOGD("cur isr: num = %d, pri=%d\n", cur_ptr->int_num, cur_ptr->pri);
169 if (new_isr->pri <= cur_ptr->pri) {
170 /* add entry at the head of the queue */
171 ICU_LOGD("add new isr: num = %d, pri=%d\n", new_isr->int_num, new_isr->pri);
172 list_add_tail(&new_isr->list, &cur_ptr->list);
173 goto int_isr_add_exit;
174 }
175 }
176
177 list_add_tail(&new_isr->list, &int_list->isr);
178 ICU_LOGD("add new isr: num = %d, pri=%d\n", new_isr->int_num, new_isr->pri);
179
180 int_isr_add_exit:
181 s_isr_mask[group_id] |= BIT(new_isr->int_num);
182 GLOBAL_INT_RESTORE();
183
184 return BK_OK;
185 }
186
bk_int_isr_register(icu_int_src_t src,int_group_isr_t isr,void * arg)187 bk_err_t bk_int_isr_register(icu_int_src_t src, int_group_isr_t isr, void*arg)
188 {
189 ICU_RETURN_ON_INVALID_DEVS(src);
190
191 bk_int_isr_unregister(src);
192
193 // icu_int_map_t icu_int_map_table[] = ICU_DEV_MAP;
194 if (src >= ARRAY_SIZE(icu_int_map_table)) {
195 ICU_LOGW("int_isr_register, int_src(%d) is out of icu_int_map_table range\r\n", src);
196 return BK_ERR_NOT_FOUND;
197 }
198 const icu_int_map_t *icu_int_map = &icu_int_map_table[src];
199
200 uint8_t int_num = icu_int_map->int_bit;
201 uint8_t int_pri = icu_int_map->int_prio;
202 uint8_t group_id = icu_int_map->group;
203 isr_t *new_isr;
204
205 ICU_LOGD("register isr: src=%d, num=%d, pri=%d, group=%d\r\n", src, int_num, int_pri, group_id );
206 new_isr = (isr_t*)os_malloc(sizeof(isr_t));
207 if(!new_isr) {
208 ICU_LOGE("cur_ptr malloc error\r\n");
209 return BK_ERR_NO_MEM;
210 }
211
212 new_isr->isr_func = isr;
213 new_isr->int_num = int_num;
214 new_isr->pri = int_pri;
215
216 return int_isr_add(new_isr, group_id);
217 }
218
bk_int_register_mac_ps_callback(int_mac_ps_callback_t mac_ps_cb)219 bk_err_t bk_int_register_mac_ps_callback(int_mac_ps_callback_t mac_ps_cb)
220 {
221 s_int_mac_ps_callback = mac_ps_cb;
222 return BK_OK;
223 }
224
group_isr(uint32_t group_id,uint32_t int_status)225 void group_isr(uint32_t group_id, uint32_t int_status)
226 {
227 uint32_t int_num;
228 isr_t *cur_ptr;
229 uint32_t status;
230 LIST_HEADER_T *next;
231 LIST_HEADER_T *pos;
232
233 status = int_status & s_isr_mask[group_id];
234 // ICU_LOGD("group_isr:%x:%x\r\n", int_status, status);
235
236 if (s_int_mac_ps_callback) {
237 s_int_mac_ps_callback(status);
238 }
239
240 list_for_each_safe(pos, next, &s_int_lists[group_id].isr) {
241 cur_ptr= list_entry(pos, isr_t, list);
242 int_num = cur_ptr->int_num;
243
244 if ((BIT(int_num) & status)) {
245 cur_ptr->isr_func();
246 status &= ~(BIT(int_num));
247 #if CONFIG_INT_STATIS
248 if(group_id == 1)
249 g_int_statis_num.fiq_int_statis[int_num-FIQ_START_COUNT_BIT] ++;
250 else
251 g_int_statis_num.irq_int_statis[int_num] ++;
252 #endif
253 }
254
255 if (0 == status)
256 return;
257 }
258 }
259
interrupt_init(void)260 void interrupt_init(void)
261 {
262 for(int i =0; i< MAX_INT_GROUP_NUM; i++) {
263 INIT_LIST_HEAD(&s_int_lists[i].isr);
264 }
265
266 soc_isr_init();
267 }
268
interrupt_deinit(void)269 void interrupt_deinit(void)
270 {
271 soc_isr_deinit();
272 }
273
bk_int_set_priority(icu_int_src_t int_src,uint32_t int_priority)274 bk_err_t bk_int_set_priority(icu_int_src_t int_src, uint32_t int_priority)
275 {
276 ICU_RETURN_ON_INVALID_DEVS(int_src);
277
278 isr_t* update_isr = int_isr_del(int_src);
279
280 if (!update_isr) {
281 return BK_ERR_INT_NOT_EXIST;
282 }
283
284 // icu_int_map_t icu_int_map_table[] = ICU_DEV_MAP;
285 const icu_int_map_t *icu_int_map = &icu_int_map_table[int_src];
286 uint8_t group_id = icu_int_map->group;
287
288 ICU_LOGI("set int prioty: from %d to %d\n", update_isr->pri, int_priority);
289 update_isr->pri = int_priority;
290 int_isr_add(update_isr, group_id);
291
292 return BK_OK;
293 }
294
bk_int_set_group(void)295 bk_err_t bk_int_set_group(void)
296 {
297 return BK_ERR_NOT_SUPPORT;
298 }
299
interrupt_spurious(void)300 void interrupt_spurious(void)
301 {
302 //BK_ASSERT(0);
303 }
304
rf_ps_wakeup_isr_idle_int_cb(void)305 void rf_ps_wakeup_isr_idle_int_cb(void)
306 {
307 #if ( CONFIG_MP3PLAYER == 1 )
308 uint32_t irq_status;
309
310 irq_status = icu_get_irq_int_status();
311
312 if (irq_status & 1 << IRQ_I2S_PCM) {
313 irq_status &= 1 << IRQ_I2S_PCM;
314 i2s_isr();
315 icu_clear_irq_int_status(irq_status);
316 }
317 #endif
318 }
319 #endif
320
321