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