xref: /rk3399_ARM-atf/plat/imx/common/sci/ipc.c (revision c948f77136c42a92d0bb660543a3600c36dcf7f1)
1 /*
2  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdlib.h>
8 
9 #include <lib/bakery_lock.h>
10 
11 #include <sci/sci_scfw.h>
12 #include <sci/sci_ipc.h>
13 #include <sci/sci_rpc.h>
14 #include "imx8_mu.h"
15 
16 DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock);
17 #define sc_ipc_lock_init()	bakery_lock_init(&sc_ipc_bakery_lock)
18 #define sc_ipc_lock()		bakery_lock_get(&sc_ipc_bakery_lock)
19 #define sc_ipc_unlock()		bakery_lock_release(&sc_ipc_bakery_lock)
20 
21 void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp)
22 {
23 	sc_ipc_lock();
24 
25 	sc_ipc_write(ipc, msg);
26 	if (!no_resp)
27 		sc_ipc_read(ipc, msg);
28 
29 	sc_ipc_unlock();
30 }
31 
32 sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id)
33 {
34 	uint32_t base = id;
35 	uint32_t i;
36 
37 	/* Get MU base associated with IPC channel */
38 	if ((ipc == NULL) || (base == 0))
39 		return SC_ERR_IPC;
40 
41 	sc_ipc_lock_init();
42 
43 	/* Init MU */
44 	MU_Init(base);
45 
46 	/* Enable all RX interrupts */
47 	for (i = 0; i < MU_RR_COUNT; i++) {
48 		MU_EnableRxFullInt(base, i);
49 	}
50 
51 	/* Return MU address as handle */
52 	*ipc = (sc_ipc_t) id;
53 
54 	return SC_ERR_NONE;
55 }
56 
57 void sc_ipc_close(sc_ipc_t ipc)
58 {
59 	uint32_t base = ipc;
60 
61 	if (base != 0)
62 		MU_Init(base);
63 }
64 
65 void sc_ipc_read(sc_ipc_t ipc, void *data)
66 {
67 	uint32_t base = ipc;
68 	sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
69 	uint8_t count = 0;
70 
71 	/* Check parms */
72 	if ((base == 0) || (msg == NULL))
73 		return;
74 
75 	/* Read first word */
76 	MU_ReceiveMsg(base, 0, (uint32_t *) msg);
77 	count++;
78 
79 	/* Check size */
80 	if (msg->size > SC_RPC_MAX_MSG) {
81 		*((uint32_t *) msg) = 0;
82 		return;
83 	}
84 
85 	/* Read remaining words */
86 	while (count < msg->size) {
87 		MU_ReceiveMsg(base, count % MU_RR_COUNT,
88 			&(msg->DATA.u32[count - 1]));
89 		count++;
90 	}
91 }
92 
93 void sc_ipc_write(sc_ipc_t ipc, void *data)
94 {
95 	sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
96 	uint32_t base = ipc;
97 	uint8_t count = 0;
98 
99 	/* Check parms */
100 	if ((base == 0) || (msg == NULL))
101 		return;
102 
103 	/* Check size */
104 	if (msg->size > SC_RPC_MAX_MSG)
105 		return;
106 
107 	/* Write first word */
108 	MU_SendMessage(base, 0, *((uint32_t *) msg));
109 	count++;
110 
111 	/* Write remaining words */
112 	while (count < msg->size) {
113 		MU_SendMessage(base, count % MU_TR_COUNT,
114 			msg->DATA.u32[count - 1]);
115 		count++;
116 	}
117 }
118 
119