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