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