1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2017-2019 NXP
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "MIMX8QX2_cm4.h"
9 #include "main/ipc.h"
10 #include "main/rpc.h"
11 #ifdef FSL_RTOS_FREE_RTOS
12 #include "FreeRTOS.h"
13 #include "task.h"
14 #endif
15
16 /*******************************************************************************
17 * Definitions
18 ******************************************************************************/
19
20 /* Component ID definition, used by tools. */
21 #ifndef FSL_COMPONENT_ID
22 #define FSL_COMPONENT_ID "platform.drivers.scfwapi"
23 #endif
24
25 /*----------------------------------------------------------------------*/
26 /* RPC command/response */
27 /*----------------------------------------------------------------------*/
sc_call_rpc(sc_ipc_t ipc,sc_rpc_msg_t * msg,sc_bool_t no_resp)28 void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, sc_bool_t no_resp)
29 {
30 #ifdef FSL_RTOS_FREE_RTOS
31 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
32 {
33 /* Suspends the scheduler to make sure there's only one rpc call ongoing at a time. */
34 vTaskSuspendAll();
35 }
36 #endif
37 sc_ipc_write(ipc, msg);
38 if (!no_resp)
39 {
40 sc_ipc_read(ipc, msg);
41 }
42 #ifdef FSL_RTOS_FREE_RTOS
43 if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
44 {
45 (void)xTaskResumeAll();
46 }
47 #endif
48 }
49
50 /*--------------------------------------------------------------------------*/
51 /* Open an IPC channel */
52 /*--------------------------------------------------------------------------*/
sc_ipc_open(sc_ipc_t * ipc,sc_ipc_id_t id)53 sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id)
54 {
55 MU_Type *base = (MU_Type *)id;
56
57 /* get mu base associated with ipc channel */
58 if ((ipc == NULL) || (base == NULL))
59 {
60 return SC_ERR_IPC;
61 }
62
63 /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
64 base->CR &= ~(MU_CR_GIEn_MASK | MU_CR_RIEn_MASK | MU_CR_TIEn_MASK | MU_CR_GIRn_MASK | MU_CR_Fn_MASK);
65
66 /* Return MU address as handle */
67 *ipc = (sc_ipc_t)id;
68
69 return SC_ERR_NONE;
70 }
71
72 /*--------------------------------------------------------------------------*/
73 /* Close an IPC channel */
74 /*--------------------------------------------------------------------------*/
sc_ipc_close(sc_ipc_t ipc)75 void sc_ipc_close(sc_ipc_t ipc)
76 {
77 }
78
79 /*--------------------------------------------------------------------------*/
80 /* Read message from an IPC channel */
81 /*--------------------------------------------------------------------------*/
sc_ipc_read(sc_ipc_t ipc,void * data)82 void sc_ipc_read(sc_ipc_t ipc, void *data)
83 {
84 MU_Type *base = (MU_Type *)ipc;
85 sc_rpc_msg_t *msg = (sc_rpc_msg_t *)data;
86 uint8_t count = 0;
87
88 /* Check parms */
89 if ((base == NULL) || (msg == NULL))
90 {
91 return;
92 }
93
94 /* Read first word */
95 /* Wait RX register to be full. */
96 while ((base->SR & (1UL << (MU_SR_RFn_SHIFT + 3U))) == 0U)
97 {
98 }
99 msg->header = base->RR[0];
100 count++;
101
102 /* Check size */
103 if (msg->size > SC_RPC_MAX_MSG)
104 {
105 msg->header = 0;
106 return;
107 }
108
109 /* Read remaining words */
110 while (count < msg->size)
111 {
112 /* Wait RX register to be full. */
113 while ((base->SR & (1UL << (MU_SR_RFn_SHIFT + 3U - count % MU_RR_COUNT))) == 0U)
114 {
115 }
116 msg->DATA.u32[count - 1U] = base->RR[count % MU_RR_COUNT];
117 count++;
118 }
119 }
120
121 /*--------------------------------------------------------------------------*/
122 /* Write a message to an IPC channel */
123 /*--------------------------------------------------------------------------*/
sc_ipc_write(sc_ipc_t ipc,const void * data)124 void sc_ipc_write(sc_ipc_t ipc, const void *data)
125 {
126 MU_Type *base = (MU_Type *)ipc;
127 const sc_rpc_msg_t *msg = (const sc_rpc_msg_t *)data;
128 uint8_t count = 0;
129
130 /* Check parms */
131 if ((base == NULL) || (msg == NULL))
132 {
133 return;
134 }
135
136 /* Check size */
137 if (msg->size > SC_RPC_MAX_MSG)
138 {
139 return;
140 }
141
142 /* Write first word */
143 while ((base->SR & (1UL << (MU_SR_TEn_SHIFT + 3U))) == 0U)
144 {
145 }
146 base->TR[0] = msg->header;
147 count++;
148
149 /* Write remaining words */
150 while (count < msg->size)
151 {
152 /* Wait Tx register to be empty and send Tx Data. */
153 while ((base->SR & (1UL << (MU_SR_TEn_SHIFT + 3U - count % MU_TR_COUNT))) == 0U)
154 {
155 }
156 base->TR[count % MU_TR_COUNT] = msg->DATA.u32[count - 1U];
157 count++;
158 }
159 }
160