wdenk | 97e8bda | 2004-09-29 22:43:59 +0000 | [diff] [blame] | 1 | /* $Id: xipif_v1_23_b.c,v 1.1 2002/03/18 23:24:52 linnj Exp $ */ |
| 2 | /****************************************************************************** |
| 3 | * |
| 4 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" |
| 5 | * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND |
| 6 | * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, |
| 7 | * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, |
| 8 | * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION |
| 9 | * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, |
| 10 | * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE |
| 11 | * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY |
| 12 | * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE |
| 13 | * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR |
| 14 | * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF |
| 15 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 16 | * FOR A PARTICULAR PURPOSE. |
| 17 | * |
| 18 | * (c) Copyright 2002 Xilinx Inc. |
| 19 | * All rights reserved. |
| 20 | * |
| 21 | ******************************************************************************/ |
| 22 | /****************************************************************************** |
| 23 | * |
| 24 | * FILENAME: |
| 25 | * |
| 26 | * xipif.c |
| 27 | * |
| 28 | * DESCRIPTION: |
| 29 | * |
| 30 | * This file contains the implementation of the XIpIf component. The |
| 31 | * XIpIf component encapsulates the IPIF, which is the standard interface |
| 32 | * that IP must adhere to when connecting to a bus. The purpose of this |
| 33 | * component is to encapsulate the IPIF processing such that maintainability |
| 34 | * is increased. This component does not provide a lot of abstraction from |
| 35 | * from the details of the IPIF as it is considered a building block for |
| 36 | * device drivers. A device driver designer must be familiar with the |
| 37 | * details of the IPIF hardware to use this component. |
| 38 | * |
| 39 | * The IPIF hardware provides a building block for all hardware devices such |
| 40 | * that each device does not need to reimplement these building blocks. The |
| 41 | * IPIF contains other building blocks, such as FIFOs and DMA channels, which |
| 42 | * are also common to many devices. These blocks are implemented as separate |
| 43 | * hardware blocks and instantiated within the IPIF. The primary hardware of |
| 44 | * the IPIF which is implemented by this software component is the interrupt |
| 45 | * architecture. Since there are many blocks of a device which may generate |
| 46 | * interrupts, all the interrupt processing is contained in the common part |
| 47 | * of the device, the IPIF. This interrupt processing is for the device level |
| 48 | * only and does not include any processing for the interrupt controller. |
| 49 | * |
| 50 | * A device is a mechanism such as an Ethernet MAC. The device is made |
| 51 | * up of several parts which include an IPIF and the IP. The IPIF contains most |
| 52 | * of the device infrastructure which is common to all devices, such as |
| 53 | * interrupt processing, DMA channels, and FIFOs. The infrastructure may also |
| 54 | * be referred to as IPIF internal blocks since they are part of the IPIF and |
| 55 | * are separate blocks that can be selected based upon the needs of the device. |
| 56 | * The IP of the device is the logic that is unique to the device and interfaces |
| 57 | * to the IPIF of the device. |
| 58 | * |
| 59 | * In general, there are two levels of registers within the IPIF. The first |
| 60 | * level, referred to as the device level, contains registers which are for the |
| 61 | * entire device. The second level, referred to as the IP level, contains |
| 62 | * registers which are specific to the IP of the device. The two levels of |
| 63 | * registers are designed to be hierarchical such that the device level is |
| 64 | * is a more general register set above the more specific registers of the IP. |
| 65 | * The IP level of registers provides functionality which is typically common |
| 66 | * across all devices and allows IP designers to focus on the unique aspects |
| 67 | * of the IP. |
| 68 | * |
| 69 | * The interrupt registers of the IPIF are parameterizable such that the only |
| 70 | * the number of bits necessary for the device are implemented. The functions |
| 71 | * of this component do not attempt to validate that the passed in arguments are |
| 72 | * valid based upon the number of implemented bits. This is necessary to |
| 73 | * maintain the level of performance required for the common components. Bits |
| 74 | * of the registers are assigned starting at the least significant bit of the |
| 75 | * registers. |
| 76 | * |
| 77 | * Critical Sections |
| 78 | * |
| 79 | * It is the responsibility of the device driver designer to use critical |
| 80 | * sections as necessary when calling functions of the IPIF. This component |
| 81 | * does not use critical sections and it does access registers using |
| 82 | * read-modify-write operations. Calls to IPIF functions from a main thread |
| 83 | * and from an interrupt context could produce unpredictable behavior such that |
| 84 | * the caller must provide the appropriate critical sections. |
| 85 | * |
| 86 | * Mutual Exclusion |
| 87 | * |
| 88 | * The functions of the IPIF are not thread safe such that the caller of all |
| 89 | * functions is responsible for ensuring mutual exclusion for an IPIF. Mutual |
| 90 | * exclusion across multiple IPIF components is not necessary. |
| 91 | * |
| 92 | * NOTES: |
| 93 | * |
| 94 | * None. |
| 95 | * |
| 96 | * MODIFICATION HISTORY: |
| 97 | * |
| 98 | * Ver Who Date Changes |
| 99 | * ----- ---- -------- ----------------------------------------------- |
| 100 | * 1.23b jhl 02/27/01 Repartioned to reduce size |
| 101 | * |
| 102 | ******************************************************************************/ |
| 103 | |
| 104 | /***************************** Include Files *********************************/ |
| 105 | |
| 106 | #include "xipif_v1_23_b.h" |
| 107 | #include "xio.h" |
| 108 | |
| 109 | /************************** Constant Definitions *****************************/ |
| 110 | |
| 111 | /* the following constant is used to generate bit masks for register testing |
| 112 | * in the self test functions, it defines the starting bit mask that is to be |
| 113 | * shifted from the LSB to MSB in creating a register test mask |
| 114 | */ |
| 115 | #define XIIF_V123B_FIRST_BIT_MASK 1UL |
| 116 | |
| 117 | /**************************** Type Definitions *******************************/ |
| 118 | |
| 119 | /***************** Macros (Inline Functions) Definitions *********************/ |
| 120 | |
| 121 | /************************** Variable Definitions *****************************/ |
| 122 | |
| 123 | /************************** Function Prototypes ******************************/ |
| 124 | |
| 125 | static XStatus IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth); |
| 126 | |
| 127 | /****************************************************************************** |
| 128 | * |
| 129 | * FUNCTION: |
| 130 | * |
| 131 | * XIpIf_SelfTest |
| 132 | * |
| 133 | * DESCRIPTION: |
| 134 | * |
| 135 | * This function performs a self test on the specified IPIF component. Many |
| 136 | * of the registers in the IPIF are tested to ensure proper operation. This |
| 137 | * function is destructive because the IPIF is reset at the start of the test |
| 138 | * and at the end of the test to ensure predictable results. The IPIF reset |
| 139 | * also resets the entire device that uses the IPIF. This function exits with |
| 140 | * all interrupts for the device disabled. |
| 141 | * |
| 142 | * ARGUMENTS: |
| 143 | * |
| 144 | * InstancePtr points to the XIpIf to operate on. |
| 145 | * |
| 146 | * DeviceRegistersWidth contains the number of bits in the device interrupt |
| 147 | * registers. The hardware is parameterizable such that only the number of bits |
| 148 | * necessary to support a device are implemented. This value must be between 0 |
| 149 | * and 32 with 0 indicating there are no device interrupt registers used. |
| 150 | * |
| 151 | * IpRegistersWidth contains the number of bits in the IP interrupt registers |
| 152 | * of the device. The hardware is parameterizable such that only the number of |
| 153 | * bits necessary to support a device are implemented. This value must be |
| 154 | * between 0 and 32 with 0 indicating there are no IP interrupt registers used. |
| 155 | * |
| 156 | * RETURN VALUE: |
| 157 | * |
| 158 | * A value of XST_SUCCESS indicates the test was successful with no errors. |
| 159 | * Any one of the following error values may also be returned. |
| 160 | * |
| 161 | * XST_IPIF_RESET_REGISTER_ERROR The value of a register at reset was |
| 162 | * not valid |
| 163 | * XST_IPIF_IP_STATUS_ERROR A write to the IP interrupt status |
| 164 | * register did not read back correctly |
| 165 | * XST_IPIF_IP_ACK_ERROR One or more bits in the IP interrupt |
| 166 | * status register did not reset when acked |
| 167 | * XST_IPIF_IP_ENABLE_ERROR The IP interrupt enable register |
| 168 | * did not read back correctly based upon |
| 169 | * what was written to it |
| 170 | * |
| 171 | * NOTES: |
| 172 | * |
| 173 | * None. |
| 174 | * |
| 175 | ******************************************************************************/ |
| 176 | |
| 177 | /* the following constant defines the maximum number of bits which may be |
| 178 | * used in the registers at the device and IP levels, this is based upon the |
| 179 | * number of bits available in the registers |
| 180 | */ |
| 181 | #define XIIF_V123B_MAX_REG_BIT_COUNT 32 |
| 182 | |
| 183 | XStatus |
| 184 | XIpIfV123b_SelfTest(u32 RegBaseAddress, u8 IpRegistersWidth) |
| 185 | { |
| 186 | XStatus Status; |
| 187 | |
| 188 | /* assert to verify arguments are valid */ |
| 189 | |
| 190 | XASSERT_NONVOID(IpRegistersWidth <= XIIF_V123B_MAX_REG_BIT_COUNT); |
| 191 | |
| 192 | /* reset the IPIF such that it's in a known state before the test |
| 193 | * and interrupts are globally disabled |
| 194 | */ |
| 195 | XIIF_V123B_RESET(RegBaseAddress); |
| 196 | |
| 197 | /* perform the self test on the IP interrupt registers, if |
| 198 | * it is not successful exit with the status |
| 199 | */ |
| 200 | Status = IpIntrSelfTest(RegBaseAddress, IpRegistersWidth); |
| 201 | if (Status != XST_SUCCESS) { |
| 202 | return Status; |
| 203 | } |
| 204 | |
| 205 | /* reset the IPIF such that it's in a known state before exiting test */ |
| 206 | |
| 207 | XIIF_V123B_RESET(RegBaseAddress); |
| 208 | |
| 209 | /* reaching this point means there were no errors, return success */ |
| 210 | |
| 211 | return XST_SUCCESS; |
| 212 | } |
| 213 | |
| 214 | /****************************************************************************** |
| 215 | * |
| 216 | * FUNCTION: |
| 217 | * |
| 218 | * IpIntrSelfTest |
| 219 | * |
| 220 | * DESCRIPTION: |
| 221 | * |
| 222 | * Perform a self test on the IP interrupt registers of the IPIF. This |
| 223 | * function modifies registers of the IPIF such that they are not guaranteed |
| 224 | * to be in the same state when it returns. Any bits in the IP interrupt |
| 225 | * status register which are set are assumed to be set by default after a reset |
| 226 | * and are not tested in the test. |
| 227 | * |
| 228 | * ARGUMENTS: |
| 229 | * |
| 230 | * InstancePtr points to the XIpIf to operate on. |
| 231 | * |
| 232 | * IpRegistersWidth contains the number of bits in the IP interrupt registers |
| 233 | * of the device. The hardware is parameterizable such that only the number of |
| 234 | * bits necessary to support a device are implemented. This value must be |
| 235 | * between 0 and 32 with 0 indicating there are no IP interrupt registers used. |
| 236 | * |
| 237 | * RETURN VALUE: |
| 238 | * |
| 239 | * A status indicating XST_SUCCESS if the test was successful. Otherwise, one |
| 240 | * of the following values is returned. |
| 241 | * |
| 242 | * XST_IPIF_RESET_REGISTER_ERROR The value of a register at reset was |
| 243 | * not valid |
| 244 | * XST_IPIF_IP_STATUS_ERROR A write to the IP interrupt status |
| 245 | * register did not read back correctly |
| 246 | * XST_IPIF_IP_ACK_ERROR One or more bits in the IP status |
| 247 | * register did not reset when acked |
| 248 | * XST_IPIF_IP_ENABLE_ERROR The IP interrupt enable register |
| 249 | * did not read back correctly based upon |
| 250 | * what was written to it |
| 251 | * NOTES: |
| 252 | * |
| 253 | * None. |
| 254 | * |
| 255 | ******************************************************************************/ |
| 256 | static XStatus |
| 257 | IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth) |
| 258 | { |
| 259 | /* ensure that the IP interrupt interrupt enable register is zero |
| 260 | * as it should be at reset, the interrupt status is dependent upon the |
| 261 | * IP such that it's reset value is not known |
| 262 | */ |
| 263 | if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { |
| 264 | return XST_IPIF_RESET_REGISTER_ERROR; |
| 265 | } |
| 266 | |
| 267 | /* if there are any used IP interrupts, then test all of the interrupt |
| 268 | * bits in all testable registers |
| 269 | */ |
| 270 | if (IpRegistersWidth > 0) { |
| 271 | u32 BitCount; |
| 272 | u32 IpInterruptMask = XIIF_V123B_FIRST_BIT_MASK; |
| 273 | u32 Mask = XIIF_V123B_FIRST_BIT_MASK; /* bits assigned MSB to LSB */ |
| 274 | u32 InterruptStatus; |
| 275 | |
| 276 | /* generate the register masks to be used for IP register tests, the |
| 277 | * number of bits supported by the hardware is parameterizable such |
| 278 | * that only that number of bits are implemented in the registers, the |
| 279 | * bits are allocated starting at the MSB of the registers |
| 280 | */ |
| 281 | for (BitCount = 1; BitCount < IpRegistersWidth; BitCount++) { |
| 282 | Mask = Mask << 1; |
| 283 | IpInterruptMask |= Mask; |
| 284 | } |
| 285 | |
| 286 | /* get the current IP interrupt status register contents, any bits |
| 287 | * already set must default to 1 at reset in the device and these |
| 288 | * bits can't be tested in the following test, remove these bits from |
| 289 | * the mask that was generated for the test |
| 290 | */ |
| 291 | InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); |
| 292 | IpInterruptMask &= ~InterruptStatus; |
| 293 | |
| 294 | /* set the bits in the device status register and verify them by reading |
| 295 | * the register again, all bits of the register are latched |
| 296 | */ |
| 297 | XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); |
| 298 | InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); |
| 299 | if ((InterruptStatus & IpInterruptMask) != IpInterruptMask) |
| 300 | { |
| 301 | return XST_IPIF_IP_STATUS_ERROR; |
| 302 | } |
| 303 | |
| 304 | /* test to ensure that the bits set in the IP interrupt status register |
| 305 | * can be cleared by acknowledging them in the IP interrupt status |
| 306 | * register then read it again and verify it was cleared |
| 307 | */ |
| 308 | XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); |
| 309 | InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); |
| 310 | if ((InterruptStatus & IpInterruptMask) != 0) { |
| 311 | return XST_IPIF_IP_ACK_ERROR; |
| 312 | } |
| 313 | |
| 314 | /* set the IP interrupt enable set register and then read the IP |
| 315 | * interrupt enable register and verify the interrupts were enabled |
| 316 | */ |
| 317 | XIIF_V123B_WRITE_IIER(RegBaseAddress, IpInterruptMask); |
| 318 | if (XIIF_V123B_READ_IIER(RegBaseAddress) != IpInterruptMask) { |
| 319 | return XST_IPIF_IP_ENABLE_ERROR; |
| 320 | } |
| 321 | |
| 322 | /* clear the IP interrupt enable register and then read the |
| 323 | * IP interrupt enable register and verify the interrupts were disabled |
| 324 | */ |
| 325 | XIIF_V123B_WRITE_IIER(RegBaseAddress, 0); |
| 326 | if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { |
| 327 | return XST_IPIF_IP_ENABLE_ERROR; |
| 328 | } |
| 329 | } |
| 330 | return XST_SUCCESS; |
| 331 | } |