1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /***********************************************************************************************************************
8 * Includes
9 **********************************************************************************************************************/
10 #include "r_mhu_ns.h"
11
12 /***********************************************************************************************************************
13 * Macro definitions
14 **********************************************************************************************************************/
15
16 /** "MHU" in ASCII, used to determine if channel is open. */
17 #define MHU_NS_OPEN (0x00774855ULL)
18
19 #define MHU_NS_SHMEM_CH_SIZE (0x8)
20 #define MHU_NS_RSP_TXD_OFFSET (0x0)
21 #define MHU_NS_MSG_TXD_OFFSET (0x4)
22
23 /**********************************************************************************************************************
24 * Typedef definitions
25 **********************************************************************************************************************/
26 #if defined(__ARMCC_VERSION) || defined(__ICCARM__)
27 typedef void (BSP_CMSE_NONSECURE_CALL * mhu_ns_prv_ns_callback)(mhu_callback_args_t * p_args);
28 #elif defined(__GNUC__)
29 typedef BSP_CMSE_NONSECURE_CALL void (*volatile mhu_ns_prv_ns_callback)(mhu_callback_args_t * p_args);
30 #endif
31
32 /***********************************************************************************************************************
33 * Private function prototypes
34 **********************************************************************************************************************/
35 static void r_mhu_ns_set_send_data(mhu_ns_instance_ctrl_t * p_instance_ctrl, uint32_t msg);
36
37 static fsp_err_t r_mhu_ns_common_preamble(mhu_ns_instance_ctrl_t * p_instance_ctrl);
38
39 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
40 static fsp_err_t r_mhu_ns_open_param_checking(mhu_ns_instance_ctrl_t * p_instance_ctrl, mhu_cfg_t const * const p_cfg);
41
42 #endif
43
44 /* ISRs. */
45 void mhu_ns_int_isr(void);
46 void metal_irq_isr_wrapper(void);
47 void metal_irq_isr(uint32_t vector);
48
49 /***********************************************************************************************************************
50 * Private global variables
51 **********************************************************************************************************************/
52
53 /** Version data structure. */
54
55 extern uint32_t __mhu_shmem_start;
56
57 static const uint32_t g_shmem_base = (uint32_t) &__mhu_shmem_start;
58
59 /***********************************************************************************************************************
60 * Global Variables
61 **********************************************************************************************************************/
62
63 /** MHU_NS Implementation of MHU Driver */
64 const mhu_api_t g_mhu_ns_on_mhu_ns =
65 {
66 .open = R_MHU_NS_Open,
67 .msgSend = R_MHU_NS_MsgSend,
68 .callbackSet = R_MHU_NS_CallbackSet,
69 .close = R_MHU_NS_Close,
70 };
71
72 /*******************************************************************************************************************//**
73 * @addtogroup MHU_NS
74 * @{
75 **********************************************************************************************************************/
76
77 /***********************************************************************************************************************
78 * Functions
79 **********************************************************************************************************************/
80
81 /*******************************************************************************************************************//**
82 * Initializes the MHU_NS module instance. Implements @ref mhu_api_t::open.
83 *
84 * @retval FSP_SUCCESS Initialization was successful.
85 * @retval FSP_ERR_ASSERTION A required input pointer is NULL.
86 * @retval FSP_ERR_ALREADY_OPEN R_MHU_NS_Open has already been called for this p_ctrl.
87 * @retval FSP_ERR_INVALID_ARGUMENT The specified IRQ number is invalid.
88 * @retval FSP_ERR_INVALID_CHANNEL Requested channel number is not available on MHU_NS.
89 **********************************************************************************************************************/
R_MHU_NS_Open(mhu_ctrl_t * const p_ctrl,mhu_cfg_t const * const p_cfg)90 fsp_err_t R_MHU_NS_Open (mhu_ctrl_t * const p_ctrl, mhu_cfg_t const * const p_cfg)
91 {
92 mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl;
93
94 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
95 fsp_err_t err = r_mhu_ns_open_param_checking(p_instance_ctrl, p_cfg);
96 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
97 #endif
98
99 p_instance_ctrl->p_regs = (R_MHU0_Type *) (R_MHU_NS0_BASE +
100 (p_cfg->channel *
101 ((intptr_t) R_MHU_NS1_BASE - (intptr_t) R_MHU_NS0_BASE)));
102 p_instance_ctrl->p_cfg = p_cfg;
103 p_instance_ctrl->channel = p_cfg->channel;
104
105 p_instance_ctrl->send_type =
106 ((1U << p_cfg->channel) &
107 BSP_FEATURE_MHU_NS_SEND_TYPE_RSP_VALID_CHANNEL_MASK) ? MHU_SEND_TYPE_RSP : MHU_SEND_TYPE_MSG;
108
109 if (0 != p_cfg->p_shared_memory)
110 {
111 /* Use specified address */
112 if (p_instance_ctrl->send_type == MHU_SEND_TYPE_RSP)
113 {
114 p_instance_ctrl->p_shared_memory_tx = (uint32_t *) (((uint32_t) p_cfg->p_shared_memory) +
115 MHU_NS_RSP_TXD_OFFSET);
116 p_instance_ctrl->p_shared_memory_rx = (uint32_t *) (((uint32_t) p_cfg->p_shared_memory) +
117 MHU_NS_MSG_TXD_OFFSET);
118 }
119 else
120 {
121 p_instance_ctrl->p_shared_memory_tx = (uint32_t *) (((uint32_t) p_cfg->p_shared_memory) +
122 MHU_NS_MSG_TXD_OFFSET);
123 p_instance_ctrl->p_shared_memory_rx = (uint32_t *) (((uint32_t) p_cfg->p_shared_memory) +
124 MHU_NS_RSP_TXD_OFFSET);
125 }
126 }
127 else
128 {
129 /* Use default location */
130 if (p_instance_ctrl->send_type == MHU_SEND_TYPE_RSP)
131 {
132 p_instance_ctrl->p_shared_memory_tx =
133 (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) +
134 MHU_NS_RSP_TXD_OFFSET);
135 p_instance_ctrl->p_shared_memory_rx =
136 (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) +
137 MHU_NS_MSG_TXD_OFFSET);
138 }
139 else
140 {
141 p_instance_ctrl->p_shared_memory_tx =
142 (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) +
143 MHU_NS_MSG_TXD_OFFSET);
144 p_instance_ctrl->p_shared_memory_rx =
145 (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) +
146 MHU_NS_RSP_TXD_OFFSET);
147 }
148 }
149
150 /* Power on the MHU_NS channel. */
151 R_BSP_MODULE_START(FSP_IP_MHU, p_cfg->channel);
152
153 R_BSP_IrqCfgEnable(p_cfg->rx_irq, p_cfg->rx_ipl, p_instance_ctrl);
154
155 /* Set callback and context pointers */
156
157 #if BSP_TZ_SECURE_BUILD
158
159 /* If this is a secure build, the callback provided in p_cfg must be secure. */
160 p_instance_ctrl->callback_is_secure = true;
161 #endif
162 p_instance_ctrl->p_callback = p_cfg->p_callback;
163 p_instance_ctrl->p_context = p_cfg->p_context;
164 p_instance_ctrl->p_callback_memory = NULL;
165
166 p_instance_ctrl->open = MHU_NS_OPEN;
167
168 /* All done. */
169 return FSP_SUCCESS;
170 }
171
172 /**********************************************************************************************************************
173 * End of function R_MHU_NS_Open
174 *********************************************************************************************************************/
175
176 /*******************************************************************************************************************//**
177 * Send message via MHU.
178 * Implements @ref mhu_api_t::msgSend.
179 *
180 * @retval FSP_SUCCESS Send message successfully.
181 * @retval FSP_ERR_ASSERTION A required pointer was NULL.
182 * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened.
183 **********************************************************************************************************************/
R_MHU_NS_MsgSend(mhu_ctrl_t * const p_ctrl,uint32_t const msg)184 fsp_err_t R_MHU_NS_MsgSend (mhu_ctrl_t * const p_ctrl, uint32_t const msg)
185 {
186 mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl;
187 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
188 #endif
189
190 fsp_err_t err = r_mhu_ns_common_preamble(p_instance_ctrl);
191 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
192
193 /* Set msg. */
194 r_mhu_ns_set_send_data(p_instance_ctrl, msg);
195
196 return FSP_SUCCESS;
197 }
198
199 /**********************************************************************************************************************
200 * End of function R_MHU_NS_MsgSend
201 *********************************************************************************************************************/
202
203 /*******************************************************************************************************************//**
204 * Updates the user callback with the option to provide memory for the callback argument structure.
205 * Implements @ref mhu_api_t::callbackSet.
206 *
207 * @retval FSP_SUCCESS Callback updated successfully.
208 * @retval FSP_ERR_ASSERTION A required pointer is NULL.
209 * @retval FSP_ERR_NOT_OPEN The control block has not been opened.
210 * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL.
211 **********************************************************************************************************************/
R_MHU_NS_CallbackSet(mhu_ctrl_t * const p_api_ctrl,void (* p_callback)(mhu_callback_args_t *),void const * const p_context,mhu_callback_args_t * const p_callback_memory)212 fsp_err_t R_MHU_NS_CallbackSet (mhu_ctrl_t * const p_api_ctrl,
213 void ( * p_callback)(mhu_callback_args_t *),
214 void const * const p_context,
215 mhu_callback_args_t * const p_callback_memory)
216 {
217 mhu_ns_instance_ctrl_t * p_ctrl = (mhu_ns_instance_ctrl_t *) p_api_ctrl;
218
219 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
220 FSP_ASSERT(p_ctrl);
221 FSP_ASSERT(p_callback);
222 FSP_ERROR_RETURN(MHU_NS_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN);
223 #endif
224
225 #if BSP_TZ_SECURE_BUILD
226
227 /* Get security state of p_callback */
228 p_ctrl->callback_is_secure =
229 (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
230
231 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
232
233 /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */
234 mhu_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory,
235 CMSE_AU_NONSECURE);
236 FSP_ERROR_RETURN(p_ctrl->callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY);
237 #endif
238 #endif
239
240 /* Store callback and context */
241
242 #if BSP_TZ_SECURE_BUILD
243
244 /* cmse_check_address_range returns NULL if p_callback is located in secure memory */
245 p_ctrl->callback_is_secure =
246 (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE));
247 #endif
248 p_ctrl->p_callback = p_callback;
249 p_ctrl->p_context = p_context;
250 p_ctrl->p_callback_memory = p_callback_memory;
251
252 return FSP_SUCCESS;
253 }
254
255 /**********************************************************************************************************************
256 * End of function R_MHU_NS_CallbackSet
257 *********************************************************************************************************************/
258
259 /*******************************************************************************************************************//**
260 * Disables interrupts, clears internal driver data.
261 * @ref mhu_api_t::close.
262 *
263 * @retval FSP_SUCCESS MHU_NS closed.
264 * @retval FSP_ERR_ASSERTION p_ctrl is NULL.
265 * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened.
266 **********************************************************************************************************************/
R_MHU_NS_Close(mhu_ctrl_t * const p_ctrl)267 fsp_err_t R_MHU_NS_Close (mhu_ctrl_t * const p_ctrl)
268 {
269 mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl;
270
271 fsp_err_t err = r_mhu_ns_common_preamble(p_instance_ctrl);
272 FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
273
274 /* Cleanup the device: disable interrupts */
275
276 NVIC_DisableIRQ(p_instance_ctrl->p_cfg->rx_irq);
277 R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->rx_irq, p_instance_ctrl);
278
279 p_instance_ctrl->open = 0U;
280
281 return FSP_SUCCESS;
282 }
283
284 /**********************************************************************************************************************
285 * End of function R_MHU_NS_Close
286 *********************************************************************************************************************/
287
288 /** @} (end addtogroup MHU_NS) */
289
290 /***********************************************************************************************************************
291 * Private Functions
292 **********************************************************************************************************************/
293
294 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
295
296 /*******************************************************************************************************************//**
297 * Parameter checking for R_MHU_NS_Open.
298 *
299 * @param[in] p_instance_ctrl Pointer to instance control structure.
300 * @param[in] p_cfg Configuration structure for this instance
301 *
302 * @retval FSP_SUCCESS Initialization was successful.
303 * @retval FSP_ERR_ASSERTION A required input pointer is NULL.
304 * @retval FSP_ERR_ALREADY_OPEN R_MHU_NS_Open has already been called for this p_ctrl.
305 * @retval FSP_ERR_INVALID_ARGUMENT The specified IRQ number is invalid.
306 * @retval FSP_ERR_INVALID_CHANNEL Requested channel number is not available on MHU_NS.
307 **********************************************************************************************************************/
r_mhu_ns_open_param_checking(mhu_ns_instance_ctrl_t * p_instance_ctrl,mhu_cfg_t const * const p_cfg)308 static fsp_err_t r_mhu_ns_open_param_checking (mhu_ns_instance_ctrl_t * p_instance_ctrl, mhu_cfg_t const * const p_cfg)
309 {
310 FSP_ASSERT(NULL != p_instance_ctrl);
311 FSP_ASSERT(NULL != p_cfg);
312 FSP_ERROR_RETURN(MHU_NS_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
313
314 /* Validate channel number. */
315 FSP_ERROR_RETURN(((1U << p_cfg->channel) & BSP_FEATURE_MHU_NS_VALID_CHANNEL_MASK), FSP_ERR_INVALID_CHANNEL);
316
317 FSP_ERROR_RETURN(FSP_INVALID_VECTOR != p_cfg->rx_irq, FSP_ERR_INVALID_ARGUMENT);
318
319 return FSP_SUCCESS;
320 }
321
322 #endif
323
324 /*******************************************************************************************************************//**
325 * Common code at the beginning of all MHU_NS functions except open.
326 *
327 * @param[in] p_instance_ctrl Pointer to instance control structure.
328 *
329 * @retval FSP_SUCCESS No invalid conditions detected, MHU_NS state matches expected state.
330 * @retval FSP_ERR_ASSERTION p_ctrl is null.
331 * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened.
332 **********************************************************************************************************************/
r_mhu_ns_common_preamble(mhu_ns_instance_ctrl_t * p_instance_ctrl)333 static fsp_err_t r_mhu_ns_common_preamble (mhu_ns_instance_ctrl_t * p_instance_ctrl)
334 {
335 #if MHU_NS_CFG_PARAM_CHECKING_ENABLE
336 FSP_ASSERT(NULL != p_instance_ctrl);
337 FSP_ERROR_RETURN(MHU_NS_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
338 #else
339 FSP_PARAMETER_NOT_USED(p_instance_ctrl);
340 #endif
341
342 return FSP_SUCCESS;
343 }
344
345 /**********************************************************************************************************************
346 * End of function r_mhu_ns_common_preamble
347 *********************************************************************************************************************/
348
349 /*******************************************************************************************************************//**
350 * Write a message to shared memory and generate inter-core interrupt
351 *
352 * @param[in] p_instance_ctrl Control block for this instance
353 * @param[in] msg 32bit send data
354 **********************************************************************************************************************/
r_mhu_ns_set_send_data(mhu_ns_instance_ctrl_t * p_instance_ctrl,uint32_t msg)355 static void r_mhu_ns_set_send_data (mhu_ns_instance_ctrl_t * p_instance_ctrl, uint32_t msg)
356 {
357 if (MHU_SEND_TYPE_MSG == p_instance_ctrl->send_type)
358 {
359 /* Check interrupt status: Has the previous message been received? */
360 do
361 {
362 /* Do Nothing */
363 } while (0 != p_instance_ctrl->p_regs->MSG_INT_STSn);
364
365 /* Store the message data. */
366 *p_instance_ctrl->p_shared_memory_tx = msg;
367
368 /* Assert interrupt. */
369 p_instance_ctrl->p_regs->MSG_INT_SETn = 1;
370 }
371 else
372 {
373 /* Check interrupt status: Has the previous message been received? */
374 do
375 {
376 /* Do Nothing */
377 } while (0 != p_instance_ctrl->p_regs->RSP_INT_STSn);
378
379 /* Store the message data. */
380 *p_instance_ctrl->p_shared_memory_tx = msg;
381
382 /* Assert interrupt. */
383 p_instance_ctrl->p_regs->RSP_INT_SETn = 1;
384 }
385 }
386
387 /**********************************************************************************************************************
388 * End of function r_mhu_ns_set_send_data
389 *********************************************************************************************************************/
390
391 /*********************************************************************************************************************
392 * MHU_NS receive interrupt (for OpenAMP)
393 **********************************************************************************************************************/
metal_irq_isr_wrapper(void)394 void metal_irq_isr_wrapper (void)
395 {
396 /* Save context if RTOS is used */
397 FSP_CONTEXT_SAVE
398
399 IRQn_Type irq = R_FSP_CurrentIrqGet();
400
401 metal_irq_isr(irq);
402
403 /* Restore context if RTOS is used */
404 FSP_CONTEXT_RESTORE
405 }
406
407 /**********************************************************************************************************************
408 * End of function metal_irq_isr_wrapper
409 *********************************************************************************************************************/
410
411 /*********************************************************************************************************************
412 * MHU_NS receive interrupt (for bere mhu_ns application).
413 **********************************************************************************************************************/
mhu_ns_int_isr(void)414 void mhu_ns_int_isr (void)
415 {
416 /* Save context if RTOS is used */
417 FSP_CONTEXT_SAVE
418
419 IRQn_Type irq = R_FSP_CurrentIrqGet();
420
421 R_MHU_NS_IsrSub(irq);
422
423 /* Restore context if RTOS is used */
424 FSP_CONTEXT_RESTORE
425 }
426
427 /**********************************************************************************************************************
428 * End of function mhu_ns_int_isr
429 *********************************************************************************************************************/
430
431 /*******************************************************************************************************************//**
432 * MHU_NS receive interrupt sub function (for OpenAMP)
433 *
434 * @param[in] irq irq number for inter-core interrupt
435 **********************************************************************************************************************/
R_MHU_NS_IsrSub(uint32_t irq)436 void R_MHU_NS_IsrSub (uint32_t irq)
437 {
438 uint32_t msg;
439
440 /* Clear pending IRQ to make sure it doesn't fire again after exiting */
441 R_BSP_IrqStatusClear(irq);
442
443 /* Recover ISR context saved in open. */
444 mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) R_FSP_IsrContextGet(irq);
445
446 /* Check interrupt reason */
447 if (
448 ((MHU_SEND_TYPE_RSP == p_instance_ctrl->send_type) && (0 != p_instance_ctrl->p_regs->MSG_INT_STSn)) ||
449 ((MHU_SEND_TYPE_MSG == p_instance_ctrl->send_type) && (0 != p_instance_ctrl->p_regs->RSP_INT_STSn)))
450 {
451 /* Read data */
452 msg = *p_instance_ctrl->p_shared_memory_rx;
453
454 /* Clear interrupt */
455 if (MHU_SEND_TYPE_RSP == p_instance_ctrl->send_type)
456 {
457 p_instance_ctrl->p_regs->MSG_INT_CLRn = 1;
458 }
459 else
460 {
461 p_instance_ctrl->p_regs->RSP_INT_CLRn = 1;
462 }
463
464 /* Invoke the callback function if it is set. */
465 if (NULL != p_instance_ctrl->p_callback)
466 {
467 /* Setup parameters for the user-supplied callback function. */
468 mhu_callback_args_t callback_args;
469
470 /* Store callback arguments in memory provided by user if available. This allows callback arguments to be
471 * stored in non-secure memory so they can be accessed by a non-secure callback function. */
472 mhu_callback_args_t * p_args = p_instance_ctrl->p_callback_memory;
473 if (NULL == p_args)
474 {
475 /* Store on stack */
476 p_args = &callback_args;
477 }
478 else
479 {
480 /* Save current arguments on the stack in case this is a nested interrupt. */
481 callback_args = *p_args;
482 }
483
484 p_args->p_context = p_instance_ctrl->p_context;
485
486 p_args->channel = p_instance_ctrl->channel;
487 p_args->msg = msg;
488
489 #if BSP_TZ_SECURE_BUILD
490
491 /* p_callback can point to a secure function or a non-secure function. */
492 if (p_instance_ctrl->callback_is_secure)
493 {
494 /* If p_callback is secure, then the project does not need to change security state. */
495 p_instance_ctrl->p_callback(p_args);
496 }
497 else
498 {
499 /* If p_callback is Non-secure, then the project must change to Non-secure state
500 * in order to call the callback. */
501 mhu_ns_prv_ns_callback p_callback = (mhu_ns_prv_ns_callback) (p_instance_ctrl->p_callback);
502 p_callback(p_args);
503 }
504
505 #else
506
507 /* If the project is not Trustzone Secure, then it will never need to change security state
508 * in order to call the callback. */
509 p_instance_ctrl->p_callback(p_args);
510 #endif
511
512 if (NULL != p_instance_ctrl->p_callback_memory)
513 {
514 /* Restore callback memory in case this is a nested interrupt. */
515 *p_instance_ctrl->p_callback_memory = callback_args;
516 }
517 }
518 }
519 }
520
521 /**********************************************************************************************************************
522 * End of function R_MHU_NS_IsrSub
523 *********************************************************************************************************************/
524