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