diff options
Diffstat (limited to 'board/xilinx/common/xipif_v1_23_b.c')
-rwxr-xr-x | board/xilinx/common/xipif_v1_23_b.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/board/xilinx/common/xipif_v1_23_b.c b/board/xilinx/common/xipif_v1_23_b.c new file mode 100755 index 0000000..c7311ab --- /dev/null +++ b/board/xilinx/common/xipif_v1_23_b.c @@ -0,0 +1,331 @@ +/* $Id: xipif_v1_23_b.c,v 1.1 2002/03/18 23:24:52 linnj Exp $ */ +/****************************************************************************** +* +* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" +* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND +* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, +* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, +* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION +* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, +* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE +* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY +* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE +* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR +* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF +* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE. +* +* (c) Copyright 2002 Xilinx Inc. +* All rights reserved. +* +******************************************************************************/ +/****************************************************************************** +* +* FILENAME: +* +* xipif.c +* +* DESCRIPTION: +* +* This file contains the implementation of the XIpIf component. The +* XIpIf component encapsulates the IPIF, which is the standard interface +* that IP must adhere to when connecting to a bus. The purpose of this +* component is to encapsulate the IPIF processing such that maintainability +* is increased. This component does not provide a lot of abstraction from +* from the details of the IPIF as it is considered a building block for +* device drivers. A device driver designer must be familiar with the +* details of the IPIF hardware to use this component. +* +* The IPIF hardware provides a building block for all hardware devices such +* that each device does not need to reimplement these building blocks. The +* IPIF contains other building blocks, such as FIFOs and DMA channels, which +* are also common to many devices. These blocks are implemented as separate +* hardware blocks and instantiated within the IPIF. The primary hardware of +* the IPIF which is implemented by this software component is the interrupt +* architecture. Since there are many blocks of a device which may generate +* interrupts, all the interrupt processing is contained in the common part +* of the device, the IPIF. This interrupt processing is for the device level +* only and does not include any processing for the interrupt controller. +* +* A device is a mechanism such as an Ethernet MAC. The device is made +* up of several parts which include an IPIF and the IP. The IPIF contains most +* of the device infrastructure which is common to all devices, such as +* interrupt processing, DMA channels, and FIFOs. The infrastructure may also +* be referred to as IPIF internal blocks since they are part of the IPIF and +* are separate blocks that can be selected based upon the needs of the device. +* The IP of the device is the logic that is unique to the device and interfaces +* to the IPIF of the device. +* +* In general, there are two levels of registers within the IPIF. The first +* level, referred to as the device level, contains registers which are for the +* entire device. The second level, referred to as the IP level, contains +* registers which are specific to the IP of the device. The two levels of +* registers are designed to be hierarchical such that the device level is +* is a more general register set above the more specific registers of the IP. +* The IP level of registers provides functionality which is typically common +* across all devices and allows IP designers to focus on the unique aspects +* of the IP. +* +* The interrupt registers of the IPIF are parameterizable such that the only +* the number of bits necessary for the device are implemented. The functions +* of this component do not attempt to validate that the passed in arguments are +* valid based upon the number of implemented bits. This is necessary to +* maintain the level of performance required for the common components. Bits +* of the registers are assigned starting at the least significant bit of the +* registers. +* +* Critical Sections +* +* It is the responsibility of the device driver designer to use critical +* sections as necessary when calling functions of the IPIF. This component +* does not use critical sections and it does access registers using +* read-modify-write operations. Calls to IPIF functions from a main thread +* and from an interrupt context could produce unpredictable behavior such that +* the caller must provide the appropriate critical sections. +* +* Mutual Exclusion +* +* The functions of the IPIF are not thread safe such that the caller of all +* functions is responsible for ensuring mutual exclusion for an IPIF. Mutual +* exclusion across multiple IPIF components is not necessary. +* +* NOTES: +* +* None. +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ----------------------------------------------- +* 1.23b jhl 02/27/01 Repartioned to reduce size +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xipif_v1_23_b.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +/* the following constant is used to generate bit masks for register testing + * in the self test functions, it defines the starting bit mask that is to be + * shifted from the LSB to MSB in creating a register test mask + */ +#define XIIF_V123B_FIRST_BIT_MASK 1UL + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +static XStatus IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth); + +/****************************************************************************** +* +* FUNCTION: +* +* XIpIf_SelfTest +* +* DESCRIPTION: +* +* This function performs a self test on the specified IPIF component. Many +* of the registers in the IPIF are tested to ensure proper operation. This +* function is destructive because the IPIF is reset at the start of the test +* and at the end of the test to ensure predictable results. The IPIF reset +* also resets the entire device that uses the IPIF. This function exits with +* all interrupts for the device disabled. +* +* ARGUMENTS: +* +* InstancePtr points to the XIpIf to operate on. +* +* DeviceRegistersWidth contains the number of bits in the device interrupt +* registers. The hardware is parameterizable such that only the number of bits +* necessary to support a device are implemented. This value must be between 0 +* and 32 with 0 indicating there are no device interrupt registers used. +* +* IpRegistersWidth contains the number of bits in the IP interrupt registers +* of the device. The hardware is parameterizable such that only the number of +* bits necessary to support a device are implemented. This value must be +* between 0 and 32 with 0 indicating there are no IP interrupt registers used. +* +* RETURN VALUE: +* +* A value of XST_SUCCESS indicates the test was successful with no errors. +* Any one of the following error values may also be returned. +* +* XST_IPIF_RESET_REGISTER_ERROR The value of a register at reset was +* not valid +* XST_IPIF_IP_STATUS_ERROR A write to the IP interrupt status +* register did not read back correctly +* XST_IPIF_IP_ACK_ERROR One or more bits in the IP interrupt +* status register did not reset when acked +* XST_IPIF_IP_ENABLE_ERROR The IP interrupt enable register +* did not read back correctly based upon +* what was written to it +* +* NOTES: +* +* None. +* +******************************************************************************/ + +/* the following constant defines the maximum number of bits which may be + * used in the registers at the device and IP levels, this is based upon the + * number of bits available in the registers + */ +#define XIIF_V123B_MAX_REG_BIT_COUNT 32 + +XStatus +XIpIfV123b_SelfTest(u32 RegBaseAddress, u8 IpRegistersWidth) +{ + XStatus Status; + + /* assert to verify arguments are valid */ + + XASSERT_NONVOID(IpRegistersWidth <= XIIF_V123B_MAX_REG_BIT_COUNT); + + /* reset the IPIF such that it's in a known state before the test + * and interrupts are globally disabled + */ + XIIF_V123B_RESET(RegBaseAddress); + + /* perform the self test on the IP interrupt registers, if + * it is not successful exit with the status + */ + Status = IpIntrSelfTest(RegBaseAddress, IpRegistersWidth); + if (Status != XST_SUCCESS) { + return Status; + } + + /* reset the IPIF such that it's in a known state before exiting test */ + + XIIF_V123B_RESET(RegBaseAddress); + + /* reaching this point means there were no errors, return success */ + + return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* IpIntrSelfTest +* +* DESCRIPTION: +* +* Perform a self test on the IP interrupt registers of the IPIF. This +* function modifies registers of the IPIF such that they are not guaranteed +* to be in the same state when it returns. Any bits in the IP interrupt +* status register which are set are assumed to be set by default after a reset +* and are not tested in the test. +* +* ARGUMENTS: +* +* InstancePtr points to the XIpIf to operate on. +* +* IpRegistersWidth contains the number of bits in the IP interrupt registers +* of the device. The hardware is parameterizable such that only the number of +* bits necessary to support a device are implemented. This value must be +* between 0 and 32 with 0 indicating there are no IP interrupt registers used. +* +* RETURN VALUE: +* +* A status indicating XST_SUCCESS if the test was successful. Otherwise, one +* of the following values is returned. +* +* XST_IPIF_RESET_REGISTER_ERROR The value of a register at reset was +* not valid +* XST_IPIF_IP_STATUS_ERROR A write to the IP interrupt status +* register did not read back correctly +* XST_IPIF_IP_ACK_ERROR One or more bits in the IP status +* register did not reset when acked +* XST_IPIF_IP_ENABLE_ERROR The IP interrupt enable register +* did not read back correctly based upon +* what was written to it +* NOTES: +* +* None. +* +******************************************************************************/ +static XStatus +IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth) +{ + /* ensure that the IP interrupt interrupt enable register is zero + * as it should be at reset, the interrupt status is dependent upon the + * IP such that it's reset value is not known + */ + if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { + return XST_IPIF_RESET_REGISTER_ERROR; + } + + /* if there are any used IP interrupts, then test all of the interrupt + * bits in all testable registers + */ + if (IpRegistersWidth > 0) { + u32 BitCount; + u32 IpInterruptMask = XIIF_V123B_FIRST_BIT_MASK; + u32 Mask = XIIF_V123B_FIRST_BIT_MASK; /* bits assigned MSB to LSB */ + u32 InterruptStatus; + + /* generate the register masks to be used for IP register tests, the + * number of bits supported by the hardware is parameterizable such + * that only that number of bits are implemented in the registers, the + * bits are allocated starting at the MSB of the registers + */ + for (BitCount = 1; BitCount < IpRegistersWidth; BitCount++) { + Mask = Mask << 1; + IpInterruptMask |= Mask; + } + + /* get the current IP interrupt status register contents, any bits + * already set must default to 1 at reset in the device and these + * bits can't be tested in the following test, remove these bits from + * the mask that was generated for the test + */ + InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); + IpInterruptMask &= ~InterruptStatus; + + /* set the bits in the device status register and verify them by reading + * the register again, all bits of the register are latched + */ + XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); + InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); + if ((InterruptStatus & IpInterruptMask) != IpInterruptMask) + { + return XST_IPIF_IP_STATUS_ERROR; + } + + /* test to ensure that the bits set in the IP interrupt status register + * can be cleared by acknowledging them in the IP interrupt status + * register then read it again and verify it was cleared + */ + XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); + InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); + if ((InterruptStatus & IpInterruptMask) != 0) { + return XST_IPIF_IP_ACK_ERROR; + } + + /* set the IP interrupt enable set register and then read the IP + * interrupt enable register and verify the interrupts were enabled + */ + XIIF_V123B_WRITE_IIER(RegBaseAddress, IpInterruptMask); + if (XIIF_V123B_READ_IIER(RegBaseAddress) != IpInterruptMask) { + return XST_IPIF_IP_ENABLE_ERROR; + } + + /* clear the IP interrupt enable register and then read the + * IP interrupt enable register and verify the interrupts were disabled + */ + XIIF_V123B_WRITE_IIER(RegBaseAddress, 0); + if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { + return XST_IPIF_IP_ENABLE_ERROR; + } + } + return XST_SUCCESS; +} |