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