blob: 83701f46eb442b672c12f90c91cb430d69521dbd [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2015 - 2016 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xipipsu.h
* @addtogroup ipipsu_v2_3
* @{
* @details
*
* This is the header file for implementation of IPIPSU driver.
* Inter Processor Interrupt (IPI) is used for communication between
* different processors on ZynqMP SoC. Each IPI register set has Trigger, Status
* and Observation registers for communication between processors. Each IPI path
* has a 32 byte buffer associated with it and these buffers are located in the
* XPPU RAM. This driver supports the following operations:
*
* - Trigger IPIs to CPUs on the SoC
* - Write and Read Message buffers
* - Read the status of Observation Register to get status of Triggered IPI
* - Enable/Disable IPIs from selected Masters
* - Read the Status register to get the source of an incoming IPI
*
* <b>Initialization</b>
* The config data for the driver is loaded and is based on the HW build. The
* XIpiPsu_Config data structure contains all the data related to the
* IPI driver instance and also teh available Target CPUs.
*
* <b>Sending an IPI</b>
* The following steps can be followed to send an IPI:
* - Write the Message into Message Buffer using XIpiPsu_WriteMessage()
* - Trigger IPI using XIpiPsu_TriggerIpi()
* - Wait for Ack using XIpiPsu_PollForAck()
* - Read response using XIpiPsu_ReadMessage()
*
* @note XIpiPsu_GetObsStatus() before sending an IPI to ensure that the
* previous IPI was serviced by the target
*
* <b>Receiving an IPI</b>
* To receive an IPI, the following sequence can be followed:
* - Register an interrupt handler for the IPIs interrupt ID
* - Enable the required sources using XIpiPsu_InterruptEnable()
* - In the interrupt handler, Check for source using XIpiPsu_GetInterruptStatus
* - Read the message form source using XIpiPsu_ReadMessage()
* - Write the response using XIpiPsu_WriteMessage()
* - Ack the IPI using XIpiPsu_ClearInterruptStatus()
*
* @note XIpiPsu_Reset can be used at startup to clear the status and
* disable all sources
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ---- --- -------- --------------------------------------------------
* 2.2 ms 01/23/17 Modified xil_printf statement in main function for all
* examples to ensure that "Successfully ran" and "Failed"
* strings are available in all examples. This is a fix
* for CR-965028.
* kvn 02/17/17 Add support for updating ConfigTable at run time
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* 2.3 ms 04/11/17 Modified tcl file to add suffix U for all macro
* definitions of ipipsu in xparameters.h
* </pre>
*
*****************************************************************************/
/*****************************************************************************/
#ifndef XIPIPSU_H_
#define XIPIPSU_H_
/***************************** Include Files *********************************/
#include "xil_io.h"
#include "xstatus.h"
#include "xipipsu_hw.h"
/************************** Constant Definitions *****************************/
#define XIPIPSU_BUF_TYPE_MSG (0x00000001U)
#define XIPIPSU_BUF_TYPE_RESP (0x00000002U)
#define XIPIPSU_MAX_MSG_LEN XIPIPSU_MSG_BUF_SIZE
/**************************** Type Definitions *******************************/
/**
* Data structure used to refer IPI Targets
*/
typedef struct {
u32 Mask; /**< Bit Mask for the target */
u32 BufferIndex; /**< Buffer Index used for calculating buffer address */
} XIpiPsu_Target;
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u32 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 BitMask; /**< BitMask to be used to identify this CPU */
u32 BufferIndex; /**< Index of the IPI Message Buffer */
u32 IntId; /**< Interrupt ID on GIC **/
u32 TargetCount; /**< Number of available IPI Targets */
XIpiPsu_Target TargetList[XIPIPSU_MAX_TARGETS] ; /** < List of IPI Targets */
} XIpiPsu_Config;
/**
* The XIpiPsu driver instance data. The user is required to allocate a
* variable of this type for each IPI device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XIpiPsu_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u32 Options; /**< Options set in the device */
} XIpiPsu;
/***************** Macros (Inline Functions) Definitions *********************/
/**
*
* Read the register specified by the base address and offset
*
* @param BaseAddress is the base address of the IPI instance
* @param RegOffset is the offset of the register relative to base
*
* @return Value of the specified register
* @note
* C-style signature
* u32 XIpiPsu_ReadReg(u32 BaseAddress, u32 RegOffset)
*
*****************************************************************************/
#define XIpiPsu_ReadReg(BaseAddress, RegOffset) \
Xil_In32((BaseAddress) + (RegOffset))
/****************************************************************************/
/**
*
* Write a value into a register specified by base address and offset
*
* @param BaseAddress is the base address of the IPI instance
* @param RegOffset is the offset of the register relative to base
* @param Data is a 32-bit value that is to be written into the specified register
*
* @note
* C-style signature
* void XIpiPsu_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data)
*
*****************************************************************************/
#define XIpiPsu_WriteReg(BaseAddress, RegOffset, Data) \
Xil_Out32(((BaseAddress) + (RegOffset)), (Data))
/****************************************************************************/
/**
*
* Enable interrupts specified in <i>Mask</i>. The corresponding interrupt for
* each bit set to 1 in <i>Mask</i>, will be enabled.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Mask contains a bit mask of interrupts to enable. The mask can
* be formed using a set of bitwise or'd values of individual CPU masks
*
* @note
* C-style signature
* void XIpiPsu_InterruptEnable(XIpiPsu *InstancePtr, u32 Mask)
*
*****************************************************************************/
#define XIpiPsu_InterruptEnable(InstancePtr, Mask) \
XIpiPsu_WriteReg((InstancePtr)->Config.BaseAddress, \
XIPIPSU_IER_OFFSET, \
((Mask) & XIPIPSU_ALL_MASK));
/****************************************************************************/
/**
*
* Disable interrupts specified in <i>Mask</i>. The corresponding interrupt for
* each bit set to 1 in <i>Mask</i>, will be disabled.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Mask contains a bit mask of interrupts to disable. The mask can
* be formed using a set of bitwise or'd values of individual CPU masks
*
* @note
* C-style signature
* void XIpiPsu_InterruptDisable(XIpiPsu *InstancePtr, u32 Mask)
*
*****************************************************************************/
#define XIpiPsu_InterruptDisable(InstancePtr, Mask) \
XIpiPsu_WriteReg((InstancePtr)->Config.BaseAddress, \
XIPIPSU_IDR_OFFSET, \
((Mask) & XIPIPSU_ALL_MASK));
/****************************************************************************/
/**
*
* Get the <i>STATUS REGISTER</i> of the current IPI instance.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @return Returns the Interrupt Status register(ISR) contents
* @note User needs to parse this 32-bit value to check the source CPU
* C-style signature
* u32 XIpiPsu_GetInterruptStatus(XIpiPsu *InstancePtr)
*
*****************************************************************************/
#define XIpiPsu_GetInterruptStatus(InstancePtr) \
XIpiPsu_ReadReg((InstancePtr)->Config.BaseAddress, \
XIPIPSU_ISR_OFFSET)
/****************************************************************************/
/**
*
* Clear the <i>STATUS REGISTER</i> of the current IPI instance.
* The corresponding interrupt status for
* each bit set to 1 in <i>Mask</i>, will be cleared
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Mask corresponding to the source CPU*
*
* @note This function should be used after handling the IPI.
* Clearing the status will automatically clear the corresponding bit in
* OBSERVATION register of Source CPU
* C-style signature
* void XIpiPsu_ClearInterruptStatus(XIpiPsu *InstancePtr, u32 Mask)
*
*****************************************************************************/
#define XIpiPsu_ClearInterruptStatus(InstancePtr, Mask) \
XIpiPsu_WriteReg((InstancePtr)->Config.BaseAddress, \
XIPIPSU_ISR_OFFSET, \
((Mask) & XIPIPSU_ALL_MASK));
/****************************************************************************/
/**
*
* Get the <i>OBSERVATION REGISTER</i> of the current IPI instance.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @return Returns the Observation register(OBS) contents
* @note User needs to parse this 32-bit value to check the status of
* individual CPUs
* C-style signature
* u32 XIpiPsu_GetObsStatus(XIpiPsu *InstancePtr)
*
*****************************************************************************/
#define XIpiPsu_GetObsStatus(InstancePtr) \
XIpiPsu_ReadReg((InstancePtr)->Config.BaseAddress, \
XIPIPSU_OBS_OFFSET)
/****************************************************************************/
/************************** Function Prototypes *****************************/
/* Static lookup function implemented in xipipsu_sinit.c */
XIpiPsu_Config *XIpiPsu_LookupConfig(u32 DeviceId);
/* Interface Functions implemented in xipipsu.c */
XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
UINTPTR EffectiveAddress);
void XIpiPsu_Reset(XIpiPsu *InstancePtr);
XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask);
XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
u32 TimeOutCount);
XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 SrcCpuMask, u32 *MsgPtr,
u32 MsgLength, u8 BufferType);
XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 DestCpuMask, u32 *MsgPtr,
u32 MsgLength, u8 BufferType);
void XIpiPsu_SetConfigTable(u32 DeviceId, XIpiPsu_Config *ConfigTblPtr);
#endif /* XIPIPSU_H_ */
/** @} */