1 /*
2 * Copyright (c) 2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "interrupts_bl2.h"
9
10 #include "device_definition.h"
11 #include "host_system.h"
12 #include "mhu_v3_x.h"
13 #include "tfm_hal_device_header.h"
14
15 #include <stdint.h>
16
17 /* Enum for id of each doorbell channel of the scp to rse MHU */
18 enum mhu_scp_rse_doorbell_channel {
19 MHU_SCP_RSE_RESERVED_CHANNEL_ID = 0,
20 MHU_SCP_RSE_SYSTOP_ON_CHANNEL_ID = 1,
21 MHU_SCP_RSE_CHANNEL_COUNT,
22 };
23
24 #define MHU_SCP_SYSTOP_FLAG 0x1
25
mhu_scp_rse_systop_on_doorbell_handler(uint32_t value)26 static int mhu_scp_rse_systop_on_doorbell_handler(uint32_t value)
27 {
28 /* Only flag 0 is used to indicate SYSTOP ON */
29 if ((value & MHU_SCP_SYSTOP_FLAG) != MHU_SCP_SYSTOP_FLAG) {
30 return 1;
31 }
32
33 host_system_scp_signal_ap_ready();
34
35 return 0;
36 }
37
38 /* Function prototype to use for mhu channel vector pointers */
39 typedef int (*mhu_vector_t) (uint32_t);
40
41 /* Array of function pointers to call if a message is received on a channel */
42 static mhu_vector_t mhu_scp_rse_doorbell_vector[MHU_SCP_RSE_CHANNEL_COUNT] = {
43 [MHU_SCP_RSE_SYSTOP_ON_CHANNEL_ID] = mhu_scp_rse_systop_on_doorbell_handler,
44 };
45
46 /* Function to handle the SCP to RSE MHUv3 combined MBX interrupt */
CMU_MHU4_Receiver_Handler(void)47 void CMU_MHU4_Receiver_Handler(void)
48 {
49 uint32_t ch, value, mask = 0;
50 enum mhu_v3_x_error_t status;
51
52 for (ch = 0; ch < MHU_SCP_RSE_CHANNEL_COUNT; ch++) {
53 /* Read the doorbell channel value */
54 status = mhu_v3_x_doorbell_read(&MHU_V3_SCP_TO_RSE_DEV, ch, &value);
55 if (status != MHU_V_3_X_ERR_NONE) {
56 break;
57 }
58
59 /* If this channel has a message (non zero value) */
60 if (value != 0) {
61
62 /* If no handler for channel then enter error state. */
63 if (mhu_scp_rse_doorbell_vector[ch] == NULL) {
64 while (1);
65 }
66 /* Call the vector function for this channel */
67 status = mhu_scp_rse_doorbell_vector[ch](value);
68 if (status != 0){
69 while (1);
70 }
71
72 /* Update mask value to clear the doorbell */
73 mask = value;
74 break;
75 }
76 }
77
78 /* Clear the pending interrupt */
79 mhu_v3_x_doorbell_clear(&MHU_V3_SCP_TO_RSE_DEV, ch, mask);
80 }
81
interrupts_bl2_init(void)82 int32_t interrupts_bl2_init(void) {
83 /* Register interrupt handler for SCP to RSE MHUv3 */
84 NVIC_SetVector(CMU_MHU4_Receiver_IRQn, CMU_MHU4_Receiver_Handler);
85 if (NVIC_GetVector(CMU_MHU4_Receiver_IRQn) != CMU_MHU4_Receiver_Handler) {
86 return 1;
87 }
88 return 0;
89 }
90