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