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