ipipsu_v1_0: Add IPI driver for ZynqMP

This is the initial version of Inter Processor Interrupt (IPI) driver
for ZynqMP,including the required tcl and an example on using the driver.

Signed-off-by: Jyotheeswar Reddy <jyothee@xilinx.com>
This commit is contained in:
Jyotheeswar Reddy 2015-03-16 16:05:54 +05:30 committed by Nava kishore Manne
parent e395d1bf1b
commit 2889468869
9 changed files with 1546 additions and 0 deletions

View file

@ -0,0 +1,42 @@
###############################################################################
#
# Copyright (C) 2015 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 THE
# XILINX CONSORTIUM 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.
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver ipipsu
OPTION supported_peripherals = (psu_ipi);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 1.0;
OPTION NAME = ipipsu;
END driver

View file

@ -0,0 +1,210 @@
###############################################################################
#
# Copyright (C) 2015 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 THE
# XILINX CONSORTIUM 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.
#
###############################################################################
##############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 1.00 mjr 02/03/15 Created
#
##############################################################################
#uses "xillib.tcl"
proc ipi_format_hexmask {bitpos} {
return [format "0x%08X" [expr 1<<$bitpos]]
}
proc ipi_define_xpar {inst param} {
set param_name [string range $param [string length "CONFIG."] [string length $param]]
set name [string range $param_name 2 end]
set param_value [common::get_property $param [hsi::get_cells $inst]]
if { [string compare $name "BIT_POSITION"] == 0} {
set name "BIT_MASK"
set param_value [ipi_format_hexmask $param_value]
}
return [format "#define XPAR_%s_%s %s" [string toupper $inst] $name $param_value]
}
#Generate Config file with data structures describing the HW
proc ipi_generate_config {drv_handle file_name} {
#Driver Prefix String
set drv_string "XIpiPsu"
#The current processor
set sw_proc_handle [::hsi::get_sw_processor]
set hw_proc_handle [::hsi::get_cells [common::get_property hw_instance $sw_proc_handle]]
# List of IPIs owned by this processor
set proc_ipi_list [lsearch -all -inline [get_property SLAVES $hw_proc_handle] psu_ipi_*]
# List of all IPIs on SoC
set ipi_list [get_cells -filter { IP_NAME == "psu_ipi" }]
set cfgfilename [file join "src" $file_name]
set config_file [open $cfgfilename w]
# Common Header
::hsi::utils::write_c_header $config_file "Driver configuration"
puts $config_file "#include \"xparameters.h\""
puts $config_file "#include \"[string tolower $drv_string].h\""
# Start generating the Config table
puts $config_file "\n/*"
puts $config_file "* The configuration table for devices"
puts $config_file "*/\n"
puts $config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string]
puts $config_file "\{"
set comma ""
foreach ipi_inst $proc_ipi_list {
puts $config_file $comma
puts $config_file "\t\{"
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $ipi_inst] "DEVICE_ID,"]
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $ipi_inst] "BASE_ADDRESS,"]
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $ipi_inst] "BIT_MASK,"]
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $ipi_inst] "BUFFER_INDEX,"]
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $ipi_inst] "INT_ID,"]
# Target Count
puts $config_file [format "\t\tXPAR_%s_%s" [string toupper $drv_string] "NUM_TARGETS,"]
# Start generating Target Table with list if all IPI slots on SoC
puts $config_file "\t\t\{"
set comma ""
foreach ipi_inst $ipi_list {
puts $config_file $comma
puts $config_file "\t\t\t\{"
puts $config_file [format "\t\t\t\tXPAR_%s_%s" [string toupper $ipi_inst] "BIT_MASK,"]
puts $config_file [format "\t\t\t\tXPAR_%s_%s" [string toupper $ipi_inst] "BUFFER_INDEX"]
puts -nonewline $config_file "\t\t\t\}"
set comma ","
}
puts $config_file "\n\t\t\}"
puts -nonewline $config_file "\t\}"
set comma ",\n"
}
puts $config_file "\n\};"
close $config_file
}
proc ipi_generate_params {file_name} {
#Driver Prefix String
set drv_string "XIpiPsu"
# open the xparameters.h file
set file_handle [::hsi::utils::open_include_file $file_name]
# List of all IPIs on SoC
set ipi_list [get_cells -filter { IP_NAME == "psu_ipi" }]
#List of all processors on SoC
set proc_list [get_cells -filter { IP_TYPE == "PROCESSOR" }]
#The current processor
set sw_proc_handle [::hsi::get_sw_processor]
set hw_proc_handle [::hsi::get_cells [common::get_property hw_instance $sw_proc_handle]]
# List of IPIs owned by this processor
set proc_ipi_list [lsearch -all -inline [get_property SLAVES $hw_proc_handle] psu_ipi_*]
#Total number of IPIs assigned to this proc
puts $file_handle [format "#define XPAR_XIPIPSU_NUM_INSTANCES %s" [llength $proc_ipi_list]]
puts $file_handle ""
# Generate all params for IPIs owned by this proc
#Idx is used to track DEVICE_ID as we loop through the list
set idx 0
foreach ipi_inst $proc_ipi_list {
puts $file_handle [format "/* Parameter definitions for peripheral %s */" $ipi_inst]
puts $file_handle [format "#define XPAR_%s_%s %s" [string toupper $ipi_inst] "DEVICE_ID" $idx]
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_BASE_ADDRESS]
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_BIT_POSITION]
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_BUFFER_INDEX]
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_INT_ID]
puts $file_handle ""
incr idx
}
set idx 0
foreach ipi_inst $proc_ipi_list {
puts $file_handle [format "/* Canonical definitions for peripheral %s */" $ipi_inst]
puts $file_handle [format "#define XPAR_%s_%s_%s XPAR_%s_%s" [string toupper $drv_string] $idx "DEVICE_ID" [string toupper $ipi_inst] "DEVICE_ID"]
puts $file_handle [format "#define XPAR_%s_%s_%s XPAR_%s_%s" [string toupper $drv_string] $idx "BASE_ADDRESS" [string toupper $ipi_inst] "BASE_ADDRESS"]
puts $file_handle [format "#define XPAR_%s_%s_%s XPAR_%s_%s" [string toupper $drv_string] $idx "BIT_MASK" [string toupper $ipi_inst] "BIT_MASK"]
puts $file_handle [format "#define XPAR_%s_%s_%s XPAR_%s_%s" [string toupper $drv_string] $idx "BUFFER_INDEX" [string toupper $ipi_inst] "BUFFER_INDEX"]
puts $file_handle [format "#define XPAR_%s_%s_%s XPAR_%s_%s" [string toupper $drv_string] $idx "INT_ID" [string toupper $ipi_inst] "INT_ID"]
puts $file_handle ""
incr idx
}
#Total number of IPIs assigned to this proc
puts $file_handle [format "#define XPAR_XIPIPSU_NUM_TARGETS %s" [llength $ipi_list]]
puts $file_handle ""
foreach ipi_inst $ipi_list {
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_BIT_POSITION]
puts $file_handle [ipi_define_xpar $ipi_inst CONFIG.C_BUFFER_INDEX]
puts ""
}
# Generate Canonical definitions to map IPI instance -> Processors
puts $file_handle "/* Target List for referring to processor IPI Targets */"
puts $file_handle ""
foreach proc $proc_list {
# List of IPIs owned by this processor
set proc_slave_list [lsearch -all -inline [get_property SLAVES $proc] psu_ipi_*]
set idx 0
foreach ipi_slave $proc_slave_list {
puts $file_handle [format "#define XPAR_XIPIPS_TARGET_%s_CH%s_MASK XPAR_%s_BIT_MASK" [string toupper $proc] $idx [string toupper $ipi_slave]]
puts $file_handle [format "#define XPAR_XIPIPS_TARGET_%s_CH%s_INDEX %s" [string toupper $proc] $idx [lsearch $ipi_list $ipi_slave]]
puts ""
incr idx
}
puts $file_handle ""
}
# close the include file
close $file_handle
}
#This is called by HSI while generating the driver
proc generate {drv_handle} {
ipi_generate_params "xparameters.h"
ipi_generate_config $drv_handle "xipipsu_g.c"
}

View file

@ -0,0 +1,315 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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_self_test_example.c
*
* This file consists of a self test example which uses the XIpiPsu driver to
* send an IPI message to self and get a response
* Each IPI channel can trigger an interrupt to itself and can exchange messages
* through the message buffer. This feature is used here to exercise the driver
* APIs.
* Example control flow:
* - Init the IPI and GIC drivers
* - Setup Interrupt System with IPI handler which inverts the received message
* and sends back as response
* - Write a Message and Trigger IPI to Self.
* - Keep polling for response till timeout
* - Interrupt handler receives IPI and sends back response
* - Read the received response and do a sanity check
* - Print PASS or FAIL based on sanity check of response message
******************************************************************************/
#include "stdlib.h"
#include "xil_types.h"
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xil_exception.h"
#include "xil_cache.h"
#include "xscugic.h"
#include "xipipsu.h"
#include "xipipsu_hw.h"
/************************* Test Configuration ********************************/
/* IPI device ID to use for this test */
#define TEST_CHANNEL_ID XPAR_XIPIPSU_1_DEVICE_ID
/* Test message length in words. Max is 8 words (32 bytes) */
#define TEST_MSG_LEN 8
/* Interrupt Controller device ID */
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
/* Time out parameter while polling for response */
#define TIMEOUT_COUNT 10000
/*****************************************************************************/
/* Global Instances of GIC and IPI devices */
XScuGic GicInst;
XIpiPsu IpiInst;
/* Buffers to store Test Data */
u32 MsgBuffer[TEST_MSG_LEN];
static void InvertBuffer(u32 *BufPtr,u32 MsgLen)
{
u32 l_Index;
for(l_Index=0;l_Index<MsgLen; l_Index++){
BufPtr[l_Index]= ~BufPtr[l_Index];
}
}
/**
* Interrupt Handler :
* -Polls for each of the valid sources
* -Checks if there is a message
* -Reads the message
* -Inverts the bits
* -Sends back the inverted message as response
*
*/
void IpiIntrHandler(void *XIpiPsuPtr)
{
u32 IpiSrcMask; /**< Holds the IPI status register value */
u32 Index;
u32 TmpBufPtr[TEST_MSG_LEN] = { 0 }; /**< Holds the received Message, later inverted and sent back as response*/
u32 SrcIndex;
XIpiPsu *InstancePtr = (XIpiPsu *) XIpiPsuPtr;
xil_printf("---->Enter Interrupt Handler\r\n");
Xil_AssertVoid(InstancePtr!=NULL);
IpiSrcMask = XIpiPsu_GetInterruptStatus(InstancePtr);
/* Poll for each source and send Response (Response = ~Msg) */
for (SrcIndex = 0U; SrcIndex < InstancePtr->Config.TargetCount;
SrcIndex++) {
if (IpiSrcMask & InstancePtr->Config.TargetList[SrcIndex].Mask) {
/* Read Incoming Message Buffer Corresponding to Source CPU */
XIpiPsu_ReadMessage(InstancePtr,
InstancePtr->Config.TargetList[SrcIndex].Mask, TmpBufPtr,
TEST_MSG_LEN, XIPIPSU_BUF_TYPE_MSG);
xil_printf("Message Received:\r\n");
for (Index = 0; Index < TEST_MSG_LEN; Index++) {
xil_printf("W%d: 0x%08x\r\n", Index, TmpBufPtr[Index]);
}
/*Process the Received Message */
InvertBuffer(TmpBufPtr, TEST_MSG_LEN);
/* Send Response */
XIpiPsu_WriteMessage(InstancePtr,
InstancePtr->Config.TargetList[SrcIndex].Mask, TmpBufPtr,
TEST_MSG_LEN, XIPIPSU_BUF_TYPE_RESP);
xil_printf("Sent back Inverted Message.\r\n");
/* Clear the Interrupt Status - This clears the OBS bit on teh SRC CPU registers */
XIpiPsu_ClearInterruptStatus(InstancePtr,
InstancePtr->Config.TargetList[SrcIndex].Mask);
}
}
xil_printf("<----Exit Interrupt Handler\r\n");
}
static XStatus SetupInterruptSystem(XScuGic *IntcInstancePtr,
XIpiPsu *IpiInstancePtr, u32 IpiIntrId) {
u32 Status = 0;
XScuGic_Config *IntcConfig; /* Config for interrupt controller */
/* Initialize the interrupt controller driver */
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&GicInst, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the interrupt controller interrupt handler to the
* hardware interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler, IntcInstancePtr);
/*
* Connect a device driver handler that will be called when an
* interrupt for the device occurs, the device driver handler
* performs the specific interrupt processing for the device
*/
xil_printf("Interrupt ID: %d\r\n",IpiIntrId);
Status = XScuGic_Connect(IntcInstancePtr, IpiIntrId,
(Xil_InterruptHandler) IpiIntrHandler, (void *) IpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Enable the interrupt for the device */
XScuGic_Enable(IntcInstancePtr, IpiIntrId);
/* Enable interrupts */
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/**
* @brief Tests the IPI by sending a message and checking the response
*/
static XStatus DoIpiTest(XIpiPsu *InstancePtr)
{
u32 Index;
u32 Status;
u32 TmpBuffer[TEST_MSG_LEN] = { 0 };
XIpiPsu_Config *DestCfgPtr;
DestCfgPtr = XIpiPsu_LookupConfig(TEST_CHANNEL_ID);
xil_printf("Message Content:\r\n");
for (Index = 0; Index < TEST_MSG_LEN; Index++) {
MsgBuffer[Index] = rand();
xil_printf("W%d: 0x%08x\r\n", Index, MsgBuffer[Index]);
}
/**
* Send a Message to TEST_TARGET and WAIT for ACK
*/
XIpiPsu_WriteMessage(InstancePtr, DestCfgPtr->BitMask, MsgBuffer,
TEST_MSG_LEN,
XIPIPSU_BUF_TYPE_MSG);
xil_printf("Triggering IPI and Waiting for Response...\r\n");
XIpiPsu_TriggerIpi(InstancePtr, DestCfgPtr->BitMask);
Status = XIpiPsu_PollForAck(InstancePtr, DestCfgPtr->BitMask,
TIMEOUT_COUNT);
if (XST_SUCCESS == Status) {
xil_printf("Received response.\r\n");
/**
* Read the Response buffer
*/
XIpiPsu_ReadMessage(InstancePtr, DestCfgPtr->BitMask, TmpBuffer,
TEST_MSG_LEN, XIPIPSU_BUF_TYPE_RESP);
/**
* Set the Status to SUCCESS; Status will be set to FAILURE incase the check fails
* in the consequent code
*/
Status = XST_SUCCESS;
/*
* Check if RESPONSE == (~MSG)
*/
xil_printf("Message : Response\r\n");
for (Index = 0; Index < TEST_MSG_LEN; Index++) {
xil_printf("W%d -> 0x%08x : 0x%08x\r\n", Index, MsgBuffer[Index],
TmpBuffer[Index]);
if (MsgBuffer[Index] != (~TmpBuffer[Index])) {
Status = XST_FAILURE;
break;
}
}
} else {
xil_printf("Error: Timed Out polling for response\r\n");
}
return Status;
}
int main() {
XIpiPsu_Config *CfgPtr;
int Status = XST_FAILURE;
xil_printf("Hello IPI! [Build: %s %s]\r\n", __DATE__, __TIME__);
Xil_DCacheDisable();
/* Look Up the config data */
CfgPtr = XIpiPsu_LookupConfig(TEST_CHANNEL_ID);
/* Init with the Cfg Data */
XIpiPsu_CfgInitialize(&IpiInst, CfgPtr, CfgPtr->BaseAddress);
/* Setup the GIC */
SetupInterruptSystem(&GicInst, &IpiInst, (IpiInst.Config.IntId));
/* Enable reception of IPIs from all CPUs */
XIpiPsu_InterruptEnable(&IpiInst, XIPIPSU_ALL_MASK);
/* Clear Any existing Interrupts */
XIpiPsu_ClearInterruptStatus(&IpiInst, XIPIPSU_ALL_MASK);
/* Call the test routine */
Status = DoIpiTest(&IpiInst);
/* Print the test result */
if (XST_SUCCESS == Status) {
xil_printf("\r\n --PASS-- \r\n");
} else {
xil_printf("\r\n --FAIL-- \r\n");
}
do {
/**
* Do Nothing
* We need to loop on to receive IPIs and respond to them
*/
__asm("wfi");
} while (1);
/* Control never reaches here */
return Status;
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner xipipsu_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling ipipsu"
xipipsu_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
.PHONY: include
include: xipipsu_includes
xipipsu_includes:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OBJECTS}

View file

@ -0,0 +1,347 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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.c
*
* This file contains the implementation of the interface functions for XIpiPsu
* driver. Refer to the header file xipipsu.h for more detailed information.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- ----------------------------------------------
* 1.00 mjr 03/15/15 First Release
* </pre>
*
*****************************************************************************/
/***************************** Include Files ********************************/
#include "xipipsu.h"
#include "xipipsu_hw.h"
/****************************************************************************/
/**
* Initialize the Instance pointer based on a given Config Pointer
*
* @param InstancePtr is a pointer to the instance to be worked on
* @param CfgPtr is the device configuration structure containing required
* hardware build data
* @param EffectiveAddress is the base address of the device. If address
* translation is not utilized, this parameter can be passed in using
* CfgPtr->Config.BaseAddress to specify the physical base address.
* @return XST_SUCCESS if initialization was successful
* XST_FAILURE in case of failure
*
*/
XStatus XIpiPsu_CfgInitialize(XIpiPsu *InstancePtr, XIpiPsu_Config * CfgPtr,
UINTPTR EffectiveAddress)
{
u32 Index;
/* Verify arguments */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(CfgPtr != NULL);
/* Set device base address and ID */
InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
InstancePtr->Config.BaseAddress = EffectiveAddress;
InstancePtr->Config.BitMask = CfgPtr->BitMask;
InstancePtr->Config.IntId = CfgPtr->IntId;
InstancePtr->Config.TargetCount = CfgPtr->TargetCount;
for (Index = 0; Index < CfgPtr->TargetCount; Index++) {
InstancePtr->Config.TargetList[Index].Mask =
CfgPtr->TargetList[Index].Mask;
InstancePtr->Config.TargetList[Index].BufferIndex =
CfgPtr->TargetList[Index].BufferIndex;
}
/* Mark the component as Ready */
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
return (XST_SUCCESS);
}
/**
* @brief Reset the given IPI register set.
* This function can be called to disable the IPIs from all
* the sources and clear any pending IPIs in status register
*
* @param InstancePtr is the pointer to current IPI instance
*
*/
void XIpiPsu_Reset(XIpiPsu *InstancePtr)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/**************Disable***************/
XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_IDR_OFFSET,
XIPIPSU_ALL_MASK);
/**************Clear***************/
XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_ISR_OFFSET,
XIPIPSU_ALL_MASK);
}
/**
* @brief Trigger an IPI to a Destination CPU
*
* @param InstancePtr is the pointer to current IPI instance
* @param DestCpuMask is the Mask of the CPU to which IPI is to be triggered
*
*
* @return XST_SUCCESS if successful
* XST_FAILURE if an error occurred
*/
XStatus XIpiPsu_TriggerIpi(XIpiPsu *InstancePtr, u32 DestCpuMask)
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Trigger an IPI to the Target */
XIpiPsu_WriteReg(InstancePtr->Config.BaseAddress, XIPIPSU_TRIG_OFFSET,
DestCpuMask);
return XST_SUCCESS;
}
/**
* @brief Poll for an acknowledgement using Observation Register
*
* @param InstancePtr is the pointer to current IPI instance
* @param DestCpuMask is the Mask of the destination CPU from which ACK is expected
* @param TimeOutCount is the Count after which the routines returns failure
*
* @return XST_SUCCESS if successful
* XST_FAILURE if a timeout occurred
*/
XStatus XIpiPsu_PollForAck(XIpiPsu *InstancePtr, u32 DestCpuMask,
u32 TimeOutCount)
{
u32 Flag, PollCount;
XStatus Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
PollCount = 0;
/* Poll the OBS register until the corresponding DestCpu bit is cleared */
do {
Flag = (XIpiPsu_ReadReg(InstancePtr->Config.BaseAddress,
XIPIPSU_OBS_OFFSET)) & (DestCpuMask);
PollCount++;
/* Check if the IPI was Acknowledged by the Target or we Timed Out*/
} while ((0x00000000U != Flag) && (PollCount < TimeOutCount));
if (PollCount >= TimeOutCount) {
Status = XST_FAILURE;
} else {
Status = XST_SUCCESS;
}
return Status;
}
/**
* @brief Get the Buffer Index for a CPU specified by Mask
*
* @param InstancePtr is the pointer to current IPI instance
* @param CpuMask is the Mask of the CPU form which Index is required
*
* @return Buffer Index value if CPU Mask is valid
* XIPIPSU_MAX_BUFF_INDEX+1 if not valid
*
* @note Static function used only by XIpiPsu_GetBufferAddress
*
*/
static u32 XIpiPsu_GetBufferIndex(XIpiPsu *InstancePtr, u32 CpuMask)
{
u32 BufferIndex;
u32 Index;
/* Init Index with an invalid value */
BufferIndex = XIPIPSU_MAX_BUFF_INDEX + 1;
/*Search for CPU in the List */
for (Index = 0; Index < InstancePtr->Config.TargetCount; Index++) {
/*If we find the CPU , then set the Index and break the loop*/
if (InstancePtr->Config.TargetList[Index].Mask == CpuMask) {
BufferIndex = InstancePtr->Config.TargetList[Index].BufferIndex;
break;
}
}
/* Return the Index */
return BufferIndex;
}
/**
* @brief Get the Buffer Address for a given pair of CPUs
*
* @param InstancePtr is the pointer to current IPI instance
* @param SrcCpuMask is the Mask for Source CPU
* @param DestCpuMask is the Mask for Destination CPU
* @param BufferType is either XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP
*
* @return Valid Buffer Address if no error
* NULL if an error occurred in calculating Address
*
*/
static u32* XIpiPsu_GetBufferAddress(XIpiPsu *InstancePtr, u32 SrcCpuMask,
u32 DestCpuMask, u32 BufferType)
{
#ifdef __aarch64__
u64 BufferAddr;
#else
u32 BufferAddr;
#endif
u32 SrcIndex;
u32 DestIndex;
/* Get the buffer indices */
SrcIndex = XIpiPsu_GetBufferIndex(InstancePtr, SrcCpuMask);
DestIndex = XIpiPsu_GetBufferIndex(InstancePtr, DestCpuMask);
/* If we got an invalid buffer index, then return NULL pointer, else valid address */
if ((SrcIndex > XIPIPSU_MAX_BUFF_INDEX)
|| (DestIndex > XIPIPSU_MAX_BUFF_INDEX)) {
BufferAddr = 0U;
} else {
if (XIPIPSU_BUF_TYPE_MSG == BufferType) {
BufferAddr = XIPIPSU_MSG_RAM_BASE
+ (SrcIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
+ (DestIndex * XIPIPSU_BUFFER_OFFSET_TARGET);
} else if (XIPIPSU_BUF_TYPE_RESP == BufferType) {
BufferAddr = XIPIPSU_MSG_RAM_BASE
+ (SrcIndex * XIPIPSU_BUFFER_OFFSET_GROUP)
+ (DestIndex * XIPIPSU_BUFFER_OFFSET_TARGET)
+ (XIPIPSU_BUFFER_OFFSET_RESPONSE);
} else {
BufferAddr = 0U;
}
}
return (u32 *) BufferAddr;
}
/**
* @brief Read an Incoming Message from a Source
*
* @param InstancePtr is the pointer to current IPI instance
* @param SrcCpuMask is the Device Mask for the CPU which has sent the message
* @param MsgPtr is the pointer to Buffer to which the read message needs to be stored
* @param MsgLength is the length of the buffer/message
* @param BufType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
*
* @return XST_SUCCESS if successful
* XST_FAILURE if an error occurred
*/
XStatus XIpiPsu_ReadMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
u32 MsgLength, u8 BufferType)
{
u32 *BufferPtr;
u32 Index;
u32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(MsgPtr != NULL);
Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr, TargetMask,
InstancePtr->Config.BitMask, BufferType);
if (BufferPtr != NULL) {
/* Copy the IPI Buffer contents into Users's Buffer*/
for (Index = 0; Index < MsgLength; Index++) {
MsgPtr[Index] = BufferPtr[Index];
}
Status = XST_SUCCESS;
} else {
Status = XST_FAILURE;
}
return Status;
}
/**
* @brief Send a Message to Destination
*
* @param InstancePtr is the pointer to current IPI instance
* @param DestCpuMask is the Device Mask for the destination CPU
* @param MsgPtr is the pointer to Buffer which contains the message to be sent
* @param MsgLength is the length of the buffer/message
* @param BufType is the type of buffer (XIPIPSU_BUF_TYPE_MSG or XIPIPSU_BUF_TYPE_RESP)
*
* @return XST_SUCCESS if successful
* XST_FAILURE if an error occurred
*/
XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 TargetMask, u32 *MsgPtr,
u32 MsgLength, u8 BufferType)
{
u32 *BufferPtr;
u32 Index;
u32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(MsgPtr != NULL);
Xil_AssertNonvoid(MsgLength <= XIPIPSU_MAX_MSG_LEN);
BufferPtr = XIpiPsu_GetBufferAddress(InstancePtr,
InstancePtr->Config.BitMask, TargetMask, BufferType);
if (BufferPtr != NULL) {
/* Copy the Message to IPI Buffer */
for (Index = 0; Index < MsgLength; Index++) {
BufferPtr[Index] = MsgPtr[Index];
}
Status = XST_SUCCESS;
} else {
Status = XST_FAILURE;
}
return Status;
}

View file

@ -0,0 +1,277 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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
*
* 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
*
*/
/*****************************************************************************/
#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 BufType);
XStatus XIpiPsu_WriteMessage(XIpiPsu *InstancePtr, u32 DestCpuMask, u32 *MsgPtr,
u32 MsgLength, u8 BufType);
#endif /* XIPIPSU_H_ */

View file

@ -0,0 +1,152 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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.
*
******************************************************************************/
#include "xparameters.h"
#include "xipipsu.h"
/*
* The configuration table for devices
*/
XIpiPsu_Config XIpiPsu_ConfigTable[] =
{
{
XPAR_PSU_IPI_0_DEVICE_ID,
XPAR_PSU_IPI_0_BASE_ADDRESS,
XPAR_PSU_IPI_0_BIT_MASK,
XPAR_PSU_IPI_0_BUFFER_INDEX,
XPAR_PSU_IPI_0_INT_ID,
XPAR_XIPIPSU_NUM_TARGETS,
{
{
XPAR_PSU_IPI_0_BIT_MASK,
XPAR_PSU_IPI_0_BUFFER_INDEX
},
{
XPAR_PSU_IPI_1_BIT_MASK,
XPAR_PSU_IPI_1_BUFFER_INDEX
},
{
XPAR_PSU_IPI_2_BIT_MASK,
XPAR_PSU_IPI_2_BUFFER_INDEX
},
{
XPAR_PSU_IPI_3_BIT_MASK,
XPAR_PSU_IPI_3_BUFFER_INDEX
},
{
XPAR_PSU_IPI_4_BIT_MASK,
XPAR_PSU_IPI_4_BUFFER_INDEX
},
{
XPAR_PSU_IPI_5_BIT_MASK,
XPAR_PSU_IPI_5_BUFFER_INDEX
},
{
XPAR_PSU_IPI_6_BIT_MASK,
XPAR_PSU_IPI_6_BUFFER_INDEX
},
{
XPAR_PSU_IPI_7_BIT_MASK,
XPAR_PSU_IPI_7_BUFFER_INDEX
},
{
XPAR_PSU_IPI_8_BIT_MASK,
XPAR_PSU_IPI_8_BUFFER_INDEX
},
{
XPAR_PSU_IPI_9_BIT_MASK,
XPAR_PSU_IPI_9_BUFFER_INDEX
},
{
XPAR_PSU_IPI_10_BIT_MASK,
XPAR_PSU_IPI_10_BUFFER_INDEX
}
}
},
{
XPAR_PSU_IPI_7_DEVICE_ID,
XPAR_PSU_IPI_7_BASE_ADDRESS,
XPAR_PSU_IPI_7_BIT_MASK,
XPAR_PSU_IPI_7_BUFFER_INDEX,
XPAR_PSU_IPI_7_INT_ID,
XPAR_XIPIPSU_NUM_TARGETS,
{
{
XPAR_PSU_IPI_0_BIT_MASK,
XPAR_PSU_IPI_0_BUFFER_INDEX
},
{
XPAR_PSU_IPI_1_BIT_MASK,
XPAR_PSU_IPI_1_BUFFER_INDEX
},
{
XPAR_PSU_IPI_2_BIT_MASK,
XPAR_PSU_IPI_2_BUFFER_INDEX
},
{
XPAR_PSU_IPI_3_BIT_MASK,
XPAR_PSU_IPI_3_BUFFER_INDEX
},
{
XPAR_PSU_IPI_4_BIT_MASK,
XPAR_PSU_IPI_4_BUFFER_INDEX
},
{
XPAR_PSU_IPI_5_BIT_MASK,
XPAR_PSU_IPI_5_BUFFER_INDEX
},
{
XPAR_PSU_IPI_6_BIT_MASK,
XPAR_PSU_IPI_6_BUFFER_INDEX
},
{
XPAR_PSU_IPI_7_BIT_MASK,
XPAR_PSU_IPI_7_BUFFER_INDEX
},
{
XPAR_PSU_IPI_8_BIT_MASK,
XPAR_PSU_IPI_8_BUFFER_INDEX
},
{
XPAR_PSU_IPI_9_BIT_MASK,
XPAR_PSU_IPI_9_BUFFER_INDEX
},
{
XPAR_PSU_IPI_10_BIT_MASK,
XPAR_PSU_IPI_10_BUFFER_INDEX
}
}
}
};

View file

@ -0,0 +1,76 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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_hw.h
*
* This file contains macro definitions for low level HW related params
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------.
* 1.0 mjr 03/15/15 First release
*
* </pre>
*
******************************************************************************/
#ifndef XIPIPSU_HW_H_ /* prevent circular inclusions */
#define XIPIPSU_HW_H_ /* by using protection macros */
/************************** Constant Definitions *****************************/
/* Message RAM related params */
#define XIPIPSU_MSG_RAM_BASE 0xFF990000U
#define XIPIPSU_MSG_BUF_SIZE 8U /* Size in Words */
#define XIPIPSU_MAX_BUFF_INDEX 7
/* EIGHT pairs of TWO buffers(msg+resp) of THIRTY TWO bytes each */
#define XIPIPSU_BUFFER_OFFSET_GROUP (8U * 2U * 32U)
#define XIPIPSU_BUFFER_OFFSET_TARGET (32U * 2U)
#define XIPIPSU_BUFFER_OFFSET_RESPONSE (32U)
/* Max Number of IPI slots on the device */
#define XIPIPSU_MAX_TARGETS 11
/* Register Offsets for each member of IPI Register Set */
#define XIPIPSU_TRIG_OFFSET 0x00U
#define XIPIPSU_OBS_OFFSET 0x04U
#define XIPIPSU_ISR_OFFSET 0x10U
#define XIPIPSU_IMR_OFFSET 0x14U
#define XIPIPSU_IER_OFFSET 0x18U
#define XIPIPSU_IDR_OFFSET 0x1CU
/* MASK of all valid IPI bits in above registers */
#define XIPIPSU_ALL_MASK 0x0F0F0301U
#endif /* XIPIPSU_HW_H_ */

View file

@ -0,0 +1,87 @@
/******************************************************************************
*
* Copyright (C) 2015 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 THE
* XILINX CONSORTIUM 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_sinit.c
*
* The implementation of the XIpiPsu component's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.0 mjr 03/15/15 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xparameters.h"
#include "xipipsu.h"
/************************** Variable Definitions *****************************/
extern XIpiPsu_Config XIpiPsu_ConfigTable[];
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId contains the ID of the device to look up the
* configuration for.
*
* @return A pointer to the configuration found or NULL if the specified
* device ID was not found. See xipipsu.h for the definition of
* XIpiPsu_Config.
*
* @note None.
*
******************************************************************************/
XIpiPsu_Config *XIpiPsu_LookupConfig(u32 DeviceId)
{
XIpiPsu_Config *CfgPtr = NULL;
int Index;
for (Index = 0; Index < XPAR_XIPIPSU_NUM_INSTANCES; Index++) {
if (XIpiPsu_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XIpiPsu_ConfigTable[Index];
break;
}
}
return CfgPtr;
}