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