1 /*
2  *  SPDX-License-Identifier: BSD-3-Clause
3  *  SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4  *
5  */
6 
7 /* FIXME: This shouldn't be required when TFM_PLAT_SPECIFIC_MULTI_CORE_COMM is
8  * enabled.
9  */
10 
11 #include "tfm_ns_mailbox.h"
12 #include "platform_multicore.h"
13 #include "region.h"
14 
15 #include "pico/multicore.h"
16 #include "hardware/irq.h"
17 #include "hardware/structs/scb.h"
18 #include "hardware/structs/sio.h"
19 
20 #include "tfm_hal_device_header.h"
21 #include "uart_stdout.h"
22 #include "Driver_Common.h"
23 
tfm_ns_platform_init(void)24 int32_t tfm_ns_platform_init(void)
25 {
26     if(sio_hw->cpuid == 0) {
27         __enable_irq();
28     } else {
29         /* Core1 */
30         __enable_irq();
31         stdio_init();
32     }
33 
34     return ARM_DRIVER_OK;
35 }
36 
37 /* Platform specific inter-processor communication interrupt handler. */
SIO_IRQ_FIFO_NS_IRQHandler(void)38 void SIO_IRQ_FIFO_NS_IRQHandler(void)
39 {
40     uint32_t msg;
41     if(multicore_fifo_rvalid())
42     {
43         msg = multicore_fifo_pop_blocking();
44         if (msg == NOTIFY_FROM_CORE0) {
45             /* Handle all the pending replies */
46             tfm_ns_mailbox_wake_reply_owner_isr();
47         }
48     }
49 }
50 
tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t * queue)51 int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue)
52 {
53     uint32_t stage;
54 
55     if(sio_hw->cpuid == 0) {
56         return MAILBOX_SUCCESS;
57     }
58 
59     if (!queue) {
60         return MAILBOX_INVAL_PARAMS;
61     }
62 
63     NVIC_SetVector(SIO_IRQ_FIFO_NS_IRQn, (uint32_t) SIO_IRQ_FIFO_NS_IRQHandler);
64 
65     /*
66      * Wait until SPE mailbox library is ready to receive NSPE mailbox queue
67      * address.
68      */
69     while (1) {
70         stage = multicore_fifo_pop_blocking();
71         if  (stage == NS_MAILBOX_INIT) {
72             break;
73         }
74     }
75 
76     /* Send out the address */
77     struct mailbox_init_t ns_init;
78     ns_init.status = &queue->status;
79     ns_init.slot_count = NUM_MAILBOX_QUEUE_SLOT;
80     ns_init.slots = &queue->slots[0];
81     multicore_fifo_push_blocking((uint32_t) &ns_init);
82 
83     /* Wait until SPE mailbox service is ready */
84     while (1) {
85         stage = multicore_fifo_pop_blocking();
86         if  (stage == S_MAILBOX_READY) {
87             break;
88         }
89     }
90 
91     NVIC_EnableIRQ(SIO_IRQ_FIFO_NS_IRQn);
92 
93     return MAILBOX_SUCCESS;
94 }
95 
tfm_ns_mailbox_hal_notify_peer(void)96 int32_t tfm_ns_mailbox_hal_notify_peer(void)
97 {
98     multicore_fifo_push_blocking(NOTIFY_FROM_CORE1);
99     return 0;
100 }
101 
tfm_ns_mailbox_hal_enter_critical(void)102 void tfm_ns_mailbox_hal_enter_critical(void)
103 {
104     /* Reading a spinlock register attempts to claim it, returning nonzero
105      * if the claim was successful and 0 if unsuccessful */
106     while(!*MAILBOX_SPINLOCK);
107     return;
108 }
109 
tfm_ns_mailbox_hal_exit_critical(void)110 void tfm_ns_mailbox_hal_exit_critical(void)
111 {
112     /* Writing to a spinlock register releases it */
113     *MAILBOX_SPINLOCK = 0x1u;
114     return;
115 }
116 
tfm_ns_mailbox_hal_enter_critical_isr(void)117 void tfm_ns_mailbox_hal_enter_critical_isr(void)
118 {
119     /* Reading a spinlock register attempts to claim it, returning nonzero
120      * if the claim was successful and 0 if unsuccessful */
121     while(!*MAILBOX_SPINLOCK);
122     return;
123 }
124 
tfm_ns_mailbox_hal_exit_critical_isr(void)125 void tfm_ns_mailbox_hal_exit_critical_isr(void)
126 {
127     /* Writing to a spinlock register releases it */
128     *MAILBOX_SPINLOCK = 0x1u;
129     return;
130 }
131 
132 extern void runtime_init(void);
133 extern int main(void);
134 extern uint32_t __StackOneTop;
135 extern uint32_t __Vectors_Start__;
136 
core1_ns_entry(void)137 void __attribute__((section(".core1_ns_entry"), used, naked)) core1_ns_entry(void)
138 {
139     scb_hw->vtor = (uintptr_t) &__Vectors_Start__;
140     __set_MSP((uint32_t)(&__StackOneTop));
141     __set_PSP((uint32_t)(&__StackOneTop));
142     runtime_init();
143     main();
144 }
145 
146 #include "stdio.h"
tfm_platform_ns_wait_for_s_cpu_ready(void)147 int32_t tfm_platform_ns_wait_for_s_cpu_ready(void)
148 {
149     if(sio_hw->cpuid == 1) {
150         /* Core1 */
151         multicore_fifo_push_blocking(CORE1_NS_READY);
152     }
153     return 0;
154 }
155