|  | /* $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; | 
|  | } |