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