1 /*
2  * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
3  * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon
4  * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5  * reserved.
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 #include "internal_status_code.h"
12 #include "tfm_hal_device_header.h"
13 #include "device_definition.h"
14 #include "spm.h"
15 #include "tfm_hal_interrupt.h"
16 #include "tfm_peripherals_def.h"
17 #include "tfm_multi_core.h"
18 #include "interrupt.h"
19 #include "load/interrupt_defs.h"
20 #include "platform_irq.h"
21 #ifdef TFM_MULTI_CORE_TOPOLOGY
22 #include "rse_comms_hal.h"
23 #endif
24 
25 static struct irq_t timer0_irq = {0};
26 
TFM_TIMER0_IRQ_Handler(void)27 void TFM_TIMER0_IRQ_Handler(void)
28 {
29     spm_handle_interrupt(timer0_irq.p_pt, timer0_irq.p_ildi);
30 }
31 
tfm_timer0_irq_init(void * p_pt,const struct irq_load_info_t * p_ildi)32 enum tfm_hal_status_t tfm_timer0_irq_init(void *p_pt,
33                                           const struct irq_load_info_t *p_ildi)
34 {
35     timer0_irq.p_ildi = p_ildi;
36     timer0_irq.p_pt = p_pt;
37 
38     NVIC_SetPriority(TFM_TIMER0_IRQ, DEFAULT_IRQ_PRIORITY);
39     NVIC_ClearTargetState(TFM_TIMER0_IRQ);
40     NVIC_DisableIRQ(TFM_TIMER0_IRQ);
41 
42     return TFM_HAL_SUCCESS;
43 }
44 
45 #ifdef TFM_MULTI_CORE_TOPOLOGY
46 static struct irq_t mbox_irq_info[2] = {0};
47 
48 /* Platform specific inter-processor communication interrupt handler. */
CMU_MHU0_Receiver_Handler(void)49 void CMU_MHU0_Receiver_Handler(void)
50 {
51     (void)tfm_multi_core_hal_receive(&MHU_AP_MONITOR_TO_RSE_DEV,
52                                      &MHU_RSE_TO_AP_MONITOR_DEV,
53                                      mbox_irq_info[0].p_ildi->source);
54 
55     /*
56      * SPM will send a MAILBOX_INTERRUPT_SIGNAL to the corresponding partition
57      * indicating that a message has arrived and can be processed.
58      */
59     spm_handle_interrupt(mbox_irq_info[0].p_pt, mbox_irq_info[0].p_ildi);
60 }
61 
62 #ifdef MHU_AP_NS_TO_RSE
63 /* Platform specific inter-processor communication interrupt handler. */
CMU_MHU1_Receiver_Handler(void)64 void CMU_MHU1_Receiver_Handler(void)
65 {
66     (void)tfm_multi_core_hal_receive(&MHU_AP_NS_TO_RSE_DEV,
67                                      &MHU_RSE_TO_AP_NS_DEV,
68                                      mbox_irq_info[1].p_ildi->source);
69 
70     /*
71      * SPM will send a MAILBOX_INTERRUPT_SIGNAL to the corresponding partition
72      * indicating that a message has arrived and can be processed.
73      */
74     spm_handle_interrupt(mbox_irq_info[1].p_pt, mbox_irq_info[1].p_ildi);
75 }
76 #endif /* MHU_AP_NS_TO_RSE */
77 
mailbox_irq_init(void * p_pt,const struct irq_load_info_t * p_ildi)78 enum tfm_hal_status_t mailbox_irq_init(void *p_pt,
79                                        const struct irq_load_info_t *p_ildi)
80 {
81     mbox_irq_info[0].p_pt = p_pt;
82     mbox_irq_info[0].p_ildi = p_ildi;
83 
84     /* Set MHU interrupt priority to the same as PendSV (the lowest)
85      * TODO: Consider advantages/disadvantages of setting it one higher
86      */
87     NVIC_SetPriority(CMU_MHU0_Receiver_IRQn, NVIC_GetPriority(PendSV_IRQn));
88 
89     /* CMU_MHU0 is a secure peripheral, so its IRQs have to target S state */
90     NVIC_ClearTargetState(CMU_MHU0_Receiver_IRQn);
91     NVIC_DisableIRQ(CMU_MHU0_Receiver_IRQn);
92 
93     if (tfm_multi_core_register_client_id_range(&MHU_RSE_TO_AP_MONITOR_DEV,
94                                                 p_ildi->client_id_base,
95                                                 p_ildi->client_id_limit)
96         != SPM_SUCCESS) {
97         return TFM_HAL_ERROR_INVALID_INPUT;
98     }
99     return TFM_HAL_SUCCESS;
100 }
101 
102 #ifdef MHU_AP_NS_TO_RSE
mailbox_irq_1_init(void * p_pt,const struct irq_load_info_t * p_ildi)103 enum tfm_hal_status_t mailbox_irq_1_init(void *p_pt,
104                                          const struct irq_load_info_t *p_ildi)
105 {
106     mbox_irq_info[1].p_pt = p_pt;
107     mbox_irq_info[1].p_ildi = p_ildi;
108 
109     /* Set MHU interrupt priority to the same as PendSV (the lowest)
110      * TODO: Consider advantages/disadvantages of setting it one higher
111      */
112     NVIC_SetPriority(CMU_MHU1_Receiver_IRQn, NVIC_GetPriority(PendSV_IRQn));
113 
114     /* CMU_MHU1 is a secure peripheral, so its IRQs have to target S state */
115     NVIC_ClearTargetState(CMU_MHU1_Receiver_IRQn);
116     NVIC_DisableIRQ(CMU_MHU1_Receiver_IRQn);
117 
118     if (tfm_multi_core_register_client_id_range(&MHU_RSE_TO_AP_NS_DEV,
119                                                 p_ildi->client_id_base,
120                                                 p_ildi->client_id_limit)
121         != SPM_SUCCESS) {
122         return TFM_HAL_ERROR_INVALID_INPUT;
123     }
124     return TFM_HAL_SUCCESS;
125 }
126 #else /* MHU_AP_NS_TO_RSE */
mailbox_irq_1_init(void * p_pt,const struct irq_load_info_t * p_ildi)127 enum tfm_hal_status_t mailbox_irq_1_init(void *p_pt,
128                                          const struct irq_load_info_t *p_ildi)
129 {
130     (void)p_pt;
131     (void)p_ildi;
132 
133     return TFM_HAL_ERROR_NOT_SUPPORTED;
134 }
135 #endif /* MHU_AP_NS_TO_RSE */
136 #endif /* TFM_MULTI_CORE_TOPOLOGY */
137 
138 static struct irq_t dma0_ch0_irq = {0};
139 
DMA_Combined_S_Handler(void)140 void DMA_Combined_S_Handler(void)
141 {
142     spm_handle_interrupt(dma0_ch0_irq.p_pt, dma0_ch0_irq.p_ildi);
143 }
144 
tfm_dma0_combined_s_irq_init(void * p_pt,struct irq_load_info_t * p_ildi)145 enum tfm_hal_status_t tfm_dma0_combined_s_irq_init(void *p_pt,
146                                           struct irq_load_info_t *p_ildi)
147 {
148     dma0_ch0_irq.p_ildi = p_ildi;
149     dma0_ch0_irq.p_pt = p_pt;
150 
151     NVIC_SetPriority(TFM_DMA0_COMBINED_S_IRQ, DEFAULT_IRQ_PRIORITY);
152     NVIC_ClearTargetState(TFM_DMA0_COMBINED_S_IRQ);
153     NVIC_DisableIRQ(TFM_DMA0_COMBINED_S_IRQ);
154 
155     return TFM_HAL_SUCCESS;
156 }
157