]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A53_64-bit_UltraScale_MPSoC/RTOSDemo_A53_bsp/psu_cortexa53_0/libsrc/ipipsu_v2_1/src/xipipsu.c
xTaskGenericNotify() now sets xYieldPending to pdTRUE even when the 'higher priority...
[freertos] / FreeRTOS / Demo / CORTEX_A53_64-bit_UltraScale_MPSoC / RTOSDemo_A53_bsp / psu_cortexa53_0 / libsrc / ipipsu_v2_1 / src / xipipsu.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2015 - 2016 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xipipsu.c
36 * @addtogroup ipipsu_v1_0
37 * @{
38 *
39 * This file contains the implementation of the interface functions for XIpiPsu
40 * driver. Refer to the header file xipipsu.h for more detailed information.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
45 * Ver   Who     Date    Changes
46 * ----- ------ -------- ----------------------------------------------
47 * 1.00  mjr     03/15/15        First Release
48 * 2.0   mjr     01/22/16        Fixed response buffer address
49 *                               calculation. CR# 932582.
50 * 2.1   kvn     05/05/16        Modified code for MISRA-C:2012 Compliance
51 * </pre>
52 *
53 *****************************************************************************/
54
55 /***************************** Include Files ********************************/
56 #include "xipipsu.h"
57 #include "xipipsu_hw.h"
58
59 /****************************************************************************/
60 /**
61  * Initialize the Instance pointer based on a given Config Pointer
62  *
63  * @param       InstancePtr is a pointer to the instance to be worked on
64  * @param       CfgPtr is the device configuration structure containing required
65  *                      hardware build data
66  * @param       EffectiveAddress is the base address of the device. If address
67  *              translation is not utilized, this parameter can be passed in using
68  *              CfgPtr->Config.BaseAddress to specify the physical base address.
69  * @return      XST_SUCCESS if initialization was successful
70  *                      XST_FAILURE in case of failure
71  *
72  */
73
74 XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
75                 UINTPTR EffectiveAddress)
76 {
77         u32 Index;
78         /* Verify arguments */
79         Xil_AssertNonvoid(InstancePtr != NULL);
80         Xil_AssertNonvoid(CfgPtr != NULL);
81         /* Set device base address and ID */
82         InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
83         InstancePtr->Config.BaseAddress = EffectiveAddress;
84         InstancePtr->Config.BitMask = CfgPtr->BitMask;
85         InstancePtr->Config.IntId = CfgPtr->IntId;
86
87         InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
88
89         for (Index = 0U; Index < CfgPtr->TargetCount; Index++) {
90                 InstancePtr->Config.TargetList[Index].Mask =
91                                 CfgPtr->TargetList[Index].Mask;
92                 InstancePtr->Config.TargetList[Index].BufferIndex =
93                                 CfgPtr->TargetList[Index].BufferIndex;
94         }
95
96         /* Mark the component as Ready */
97         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
98         return (XST_SUCCESS);
99 }
100
101 /**
102  * @brief       Reset the given IPI register set.
103  *              This function can be called to disable the IPIs from all
104  *              the sources and clear any pending IPIs in status register
105  *
106  * @param       InstancePtr is the pointer to current IPI instance
107  *
108  */
109
110 void XIpiPsu_Reset(XIpiPsu *InstancePtr)
111 {
112
113         Xil_AssertVoid(InstancePtr != NULL);
114         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
115
116         /**************Disable***************/
117
118         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
119                         XIPIPSU_ALL_MASK);
120
121         /**************Clear***************/
122         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
123                         XIPIPSU_ALL_MASK);
124
125 }
126
127 /**
128  * @brief       Trigger an IPI to a Destination CPU
129  *
130  * @param       InstancePtr is the pointer to current IPI instance
131  * @param       DestCpuMask is the Mask of the CPU to which IPI is to be triggered
132  *
133  *
134  * @return      XST_SUCCESS if successful
135  *                      XST_FAILURE if an error occurred
136  */
137
138 XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
139 {
140
141         Xil_AssertNonvoid(InstancePtr != NULL);
142         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
143
144         /* Trigger an IPI to the Target */
145         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
146                         DestCpuMask);
147         return XST_SUCCESS;
148
149 }
150
151 /**
152  * @brief Poll for an acknowledgement using Observation Register
153  *
154  * @param       InstancePtr is the pointer to current IPI instance
155  * @param       DestCpuMask is the Mask of the destination CPU from which ACK is expected
156  * @param       TimeOutCount is the Count after which the routines returns failure
157  *
158  * @return      XST_SUCCESS if successful
159  *                      XST_FAILURE if a timeout occurred
160  */
161
162 XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
163                 u32 TimeOutCount)
164 {
165         u32 Flag, PollCount;
166         XStatus Status;
167
168         Xil_AssertNonvoid(InstancePtr != NULL);
169         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
170
171         PollCount = 0U;
172         /* Poll the OBS register until the corresponding DestCpu bit is cleared */
173         do {
174                 Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
175                                 XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
176                 PollCount++;
177                 /* Check if the IPI was Acknowledged by the Target or we Timed Out*/
178         } while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
179
180         if (PollCount >= TimeOutCount) {
181                 Status = XST_FAILURE;
182         } else {
183                 Status = XST_SUCCESS;
184         }
185
186         return Status;
187 }
188
189 /**
190  * @brief       Get the Buffer Index for a CPU specified by Mask
191  *
192  * @param       InstancePtr is the pointer to current IPI instance
193  * @param       CpuMask is the Mask of the CPU form which Index is required
194  *
195  * @return      Buffer Index value if CPU Mask is valid
196  *                      XIPIPSU_MAX_BUFF_INDEX+1 if not valid
197  *
198  * @note        Static function used only by XIpiPsu_GetBufferAddress
199  *
200  */
201 static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
202 {
203         u32 BufferIndex;
204         u32 Index;
205         /* Init Index with an invalid value */
206         BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1U;
207
208         /*Search for CPU in the List */
209         for (Index = 0U; Index < InstancePtr->Config.TargetCount; Index++) {
210                 /*If we find the CPU , then set the Index and break the loop*/
211                 if (InstancePtr->Config.TargetList[Index].Mask == CpuMask) {
212                         BufferIndex = InstancePtr->Config.TargetList[Index].BufferIndex;
213                         break;
214                 }
215         }
216
217         /* Return the Index */
218         return BufferIndex;
219 }
220
221 /**
222  * @brief       Get the Buffer Address for a given pair of CPUs
223  *
224  * @param       InstancePtr is the pointer to current IPI instance
225  * @param       SrcCpuMask is the Mask for Source CPU
226  * @param       DestCpuMask is the Mask for Destination CPU
227  * @param       BufferType is either XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP
228  *
229  * @return      Valid Buffer Address if no error
230  *                      NULL if an error occurred in calculating Address
231  *
232  */
233
234 static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
235                 u32 DestCpuMask, u32 BufferType)
236 {
237 #ifdef __aarch64__
238         u64 BufferAddr;
239 #else
240         u32 BufferAddr;
241 #endif
242
243         u32 SrcIndex;
244         u32 DestIndex;
245         /* Get the buffer indices */
246         SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
247         DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
248
249         /* If we got an invalid buffer index, then return NULL pointer, else valid address */
250         if ((SrcIndex > XIPIPSU_MAX_BUFF_INDEX)
251                         || (DestIndex > XIPIPSU_MAX_BUFF_INDEX)) {
252                 BufferAddr = 0U;
253         } else {
254
255                 if (XIPIPSU_BUF_TYPE_MSG == BufferType) {
256                         BufferAddr = XIPIPSU_MSG_RAM_BASE
257                                         + (SrcIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
258                                         + (DestIndex * XIPIPSU_BUFFER_OFFSET_TARGET);
259                 } else if (XIPIPSU_BUF_TYPE_RESP == BufferType) {
260                         BufferAddr = XIPIPSU_MSG_RAM_BASE
261                                         + (DestIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
262                                         + (SrcIndex * XIPIPSU_BUFFER_OFFSET_TARGET)
263                                         + (XIPIPSU_BUFFER_OFFSET_RESPONSE);
264                 } else {
265                         BufferAddr = 0U;
266                 }
267
268         }
269
270         return (u32 *) BufferAddr;
271 }
272
273 /**
274  * @brief       Read an Incoming Message from a Source
275  *
276  * @param       InstancePtr is the pointer to current IPI instance
277  * @param       SrcCpuMask is the Device Mask for the CPU which has sent the message
278  * @param       MsgPtr is the pointer to Buffer to which the read message needs to be stored
279  * @param       MsgLength is the length of the buffer/message
280  * @param       BufferType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
281  *
282  * @return      XST_SUCCESS if successful
283  *                      XST_FAILURE if an error occurred
284  */
285
286 XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 SrcCpuMask, u32 *MsgPtr,
287                 u32 MsgLength, u8 BufferType)
288 {
289         u32 *BufferPtr;
290         u32 Index;
291         XStatus Status;
292
293         Xil_AssertNonvoid(InstancePtr != NULL);
294         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
295         Xil_AssertNonvoid(MsgPtr != NULL);
296         Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
297
298         BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr, SrcCpuMask,
299                         InstancePtr->Config.BitMask, BufferType);
300         if (BufferPtr != NULL) {
301                 /* Copy the IPI Buffer contents into Users's Buffer*/
302                 for (Index = 0U; Index < MsgLength; Index++) {
303                         MsgPtr[Index] = BufferPtr[Index];
304                 }
305                 Status = XST_SUCCESS;
306         } else {
307                 Status = XST_FAILURE;
308         }
309
310         return Status;
311 }
312
313
314 /**
315  * @brief       Send a Message to Destination
316  *
317  * @param       InstancePtr is the pointer to current IPI instance
318  * @param       DestCpuMask is the Device Mask for the destination CPU
319  * @param       MsgPtr is the pointer to Buffer which contains the message to be sent
320  * @param       MsgLength is the length of the buffer/message
321  * @param       BufferType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
322  *
323  * @return      XST_SUCCESS if successful
324  *                      XST_FAILURE if an error occurred
325  */
326
327 XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 DestCpuMask, u32 *MsgPtr,
328                 u32 MsgLength, u8 BufferType)
329 {
330         u32 *BufferPtr;
331         u32 Index;
332         XStatus Status;
333
334         Xil_AssertNonvoid(InstancePtr != NULL);
335         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
336         Xil_AssertNonvoid(MsgPtr != NULL);
337         Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
338
339         BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr,
340                         InstancePtr->Config.BitMask, DestCpuMask, BufferType);
341         if (BufferPtr != NULL) {
342                 /* Copy the Message to IPI Buffer */
343                 for (Index = 0U; Index < MsgLength; Index++) {
344                         BufferPtr[Index] = MsgPtr[Index];
345                 }
346                 Status = XST_SUCCESS;
347         } else {
348                 Status = XST_FAILURE;
349         }
350
351         return Status;
352 }
353 /** @} */