1 /**
2 ******************************************************************************
3 * @file mbox_ipcc.c
4 * @author MCD Application Team
5 * @brief This file provides code for the configuration
6 * of the mailbox_ipcc_if.c MiddleWare.
7 ******************************************************************************
8 * @attention
9 *
10 * <h2><center>© Copyright (c) 2019 STMicroelectronics.
11 * All rights reserved.</center></h2>
12 *
13 * This software component is licensed by ST under BSD 3-Clause license,
14 * the "License"; You may not use this file except in compliance with the
15 * License. You may obtain a copy of the License at:
16 * opensource.org/licenses/BSD-3-Clause
17 *
18 ******************************************************************************
19 */
20
21 /*
22 * Channel direction and usage:
23 *
24 * ======== <-- new msg ---=============--------<------ =======
25 * || || || CHANNEL 1 || || ||
26 * || A7 || ------->-------=============--- buf free--> || M4 ||
27 * || || || ||
28 * ||master|| <-- buf free---=============--------<------ ||slave||
29 * || || || CHANNEL 2 || || ||
30 * ======== ------->-------=============----new msg --> =======
31 */
32
33 /* Includes ------------------------------------------------------------------*/
34 #include "openamp/open_amp.h"
35 #include "stm32mp1xx_hal.h"
36 #include "openamp_conf.h"
37
38 /* Within 'USER CODE' section, code will be kept by default at each generation */
39 /* USER CODE BEGIN 0 */
40
41 /* USER CODE END 0 */
42
43 /* Private define ------------------------------------------------------------*/
44 #define MASTER_CPU_ID 0
45 #define REMOTE_CPU_ID 1
46 #define IPCC_CPU_A7 MASTER_CPU_ID
47 #define IPCC_CPU_M4 REMOTE_CPU_ID
48 #define RX_NO_MSG 0
49 #define RX_NEW_MSG 1
50 #define RX_BUF_FREE 2
51
52 /* Private variables ---------------------------------------------------------*/
53 extern IPCC_HandleTypeDef hipcc;
54 int msg_received_ch1 = RX_NO_MSG;
55 int msg_received_ch2 = RX_NO_MSG;
56 uint32_t vring0_id = 0; /* used for channel 1 */
57 uint32_t vring1_id = 1; /* used for channel 2 */
58
59 /* Private function prototypes -----------------------------------------------*/
60 void IPCC_channel1_callback(IPCC_HandleTypeDef * hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
61 void IPCC_channel2_callback(IPCC_HandleTypeDef * hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
62
63 /**
64 * @brief Initialize MAILBOX with IPCC peripheral
65 * @param None
66 * @retval : Operation result
67 */
MAILBOX_Init(void)68 int MAILBOX_Init(void)
69 {
70
71 if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX,
72 IPCC_channel1_callback) != HAL_OK) {
73 OPENAMP_log_err("%s: ch_1 RX fail\n", __func__);
74 return -1;
75 }
76
77 if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_2, IPCC_CHANNEL_DIR_RX,
78 IPCC_channel2_callback) != HAL_OK) {
79 OPENAMP_log_err("%s: ch_2 RX fail\n", __func__);
80 return -1;
81 }
82
83 return 0;
84 }
85
86 /**
87 * @brief Initialize MAILBOX with IPCC peripheral
88 * @param virtio device
89 * @retval : Operation result
90 */
MAILBOX_Poll(struct virtio_device * vdev)91 int MAILBOX_Poll(struct virtio_device *vdev)
92 {
93 /* If we got an interrupt, ask for the corresponding virtqueue processing */
94
95 if (msg_received_ch1 == RX_BUF_FREE) {
96 OPENAMP_log_dbg("Running virt0 (ch_1 buf free)\r\n");
97 rproc_virtio_notified(vdev, VRING0_ID);
98 msg_received_ch1 = RX_NO_MSG;
99 return 0;
100 }
101
102 if (msg_received_ch2 == RX_NEW_MSG) {
103 OPENAMP_log_dbg("Running virt1 (ch_2 new msg)\r\n");
104 rproc_virtio_notified(vdev, VRING1_ID);
105 msg_received_ch2 = RX_NO_MSG;
106
107 /* The OpenAMP framework does not notify for free buf: do it here */
108 rproc_virtio_notified(NULL, VRING1_ID);
109 return 0;
110 }
111
112 return -1;
113 }
114
115 /**
116 * @brief Callback function called by OpenAMP MW to notify message processing
117 * @param VRING id
118 * @retval Operation result
119 */
MAILBOX_Notify(void * priv,uint32_t id)120 int MAILBOX_Notify(void *priv, uint32_t id)
121 {
122 uint32_t channel;
123 (void)priv;
124
125 /* Called after virtqueue processing: time to inform the remote */
126 if (id == VRING0_ID) {
127 channel = IPCC_CHANNEL_1;
128 OPENAMP_log_dbg("Send msg on ch_1\r\n");
129 }
130 else if (id == VRING1_ID) {
131 /* Note: the OpenAMP framework never notifies this */
132 channel = IPCC_CHANNEL_2;
133 OPENAMP_log_dbg("Send 'buff free' on ch_2\r\n");
134 }
135 else {
136 OPENAMP_log_err("invalid vring (%d)\r\n", (int)id);
137 return -1;
138 }
139
140 /* Check that the channel is free (otherwise wait until it is) */
141 if (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) {
142 OPENAMP_log_dbg("Waiting for channel to be freed\r\n");
143 while (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED)
144 ;
145 }
146
147 /* Inform A7 (either new message, or buf free) */
148 HAL_IPCC_NotifyCPU(&hipcc, channel, IPCC_CHANNEL_DIR_TX);
149
150 return 0;
151 }
152
153 /* Private function ---------------------------------------------------------*/
154 /* Callback from IPCC Interrupt Handler: Master Processor informs that there are some free buffers */
IPCC_channel1_callback(IPCC_HandleTypeDef * hipcc,uint32_t ChannelIndex,IPCC_CHANNELDirTypeDef ChannelDir)155 void IPCC_channel1_callback(IPCC_HandleTypeDef * hipcc,
156 uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
157 {
158 if (msg_received_ch1 != RX_NO_MSG)
159 OPENAMP_log_dbg("IPCC_channel1_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch1);
160
161 msg_received_ch1 = RX_BUF_FREE;
162
163 /* Inform A7 that we have received the 'buff free' msg */
164 OPENAMP_log_dbg("Ack 'buff free' message on ch1\r\n");
165 HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX);
166 }
167
168 /* Callback from IPCC Interrupt Handler: new message received from Master Processor */
IPCC_channel2_callback(IPCC_HandleTypeDef * hipcc,uint32_t ChannelIndex,IPCC_CHANNELDirTypeDef ChannelDir)169 void IPCC_channel2_callback(IPCC_HandleTypeDef * hipcc,
170 uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
171 {
172 if (msg_received_ch2 != RX_NO_MSG)
173 OPENAMP_log_dbg("IPCC_channel2_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch2);
174
175 msg_received_ch2 = RX_NEW_MSG;
176
177 /* Inform A7 that we have received the new msg */
178 OPENAMP_log_dbg("Ack new message on ch2\r\n");
179 HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX);
180 }
181
182 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
183