1 /*
2 // Copyright (C) 2022 Beken Corporation
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
16 #include <stdio.h>
17 #include <string.h>
18
19 #include <os/os.h>
20 #include "mailbox_channel.h"
21 #include "mb_ipc_cmd.h"
22 #include "amp_res_lock.h"
23 #include "amp_lock_api.h"
24
25 #define AMP_CPU_CNT 2 /* < 32 CPUs. for the xchg_buff is 64-bytes. */
26
27 typedef struct
28 {
29 u8 inited;
30 beken_semaphore_t res_sema;
31
32 #if CONFIG_MASTER_CORE
33 u16 req_cnt[AMP_CPU_CNT];
34 #endif
35
36 } amp_res_sync_t;
37
38 static amp_res_sync_t amp_res_sync[AMP_RES_ID_MAX];
39
40 #if CONFIG_MASTER_CORE
41
42 /* call this API in interrupt disabled state. */
amp_res_acquire_cnt(u16 res_id,u16 cpu_id,amp_res_req_cnt_t * cnt_list)43 bk_err_t amp_res_acquire_cnt(u16 res_id, u16 cpu_id, amp_res_req_cnt_t *cnt_list)
44 {
45 if(res_id >= AMP_RES_ID_MAX)
46 return BK_ERR_PARAM;
47
48 if(amp_res_sync[res_id].inited == 0)
49 return BK_ERR_NOT_INIT;
50
51 if(cpu_id >= AMP_CPU_CNT)
52 return BK_ERR_PARAM;
53
54 u16 i = 0;
55 u16 other_cnt = 0;
56
57 cnt_list->self_req_cnt = amp_res_sync[res_id].req_cnt[cpu_id];
58
59 for(i = 0; i < AMP_CPU_CNT; i++)
60 {
61 other_cnt += amp_res_sync[res_id].req_cnt[i];
62 }
63
64 cnt_list->others_req_cnt = other_cnt - cnt_list->self_req_cnt;
65
66 amp_res_sync[res_id].req_cnt[cpu_id]++;
67
68 return BK_OK;
69
70 }
71
72 /* call this API in interrupt disabled state. */
amp_res_release_cnt(u16 res_id,u16 cpu_id,amp_res_req_cnt_t * cnt_list)73 bk_err_t amp_res_release_cnt(u16 res_id, u16 cpu_id, amp_res_req_cnt_t *cnt_list)
74 {
75 if(res_id >= AMP_RES_ID_MAX)
76 return BK_ERR_PARAM;
77
78 if(amp_res_sync[res_id].inited == 0)
79 return BK_ERR_NOT_INIT;
80
81 if(cpu_id >= AMP_CPU_CNT)
82 return BK_ERR_PARAM;
83
84 u16 i = 0;
85
86 if(amp_res_sync[res_id].req_cnt[cpu_id] > 0)
87 {
88 amp_res_sync[res_id].req_cnt[cpu_id]--;
89
90 u16 other_cnt = 0;
91
92 for(i = 0; i < AMP_CPU_CNT; i++)
93 {
94 other_cnt += amp_res_sync[res_id].req_cnt[i];
95 }
96
97 cnt_list->self_req_cnt = amp_res_sync[res_id].req_cnt[cpu_id];
98 cnt_list->others_req_cnt = other_cnt - cnt_list->self_req_cnt;
99
100 return BK_OK;
101 }
102 else
103 {
104 return BK_FAIL;
105 }
106
107 }
108
109 #endif
110
111 #ifdef CONFIG_DUAL_CORE
112
113 /* Apps can't call this API, it's for IPC isr only. */
amp_res_available(u16 res_id)114 bk_err_t amp_res_available(u16 res_id)
115 {
116 if(res_id >= AMP_RES_ID_MAX)
117 return BK_ERR_PARAM;
118
119 if(amp_res_sync[res_id].inited == 0)
120 return BK_ERR_NOT_INIT;
121
122 return rtos_set_semaphore(&_res_sync[res_id].res_sema);
123 }
124
125 #endif
126
amp_res_lock_acquire(u16 res_id,u32 timeout_ms,const char * func_name,int line_no)127 bk_err_t amp_res_lock_acquire(u16 res_id, u32 timeout_ms, const char * func_name, int line_no)
128 {
129 bk_err_t ret_val = BK_FAIL;
130
131 if( rtos_is_in_interrupt_context() )
132 {
133 BK_LOGE("AMP", "can't call in ISR %s,%d\r\n", func_name, line_no);
134
135 return BK_FAIL;
136 }
137
138 if(res_id >= AMP_RES_ID_MAX)
139 return BK_ERR_PARAM;
140
141 if(amp_res_sync[res_id].inited == 0)
142 return BK_ERR_NOT_INIT;
143
144 #ifdef CONFIG_DUAL_CORE
145
146 amp_res_req_cnt_t cnt_list;
147
148 #if CONFIG_MASTER_CORE
149
150 u32 int_mask = rtos_disable_int();
151
152 ret_val = amp_res_acquire_cnt(res_id, SRC_CPU, &cnt_list);
153
154 rtos_enable_int(int_mask);
155
156 #endif
157
158 #if CONFIG_SLAVE_CORE
159
160 ret_val = ipc_send_res_acquire_cnt(res_id, SRC_CPU, &cnt_list);
161
162 #endif
163
164 if(ret_val != BK_OK)
165 {
166 return ret_val;
167 }
168
169 if((cnt_list.self_req_cnt == 0) && (cnt_list.others_req_cnt > 0))
170 {
171 /* resource was occupied by other CPU, so set semaphore state to unavailable. */
172 ret_val = rtos_get_semaphore(&_res_sync[res_id].res_sema, 0);
173
174 if(ret_val != BK_OK)
175 {
176 return ret_val;
177 }
178 }
179
180 #endif
181
182 ret_val = rtos_get_semaphore(&_res_sync[res_id].res_sema, timeout_ms);
183
184 return ret_val;
185
186 }
187
amp_res_lock_release(u16 res_id,const char * func_name,int line_no)188 bk_err_t amp_res_lock_release(u16 res_id, const char * func_name, int line_no)
189 {
190 bk_err_t ret_val = BK_FAIL;
191
192 if( rtos_is_in_interrupt_context() )
193 {
194 BK_LOGE("AMP", "can't call in ISR %s,%d\r\n", func_name, line_no);
195
196 return BK_FAIL;
197 }
198
199 if(res_id >= AMP_RES_ID_MAX)
200 return BK_ERR_PARAM;
201
202 if(amp_res_sync[res_id].inited == 0)
203 return BK_ERR_NOT_INIT;
204
205 #ifdef CONFIG_DUAL_CORE
206
207 amp_res_req_cnt_t cnt_list;
208
209 #if CONFIG_MASTER_CORE
210
211 u32 int_mask = rtos_disable_int();
212
213 ret_val = amp_res_release_cnt(res_id, SRC_CPU, &cnt_list);
214
215 rtos_enable_int(int_mask);
216
217 #endif
218
219 #if CONFIG_SLAVE_CORE
220
221 ret_val = ipc_send_res_release_cnt(res_id, SRC_CPU, &cnt_list);
222
223 #endif
224
225 if(ret_val != BK_OK)
226 {
227 return ret_val;
228 }
229
230 if((cnt_list.self_req_cnt == 0) && (cnt_list.others_req_cnt > 0))
231 {
232 /* other CPU is waiting for the resource, so inform CPU that it is available. */
233 /* which CPU is selected in multi-cores? (over than 2 cores)*/
234 ret_val = ipc_send_available_ind(res_id);
235
236 if(ret_val != BK_OK)
237 {
238 return ret_val;
239 }
240 }
241
242 #endif
243
244 ret_val = rtos_set_semaphore(&_res_sync[res_id].res_sema);
245
246 return ret_val;
247
248 }
249
amp_res_lock_init(u16 res_id)250 bk_err_t amp_res_lock_init(u16 res_id)
251 {
252 bk_err_t ret_val = BK_FAIL;
253
254 if(res_id >= AMP_RES_ID_MAX)
255 return BK_ERR_PARAM;
256
257 if(amp_res_sync[res_id].inited != 0)
258 return BK_OK;
259
260 #if CONFIG_MASTER_CORE
261
262 u16 i = 0;
263
264 for(i = 0; i < AMP_CPU_CNT; i++)
265 {
266 amp_res_sync[res_id].req_cnt[i] = 0;
267 }
268
269 #endif
270
271 ret_val = rtos_init_semaphore_adv(&_res_sync[res_id].res_sema, 1, 1);
272
273 if(ret_val != BK_OK)
274 return ret_val;
275
276 amp_res_sync[res_id].inited = 1;
277
278 return BK_OK;
279 }
280
281