1 /*
2 * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
3 * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /* -------------------------------------- Includes ----------------------------------- */
9 #include <limits.h>
10 #include <string.h>
11
12 #include "cmsis_compiler.h"
13
14 #include "cy_ipc_drv.h"
15 #include "cy_sysint.h"
16
17 #include "ns_ipc_config.h"
18 #include "os_wrapper/thread.h"
19 #include "tfm_ns_mailbox.h"
20 #include "platform_multicore.h"
21
22 static uint8_t saved_irq_state = 1;
23
24 /* -------------------------------------- HAL API ------------------------------------ */
25
mailbox_ipc_init(void)26 static void mailbox_ipc_init(void)
27 {
28 Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT),
29 0, IPC_RX_INT_MASK);
30 }
31
mailbox_ipc_config(void)32 static void mailbox_ipc_config(void)
33 {
34 NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY);
35
36 NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn);
37 }
38
tfm_ns_mailbox_hal_notify_peer(void)39 int32_t tfm_ns_mailbox_hal_notify_peer(void)
40 {
41 cy_en_ipcdrv_status_t status;
42
43 status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN),
44 IPC_TX_NOTIFY_MASK,
45 PSA_CLIENT_CALL_REQ_MAGIC);
46
47 if (status == CY_IPC_DRV_SUCCESS) {
48 return MAILBOX_SUCCESS;
49 } else {
50 return MAILBOX_CHAN_BUSY;
51 }
52 }
53
tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t * queue)54 int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue)
55 {
56 uint32_t stage;
57
58 if (!queue) {
59 return MAILBOX_INVAL_PARAMS;
60 }
61
62 /*
63 * FIXME
64 * Further verification of mailbox queue address may be required according
65 * to diverse NSPE implementations.
66 */
67
68 mailbox_ipc_init();
69
70 /*
71 * Wait until SPE mailbox library is ready to receive NSPE mailbox queue
72 * address.
73 */
74 while (1) {
75 platform_mailbox_wait_for_notify();
76
77 platform_mailbox_fetch_msg_data(&stage);
78 if (stage == NS_MAILBOX_INIT_ENABLE) {
79 break;
80 }
81 }
82
83 /* Send out the address */
84 platform_mailbox_send_msg_ptr(queue);
85
86 /* Wait until SPE mailbox service is ready */
87 while (1) {
88 platform_mailbox_wait_for_notify();
89
90 platform_mailbox_fetch_msg_data(&stage);
91 if (stage == S_MAILBOX_READY) {
92 break;
93 }
94 }
95
96 mailbox_ipc_config();
97
98 return MAILBOX_SUCCESS;
99 }
100
tfm_ns_mailbox_hal_enter_critical(void)101 void tfm_ns_mailbox_hal_enter_critical(void)
102 {
103 saved_irq_state = Cy_SysLib_EnterCriticalSection();
104
105 IPC_STRUCT_Type* ipc_struct =
106 Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN);
107 while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct))
108 {
109 }
110 }
111
tfm_ns_mailbox_hal_exit_critical(void)112 void tfm_ns_mailbox_hal_exit_critical(void)
113 {
114 IPC_STRUCT_Type* ipc_struct =
115 Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN);
116 Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION);
117 Cy_SysLib_ExitCriticalSection(saved_irq_state);
118 }
119
tfm_ns_mailbox_hal_enter_critical_isr(void)120 void tfm_ns_mailbox_hal_enter_critical_isr(void)
121 {
122 IPC_STRUCT_Type* ipc_struct =
123 Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN);
124 while(CY_IPC_DRV_SUCCESS != Cy_IPC_Drv_LockAcquire (ipc_struct))
125 {
126 }
127 }
128
tfm_ns_mailbox_hal_exit_critical_isr(void)129 void tfm_ns_mailbox_hal_exit_critical_isr(void)
130 {
131 IPC_STRUCT_Type* ipc_struct =
132 Cy_IPC_Drv_GetIpcBaseAddress(IPC_PSA_MAILBOX_LOCK_CHAN);
133 Cy_IPC_Drv_LockRelease(ipc_struct, CY_IPC_NO_NOTIFICATION);
134 }
135
mailbox_clear_intr(void)136 static bool mailbox_clear_intr(void)
137 {
138 uint32_t status;
139
140 status = Cy_IPC_Drv_GetInterruptStatusMasked(
141 Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT));
142 status >>= CY_IPC_NOTIFY_SHIFT;
143 if ((status & IPC_RX_INT_MASK) == 0) {
144 return false;
145 }
146
147 Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT),
148 0, IPC_RX_INT_MASK);
149 return true;
150 }
151
cpuss_interrupts_ipc_8_IRQHandler(void)152 void cpuss_interrupts_ipc_8_IRQHandler(void)
153 {
154 uint32_t magic;
155
156 if (!mailbox_clear_intr())
157 return;
158
159 platform_mailbox_fetch_msg_data(&magic);
160 if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) {
161 /* Handle all the pending replies */
162 tfm_ns_mailbox_wake_reply_owner_isr();
163 }
164 }
165