]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/ipipsu_v2_3/src/xipipsu.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / ipipsu_v2_3 / 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_v2_3
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 * 2.2   kvn     02/17/17        Add support for updating ConfigTable at run time
52 * </pre>
53 *
54 *****************************************************************************/
55
56 /***************************** Include Files ********************************/
57 #include "xipipsu.h"
58 #include "xipipsu_hw.h"
59
60 /************************** Variable Definitions *****************************/
61 extern XIpiPsu_Config XIpiPsu_ConfigTable[XPAR_XIPIPSU_NUM_INSTANCES];
62
63 /****************************************************************************/
64 /**
65  * Initialize the Instance pointer based on a given Config Pointer
66  *
67  * @param       InstancePtr is a pointer to the instance to be worked on
68  * @param       CfgPtr is the device configuration structure containing required
69  *                      hardware build data
70  * @param       EffectiveAddress is the base address of the device. If address
71  *              translation is not utilized, this parameter can be passed in using
72  *              CfgPtr->Config.BaseAddress to specify the physical base address.
73  * @return      XST_SUCCESS if initialization was successful
74  *                      XST_FAILURE in case of failure
75  *
76  */
77
78 XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
79                 UINTPTR EffectiveAddress)
80 {
81         u32 Index;
82         /* Verify arguments */
83         Xil_AssertNonvoid(InstancePtr != NULL);
84         Xil_AssertNonvoid(CfgPtr != NULL);
85         /* Set device base address and ID */
86         InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
87         InstancePtr->Config.BaseAddress = EffectiveAddress;
88         InstancePtr->Config.BitMask = CfgPtr->BitMask;
89         InstancePtr->Config.IntId = CfgPtr->IntId;
90
91         InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
92
93         for (Index = 0U; Index < CfgPtr->TargetCount; Index++) {
94                 InstancePtr->Config.TargetList[Index].Mask =
95                                 CfgPtr->TargetList[Index].Mask;
96                 InstancePtr->Config.TargetList[Index].BufferIndex =
97                                 CfgPtr->TargetList[Index].BufferIndex;
98         }
99
100         /* Mark the component as Ready */
101         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
102         return (XST_SUCCESS);
103 }
104
105 /**
106  * @brief       Reset the given IPI register set.
107  *              This function can be called to disable the IPIs from all
108  *              the sources and clear any pending IPIs in status register
109  *
110  * @param       InstancePtr is the pointer to current IPI instance
111  *
112  */
113
114 void XIpiPsu_Reset(XIpiPsu *InstancePtr)
115 {
116
117         Xil_AssertVoid(InstancePtr != NULL);
118         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
119
120         /**************Disable***************/
121
122         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
123                         XIPIPSU_ALL_MASK);
124
125         /**************Clear***************/
126         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
127                         XIPIPSU_ALL_MASK);
128
129 }
130
131 /**
132  * @brief       Trigger an IPI to a Destination CPU
133  *
134  * @param       InstancePtr is the pointer to current IPI instance
135  * @param       DestCpuMask is the Mask of the CPU to which IPI is to be triggered
136  *
137  *
138  * @return      XST_SUCCESS if successful
139  *                      XST_FAILURE if an error occurred
140  */
141
142 XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
143 {
144
145         Xil_AssertNonvoid(InstancePtr != NULL);
146         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
147
148         /* Trigger an IPI to the Target */
149         XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
150                         DestCpuMask);
151         return XST_SUCCESS;
152
153 }
154
155 /**
156  * @brief Poll for an acknowledgement using Observation Register
157  *
158  * @param       InstancePtr is the pointer to current IPI instance
159  * @param       DestCpuMask is the Mask of the destination CPU from which ACK is expected
160  * @param       TimeOutCount is the Count after which the routines returns failure
161  *
162  * @return      XST_SUCCESS if successful
163  *                      XST_FAILURE if a timeout occurred
164  */
165
166 XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
167                 u32 TimeOutCount)
168 {
169         u32 Flag, PollCount;
170         XStatus Status;
171
172         Xil_AssertNonvoid(InstancePtr != NULL);
173         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
174
175         PollCount = 0U;
176         /* Poll the OBS register until the corresponding DestCpu bit is cleared */
177         do {
178                 Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
179                                 XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
180                 PollCount++;
181                 /* Check if the IPI was Acknowledged by the Target or we Timed Out*/
182         } while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
183
184         if (PollCount >= TimeOutCount) {
185                 Status = XST_FAILURE;
186         } else {
187                 Status = XST_SUCCESS;
188         }
189
190         return Status;
191 }
192
193 /**
194  * @brief       Get the Buffer Index for a CPU specified by Mask
195  *
196  * @param       InstancePtr is the pointer to current IPI instance
197  * @param       CpuMask is the Mask of the CPU form which Index is required
198  *
199  * @return      Buffer Index value if CPU Mask is valid
200  *                      XIPIPSU_MAX_BUFF_INDEX+1 if not valid
201  *
202  * @note        Static function used only by XIpiPsu_GetBufferAddress
203  *
204  */
205 static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
206 {
207         u32 BufferIndex;
208         u32 Index;
209         /* Init Index with an invalid value */
210         BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1U;
211
212         /*Search for CPU in the List */
213         for (Index = 0U; Index < InstancePtr->Config.TargetCount; Index++) {
214                 /*If we find the CPU , then set the Index and break the loop*/
215                 if (InstancePtr->Config.TargetList[Index].Mask == CpuMask) {
216                         BufferIndex = InstancePtr->Config.TargetList[Index].BufferIndex;
217                         break;
218                 }
219         }
220
221         /* Return the Index */
222         return BufferIndex;
223 }
224
225 /**
226  * @brief       Get the Buffer Address for a given pair of CPUs
227  *
228  * @param       InstancePtr is the pointer to current IPI instance
229  * @param       SrcCpuMask is the Mask for Source CPU
230  * @param       DestCpuMask is the Mask for Destination CPU
231  * @param       BufferType is either XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP
232  *
233  * @return      Valid Buffer Address if no error
234  *                      NULL if an error occurred in calculating Address
235  *
236  */
237
238 static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
239                 u32 DestCpuMask, u32 BufferType)
240 {
241 #ifdef __aarch64__
242         u64 BufferAddr;
243 #else
244         u32 BufferAddr;
245 #endif
246
247         u32 SrcIndex;
248         u32 DestIndex;
249         /* Get the buffer indices */
250         SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
251         DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
252
253         /* If we got an invalid buffer index, then return NULL pointer, else valid address */
254         if ((SrcIndex > XIPIPSU_MAX_BUFF_INDEX)
255                         || (DestIndex > XIPIPSU_MAX_BUFF_INDEX)) {
256                 BufferAddr = 0U;
257         } else {
258
259                 if (XIPIPSU_BUF_TYPE_MSG == BufferType) {
260                         BufferAddr = XIPIPSU_MSG_RAM_BASE
261                                         + (SrcIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
262                                         + (DestIndex * XIPIPSU_BUFFER_OFFSET_TARGET);
263                 } else if (XIPIPSU_BUF_TYPE_RESP == BufferType) {
264                         BufferAddr = XIPIPSU_MSG_RAM_BASE
265                                         + (DestIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
266                                         + (SrcIndex * XIPIPSU_BUFFER_OFFSET_TARGET)
267                                         + (XIPIPSU_BUFFER_OFFSET_RESPONSE);
268                 } else {
269                         BufferAddr = 0U;
270                 }
271
272         }
273
274         return (u32 *) BufferAddr;
275 }
276
277 /**
278  * @brief       Read an Incoming Message from a Source
279  *
280  * @param       InstancePtr is the pointer to current IPI instance
281  * @param       SrcCpuMask is the Device Mask for the CPU which has sent the message
282  * @param       MsgPtr is the pointer to Buffer to which the read message needs to be stored
283  * @param       MsgLength is the length of the buffer/message
284  * @param       BufferType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
285  *
286  * @return      XST_SUCCESS if successful
287  *                      XST_FAILURE if an error occurred
288  */
289
290 XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 SrcCpuMask, u32 *MsgPtr,
291                 u32 MsgLength, u8 BufferType)
292 {
293         u32 *BufferPtr;
294         u32 Index;
295         XStatus Status;
296
297         Xil_AssertNonvoid(InstancePtr != NULL);
298         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
299         Xil_AssertNonvoid(MsgPtr != NULL);
300         Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
301
302         BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr, SrcCpuMask,
303                         InstancePtr->Config.BitMask, BufferType);
304         if (BufferPtr != NULL) {
305                 /* Copy the IPI Buffer contents into Users's Buffer*/
306                 for (Index = 0U; Index < MsgLength; Index++) {
307                         MsgPtr[Index] = BufferPtr[Index];
308                 }
309                 Status = XST_SUCCESS;
310         } else {
311                 Status = XST_FAILURE;
312         }
313
314         return Status;
315 }
316
317
318 /**
319  * @brief       Send a Message to Destination
320  *
321  * @param       InstancePtr is the pointer to current IPI instance
322  * @param       DestCpuMask is the Device Mask for the destination CPU
323  * @param       MsgPtr is the pointer to Buffer which contains the message to be sent
324  * @param       MsgLength is the length of the buffer/message
325  * @param       BufferType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
326  *
327  * @return      XST_SUCCESS if successful
328  *                      XST_FAILURE if an error occurred
329  */
330
331 XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 DestCpuMask, u32 *MsgPtr,
332                 u32 MsgLength, u8 BufferType)
333 {
334         u32 *BufferPtr;
335         u32 Index;
336         XStatus Status;
337
338         Xil_AssertNonvoid(InstancePtr != NULL);
339         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
340         Xil_AssertNonvoid(MsgPtr != NULL);
341         Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
342
343         BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr,
344                         InstancePtr->Config.BitMask, DestCpuMask, BufferType);
345         if (BufferPtr != NULL) {
346                 /* Copy the Message to IPI Buffer */
347                 for (Index = 0U; Index < MsgLength; Index++) {
348                         BufferPtr[Index] = MsgPtr[Index];
349                 }
350                 Status = XST_SUCCESS;
351         } else {
352                 Status = XST_FAILURE;
353         }
354
355         return Status;
356 }
357
358 /*****************************************************************************/
359 /**
360 *
361 * Set up the device configuration based on the unique device ID. A table
362 * contains the configuration info for each device in the system.
363 *
364 * @param        DeviceId contains the ID of the device to set up the
365 *                       configuration for.
366 *
367 * @return       A pointer to the device configuration for the specified
368 *                       device ID. See xipipsu.h for the definition of
369 *                       XIpiPsu_Config.
370 *
371 * @note         This is for safety use case where in this function has to
372 *                       be called before CfgInitialize. So that driver will be
373 *                       initialized with the provided configuration. For non-safe
374 *                       use cases, this is not needed.
375 *
376 ******************************************************************************/
377 void XIpiPsu_SetConfigTable(u32 DeviceId, XIpiPsu_Config *ConfigTblPtr)
378 {
379         u32 Index;
380
381         Xil_AssertVoid(ConfigTblPtr != NULL);
382
383         for (Index = 0U; Index < XPAR_XIPIPSU_NUM_INSTANCES; Index++) {
384                 if (XIpiPsu_ConfigTable[Index].DeviceId == DeviceId) {
385                         XIpiPsu_ConfigTable[Index].BaseAddress = ConfigTblPtr->BaseAddress;
386                         XIpiPsu_ConfigTable[Index].BitMask = ConfigTblPtr->BitMask;
387                         XIpiPsu_ConfigTable[Index].BufferIndex = ConfigTblPtr->BufferIndex;
388                         XIpiPsu_ConfigTable[Index].IntId = ConfigTblPtr->IntId;
389                 }
390         }
391 }
392 /** @} */