1 /******************************************************************************
3 * Copyright (C) 2015 - 2016 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.
50 * 2.1 kvn 05/05/16 Modified code for MISRA-C:2012 Compliance
53 *****************************************************************************/
55 /***************************** Include Files ********************************/
57 #include "xipipsu_hw.h"
59 /****************************************************************************/
61 * Initialize the Instance pointer based on a given Config Pointer
63 * @param InstancePtr is a pointer to the instance to be worked on
64 * @param CfgPtr is the device configuration structure containing required
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
74 XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
75 UINTPTR EffectiveAddress)
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;
87 InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
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;
96 /* Mark the component as Ready */
97 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
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
106 * @param InstancePtr is the pointer to current IPI instance
110 void XIpiPsu_Reset(XIpiPsu *InstancePtr)
113 Xil_AssertVoid(InstancePtr != NULL);
114 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
116 /**************Disable***************/
118 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
121 /**************Clear***************/
122 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
128 * @brief Trigger an IPI to a Destination CPU
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
134 * @return XST_SUCCESS if successful
135 * XST_FAILURE if an error occurred
138 XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
141 Xil_AssertNonvoid(InstancePtr != NULL);
142 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
144 /* Trigger an IPI to the Target */
145 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
152 * @brief Poll for an acknowledgement using Observation Register
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
158 * @return XST_SUCCESS if successful
159 * XST_FAILURE if a timeout occurred
162 XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
168 Xil_AssertNonvoid(InstancePtr != NULL);
169 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
172 /* Poll the OBS register until the corresponding DestCpu bit is cleared */
174 Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
175 XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
177 /* Check if the IPI was Acknowledged by the Target or we Timed Out*/
178 } while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
180 if (PollCount >= TimeOutCount) {
181 Status = XST_FAILURE;
183 Status = XST_SUCCESS;
190 * @brief Get the Buffer Index for a CPU specified by Mask
192 * @param InstancePtr is the pointer to current IPI instance
193 * @param CpuMask is the Mask of the CPU form which Index is required
195 * @return Buffer Index value if CPU Mask is valid
196 * XIPIPSU_MAX_BUFF_INDEX+1 if not valid
198 * @note Static function used only by XIpiPsu_GetBufferAddress
201 static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
205 /* Init Index with an invalid value */
206 BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1U;
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;
217 /* Return the Index */
222 * @brief Get the Buffer Address for a given pair of CPUs
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
229 * @return Valid Buffer Address if no error
230 * NULL if an error occurred in calculating Address
234 static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
235 u32 DestCpuMask, u32 BufferType)
245 /* Get the buffer indices */
246 SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
247 DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
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)) {
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);
270 return (u32 *) BufferAddr;
274 * @brief Read an Incoming Message from a Source
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)
282 * @return XST_SUCCESS if successful
283 * XST_FAILURE if an error occurred
286 XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 SrcCpuMask, u32 *MsgPtr,
287 u32 MsgLength, u8 BufferType)
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);
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];
305 Status = XST_SUCCESS;
307 Status = XST_FAILURE;
315 * @brief Send a Message to Destination
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)
323 * @return XST_SUCCESS if successful
324 * XST_FAILURE if an error occurred
327 XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 DestCpuMask, u32 *MsgPtr,
328 u32 MsgLength, u8 BufferType)
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);
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];
346 Status = XST_SUCCESS;
348 Status = XST_FAILURE;