• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
16 #include <string.h>
17 
18 #include <os/os.h>
19 #include "mailbox_channel.h"
20 #include "mb_ipc_cmd.h"
21 #include "dma_driver.h"
22 
23 #define MOD_TAG		"IPC"
24 
25 #define IPC_RSP_CMD_FLAG		0x80
26 #define IPC_RSP_CMD_MASK		0x7F
27 
28 #define IPC_RSP_TIMEOUT			10		/* 10ms */
29 #define IPC_XCHG_DATA_MAX		64
30 
31 typedef union
32 {
33 	struct
34 	{
35 		mb_chnl_hdr_t	chnl_hdr;
36 		void *	cmd_buff;
37 		u16		cmd_data_len;
38 	};
39 
40 	mb_chnl_cmd_t	mb_cmd;
41 } ipc_cmd_t;
42 
43 typedef union
44 {
45 	struct
46 	{
47 		mb_chnl_hdr_t	chnl_hdr;
48 		void *	rsp_buff;
49 		u16		rsp_data_len;
50 	};
51 
52 	mb_chnl_ack_t	mb_ack;
53 } ipc_rsp_t;
54 
55 typedef struct
56 {
57 	u8		client_buff[IPC_XCHG_DATA_MAX];
58 	u8		server_buff[IPC_XCHG_DATA_MAX];
59 } ipc_chnl_buf_t;
60 
61 typedef u32 (* ipc_rx_cmd_hdlr_t)(void * chnl_cb, mb_chnl_ack_t *ack_buf);
62 
63 typedef struct
64 {
65 	/* chnl data */
66 	u8					chnl_inited;
67 	u8					chnl_id;
68 	beken_semaphore_t	chnl_sema;
69 
70 	/* tx cmd data */
71 	beken_semaphore_t	rsp_sema;
72 	u8			*	tx_xchg_buff;
73 	u8				tx_cmd;
74 	volatile u8		tx_cmd_in_process;
75 	volatile u8		tx_cmd_failed;
76 	u32				rsp_buf[IPC_XCHG_DATA_MAX / sizeof(u32)];
77 	u16				rsp_len;
78 
79 	/* rx cmd data */
80 	ipc_rx_cmd_hdlr_t	rx_cmd_handler;
81 	u8			*	rx_xchg_buff;
82 	u8				rx_cmd;
83 	volatile u8		rx_cmd_in_process;
84 	u32				cmd_buf[IPC_XCHG_DATA_MAX / sizeof(u32)];
85 	u16				cmd_len;
86 } ipc_chnl_cb_t;
87 
88 extern char _swap_start;
89 static ipc_chnl_buf_t * const ipc_xchg_buf = (ipc_chnl_buf_t *)(&_swap_start);
90 
ipc_cmd_rx_isr(ipc_chnl_cb_t * chnl_cb,mb_chnl_cmd_t * cmd_buf)91 static void ipc_cmd_rx_isr(ipc_chnl_cb_t *chnl_cb, mb_chnl_cmd_t *cmd_buf)
92 {
93 	u32		result = ACK_STATE_FAIL;
94 	mb_chnl_ack_t * ack_buf = (mb_chnl_ack_t *)cmd_buf;
95 	ipc_cmd_t     * ipc_cmd = (ipc_cmd_t *)cmd_buf;
96 
97 	/* chnl_cb->rx_xchg_buff == ipc_cmd->cmd_buff. MUST be true. */
98 
99 	if(cmd_buf->hdr.cmd & IPC_RSP_CMD_FLAG)  /* ipc rsp from other CPU. */
100 	{
101 		if(chnl_cb->tx_cmd_in_process == 0)	/* unsolicited ipc response. */
102 		{
103 			goto ipc_cmd_rx_isr_exit;
104 		}
105 
106 		if(chnl_cb->tx_cmd != (cmd_buf->hdr.cmd & IPC_RSP_CMD_MASK))
107 		{
108 			/* un-matched rpc response. */
109 			goto ipc_cmd_rx_isr_exit;
110 		}
111 
112 		/* communication ok, function is completed. */
113 		chnl_cb->tx_cmd_failed = 0;
114 		chnl_cb->tx_cmd_in_process = 0;
115 
116 		BK_LOGI(MOD_TAG, "IPC_RSP_CMD: %d, %d, %d\r\n", cmd_buf->param1, cmd_buf->param2, cmd_buf->param3);
117 
118 		if(ipc_cmd->cmd_data_len > sizeof(chnl_cb->rsp_buf))
119 		{
120 			/* buffer insufficient, failed. */
121 			chnl_cb->tx_cmd_failed = 1;
122 			chnl_cb->rsp_len = 0;
123 		}
124 		else
125 		{
126 			/* returns ACK_STATE_COMPLETE,
127 			   so must copy data from cmd_buff in case that the buffer is released. */
128 			if((ipc_cmd->cmd_buff != NULL) && (ipc_cmd->cmd_data_len > 0))
129 			{
130 				memcpy(chnl_cb->rsp_buf, ipc_cmd->cmd_buff, ipc_cmd->cmd_data_len);
131 
132 				chnl_cb->rsp_len = ipc_cmd->cmd_data_len;
133 			}
134 			else
135 			{
136 				chnl_cb->rsp_len = 0;
137 			}
138 		}
139 
140 		rtos_set_semaphore(&chnl_cb->rsp_sema);
141 
142 		ipc_rsp_t * ipc_rsp = (ipc_rsp_t *)ack_buf;
143 
144 		/* it is a rsp command, nothing need to be returned. */
145 		ipc_rsp->rsp_buff = NULL;
146 		ipc_rsp->rsp_data_len = 0;
147 
148 		result = ACK_STATE_COMPLETE;
149 
150 		goto ipc_cmd_rx_isr_exit;
151 	}
152 	else
153 	{
154 		chnl_cb->rx_cmd = cmd_buf->hdr.cmd;
155 		chnl_cb->rx_cmd_in_process = 1;
156 
157 		BK_LOGD(MOD_TAG, "IPC_CMD: %d, %d, %d\r\n", cmd_buf->param1, cmd_buf->param2, cmd_buf->param3);
158 
159 		if(ipc_cmd->cmd_data_len > sizeof(chnl_cb->cmd_buf))
160 		{
161 			result = ACK_STATE_FAIL;
162 		}
163 		else
164 		{
165 			/* may return ACK_STATE_COMPLETE,
166 			   so must copy data from cmd_buff in case that the buffer is released. */
167 			if((ipc_cmd->cmd_buff != NULL) && (ipc_cmd->cmd_data_len > 0))
168 			{
169 				memcpy(chnl_cb->cmd_buf, ipc_cmd->cmd_buff, ipc_cmd->cmd_data_len);
170 
171 				chnl_cb->cmd_len = ipc_cmd->cmd_data_len;
172 			}
173 			else
174 			{
175 				chnl_cb->cmd_len = 0;
176 			}
177 
178 			result = chnl_cb->rx_cmd_handler(chnl_cb, ack_buf);
179 		}
180 
181 		if(result != ACK_STATE_PENDING)
182 			chnl_cb->rx_cmd_in_process = 0;
183 	}
184 
185 ipc_cmd_rx_isr_exit:
186 
187 	/* overwrite the cmd_buf after the ISR handle complete.
188 	 * return the ack info to caller using the SAME buffer with cmd buffer.
189 	 *     !!!! [input as param / output as result ]  !!!!
190 	 */
191 	ack_buf->ack_state = result;
192 
193 	return;
194 
195 }
196 
ipc_cmd_tx_cmpl_isr(ipc_chnl_cb_t * chnl_cb,mb_chnl_ack_t * ack_buf)197 static void ipc_cmd_tx_cmpl_isr(ipc_chnl_cb_t *chnl_cb, mb_chnl_ack_t *ack_buf)  /* tx_cmpl_isr */
198 {
199 	if(ack_buf->hdr.cmd == chnl_cb->tx_cmd)
200 	{
201 		if(chnl_cb->tx_cmd_in_process == 0)	/* RSP_CMD rx_isr may arrive before this tx_cmpl_isr. */
202 			return;
203 
204 		/* IPC cmd tx complete. */
205 
206 		if( (ack_buf->hdr.state & CHNL_STATE_COM_FAIL)
207 			|| (ack_buf->ack_state == ACK_STATE_FAIL) )
208 		{
209 			chnl_cb->tx_cmd_failed = 1;
210 			chnl_cb->tx_cmd_in_process  = 0;
211 
212 			/* communication failed or function failed. */
213 			rtos_set_semaphore(&chnl_cb->rsp_sema);
214 		}
215 		else if(ack_buf->ack_state == ACK_STATE_COMPLETE)
216 		{
217 			/* communication ok, function is completed. */
218 			chnl_cb->tx_cmd_failed = 0;
219 			chnl_cb->tx_cmd_in_process = 0;
220 
221 			ipc_rsp_t * ipc_rsp = (ipc_rsp_t *)ack_buf;
222 
223 			/* chnl_cb->tx_xchg_buff == ipc_rsp->rsp_buff. MUST be true. */
224 
225 			if(ipc_rsp->rsp_data_len > sizeof(chnl_cb->rsp_buf))
226 			{
227 				/* buffer insufficient, failed. */
228 				chnl_cb->tx_cmd_failed = 1;
229 				chnl_cb->rsp_len = 0;
230 			}
231 			else
232 			{
233 				if((ipc_rsp->rsp_buff != NULL) && (ipc_rsp->rsp_data_len > 0))
234 				{
235 					memcpy(chnl_cb->rsp_buf, ipc_rsp->rsp_buff, ipc_rsp->rsp_data_len);
236 					chnl_cb->rsp_len = ipc_rsp->rsp_data_len;
237 				}
238 				else
239 				{
240 					chnl_cb->rsp_len = 0;
241 				}
242 			}
243 
244 			rtos_set_semaphore(&chnl_cb->rsp_sema);
245 		}
246 		else
247 		{
248 			/* communication ok, function is pending. */
249 		}
250 
251 		return;
252 	}
253 
254 	/*
255 	 *   !!!  FAULT  !!!
256 	 */
257 	BK_LOGE(MOD_TAG, "Fault in %s,cmd:%d\r\n", __func__, ack_buf->hdr.cmd);
258 
259 	return;
260 
261 }
262 
ipc_chnl_init(u8 client,ipc_chnl_cb_t * chnl_cb,u8 chnl_id,ipc_rx_cmd_hdlr_t rx_handler)263 static bk_err_t ipc_chnl_init(u8 client, ipc_chnl_cb_t *chnl_cb, u8 chnl_id, ipc_rx_cmd_hdlr_t rx_handler)
264 {
265 	bk_err_t		ret_code;
266 
267 	if(chnl_cb->chnl_inited)
268 		return BK_OK;
269 
270 	memset(chnl_cb, 0, sizeof(ipc_chnl_cb_t));
271 	chnl_cb->chnl_id = chnl_id;
272 
273 	if(client)
274 	{
275 		/* client rx cmds from server. */
276 		chnl_cb->tx_xchg_buff = ipc_xchg_buf[chnl_id].client_buff;
277 		chnl_cb->rx_xchg_buff = ipc_xchg_buf[chnl_id].server_buff;
278 	}
279 	else
280 	{
281 		/* server rx cmds from client. */
282 		chnl_cb->tx_xchg_buff = ipc_xchg_buf[chnl_id].server_buff;
283 		chnl_cb->rx_xchg_buff = ipc_xchg_buf[chnl_id].client_buff;
284 	}
285 
286 	ret_code = rtos_init_semaphore_adv(&chnl_cb->chnl_sema, 1, 1);
287 	if(ret_code != BK_OK)
288 	{
289 		return ret_code;
290 	}
291 
292 	ret_code = rtos_init_semaphore(&chnl_cb->rsp_sema, 1);
293 	if(ret_code != BK_OK)
294 	{
295 		rtos_deinit_semaphore(&chnl_cb->chnl_sema);
296 
297 		return ret_code;
298 	}
299 
300 	ret_code = mb_chnl_open(chnl_id, chnl_cb);
301 	if(ret_code != BK_OK)
302 	{
303 		rtos_deinit_semaphore(&chnl_cb->chnl_sema);
304 		rtos_deinit_semaphore(&chnl_cb->rsp_sema);
305 
306 		return ret_code;
307 	}
308 
309 	chnl_cb->rx_cmd_handler = rx_handler;
310 
311 	mb_chnl_ctrl(chnl_id, MB_CHNL_SET_RX_ISR, (void *)ipc_cmd_rx_isr);
312 	mb_chnl_ctrl(chnl_id, MB_CHNL_SET_TX_CMPL_ISR, (void *)ipc_cmd_tx_cmpl_isr);
313 
314 	chnl_cb->chnl_inited = 1;
315 
316 	return BK_OK;
317 }
318 
ipc_send_cmd(ipc_chnl_cb_t * chnl_cb,u8 cmd,u8 * cmd_buf,u16 cmd_len,u8 * rsp_buf,u16 buf_len)319 static bk_err_t ipc_send_cmd(ipc_chnl_cb_t *chnl_cb, u8 cmd, u8 *cmd_buf, u16 cmd_len, u8 * rsp_buf, u16 buf_len)
320 {
321 	bk_err_t	ret_val = BK_FAIL;
322 	ipc_cmd_t	ipc_cmd;
323 
324 	if(!chnl_cb->chnl_inited)
325 		return BK_FAIL;
326 
327 	rtos_get_semaphore(&chnl_cb->chnl_sema, BEKEN_WAIT_FOREVER);
328 
329 	chnl_cb->tx_cmd = cmd;
330 	chnl_cb->tx_cmd_failed = 0;
331 	chnl_cb->tx_cmd_in_process = 1;
332 
333 	/* client uses the CLIENT buffer to exchange info(Cmd/Rsp) with server. */
334 	/* server uses the SERVER buffer to exchange info(Cmd/Rsp) with client. */
335 	void * dst_buf = (void *)chnl_cb->tx_xchg_buff;
336 
337 	do
338 	{
339 		if(cmd_len > IPC_XCHG_DATA_MAX)
340 		{
341 			ret_val = BK_ERR_PARAM;
342 			break;
343 		}
344 
345 		if(cmd_buf == NULL)
346 			cmd_len = 0;
347 
348 		if(cmd_len > 0)
349 			memcpy(dst_buf, cmd_buf, cmd_len);
350 
351 		ipc_cmd.chnl_hdr.data = 0;	/* clear hdr. */
352 		ipc_cmd.chnl_hdr.cmd  = cmd;
353 		ipc_cmd.cmd_buff      = dst_buf;
354 		ipc_cmd.cmd_data_len  = cmd_len;
355 
356 		ret_val = mb_chnl_write(chnl_cb->chnl_id, (mb_chnl_cmd_t *)&ipc_cmd);
357 		if(ret_val != BK_OK)
358 		{
359 			break;
360 		}
361 
362 		ret_val = rtos_get_semaphore(&chnl_cb->rsp_sema, IPC_RSP_TIMEOUT);  /* isr_callback will set this semaphore. */
363 		if(ret_val != BK_OK)
364 		{
365 			break;
366 		}
367 
368 		chnl_cb->tx_cmd_in_process  = 0;  /* must have been set to 0 by callback. */
369 
370 		if(chnl_cb->tx_cmd_failed)
371 		{
372 			ret_val = BK_FAIL;
373 			break;
374 		}
375 
376 		if((rsp_buf == NULL) || (buf_len == 0))
377 		{
378 			ret_val = BK_OK;
379 			break;
380 		}
381 
382 		if(buf_len < chnl_cb->rsp_len)
383 		{
384 			ret_val = BK_ERR_PARAM;
385 			break;
386 		}
387 
388 		if(chnl_cb->rsp_len > 0)
389 			memcpy(rsp_buf, chnl_cb->rsp_buf, chnl_cb->rsp_len);
390 
391 		ret_val = BK_OK;
392 
393 	}while(0);
394 
395 	chnl_cb->tx_cmd_in_process = 0;
396 
397 	rtos_set_semaphore(&chnl_cb->chnl_sema);
398 
399 	return ret_val;
400 
401 }
402 
403 static ipc_chnl_cb_t	ipc_chnl_cb; // = { .chnl_id = MB_CHNL_HW_CTRL, .chnl_inited = 0 };
404 
405 typedef struct
406 {
407 	u16		res_id;
408 	u16		cpu_id;
409 } ipc_res_req_t;
410 
411 typedef struct
412 {
413 	u32		user_id;
414 	u32		chnl_id;
415 } ipc_dma_free_t;
416 
417 #if CONFIG_SLAVE_CORE
418 
419 /**    ============================      IPC client    ============================   **/
420 
ipc_client_cmd_handler(ipc_chnl_cb_t * chnl_cb,mb_chnl_ack_t * ack_buf)421 static u32 ipc_client_cmd_handler(ipc_chnl_cb_t *chnl_cb, mb_chnl_ack_t *ack_buf)
422 {
423 	/* must NOT change ack_buf->hdr. */
424 
425 	u32		result = ACK_STATE_FAIL;
426 	ipc_rsp_t * ipc_rsp = (ipc_rsp_t *)ack_buf;
427 
428 	/* chnl_cb->rx_xchg_buff == ipc_cmd->cmd_buff == ipc_rsp->rsp_buff. MUST be true. */
429 
430 	ipc_rsp->rsp_buff = chnl_cb->rx_xchg_buff; //ipc_xchg_buf[chnl_cb->chnl_id].server_buff;
431 
432 	switch(chnl_cb->rx_cmd)
433 	{
434 		case IPC_TEST_CMD:
435 			if(chnl_cb->cmd_len >= sizeof(u32))
436 			{
437 				ipc_rsp->rsp_data_len = sizeof(u32);
438 
439 				u32 * p_src = (u32 *)chnl_cb->cmd_buf;
440 				u32 * p_dst = (u32 *)ipc_rsp->rsp_buff;
441 
442 				*p_dst = (*p_src) + 1;
443 
444 				result = ACK_STATE_COMPLETE;
445 			}
446 			else
447 			{
448 				ipc_rsp->rsp_data_len = 0;
449 				result = ACK_STATE_FAIL;
450 			}
451 			break;
452 
453 		case IPC_GET_POWER_SAVE_FLAG:
454 			{
455 				ipc_rsp->rsp_data_len = sizeof(u32);
456 
457 				u32 * p_dst = (u32 *)ipc_rsp->rsp_buff;
458 
459 				// return PS flag to caller.
460 				*p_dst = 0xAA; //(u32)get_cpu1_ps_flag();
461 
462 				result = ACK_STATE_COMPLETE;
463 			}
464 			break;
465 
466 		case IPC_SET_CPU1_HEART_RATE:
467 			if(chnl_cb->cmd_len >= sizeof(u32))
468 			{
469 				ipc_rsp->rsp_data_len = 0;
470 
471 				//u32 * p_src = (u32 *)chnl_cb->cmd_buf;
472 
473 				// save the param.
474 				//set_cpu1_heart_rate(*p_src);
475 
476 				result = ACK_STATE_COMPLETE;
477 			}
478 			else
479 			{
480 				ipc_rsp->rsp_data_len = 0;
481 				result = ACK_STATE_FAIL;
482 			}
483 			break;
484 
485 		case IPC_GET_CPU1_HEART_RATE:
486 			{
487 				ipc_rsp->rsp_data_len = sizeof(u32);
488 
489 				u32 * p_dst = (u32 *)ipc_rsp->rsp_buff;
490 
491 				// return heart_rate to caller.
492 				*p_dst = 0xBB; //(u32)get_cpu1_heart_rate();
493 
494 				result = ACK_STATE_COMPLETE;
495 			}
496 			break;
497 
498 		case IPC_RES_AVAILABLE_INDICATION:
499 			if(chnl_cb->cmd_len >= sizeof(u16))
500 			{
501 				ipc_rsp->rsp_data_len = 0;
502 
503 				u16  res_id = *((u16 *)chnl_cb->cmd_buf);
504 
505 				if(amp_res_available(res_id) == BK_OK)
506 				{
507 					result = ACK_STATE_COMPLETE;
508 				}
509 				else
510 				{
511 					result = ACK_STATE_FAIL;
512 				}
513 			}
514 			else
515 			{
516 				ipc_rsp->rsp_data_len = 0;
517 				result = ACK_STATE_FAIL;
518 			}
519 			break;
520 
521 		default:
522 			{
523 				ipc_rsp->rsp_data_len = 0;
524 				result = ACK_STATE_FAIL;
525 			}
526 			break;
527 	}
528 
529 	return result;
530 }
531 
ipc_client_init(void)532 bk_err_t ipc_client_init(void)
533 {
534 	return ipc_chnl_init(1, &ipc_chnl_cb, MB_CHNL_HW_CTRL, (ipc_rx_cmd_hdlr_t)ipc_client_cmd_handler);
535 }
536 
537 /**    ============================    IPC client end  ============================   **/
538 
ipc_send_power_up(void)539 bk_err_t ipc_send_power_up(void)
540 {
541 	return ipc_send_cmd(&ipc_chnl_cb, IPC_CPU1_POWER_UP_INDICATION, NULL, 0, NULL, 0);
542 }
543 
ipc_send_heart_beat(u32 param)544 bk_err_t ipc_send_heart_beat(u32 param)
545 {
546 	return ipc_send_cmd(&ipc_chnl_cb, IPC_CPU1_HEART_BEAT_INDICATION, (u8 *)&param, sizeof(param), NULL, 0);
547 }
548 
ipc_send_res_acquire_cnt(u16 resource_id,u16 cpu_id,amp_res_req_cnt_t * cnt_list)549 bk_err_t ipc_send_res_acquire_cnt(u16 resource_id, u16 cpu_id, amp_res_req_cnt_t *cnt_list)
550 {
551 	ipc_res_req_t	res_req;
552 
553 	res_req.res_id = resource_id;
554 	res_req.cpu_id = cpu_id;
555 
556 	return ipc_send_cmd(&ipc_chnl_cb, IPC_RES_ACQUIRE_CNT, \
557 						(u8 *)&res_req, sizeof(res_req), (u8 *)cnt_list, sizeof(amp_res_req_cnt_t));
558 }
559 
ipc_send_res_release_cnt(u16 resource_id,u16 cpu_id,amp_res_req_cnt_t * cnt_list)560 bk_err_t ipc_send_res_release_cnt(u16 resource_id, u16 cpu_id, amp_res_req_cnt_t *cnt_list)
561 {
562 	ipc_res_req_t	res_req;
563 
564 	res_req.res_id = resource_id;
565 	res_req.cpu_id = cpu_id;
566 
567 	return ipc_send_cmd(&ipc_chnl_cb, IPC_RES_RELEASE_CNT, \
568 						(u8 *)&res_req, sizeof(res_req), (u8 *)cnt_list, sizeof(amp_res_req_cnt_t));
569 }
570 
ipc_send_alloc_dma_chnl(u32 user_id)571 u8 ipc_send_alloc_dma_chnl(u32 user_id)
572 {
573 	bk_err_t	ret_val = BK_FAIL;
574 	u8	dma_chnl_id = -1;
575 
576 	ret_val = ipc_send_cmd(&ipc_chnl_cb, IPC_ALLOC_DMA_CHNL, \
577 						(u8 *)&user_id, sizeof(user_id), (u8 *)&dma_chnl_id, sizeof(dma_chnl_id));
578 
579 	if(ret_val != BK_OK)
580 		return (u8)(-1);
581 
582 	return dma_chnl_id;
583 }
584 
ipc_send_free_dma_chnl(u32 user_id,u8 chnl_id)585 bk_err_t ipc_send_free_dma_chnl(u32 user_id, u8 chnl_id)
586 {
587 	bk_err_t	ret_val = BK_FAIL;
588 
589 	ipc_dma_free_t	dma_free;
590 
591 	dma_free.user_id = user_id;
592 	dma_free.chnl_id = chnl_id;
593 
594 	ret_val = ipc_send_cmd(&ipc_chnl_cb, IPC_FREE_DMA_CHNL, \
595 						(u8 *)&dma_free, sizeof(dma_free), NULL, 0);
596 
597 	return ret_val;
598 }
599 
ipc_send_dma_chnl_user(u8 chnl_id)600 u32 ipc_send_dma_chnl_user(u8 chnl_id)
601 {
602 	bk_err_t	ret_val = BK_FAIL;
603 	u32		user_id = -1;
604 
605 	ret_val = ipc_send_cmd(&ipc_chnl_cb, IPC_DMA_CHNL_USER, \
606 						(u8 *)&chnl_id, sizeof(chnl_id), (u8 *)&user_id, sizeof(user_id));
607 
608 	if(ret_val != BK_OK)
609 		return (u32)(-1);
610 
611 	return user_id;
612 }
613 
614 #endif
615 
616 #ifdef CONFIG_DUAL_CORE
617 
ipc_send_test_cmd(u32 param)618 u32 ipc_send_test_cmd(u32 param)
619 {
620 	ipc_send_cmd(&ipc_chnl_cb, IPC_TEST_CMD, (u8 *)&param, sizeof(param), (u8 *)&param, sizeof(param));
621 
622 	return param;
623 }
624 
ipc_send_available_ind(u16 resource_id)625 bk_err_t ipc_send_available_ind(u16 resource_id)
626 {
627 	return ipc_send_cmd(&ipc_chnl_cb, IPC_RES_AVAILABLE_INDICATION, \
628 						(u8 *)&resource_id, sizeof(resource_id), NULL, 0);
629 }
630 
631 #endif
632 
633 #if CONFIG_MASTER_CORE
634 
635 /**    ============================      IPC server    ============================   **/
636 
ipc_server_cmd_handler(ipc_chnl_cb_t * chnl_cb,mb_chnl_ack_t * ack_buf)637 static u32 ipc_server_cmd_handler(ipc_chnl_cb_t *chnl_cb, mb_chnl_ack_t *ack_buf)
638 {
639 	/* must NOT change ack_buf->hdr. */
640 
641 	u32		result = ACK_STATE_FAIL;
642 	ipc_rsp_t * ipc_rsp = (ipc_rsp_t *)ack_buf;
643 
644 	/* chnl_cb->rx_xchg_buff == ipc_cmd->cmd_buff == ipc_rsp->rsp_buff. MUST be true. */
645 
646 	ipc_rsp->rsp_buff = chnl_cb->rx_xchg_buff;
647 
648 	switch(chnl_cb->rx_cmd)
649 	{
650 		case IPC_TEST_CMD:
651 			if(chnl_cb->cmd_len >= sizeof(u32))
652 			{
653 				ipc_rsp->rsp_data_len = sizeof(u32);
654 
655 				u32 * p_src = (u32 *)chnl_cb->cmd_buf;
656 				u32 * p_dst = (u32 *)ipc_rsp->rsp_buff;
657 
658 				*p_dst = (*p_src) + 1;
659 
660 				result = ACK_STATE_COMPLETE;
661 			}
662 			else
663 			{
664 				ipc_rsp->rsp_data_len = 0;
665 				result = ACK_STATE_FAIL;
666 			}
667 			break;
668 
669 		case IPC_CPU1_POWER_UP_INDICATION:		// cpu1 indication, power up successfully.
670 			{
671 				ipc_rsp->rsp_data_len = 0;
672 				result = ACK_STATE_COMPLETE;
673 
674 				/* no params, no returns. */
675 
676 				/* inform modules who care CPU1 state. */
677 			}
678 			break;
679 
680 		case IPC_CPU1_HEART_BEAT_INDICATION:	// cpu1 indication, alive indication.
681 			// contains the power save flag?
682 			if(chnl_cb->cmd_len >= sizeof(u32))
683 			{
684 				//u32 * p_src = (u32 *)chnl_cb->cmd_buf;
685 
686 				// save the param.
687 				//set_cpu1_ps_flag(*p_src);
688 			}
689 
690 			/* succeeded anyway but no returns. */
691 			ipc_rsp->rsp_data_len = 0;
692 			result = ACK_STATE_COMPLETE;
693 			break;
694 
695 		case IPC_RES_ACQUIRE_CNT:
696 			if(chnl_cb->cmd_len >= sizeof(ipc_res_req_t))
697 			{
698 				ipc_res_req_t * res_req = (ipc_res_req_t *)chnl_cb->cmd_buf;
699 				amp_res_req_cnt_t * res_cnt_list = (amp_res_req_cnt_t *)ipc_rsp->rsp_buff;
700 
701 				/* call amp_res_acquire_cnt in interrupt disabled state. */
702 				if(amp_res_acquire_cnt(res_req->res_id, res_req->cpu_id, res_cnt_list) == BK_OK)
703 				{
704 					ipc_rsp->rsp_data_len = sizeof(amp_res_req_cnt_t);
705 
706 					result = ACK_STATE_COMPLETE;
707 				}
708 				else
709 				{
710 					ipc_rsp->rsp_data_len = 0;
711 					result = ACK_STATE_FAIL;
712 				}
713 			}
714 			else
715 			{
716 				ipc_rsp->rsp_data_len = 0;
717 				result = ACK_STATE_FAIL;
718 			}
719 			break;
720 
721 		case IPC_RES_RELEASE_CNT:
722 			if(chnl_cb->cmd_len >= sizeof(ipc_res_req_t))
723 			{
724 				ipc_res_req_t * res_req = (ipc_res_req_t *)chnl_cb->cmd_buf;
725 				amp_res_req_cnt_t * res_cnt_list = (amp_res_req_cnt_t *)ipc_rsp->rsp_buff;
726 
727 				/* call amp_res_release_cnt in interrupt disabled state. */
728 				if(amp_res_release_cnt(res_req->res_id, res_req->cpu_id, res_cnt_list) == BK_OK)
729 				{
730 					ipc_rsp->rsp_data_len = sizeof(amp_res_req_cnt_t);
731 
732 					result = ACK_STATE_COMPLETE;
733 				}
734 				else
735 				{
736 					ipc_rsp->rsp_data_len = 0;
737 					result = ACK_STATE_FAIL;
738 				}
739 			}
740 			else
741 			{
742 				ipc_rsp->rsp_data_len = 0;
743 				result = ACK_STATE_FAIL;
744 			}
745 			break;
746 
747 		case IPC_RES_AVAILABLE_INDICATION:
748 			if(chnl_cb->cmd_len >= sizeof(u16))
749 			{
750 				ipc_rsp->rsp_data_len = 0;
751 
752 				u16  res_id = *((u16 *)chnl_cb->cmd_buf);
753 
754 				if(amp_res_available(res_id) == BK_OK)
755 				{
756 					result = ACK_STATE_COMPLETE;
757 				}
758 				else
759 				{
760 					result = ACK_STATE_FAIL;
761 				}
762 			}
763 			else
764 			{
765 				ipc_rsp->rsp_data_len = 0;
766 				result = ACK_STATE_FAIL;
767 			}
768 			break;
769 
770 		case IPC_ALLOC_DMA_CHNL:
771 			if(chnl_cb->cmd_len >= sizeof(u32))
772 			{
773 				u32  user_id = *((u32 *)chnl_cb->cmd_buf);
774 
775 				ipc_rsp->rsp_data_len = sizeof(u8);
776 
777 				u8 * chnl_id = (u8 *)ipc_rsp->rsp_buff;
778 
779 				extern u8 dma_chnl_alloc(u32 user_id);
780 
781 				*chnl_id = dma_chnl_alloc(user_id);
782 
783 				result = ACK_STATE_COMPLETE;
784 			}
785 			else
786 			{
787 				ipc_rsp->rsp_data_len = 0;
788 				result = ACK_STATE_FAIL;
789 			}
790 			break;
791 
792 		case IPC_FREE_DMA_CHNL:
793 			if(chnl_cb->cmd_len >= sizeof(ipc_dma_free_t))
794 			{
795 				ipc_dma_free_t * free_req = (ipc_dma_free_t *)chnl_cb->cmd_buf;
796 
797 				extern bk_err_t dma_chnl_free(u32 user_id, dma_id_t chnl_id);
798 
799 				bk_err_t ret_val = dma_chnl_free(free_req->user_id, (dma_id_t)free_req->chnl_id);
800 
801 				ipc_rsp->rsp_data_len = 0;
802 
803 				if(ret_val == BK_OK)
804 					result = ACK_STATE_COMPLETE;
805 				else
806 					result = ACK_STATE_FAIL;
807 			}
808 			else
809 			{
810 				ipc_rsp->rsp_data_len = 0;
811 				result = ACK_STATE_FAIL;
812 			}
813 			break;
814 
815 		case IPC_DMA_CHNL_USER:
816 			if(chnl_cb->cmd_len >= sizeof(u8))
817 			{
818 				u8    chnl_id = *((u8 *)chnl_cb->cmd_buf);
819 
820 				ipc_rsp->rsp_data_len = sizeof(u32);
821 
822 				u32 * user_id = (u32 *)ipc_rsp->rsp_buff;
823 
824 				extern u32 dma_chnl_user(dma_id_t user_id);
825 
826 				*user_id = dma_chnl_user((dma_id_t)chnl_id);
827 
828 				result = ACK_STATE_COMPLETE;
829 			}
830 			else
831 			{
832 				ipc_rsp->rsp_data_len = 0;
833 				result = ACK_STATE_FAIL;
834 			}
835 			break;
836 
837 		case IPC_CALL_CMD:
838 			/* will handle it in RPC channel. */
839 			break;
840 
841 		default:
842 			{
843 				ipc_rsp->rsp_data_len = 0;
844 				result = ACK_STATE_FAIL;
845 			}
846 			break;
847 	}
848 
849 	return result;
850 }
851 
ipc_server_init(void)852 bk_err_t ipc_server_init(void)
853 {
854 	return ipc_chnl_init(0, &ipc_chnl_cb, MB_CHNL_HW_CTRL, (ipc_rx_cmd_hdlr_t)ipc_server_cmd_handler);
855 }
856 
857 /**    ============================    IPC server end  ============================   **/
858 
ipc_send_get_ps_flag(void)859 u32 ipc_send_get_ps_flag(void)
860 {
861 	u32  param = -1;
862 
863 	ipc_send_cmd(&ipc_chnl_cb, IPC_GET_POWER_SAVE_FLAG, NULL, 0, (u8 *)&param, sizeof(param));
864 
865 	return param;
866 }
867 
ipc_send_get_heart_rate(void)868 u32 ipc_send_get_heart_rate(void)
869 {
870 	u32  param = -1;
871 
872 	ipc_send_cmd(&ipc_chnl_cb, IPC_GET_CPU1_HEART_RATE, NULL, 0, (u8 *)&param, sizeof(param));
873 
874 	return param;
875 }
876 
ipc_send_set_heart_rate(u32 param)877 bk_err_t ipc_send_set_heart_rate(u32 param)
878 {
879 	return ipc_send_cmd(&ipc_chnl_cb, IPC_SET_CPU1_HEART_RATE, (u8 *)&param, sizeof(param), NULL, 0);
880 }
881 
882 #endif
883 
884 static ipc_chnl_cb_t		rpc_chnl_cb; // = { .chnl_id = MB_CHNL_RPC, .chnl_inited = 0 };
885 
886 #if CONFIG_SLAVE_CORE
887 
888 /**    ============================      RPC client    ============================   **/
889 
rpc_client_init(void)890 bk_err_t rpc_client_init(void)
891 {
892 	return ipc_chnl_init(1, &rpc_chnl_cb, MB_CHNL_RPC, (ipc_rx_cmd_hdlr_t)ipc_client_cmd_handler);
893 }
894 
rpc_client_call(rpc_call_def_t * rpc_param,u16 param_len,rpc_ret_def_t * ret_buf,u16 buf_len)895 bk_err_t rpc_client_call(rpc_call_def_t *rpc_param, u16 param_len, rpc_ret_def_t *ret_buf, u16 buf_len)
896 {
897 	if(!rpc_chnl_cb.chnl_inited)
898 		return BK_FAIL;
899 
900 	bk_err_t	ret_val;
901 
902 	ret_val = ipc_send_cmd(&rpc_chnl_cb, IPC_CALL_CMD, (u8 *)rpc_param, param_len, (u8 *)ret_buf, buf_len);
903 
904 	if(ret_val != BK_OK)
905 		return ret_val;
906 
907 	if((ret_buf == NULL) || (buf_len == 0))
908 	{
909 		return BK_OK;
910 	}
911 
912 	if( (rpc_param->call_hdr.mod_id != ret_buf->call_hdr.mod_id) ||
913 		(rpc_param->call_hdr.mod_id != ret_buf->call_hdr.mod_id) )
914 	{
915 		/* un-matched rpc response. */
916 		return BK_FAIL;
917 	}
918 
919 	return BK_OK;
920 
921 }
922 
923 
924 /**    ============================    RPC client end  ============================   **/
925 
926 #endif
927 
928 #if CONFIG_MASTER_CORE
929 
930 /**    ============================      RPC server    ============================   **/
931 
932 static beken_semaphore_t	server_ind_sema;
933 
934 static void rpc_svr_task( void *para );
935 
rpc_server_cmd_handler(ipc_chnl_cb_t * chnl_cb,mb_chnl_ack_t * ack_buf)936 static u32 rpc_server_cmd_handler(ipc_chnl_cb_t *chnl_cb, mb_chnl_ack_t *ack_buf)
937 {
938 	/* must NOT change ack_buf->hdr. */
939 
940 	u32		result = ACK_STATE_FAIL;
941 
942 	switch(chnl_cb->rx_cmd)
943 	{
944 		case IPC_CALL_CMD:
945 			result = ACK_STATE_PENDING;
946 
947 			/* informs server task to process the call. */
948 			rtos_set_semaphore(&server_ind_sema);
949 
950 			break;
951 
952 		default:
953 			return ipc_server_cmd_handler(chnl_cb, ack_buf);
954 			break;
955 	}
956 
957 	return result;
958 }
959 
rpc_server_init(void)960 bk_err_t rpc_server_init(void)
961 {
962 	bk_err_t		ret_code;
963 	beken_thread_t	thread_handle = NULL;
964 
965 	ret_code = rtos_init_semaphore(&server_ind_sema, 1);
966 	if(ret_code != BK_OK)
967 	{
968 		return ret_code;
969 	}
970 
971 	ret_code = ipc_chnl_init(0, &rpc_chnl_cb, MB_CHNL_RPC, (ipc_rx_cmd_hdlr_t)rpc_server_cmd_handler);
972 
973 	if(ret_code != BK_OK)
974 	{
975 		rtos_deinit_semaphore(&server_ind_sema);
976 
977 		return ret_code;
978 	}
979 
980 	ret_code = rtos_create_thread(&thread_handle,
981 							 BEKEN_DEFAULT_WORKER_PRIORITY, //BK_SYS_TASK_PRIO_7,
982 							 "rpc_svr",
983 							 (beken_thread_function_t)rpc_svr_task,
984 							 4096,
985 							 0);
986 
987 	return BK_OK;
988 }
989 
rpc_server_listen_cmd(u32 timeout_ms)990 int rpc_server_listen_cmd(u32 timeout_ms)
991 {
992 	bk_err_t	ret_val;
993 
994 	ret_val = rtos_get_semaphore(&server_ind_sema, timeout_ms);
995 
996 	if(ret_val == BK_OK)
997 		return 1;
998 	else
999 		return 0;
1000 }
1001 
1002 typedef int (*rpc_svr_handler_t)(rpc_call_def_t * call_buf);
1003 
1004 typedef struct
1005 {
1006 	u8		rpc_mod_id;
1007 	rpc_svr_handler_t	svr_handler;
1008 } rpc_svr_dispatcher_t;
1009 
1010 typedef struct
1011 {
1012 	rpc_call_hdr_t	call_hdr;
1013 	bk_err_t		ret_val;		/* return fail code. */ /* struct of api_ret_data_t */
1014 } rpc_ret_fail_t;
1015 
1016 extern int bk_gpio_api_svr(rpc_call_def_t * call_buf);
1017 extern int bk_dma_api_svr(rpc_call_def_t * call_buf);
1018 
1019 static rpc_svr_dispatcher_t    svr_dispatcher[] =
1020 {
1021 	{RPC_MOD_GPIO,     bk_gpio_api_svr   },
1022 	{RPC_MOD_DMA,      bk_dma_api_svr    },
1023 };
1024 
rpc_server_handle_cmd(void)1025 void rpc_server_handle_cmd(void)
1026 {
1027 	int		rpc_handled = 0;
1028 	int		i;
1029 
1030 	if(rpc_chnl_cb.rx_cmd_in_process == 0)  /* no rpc call cmd to handle. */
1031 		return;
1032 
1033 	rpc_call_def_t *rpc_call = (rpc_call_def_t *)rpc_chnl_cb.cmd_buf;
1034 
1035 	for(i = 0; i < ARRAY_SIZE(svr_dispatcher); i++)
1036 	{
1037 		if(rpc_call->call_hdr.mod_id == svr_dispatcher[i].rpc_mod_id)
1038 		{
1039 			rpc_handled = svr_dispatcher[i].svr_handler(rpc_call);
1040 		}
1041 	}
1042 
1043 	if(rpc_handled == 0)  /* rpc api not handled. */
1044 	{
1045 		rpc_ret_fail_t	rsp_buf;
1046 
1047 		rsp_buf.call_hdr.call_id = rpc_call->call_hdr.call_id;
1048 		rsp_buf.call_hdr.data_len = sizeof(rsp_buf) - sizeof(rsp_buf.call_hdr);
1049 		rsp_buf.ret_val = BK_ERR_NOT_SUPPORT;
1050 
1051 		rpc_server_rsp((rpc_ret_def_t *)&rsp_buf, sizeof(rsp_buf)); // return fail info.
1052 	}
1053 
1054 	return;
1055 }
1056 
rpc_server_rsp(rpc_ret_def_t * rsp_param,u16 param_len)1057 bk_err_t rpc_server_rsp(rpc_ret_def_t *rsp_param, u16 param_len)
1058 {
1059 	if(!rpc_chnl_cb.chnl_inited)
1060 		return BK_FAIL;
1061 
1062 	if(rpc_chnl_cb.rx_cmd_in_process == 0)
1063 		return BK_FAIL;
1064 
1065 	bk_err_t	ret_val;
1066 
1067 	ret_val = ipc_send_cmd(&rpc_chnl_cb, IPC_CALL_CMD | IPC_RSP_CMD_FLAG, (u8 *)rsp_param, param_len, NULL, 0);
1068 
1069 	rpc_chnl_cb.rx_cmd_in_process  = 0;
1070 
1071 	return ret_val;
1072 
1073 }
1074 
rpc_svr_task(void * para)1075 static void rpc_svr_task( void *para )
1076 {
1077 	// rpc_server_init
1078 
1079 	while(1)
1080 	{
1081 		rpc_server_listen_cmd(BEKEN_WAIT_FOREVER);
1082 		rpc_server_handle_cmd();
1083 	}
1084 }
1085 
1086 /**    ============================    RPC server end  ============================   **/
1087 
1088 #endif
1089 
1090