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 /****************************************************************************/
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.
41 * MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- ------ -------- ----------------------------------------------
45 * 1.00 mjr 03/15/15 First Release
48 *****************************************************************************/
50 /***************************** Include Files ********************************/
52 #include "xipipsu_hw.h"
54 /****************************************************************************/
56 * Initialize the Instance pointer based on a given Config Pointer
58 * @param InstancePtr is a pointer to the instance to be worked on
59 * @param CfgPtr is the device configuration structure containing required
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
69 XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
70 UINTPTR EffectiveAddress)
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;
82 InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
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;
91 /* Mark the component as Ready */
92 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
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
101 * @param InstancePtr is the pointer to current IPI instance
105 void XIpiPsu_Reset(XIpiPsu *InstancePtr)
108 Xil_AssertVoid(InstancePtr != NULL);
109 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
111 /**************Disable***************/
113 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
116 /**************Clear***************/
117 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
123 * @brief Trigger an IPI to a Destination CPU
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
129 * @return XST_SUCCESS if successful
130 * XST_FAILURE if an error occurred
133 XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
136 Xil_AssertNonvoid(InstancePtr != NULL);
137 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
139 /* Trigger an IPI to the Target */
140 XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
147 * @brief Poll for an acknowledgement using Observation Register
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
153 * @return XST_SUCCESS if successful
154 * XST_FAILURE if a timeout occurred
157 XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
163 Xil_AssertNonvoid(InstancePtr != NULL);
164 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
167 /* Poll the OBS register until the corresponding DestCpu bit is cleared */
169 Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
170 XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
172 /* Check if the IPI was Acknowledged by the Target or we Timed Out*/
173 } while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
175 if (PollCount >= TimeOutCount) {
176 Status = XST_FAILURE;
178 Status = XST_SUCCESS;
185 * @brief Get the Buffer Index for a CPU specified by Mask
187 * @param InstancePtr is the pointer to current IPI instance
188 * @param CpuMask is the Mask of the CPU form which Index is required
190 * @return Buffer Index value if CPU Mask is valid
191 * XIPIPSU_MAX_BUFF_INDEX+1 if not valid
193 * @note Static function used only by XIpiPsu_GetBufferAddress
196 static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
200 /* Init Index with an invalid value */
201 BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1;
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;
212 /* Return the Index */
217 * @brief Get the Buffer Address for a given pair of CPUs
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
224 * @return Valid Buffer Address if no error
225 * NULL if an error occurred in calculating Address
229 static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
230 u32 DestCpuMask, u32 BufferType)
240 /* Get the buffer indices */
241 SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
242 DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
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)) {
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);
265 return (u32 *) BufferAddr;
269 * @brief Read an Incoming Message from a Source
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)
277 * @return XST_SUCCESS if successful
278 * XST_FAILURE if an error occurred
281 XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
282 u32 MsgLength, u8 BufferType)
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);
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];
300 Status = XST_SUCCESS;
302 Status = XST_FAILURE;
310 * @brief Send a Message to Destination
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)
318 * @return XST_SUCCESS if successful
319 * XST_FAILURE if an error occurred
322 XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
323 u32 MsgLength, u8 BufferType)
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);
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];
341 Status = XST_SUCCESS;
343 Status = XST_FAILURE;