wdenk | 97e8bda | 2004-09-29 22:43:59 +0000 | [diff] [blame] | 1 | /* $Id: xiic_l.c,v 1.2 2002/12/05 19:32:40 meinelte 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 | * |
| 25 | * @file xiic_l.c |
| 26 | * |
| 27 | * This file contains low-level driver functions that can be used to access the |
| 28 | * device. The user should refer to the hardware device specification for more |
| 29 | * details of the device operation. |
| 30 | * |
| 31 | * <pre> |
| 32 | * MODIFICATION HISTORY: |
| 33 | * |
| 34 | * Ver Who Date Changes |
| 35 | * ----- --- ------- ----------------------------------------------- |
| 36 | * 1.01b jhl 5/13/02 First release |
| 37 | * 1.01b jhl 10/14/02 Corrected bug in the receive function, the setup of the |
| 38 | * interrupt status mask was not being done in the loop such |
| 39 | * that a read would sometimes fail on the last byte because |
| 40 | * the transmit error which should have been ignored was |
| 41 | * being used. This would leave an extra byte in the FIFO |
| 42 | * and the bus throttled such that the next operation would |
| 43 | * also fail. Also updated the receive function to not |
| 44 | * disable the device after the last byte until after the |
| 45 | * bus transitions to not busy which is more consistent |
| 46 | * with the expected behavior. |
| 47 | * 1.01c ecm 12/05/02 new rev |
| 48 | * </pre> |
| 49 | * |
| 50 | ****************************************************************************/ |
| 51 | |
| 52 | /***************************** Include Files *******************************/ |
| 53 | |
| 54 | #include "xbasic_types.h" |
| 55 | #include "xio.h" |
| 56 | #include "xipif_v1_23_b.h" |
| 57 | #include "xiic_l.h" |
| 58 | |
| 59 | /************************** Constant Definitions ***************************/ |
| 60 | |
| 61 | /**************************** Type Definitions *****************************/ |
| 62 | |
| 63 | |
| 64 | /***************** Macros (Inline Functions) Definitions *******************/ |
| 65 | |
| 66 | |
| 67 | /****************************************************************************** |
| 68 | * |
| 69 | * This macro clears the specified interrupt in the IPIF interrupt status |
| 70 | * register. It is non-destructive in that the register is read and only the |
| 71 | * interrupt specified is cleared. Clearing an interrupt acknowledges it. |
| 72 | * |
| 73 | * @param BaseAddress contains the IPIF registers base address. |
| 74 | * |
| 75 | * @param InterruptMask contains the interrupts to be disabled |
| 76 | * |
| 77 | * @return |
| 78 | * |
| 79 | * None. |
| 80 | * |
| 81 | * @note |
| 82 | * |
| 83 | * Signature: void XIic_mClearIisr(u32 BaseAddress, |
| 84 | * u32 InterruptMask); |
| 85 | * |
| 86 | ******************************************************************************/ |
| 87 | #define XIic_mClearIisr(BaseAddress, InterruptMask) \ |
| 88 | XIIF_V123B_WRITE_IISR((BaseAddress), \ |
| 89 | XIIF_V123B_READ_IISR(BaseAddress) & (InterruptMask)) |
| 90 | |
| 91 | /****************************************************************************** |
| 92 | * |
| 93 | * This macro sends the address for a 7 bit address during both read and write |
| 94 | * operations. It takes care of the details to format the address correctly. |
| 95 | * This macro is designed to be called internally to the drivers. |
| 96 | * |
| 97 | * @param SlaveAddress contains the address of the slave to send to. |
| 98 | * |
| 99 | * @param Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION |
| 100 | * |
| 101 | * @return |
| 102 | * |
| 103 | * None. |
| 104 | * |
| 105 | * @note |
| 106 | * |
| 107 | * Signature: void XIic_mSend7BitAddr(u16 SlaveAddress, u8 Operation); |
| 108 | * |
| 109 | ******************************************************************************/ |
| 110 | #define XIic_mSend7BitAddress(BaseAddress, SlaveAddress, Operation) \ |
| 111 | { \ |
| 112 | u8 LocalAddr = (u8)(SlaveAddress << 1); \ |
| 113 | LocalAddr = (LocalAddr & 0xFE) | (Operation); \ |
| 114 | XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, LocalAddr); \ |
| 115 | } |
| 116 | |
| 117 | /************************** Function Prototypes ****************************/ |
| 118 | |
| 119 | static unsigned RecvData (u32 BaseAddress, u8 * BufferPtr, |
| 120 | unsigned ByteCount); |
| 121 | static unsigned SendData (u32 BaseAddress, u8 * BufferPtr, |
| 122 | unsigned ByteCount); |
| 123 | |
| 124 | /************************** Variable Definitions **************************/ |
| 125 | |
| 126 | |
| 127 | /****************************************************************************/ |
| 128 | /** |
| 129 | * Receive data as a master on the IIC bus. This function receives the data |
| 130 | * using polled I/O and blocks until the data has been received. It only |
| 131 | * supports 7 bit addressing and non-repeated start modes of operation. The |
| 132 | * user is responsible for ensuring the bus is not busy if multiple masters |
| 133 | * are present on the bus. |
| 134 | * |
| 135 | * @param BaseAddress contains the base address of the IIC device. |
| 136 | * @param Address contains the 7 bit IIC address of the device to send the |
| 137 | * specified data to. |
| 138 | * @param BufferPtr points to the data to be sent. |
| 139 | * @param ByteCount is the number of bytes to be sent. |
| 140 | * |
| 141 | * @return |
| 142 | * |
| 143 | * The number of bytes received. |
| 144 | * |
| 145 | * @note |
| 146 | * |
| 147 | * None |
| 148 | * |
| 149 | ******************************************************************************/ |
| 150 | unsigned XIic_Recv (u32 BaseAddress, u8 Address, |
| 151 | u8 * BufferPtr, unsigned ByteCount) |
| 152 | { |
| 153 | u8 CntlReg; |
| 154 | unsigned RemainingByteCount; |
| 155 | |
| 156 | /* Tx error is enabled incase the address (7 or 10) has no device to answer |
| 157 | * with Ack. When only one byte of data, must set NO ACK before address goes |
| 158 | * out therefore Tx error must not be enabled as it will go off immediately |
| 159 | * and the Rx full interrupt will be checked. If full, then the one byte |
| 160 | * was received and the Tx error will be disabled without sending an error |
| 161 | * callback msg. |
| 162 | */ |
| 163 | XIic_mClearIisr (BaseAddress, |
| 164 | XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK | |
| 165 | XIIC_INTR_ARB_LOST_MASK); |
| 166 | |
| 167 | /* Set receive FIFO occupancy depth for 1 byte (zero based) |
| 168 | */ |
| 169 | XIo_Out8 (BaseAddress + XIIC_RFD_REG_OFFSET, 0); |
| 170 | |
| 171 | /* 7 bit slave address, send the address for a read operation |
| 172 | * and set the state to indicate the address has been sent |
| 173 | */ |
| 174 | XIic_mSend7BitAddress (BaseAddress, Address, XIIC_READ_OPERATION); |
| 175 | |
| 176 | /* MSMS gets set after putting data in FIFO. Start the master receive |
| 177 | * operation by setting CR Bits MSMS to Master, if the buffer is only one |
| 178 | * byte, then it should not be acknowledged to indicate the end of data |
| 179 | */ |
| 180 | CntlReg = XIIC_CR_MSMS_MASK | XIIC_CR_ENABLE_DEVICE_MASK; |
| 181 | if (ByteCount == 1) { |
| 182 | CntlReg |= XIIC_CR_NO_ACK_MASK; |
| 183 | } |
| 184 | |
| 185 | /* Write out the control register to start receiving data and call the |
| 186 | * function to receive each byte into the buffer |
| 187 | */ |
| 188 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, CntlReg); |
| 189 | |
| 190 | /* Clear the latched interrupt status for the bus not busy bit which must |
| 191 | * be done while the bus is busy |
| 192 | */ |
| 193 | XIic_mClearIisr (BaseAddress, XIIC_INTR_BNB_MASK); |
| 194 | |
| 195 | /* Try to receive the data from the IIC bus */ |
| 196 | |
| 197 | RemainingByteCount = RecvData (BaseAddress, BufferPtr, ByteCount); |
| 198 | /* |
| 199 | * The receive is complete, disable the IIC device and return the number of |
| 200 | * bytes that was received |
| 201 | */ |
| 202 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, 0); |
| 203 | |
| 204 | /* Return the number of bytes that was received */ |
| 205 | |
| 206 | return ByteCount - RemainingByteCount; |
| 207 | } |
| 208 | |
| 209 | /****************************************************************************** |
| 210 | * |
| 211 | * Receive the specified data from the device that has been previously addressed |
| 212 | * on the IIC bus. This function assumes that the 7 bit address has been sent |
| 213 | * and it should wait for the transmit of the address to complete. |
| 214 | * |
| 215 | * @param BaseAddress contains the base address of the IIC device. |
| 216 | * @param BufferPtr points to the buffer to hold the data that is received. |
| 217 | * @param ByteCount is the number of bytes to be received. |
| 218 | * |
| 219 | * @return |
| 220 | * |
| 221 | * The number of bytes remaining to be received. |
| 222 | * |
| 223 | * @note |
| 224 | * |
| 225 | * This function does not take advantage of the receive FIFO because it is |
| 226 | * designed for minimal code space and complexity. It contains loops that |
| 227 | * that could cause the function not to return if the hardware is not working. |
| 228 | * |
| 229 | * This function assumes that the calling function will disable the IIC device |
| 230 | * after this function returns. |
| 231 | * |
| 232 | ******************************************************************************/ |
| 233 | static unsigned RecvData (u32 BaseAddress, u8 * BufferPtr, unsigned ByteCount) |
| 234 | { |
| 235 | u8 CntlReg; |
| 236 | u32 IntrStatusMask; |
| 237 | u32 IntrStatus; |
| 238 | |
| 239 | /* Attempt to receive the specified number of bytes on the IIC bus */ |
| 240 | |
| 241 | while (ByteCount > 0) { |
| 242 | /* Setup the mask to use for checking errors because when receiving one |
| 243 | * byte OR the last byte of a multibyte message an error naturally |
| 244 | * occurs when the no ack is done to tell the slave the last byte |
| 245 | */ |
| 246 | if (ByteCount == 1) { |
| 247 | IntrStatusMask = |
| 248 | XIIC_INTR_ARB_LOST_MASK | XIIC_INTR_BNB_MASK; |
| 249 | } else { |
| 250 | IntrStatusMask = |
| 251 | XIIC_INTR_ARB_LOST_MASK | |
| 252 | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_BNB_MASK; |
| 253 | } |
| 254 | |
| 255 | /* Wait for the previous transmit and the 1st receive to complete |
| 256 | * by checking the interrupt status register of the IPIF |
| 257 | */ |
| 258 | while (1) { |
| 259 | IntrStatus = XIIF_V123B_READ_IISR (BaseAddress); |
| 260 | if (IntrStatus & XIIC_INTR_RX_FULL_MASK) { |
| 261 | break; |
| 262 | } |
| 263 | /* Check the transmit error after the receive full because when |
| 264 | * sending only one byte transmit error will occur because of the |
| 265 | * no ack to indicate the end of the data |
| 266 | */ |
| 267 | if (IntrStatus & IntrStatusMask) { |
| 268 | return ByteCount; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | CntlReg = XIo_In8 (BaseAddress + XIIC_CR_REG_OFFSET); |
| 273 | |
| 274 | /* Special conditions exist for the last two bytes so check for them |
| 275 | * Note that the control register must be setup for these conditions |
| 276 | * before the data byte which was already received is read from the |
| 277 | * receive FIFO (while the bus is throttled |
| 278 | */ |
| 279 | if (ByteCount == 1) { |
| 280 | /* For the last data byte, it has already been read and no ack |
| 281 | * has been done, so clear MSMS while leaving the device enabled |
| 282 | * so it can get off the IIC bus appropriately with a stop. |
| 283 | */ |
| 284 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, |
| 285 | XIIC_CR_ENABLE_DEVICE_MASK); |
| 286 | } |
| 287 | |
| 288 | /* Before the last byte is received, set NOACK to tell the slave IIC |
| 289 | * device that it is the end, this must be done before reading the byte |
| 290 | * from the FIFO |
| 291 | */ |
| 292 | if (ByteCount == 2) { |
| 293 | /* Write control reg with NO ACK allowing last byte to |
| 294 | * have the No ack set to indicate to slave last byte read. |
| 295 | */ |
| 296 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, |
| 297 | CntlReg | XIIC_CR_NO_ACK_MASK); |
| 298 | } |
| 299 | |
| 300 | /* Read in data from the FIFO and unthrottle the bus such that the |
| 301 | * next byte is read from the IIC bus |
| 302 | */ |
| 303 | *BufferPtr++ = XIo_In8 (BaseAddress + XIIC_DRR_REG_OFFSET); |
| 304 | |
| 305 | /* Clear the latched interrupt status so that it will be updated with |
| 306 | * the new state when it changes, this must be done after the receive |
| 307 | * register is read |
| 308 | */ |
| 309 | XIic_mClearIisr (BaseAddress, XIIC_INTR_RX_FULL_MASK | |
| 310 | XIIC_INTR_TX_ERROR_MASK | |
| 311 | XIIC_INTR_ARB_LOST_MASK); |
| 312 | ByteCount--; |
| 313 | } |
| 314 | |
| 315 | /* Wait for the bus to transition to not busy before returning, the IIC |
| 316 | * device cannot be disabled until this occurs. It should transition as |
| 317 | * the MSMS bit of the control register was cleared before the last byte |
| 318 | * was read from the FIFO. |
| 319 | */ |
| 320 | while (1) { |
| 321 | if (XIIF_V123B_READ_IISR (BaseAddress) & XIIC_INTR_BNB_MASK) { |
| 322 | break; |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | return ByteCount; |
| 327 | } |
| 328 | |
| 329 | /****************************************************************************/ |
| 330 | /** |
| 331 | * Send data as a master on the IIC bus. This function sends the data |
| 332 | * using polled I/O and blocks until the data has been sent. It only supports |
| 333 | * 7 bit addressing and non-repeated start modes of operation. The user is |
| 334 | * responsible for ensuring the bus is not busy if multiple masters are present |
| 335 | * on the bus. |
| 336 | * |
| 337 | * @param BaseAddress contains the base address of the IIC device. |
| 338 | * @param Address contains the 7 bit IIC address of the device to send the |
| 339 | * specified data to. |
| 340 | * @param BufferPtr points to the data to be sent. |
| 341 | * @param ByteCount is the number of bytes to be sent. |
| 342 | * |
| 343 | * @return |
| 344 | * |
| 345 | * The number of bytes sent. |
| 346 | * |
| 347 | * @note |
| 348 | * |
| 349 | * None |
| 350 | * |
| 351 | ******************************************************************************/ |
| 352 | unsigned XIic_Send (u32 BaseAddress, u8 Address, |
| 353 | u8 * BufferPtr, unsigned ByteCount) |
| 354 | { |
| 355 | unsigned RemainingByteCount; |
| 356 | |
| 357 | /* Put the address into the FIFO to be sent and indicate that the operation |
| 358 | * to be performed on the bus is a write operation |
| 359 | */ |
| 360 | XIic_mSend7BitAddress (BaseAddress, Address, XIIC_WRITE_OPERATION); |
| 361 | |
| 362 | /* Clear the latched interrupt status so that it will be updated with the |
| 363 | * new state when it changes, this must be done after the address is put |
| 364 | * in the FIFO |
| 365 | */ |
| 366 | XIic_mClearIisr (BaseAddress, XIIC_INTR_TX_EMPTY_MASK | |
| 367 | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK); |
| 368 | |
| 369 | /* MSMS must be set after putting data into transmit FIFO, indicate the |
| 370 | * direction is transmit, this device is master and enable the IIC device |
| 371 | */ |
| 372 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, |
| 373 | XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK | |
| 374 | XIIC_CR_ENABLE_DEVICE_MASK); |
| 375 | |
| 376 | /* Clear the latched interrupt |
| 377 | * status for the bus not busy bit which must be done while the bus is busy |
| 378 | */ |
| 379 | XIic_mClearIisr (BaseAddress, XIIC_INTR_BNB_MASK); |
| 380 | |
| 381 | /* Send the specified data to the device on the IIC bus specified by the |
| 382 | * the address |
| 383 | */ |
| 384 | RemainingByteCount = SendData (BaseAddress, BufferPtr, ByteCount); |
| 385 | |
| 386 | /* |
| 387 | * The send is complete, disable the IIC device and return the number of |
| 388 | * bytes that was sent |
| 389 | */ |
| 390 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, 0); |
| 391 | |
| 392 | return ByteCount - RemainingByteCount; |
| 393 | } |
| 394 | |
| 395 | /****************************************************************************** |
| 396 | * |
| 397 | * Send the specified buffer to the device that has been previously addressed |
| 398 | * on the IIC bus. This function assumes that the 7 bit address has been sent |
| 399 | * and it should wait for the transmit of the address to complete. |
| 400 | * |
| 401 | * @param BaseAddress contains the base address of the IIC device. |
| 402 | * @param BufferPtr points to the data to be sent. |
| 403 | * @param ByteCount is the number of bytes to be sent. |
| 404 | * |
| 405 | * @return |
| 406 | * |
| 407 | * The number of bytes remaining to be sent. |
| 408 | * |
| 409 | * @note |
| 410 | * |
| 411 | * This function does not take advantage of the transmit FIFO because it is |
| 412 | * designed for minimal code space and complexity. It contains loops that |
| 413 | * that could cause the function not to return if the hardware is not working. |
| 414 | * |
| 415 | ******************************************************************************/ |
| 416 | static unsigned SendData (u32 BaseAddress, u8 * BufferPtr, unsigned ByteCount) |
| 417 | { |
| 418 | u32 IntrStatus; |
| 419 | |
| 420 | /* Send the specified number of bytes in the specified buffer by polling |
| 421 | * the device registers and blocking until complete |
| 422 | */ |
| 423 | while (ByteCount > 0) { |
| 424 | /* Wait for the transmit to be empty before sending any more data |
| 425 | * by polling the interrupt status register |
| 426 | */ |
| 427 | while (1) { |
| 428 | IntrStatus = XIIF_V123B_READ_IISR (BaseAddress); |
| 429 | |
| 430 | if (IntrStatus & (XIIC_INTR_TX_ERROR_MASK | |
| 431 | XIIC_INTR_ARB_LOST_MASK | |
| 432 | XIIC_INTR_BNB_MASK)) { |
| 433 | return ByteCount; |
| 434 | } |
| 435 | |
| 436 | if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) { |
| 437 | break; |
| 438 | } |
| 439 | } |
| 440 | /* If there is more than one byte to send then put the next byte to send |
| 441 | * into the transmit FIFO |
| 442 | */ |
| 443 | if (ByteCount > 1) { |
| 444 | XIo_Out8 (BaseAddress + XIIC_DTR_REG_OFFSET, |
| 445 | *BufferPtr++); |
| 446 | } else { |
| 447 | /* Set the stop condition before sending the last byte of data so that |
| 448 | * the stop condition will be generated immediately following the data |
| 449 | * This is done by clearing the MSMS bit in the control register. |
| 450 | */ |
| 451 | XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, |
| 452 | XIIC_CR_ENABLE_DEVICE_MASK | |
| 453 | XIIC_CR_DIR_IS_TX_MASK); |
| 454 | |
| 455 | /* Put the last byte to send in the transmit FIFO */ |
| 456 | |
| 457 | XIo_Out8 (BaseAddress + XIIC_DTR_REG_OFFSET, |
| 458 | *BufferPtr++); |
| 459 | } |
| 460 | |
| 461 | /* Clear the latched interrupt status register and this must be done after |
| 462 | * the transmit FIFO has been written to or it won't clear |
| 463 | */ |
| 464 | XIic_mClearIisr (BaseAddress, XIIC_INTR_TX_EMPTY_MASK); |
| 465 | |
| 466 | /* Update the byte count to reflect the byte sent and clear the latched |
| 467 | * interrupt status so it will be updated for the new state |
| 468 | */ |
| 469 | ByteCount--; |
| 470 | } |
| 471 | |
| 472 | /* Wait for the bus to transition to not busy before returning, the IIC |
| 473 | * device cannot be disabled until this occurs. |
| 474 | * Note that this is different from a receive operation because the stop |
| 475 | * condition causes the bus to go not busy. |
| 476 | */ |
| 477 | while (1) { |
| 478 | if (XIIF_V123B_READ_IISR (BaseAddress) & XIIC_INTR_BNB_MASK) { |
| 479 | break; |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | return ByteCount; |
| 484 | } |