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>&copy; 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