diff --git a/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.mdd b/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.mdd new file mode 100644 index 00000000..b9849773 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.mdd @@ -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 diff --git a/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.tcl b/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.tcl new file mode 100644 index 00000000..52a927b4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/data/ipipsu.tcl @@ -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" +} diff --git a/XilinxProcessorIPLib/drivers/ipipsu/examples/xipipsu_self_test_example.c b/XilinxProcessorIPLib/drivers/ipipsu/examples/xipipsu_self_test_example.c new file mode 100644 index 00000000..c98ea89b --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/examples/xipipsu_self_test_example.c @@ -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_IndexEnter 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; + +} diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/Makefile b/XilinxProcessorIPLib/drivers/ipipsu/src/Makefile new file mode 100644 index 00000000..3e1fc71f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/Makefile @@ -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} diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.c b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.c new file mode 100644 index 00000000..18061410 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.c @@ -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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver	Who	Date	Changes
+* ----- ------ -------- ----------------------------------------------
+* 1.00	mjr	03/15/15	First Release
+* 
+* +*****************************************************************************/ + +/***************************** 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; +} diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.h b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.h new file mode 100644 index 00000000..5ccbb363 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu.h @@ -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 + * + * Initialization + * 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. + * + * Sending an IPI + * 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 + * + * Receiving an IPI + * 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 Mask. The corresponding interrupt for +* each bit set to 1 in Mask, 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 Mask. The corresponding interrupt for +* each bit set to 1 in Mask, 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 STATUS REGISTER 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 STATUS REGISTER of the current IPI instance. +* The corresponding interrupt status for +* each bit set to 1 in Mask, 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 OBSERVATION REGISTER 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_ */ diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_g.c b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_g.c new file mode 100644 index 00000000..7b9a96d5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_g.c @@ -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 + } + } + } +}; diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_hw.h b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_hw.h new file mode 100644 index 00000000..ec111362 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_hw.h @@ -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 +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------.
+* 1.0   mjr  03/15/15 First release
+*
+* 
+* +******************************************************************************/ +#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_ */ diff --git a/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_sinit.c b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_sinit.c new file mode 100644 index 00000000..d04d9411 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/ipipsu/src/xipipsu_sinit.c @@ -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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0   mjr  03/15/15 First release
+* 
+* +******************************************************************************/ + +/***************************** 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; +}