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