1 /******************************************************************************
3 * Copyright (C) 2015 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /****************************************************************************/
36 * @addtogroup ipipsu_v1_0
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.
43 * MODIFICATION HISTORY:
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.
52 *****************************************************************************/
54 /***************************** Include Files ********************************/
56 #include "xipipsu_hw.h"
58 /****************************************************************************/
60 * Initialize the Instance pointer based on a given Config Pointer
62 * @param InstancePtr is a pointer to the instance to be worked on
63 * @param CfgPtr is the device configuration structure containing required
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
73 XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
74 UINTPTR EffectiveAddress)
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;
86 InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
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;
95 /* Mark the component as Ready */
96 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
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
105 * @param InstancePtr is the pointer to current IPI instance
109 void XIpiPsu_Reset(XIpiPsu *InstancePtr)
112 Xil_AssertVoid(InstancePtr != NULL);
113 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
115 /**************Disable***************/
117 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
120 /**************Clear***************/
121 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
127 * @brief Trigger an IPI to a Destination CPU
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
133 * @return XST_SUCCESS if successful
134 * XST_FAILURE if an error occurred
137 XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
140 Xil_AssertNonvoid(InstancePtr != NULL);
141 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
143 /* Trigger an IPI to the Target */
144 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
151 * @brief Poll for an acknowledgement using Observation Register
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
157 * @return XST_SUCCESS if successful
158 * XST_FAILURE if a timeout occurred
161 XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
167 Xil_AssertNonvoid(InstancePtr != NULL);
168 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
171 /* Poll the OBS register until the corresponding DestCpu bit is cleared */
173 Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
174 XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
176 /* Check if the IPI was Acknowledged by the Target or we Timed Out*/
177 } while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
179 if (PollCount >= TimeOutCount) {
180 Status = XST_FAILURE;
182 Status = XST_SUCCESS;
189 * @brief Get the Buffer Index for a CPU specified by Mask
191 * @param InstancePtr is the pointer to current IPI instance
192 * @param CpuMask is the Mask of the CPU form which Index is required
194 * @return Buffer Index value if CPU Mask is valid
195 * XIPIPSU_MAX_BUFF_INDEX+1 if not valid
197 * @note Static function used only by XIpiPsu_GetBufferAddress
200 static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
204 /* Init Index with an invalid value */
205 BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1;
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;
216 /* Return the Index */
221 * @brief Get the Buffer Address for a given pair of CPUs
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
228 * @return Valid Buffer Address if no error
229 * NULL if an error occurred in calculating Address
233 static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
234 u32 DestCpuMask, u32 BufferType)
244 /* Get the buffer indices */
245 SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
246 DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
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)) {
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);
269 return (u32 *) BufferAddr;
273 * @brief Read an Incoming Message from a Source
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)
281 * @return XST_SUCCESS if successful
282 * XST_FAILURE if an error occurred
285 XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
286 u32 MsgLength, u8 BufferType)
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);
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];
304 Status = XST_SUCCESS;
306 Status = XST_FAILURE;
314 * @brief Send a Message to Destination
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)
322 * @return XST_SUCCESS if successful
323 * XST_FAILURE if an error occurred
326 XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
327 u32 MsgLength, u8 BufferType)
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);
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];
345 Status = XST_SUCCESS;
347 Status = XST_FAILURE;