[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_1_eng / packages / ti / board / src / flash / platform_flash / evm66x_i2c.c
1 /*
2 * Copyright (c) 2010-2015, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
34 /**
35 *
36 * \file evm66x_i2c.c
37 *
38 * \brief This contains C66x specific i2c functions.
39 *
40 ******************************************************************************/
42 /* I2C modules */
43 #include "platform_internal.h"
45 #define CUSTOM_DELAY 0x100
47 #if (PLATFORM_I2C_IN)
49 /******************************************************************************
50 *
51 * Function: i2c_check_bus_busy
52 *
53 * Description: Checks the bus busy state of I2C device
54 *
55 * Parameters: CSL_I2cRegs *i2cReg - I2C register base address
56 *
57 * Return Value: I2C_RET - status
58 *
59 ******************************************************************************/
60 static I2C_RET i2c_check_bus_busy(CSL_I2cRegs *i2cReg)
61 {
62 uint32_t timeoutCounter;
63 uint32_t pollingStatus;
65 if(i2cReg == NULL)
66 {
67 IFPRINT(platform_write("i2c_check_bus_busy: Invalid Register Base Address\n"));
68 return (I2C_RET_INVALID_PARAM);
69 }
71 /* Check for the bus busy signal */
72 timeoutCounter = 0;
74 do
75 {
76 pollingStatus = CSL_FEXT(i2cReg->ICSTR, I2C_ICSTR_BB);
78 if (pollingStatus)
79 {
80 i2cDelay (I2C_MASTER_TRANSMITTER_BUS_ACCESS_DELAY_US);
82 timeoutCounter += 1;
83 if (timeoutCounter >= I2C_MAX_MASTER_TRANSMITTER_BUS_ACCESS_TIMEOUT)
84 {
85 /* Return to slave receiver, clear nack and bus busy */
86 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
87 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
88 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
90 IFPRINT(platform_write("i2c_check_bus_busy: I2C Busy Timeout.\n"));
92 return (I2C_RET_IDLE_TIMEOUT);
93 }
94 }
95 else
96 {
97 /* The bus is free */
98 timeoutCounter = 0;
99 }
100 } while (timeoutCounter != 0);
102 return (I2C_RET_OK);
104 } // i2c_check_bus_busy
106 /******************************************************************************
107 *
108 * Function: i2c_send_stop
109 *
110 * Description: Sends stop bit on I2C bus
111 *
112 * Parameters: CSL_I2cRegs *i2cReg - I2C register base address
113 *
114 * Return Value: I2C_RET - status
115 *
116 ******************************************************************************/
117 static I2C_RET i2c_send_stop(CSL_I2cRegs *i2cReg)
118 {
119 uint32_t timeoutCounter;
120 uint32_t statusReg;
122 /* Wait for the ardy bit to go high */
123 timeoutCounter = 0;
124 do
125 {
126 statusReg = i2cReg->ICSTR;
127 if (I2C_REG_STR_FIELD_ARDY(statusReg))
128 {
129 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMTSTOP;
130 i2cReg->ICSTR = I2C_VAL_REG_STR_CLR_BUSY;
131 i2cDelay (DELAY_CONST);
132 timeoutCounter = 0;
133 }
134 else
135 {
136 /* Registers not ready for access */
137 timeoutCounter += 1;
139 if (timeoutCounter >= I2C_MAX_MASTER_TRANSMITTER_ARDY_TIMEOUT)
140 {
141 /* On timeout put the peripheral into reset, wait, then
142 * take it out of reset */
143 i2cReg->ICMDR = I2C_VAL_REG_MDR_RESET;
144 i2cDelay (DELAY_CONST);
145 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
146 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
148 IFPRINT(platform_write("i2c_send_stop: I2C Device Timeout - ARDY Not Set\n"));
150 return (I2C_RET_IDLE_TIMEOUT);
151 }
153 i2cDelay (DELAY_CONST);
154 }
155 } while (timeoutCounter != 0);
157 return (I2C_RET_OK);
159 } // i2c_send_stop
161 /******************************************************************************
162 *
163 * Function: i2c_transfer
164 *
165 * Description: Function to transfer a byte of data on I2C bus
166 *
167 * Parameters: CSL_I2cRegs *i2cReg - I2C register base address
168 * uint8_t *pData - Pointer to the data byte
169 * uint8_t rdWrFlag - Flag to indicate whether to read data
170 * from the bus or write data to bus
171 * I2C_TRANSFER_READ - Reads data
172 * I2C_TRANSFER_WRITE - Writes data
173 *
174 * Return Value: I2C_RET - status
175 *
176 ******************************************************************************/
177 static I2C_RET i2c_transfer(CSL_I2cRegs *i2cReg, uint8_t *pData, uint8_t rdWrFlag)
178 {
179 uint32_t timeoutCounter;
180 uint32_t statusReg;
182 IFPRINT_I2CDEBUG(platform_write("%s\n", __FUNCTION__));
183 do
184 {
185 /* Read status */
186 statusReg = i2cReg->ICSTR;
188 /* On Nack return failure */
189 if (I2C_REG_STR_FIELD_NACK(statusReg))
190 {
191 /* Return to slave receiver, clear nack and bus busy */
192 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
193 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
194 platform_errno = PLATFORM_ERRNO_DEV_NAK;
196 IFPRINT(platform_write("i2c_transfer: I2C NAK Error\n"));
198 return (I2C_RET_NO_ACK);
199 }
201 /* Check if bus is ready for data transfer */
202 if ((rdWrFlag == I2C_TRANSFER_WRITE) &&
203 I2C_REG_STR_FIELD_XRDY(statusReg))
204 {
205 /* Write data Transmit Data Register */
206 i2cReg->ICDXR = *pData;
207 timeoutCounter = 0;
208 }
209 else if ((rdWrFlag == I2C_TRANSFER_READ) &&
210 I2C_REG_STR_FIELD_RRDY(statusReg))
211 {
212 *pData = i2cReg->ICDRR & 0x00ff;
213 timeoutCounter = 0;
214 }
215 else
216 {
217 /* Bus is not ready for transfer */
218 i2cDelay (DELAY_CONST);
219 timeoutCounter += 1;
221 if (timeoutCounter >= I2C_MAX_MASTER_TRANSFER_TIMEOUT)
222 {
223 /* Return to slave receiver, clear nack and bus busy */
224 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
225 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
226 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
228 IFPRINT(platform_write("i2c_transfer: I2C Device Timeout - Not Ready for Data Transfer\n"));
230 return (I2C_RET_IDLE_TIMEOUT);
231 }
232 }
233 } while (timeoutCounter != 0);
235 return (I2C_RET_OK);
237 } // i2c_transfer
239 /******************************************************************************
240 *
241 * Function: i2cGetRegBaseAddr
242 *
243 * Description: Returns base address of given I2C port number.
244 *
245 * Return Value: CSL_I2cRegs*
246 ******************************************************************************/
247 CSL_I2cRegs* i2cGetRegBaseAddr(uint8_t i2cPortNumber)
248 {
249 CSL_I2cRegs *addr;
251 switch(i2cPortNumber)
252 {
253 case I2C_PORT_0:
254 addr = (CSL_I2cRegs *)CSL_I2C_0_DATA_CFG_REGS;
255 break;
257 case I2C_PORT_1:
258 addr = (CSL_I2cRegs *)CSL_I2C_1_DATA_CFG_REGS;
259 break;
261 case I2C_PORT_2:
262 addr = (CSL_I2cRegs *)CSL_I2C_2_DATA_CFG_REGS;
263 break;
265 default :
266 IFPRINT(platform_write("i2cGetRegBaseAddr: Invalid I2C Port Number\n"));
267 addr = NULL;
268 break;
269 }
271 return (addr);
272 } //i2cGetRegBaseAddr
274 /******************************************************************************
275 *
276 * Function: evmI2CInit
277 *
278 * Description: This function initializes I2C module.
279 *
280 * Parameters: uint8_t i2cportnumber - The i2c port number
281 *
282 * Return Value: void
283 ******************************************************************************/
284 void evmI2CInit(uint8_t i2cportnumber)
285 {
286 i2cConfig(i2cportnumber);
287 } //evmI2CInit
289 /******************************************************************************
290 *
291 * Function: i2cConfig
292 *
293 * Description: This function configures I2C module.
294 *
295 * Parameters: uint8_t i2cportnumber - The i2c port number
296 *
297 * Return Value: void
298 ******************************************************************************/
299 I2C_RET i2cConfig(uint8_t i2cPortNumber)
300 {
301 CSL_I2cRegs *i2cReg;
303 if(i2cPortNumber < CSL_I2C_CNT)
304 {
305 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
306 }
307 else
308 {
309 IFPRINT(platform_write("i2cConfig: Invalid I2C Port Number\n"));
310 return (I2C_RET_INVALID_PARAM);
311 }
313 // Set I2C in reset
314 i2cReg->ICMDR &= (~CSL_I2C_ICMDR_IRS_MASK);
316 i2cDelay(100);
318 // Set Own Address
319 i2cReg->ICOAR = I2C_OWN_ADDR;
321 // Set Default I2C High and Low Clock Hold
322 i2cReg->ICPSC = I2C_PRESCALER;
323 i2cReg->ICCLKL = I2C_CLK_LOW;
324 i2cReg->ICCLKH = I2C_CLK_HIGH;
326 // Enable the Xmt, Master Mode
327 i2cReg->ICMDR = ( CSL_I2C_ICMDR_MST_MASK |
328 CSL_I2C_ICMDR_TRX_MASK |
329 CSL_I2C_ICMDR_FREE_MASK );
331 // Take I2C Out of Reset
332 i2cReg->ICMDR |= CSL_I2C_ICMDR_IRS_MASK;
334 i2cDelay(100);
336 return (I2C_RET_OK);
337 } //i2cConfig
339 /******************************************************************************
340 *
341 * Function: i2cWrite
342 *
343 * Description: Enters master transmitter mode, writes a specified number
344 * of bytes to the given slave address.
345 *
346 * Note: It is expected that address offset of the I2C slave device to write
347 * data is part of pData in the format expected by the device.
348 *
349 * Parameters: uint8_t i2cPortNumber - The i2c port number
350 * uint8_t slaveAddress - i2c slave device address
351 * uint8_t *pData - Pointer to the buffer base address
352 * uint32_t numBytes - Number of bytes of buffer
353 * uint32_t endBusState - The state on which bus should be left
354 *
355 * Return Value: I2C_RET - status
356 *
357 ******************************************************************************/
358 I2C_RET i2cWrite( uint8_t i2cPortNumber, uint8_t slaveAddress, uint8_t *pData,
359 uint32_t numBytes, uint32_t endBusState)
360 {
361 uint32_t count;
362 I2C_RET returnValue;
363 CSL_I2cRegs *i2cReg;
365 IFPRINT_I2CDEBUG(platform_write("i2cWrite: "
366 "I2C Port Number - %d "
367 "I2C Slave Address - 0x%x "
368 "Bytes to Write - %d "
369 "End Bus State - %d\n",
370 i2cPortNumber, slaveAddress,
371 numBytes, endBusState));
373 returnValue = I2C_RET_OK;
375 if((i2cPortNumber < CSL_I2C_CNT) && (pData != NULL))
376 {
377 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
378 }
379 else
380 {
381 IFPRINT(platform_write("i2cWrite: Invalid I2C Port Number\n"));
382 return (I2C_RET_INVALID_PARAM);
383 }
385 /* Check for the bus busy signal */
386 returnValue = i2c_check_bus_busy(i2cReg);
387 if(returnValue != I2C_RET_OK)
388 {
389 IFPRINT(platform_write("i2cWrite: I2C Busy Check Failed\n"));
390 return (returnValue);
391 }
393 /* Enter master transmitter mode, set the slave address register */
394 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMT;
395 i2cReg->ICCNT = numBytes;
396 i2cReg->ICSAR = slaveAddress;
397 i2cDelay (DELAY_CONST);
399 /* Set the start bit */
400 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMTSTRT;
402 for (count = 0; count < numBytes; count++)
403 {
404 returnValue = i2c_transfer(i2cReg, pData, I2C_TRANSFER_WRITE);
405 if(returnValue != I2C_RET_OK)
406 {
407 IFPRINT(platform_write("i2cWrite: I2C Data Transfer Failed\n"));
408 return (returnValue);
409 }
411 pData += 1;
412 } /* end for loop */
414 /* If releasing the bus, send a stop bit */
415 if (endBusState == I2C_RELEASE_BUS)
416 {
417 returnValue = i2c_send_stop(i2cReg);
418 }
420 return (returnValue);
422 } // i2cWrite
424 /******************************************************************************
425 *
426 * Function: i2cRead
427 *
428 * Description: Reads a fixed number of bytes from an I2C device. The read
429 * consists of a master write of slave address (maximum 4 bytes)
430 * followed by a master read of the input number of bytes.
431 *
432 * Parameters: uint8_t i2cPortNumber - The i2c port number
433 * uint8_t slaveAddress - i2c slave device address
434 * uint8_t *pData - Pointer to the buffer base address
435 * uint8_t readOffset - Offset to read from
436 * uint8_t OffsetLen - Length of read offset in bytes (1 to 4)
437 * uint32_t numBytes - Number of bytes of buffer
438 *
439 * Return Value: I2C_RET - status
440 *
441 ******************************************************************************/
442 I2C_RET i2cRead ( uint8_t i2cPortNumber, uint8_t slaveAddress, uint8_t *pData,
443 uint32_t readOffset, uint32_t OffsetLen, uint32_t numBytes)
444 {
446 uint32_t statusReg;
447 uint32_t timeoutCounter;
448 uint32_t count;
449 uint16_t ushValue;
450 I2C_RET returnValue;
451 uint8_t offsetByte[4];
452 CSL_I2cRegs *i2cReg;
454 IFPRINT_I2CDEBUG(platform_write("i2cRead: "
455 "I2C Port Number - %d "
456 "I2C Slave Address - %d "
457 "Bytes to Read - %d "
458 "Read Offset - %d "
459 "Read Offset Length - %d\n",
460 i2cPortNumber, slaveAddress,
461 numBytes, readOffset, OffsetLen));
463 if(i2cPortNumber < CSL_I2C_CNT)
464 {
465 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
466 }
467 else
468 {
469 IFPRINT(platform_write("i2cRead: Invalid I2C Port Number\n"));
470 return (I2C_RET_INVALID_PARAM);
471 }
473 if((OffsetLen < I2C_MIN_OFFSET_LEN) ||
474 (OffsetLen > I2C_MAX_OFFSET_LEN))
475 {
476 IFPRINT(platform_write("i2cRead: Invalid Offset Length\n"));
477 return (I2C_RET_INVALID_PARAM);
478 }
480 for (count = OffsetLen; count > 0; count--)
481 {
482 offsetByte[OffsetLen - count] = (readOffset >> (8*(count-1))) & 0xff;
483 }
485 /* Write the byte address to the eeprom. Do not send a stop */
486 returnValue = i2cWrite(i2cPortNumber, slaveAddress, offsetByte,
487 OffsetLen, I2C_DO_NOT_RELEASE_BUS);
488 if (returnValue != I2C_RET_OK)
489 {
490 IFPRINT(platform_write("i2cRead: Slave Address Write Failed\n"));
491 return (returnValue);
492 }
494 /* Give the I2C prom 10ms to process the read command */
495 i2cDelay (DELAY_CONST);
497 /* Set the start bit, begin the master read */
498 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTRCV;
499 i2cReg->ICCNT = numBytes;
501 for (count = 0; count < numBytes; count++)
502 {
503 returnValue = i2c_transfer(i2cReg, pData, I2C_TRANSFER_READ);
504 if (returnValue != I2C_RET_OK)
505 {
506 IFPRINT(platform_write("i2cRead: I2C Data Read Failed\n"));
507 return (returnValue);
508 }
509 pData++;
510 }
512 /* The data block has been read. Send the stop bit */
513 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTRCVSTOP;
515 /* Wait for the rrdy and read the dummy byte */
516 timeoutCounter = 0;
517 do
518 {
519 statusReg = i2cReg->ICSTR;
521 /* Check for receive byte ready */
522 if (I2C_REG_STR_FIELD_RRDY(statusReg))
523 {
524 ushValue = i2cReg->ICDRR & 0x00ff;
525 ushValue = ushValue; // To avoid compilation warning!
526 timeoutCounter = 0;
527 }
528 else
529 { /* rrdy not set */
530 i2cDelay (DELAY_CONST);
531 timeoutCounter += 1;
533 if (timeoutCounter >= I2C_MAX_MASTER_RECEIVE_TIMEOUT)
534 {
535 /* Return to slave receiver, clear nack and bus busy */
536 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
537 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
538 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
540 IFPRINT(platform_write("i2cRead: I2C Timeout While Reading Dummy Byte\n"));
542 return (I2C_RET_IDLE_TIMEOUT);
543 }
544 }
545 } while (timeoutCounter != 0);
547 return (I2C_RET_OK);
549 } // i2cRead
551 /******************************************************************************
552 *
553 * Function: i2cWriteLong
554 *
555 * Description: Function to write long format (32 bit) data to I2C device.
556 * Enters master transmitter mode, writes a specified number
557 * of bytes to the given slave address. Data will be written
558 * with MSB first.
559 *
560 * Note: This function is provided for special use-cases to save CPU cycles
561 * when the data buffers are available in long format. i2cWrite shall be used
562 * for all the normal I2C data write requirements. Address to write the data
563 * shall be provided separately to this function instead of adding at the
564 * beginning of data buffer. This is to avoid aligning of address offset with
565 * long data format as address offset will be 1 or 2 bytes in general.
566 *
567 * Parameters: uint8_t i2cPortNumber - The i2c port number
568 * uint8_t slaveAddress - i2c slave device address
569 * uint32_t *pData - Pointer to the buffer base address
570 * uint8_t writeOffset - Offset to write data
571 * uint8_t OffsetLen - Length of write offset in bytes(1 to 4)
572 * uint32_t numBytes - Number of bytes in 'pData'
573 * uint32_t endBusState - The state on which bus should be left
574 *
575 * Return Value: I2C_RET - status
576 *
577 ******************************************************************************/
578 I2C_RET i2cWriteLong( uint8_t i2cPortNumber, uint8_t slaveAddress,
579 uint32_t *pData, uint32_t writeOffset, uint32_t OffsetLen,
580 uint32_t numBytes, uint32_t endBusState)
581 {
582 uint32_t count;
583 I2C_RET returnValue = I2C_RET_OK;
584 uint8_t byteCount;
585 uint8_t data;
586 CSL_I2cRegs *i2cReg;
588 IFPRINT_I2CDEBUG(platform_write("i2cWriteLong: "
589 "I2C Port Number - %d "
590 "I2C Slave Address - %d "
591 "Bytes to Write - %d "
592 "End Bus State - %d ",
593 "Write Offset - %d ",
594 "Write Offset Length - %d\n",
595 i2cPortNumber, slaveAddress,
596 numBytes, endBusState,
597 writeOffset, OffsetLen));
599 if((i2cPortNumber < CSL_I2C_CNT) && (pData != NULL))
600 {
601 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
602 }
603 else
604 {
605 IFPRINT(platform_write("i2cWriteLong: Invalid I2C Port Number\n"));
606 return (I2C_RET_INVALID_PARAM);
607 }
609 if((OffsetLen < I2C_MIN_OFFSET_LEN) ||
610 (OffsetLen > I2C_MAX_OFFSET_LEN))
611 {
612 IFPRINT(platform_write("i2cWriteLong: Invalid Offset Length\n"));
613 return (I2C_RET_INVALID_PARAM);
614 }
616 /* Check for the bus busy signal */
617 returnValue = i2c_check_bus_busy(i2cReg);
618 if(returnValue != I2C_RET_OK)
619 {
620 IFPRINT(platform_write("i2cWriteLong: I2C Busy Check Failed\n"));
621 return (returnValue);
622 }
624 /* Enter master transmitter mode, set the slave address register */
625 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMT;
626 i2cReg->ICSAR = slaveAddress;
627 i2cReg->ICCNT = numBytes + OffsetLen;
628 i2cDelay (DELAY_CONST);
630 /* Set the start bit */
631 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMTSTRT;
633 for (count = OffsetLen; count > 0; count--)
634 {
635 data = (writeOffset >> (8*(count-1))) & 0xff;
636 returnValue = i2c_transfer(i2cReg, &data, I2C_TRANSFER_WRITE);
637 if(returnValue != I2C_RET_OK)
638 {
639 IFPRINT(platform_write("i2cWriteLong: I2C Slave Write Failed\n"));
640 return (returnValue);
641 }
642 }
644 for (count = 0; count < numBytes; )
645 {
646 for(byteCount = 4; (byteCount > 0) && (count < numBytes); byteCount--)
647 {
648 data = (*pData >> (8*(byteCount-1))) & 0xff;
649 returnValue = i2c_transfer(i2cReg, &data, I2C_TRANSFER_WRITE);
650 if(returnValue != I2C_RET_OK)
651 {
652 IFPRINT(platform_write("i2cWriteLong: I2C Data Write Failed\n"));
653 return (returnValue);
654 }
656 count += 1;
657 }
659 pData += 1;
661 } /* end for loop */
663 /* If releasing the bus, send a stop bit */
664 if (endBusState == I2C_RELEASE_BUS)
665 {
666 returnValue = i2c_send_stop(i2cReg);
667 }
669 return (returnValue);
671 } // i2cWriteLong
673 /******************************************************************************
674 *
675 * Function: i2cDelay
676 *
677 * Description: Creates a delay.
678 *
679 * Parameters: uint32_t count - Counter for the loop
680 *
681 * Return Value: void
682 *
683 ******************************************************************************/
684 void i2cDelay (uint32_t count)
685 {
686 uint32_t i;
688 for (i = 0; i < count; i++)
689 {
690 platform_delaycycles(50000);
691 }
692 } //i2cDelay
694 /******************************************************************************
695 *
696 * Function: i2c_force_release_bus
697 *
698 * Description: Performs force release of I2C bus
699 *
700 * Parameters: uint8_t i2cPortNumber - The i2c port number
701 *
702 * Return Value: I2C_RET - status
703 *
704 ******************************************************************************/
705 static I2C_RET i2c_force_release_bus(uint8_t i2cPortNumber)
706 {
707 uint32_t timeoutCounter;
708 uint32_t statusReg;
709 CSL_I2cRegs *i2cReg;
711 if(i2cPortNumber < CSL_I2C_CNT)
712 {
713 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
714 }
715 else
716 {
717 IFPRINT(platform_write("i2c_force_release_bus: Invalid I2C Port Number\n"));
718 return (I2C_RET_INVALID_PARAM);
719 }
721 /* If releasing the bus, send a stop bit */
722 /* Wait for the ardy bit to go high */
723 timeoutCounter = 0;
725 do
726 {
727 statusReg = i2cReg->ICSTR;
728 if (I2C_REG_STR_FIELD_ARDY(statusReg))
729 {
730 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTXMTSTOP;
731 i2cReg->ICSTR = I2C_VAL_REG_STR_CLR_BUSY;
732 i2cDelay (DELAY_CONST);
734 if(I2C_REG_STR_FIELD_BB(i2cReg->ICSTR))
735 {
736 /* Some grave issue -- Issue reset*/
737 i2cReg->ICMDR = I2C_VAL_REG_MDR_RESET;
738 i2cDelay (0x100);
739 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
740 }
742 i2cDelay (DELAY_CONST);
743 timeoutCounter = 0;
744 }
745 else
746 {
747 /* Registers not ready for access */
748 timeoutCounter += 1;
749 if (timeoutCounter >= I2C_MAX_MASTER_TRANSMITTER_ARDY_TIMEOUT)
750 {
751 /* On timeout put the peripheral into reset, wait, then
752 * take it out of reset */
753 i2cReg->ICMDR = I2C_VAL_REG_MDR_RESET;
754 i2cDelay (0x100);
755 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
756 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
758 IFPRINT(platform_write("i2c_force_release_bus: I2C Device Timeout - ARDY Not Set\n"));
760 return (I2C_RET_IDLE_TIMEOUT);
761 }
763 i2cDelay (DELAY_CONST);
764 }
765 } while (timeoutCounter != 0);
767 return (I2C_RET_OK);
768 } // i2c_force_release_bus
770 /******************************************************************************
771 *
772 * Function: i2cProbe
773 *
774 * Description: Function to probe I2C devices
775 *
776 * This function initiates data transfer with given I2C slave address and checks
777 * if it responds with proper acknowledgement
778 *
779 * Parameters: uint8_t i2cPortNumber - The i2c port number
780 * uint8_t slaveAddress - i2c slave device address
781 * uint8_t offset - Offset with in slave device
782 * uint32_t *pData - Pointer to the buffer base address
783 * uint32_t numBytes - Number of bytes in 'pData'
784 *
785 * Return Value: I2C_RET - status
786 *
787 ******************************************************************************/
788 I2C_RET i2cProbe (uint8_t i2cPortNumber, uint8_t slaveAddress,
789 uint32_t offset, uint8_t *pData, uint32_t numBytes)
790 {
791 uint32_t statusReg;
792 uint32_t timeoutCounter;
793 uint32_t count;
794 I2C_RET returnValue;
795 uint16_t ushValue;
796 uint8_t offsetPtr[4];
797 uint8_t offsetLen=0;
798 uint32_t index;
799 CSL_I2cRegs *i2cReg;
801 if(i2cPortNumber < CSL_I2C_CNT)
802 {
803 i2cReg = i2cGetRegBaseAddr(i2cPortNumber);
804 }
805 else
806 {
807 IFPRINT(platform_write("i2cProbe: Invalid I2C Port Number\n"));
808 return (I2C_RET_INVALID_PARAM);
809 }
811 offsetLen = 1;
813 for (index = 0; index < offsetLen; index++)
814 {
815 offsetPtr[offsetLen - index - 1] = ((offset >> (8*index)) & 0xFF);
816 }
818 /* Write the offset address to the I2C slave. Do not send a stop */
819 returnValue = i2cWrite( i2cPortNumber, slaveAddress, offsetPtr,
820 offsetLen, I2C_DO_NOT_RELEASE_BUS);
821 if (returnValue != I2C_RET_OK)
822 {
823 IFPRINT(platform_write("i2cProbe: I2C Slave Address Write Failed\n"));
824 return (returnValue);
825 }
827 /* Give the I2C prom 10ms to process the read command */
828 i2cDelay (DELAY_CONST);
829 i2cDelay (DELAY_CONST);
831 /* Set the start bit, begin the master read */
832 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTRCV;
834 for (count = 0; count < numBytes; count++)
835 {
836 timeoutCounter = 0;
838 do
839 {
840 /* Read status */
841 statusReg = i2cReg->ICSTR;
843 /* On Nack return failure */
844 if (I2C_REG_STR_FIELD_NACK(statusReg))
845 {
846 /* Return to slave receiver, clear nack and bus busy */
847 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
848 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
849 platform_errno = PLATFORM_ERRNO_DEV_NAK;
851 IFPRINT(platform_write("i2cProbe: I2C NAK Error\n"));
852 i2cDelay(CUSTOM_DELAY);
853 i2c_force_release_bus(i2cPortNumber);
854 i2cDelay(CUSTOM_DELAY);
855 return (I2C_RET_NO_ACK_READ);
856 }
858 /* Check for receive byte ready */
859 if (I2C_REG_STR_FIELD_RRDY(statusReg))
860 {
861 ushValue = i2cReg->ICDRR & 0x00ff;
862 timeoutCounter = 0;
863 *pData = ushValue;
864 pData++;
865 }
866 else
867 { /* RRDY bit not set */
868 i2cDelay (DELAY_CONST);
869 timeoutCounter += 1;
871 if (timeoutCounter >= I2C_MAX_MASTER_RECEIVE_TIMEOUT)
872 {
873 /* Return to slave receiver, clear nack and bus busy */
874 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
875 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
876 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
878 IFPRINT(platform_write("i2cProbe: I2C Device Timeout\n"));
879 i2cDelay(CUSTOM_DELAY);
880 i2c_force_release_bus(i2cPortNumber);
881 i2cDelay(CUSTOM_DELAY);
882 return (I2C_RET_IDLE_TIMEOUT);
883 }
884 }
885 } while (timeoutCounter != 0);
886 } /* end for loop */
888 /* The data block has been read. Send the stop bit */
889 i2cReg->ICMDR = I2C_VAL_REG_MDR_MSTRCVSTOP;
891 /* Wait for the rrdy and read the dummy byte */
892 timeoutCounter = 0;
894 do
895 {
896 statusReg = i2cReg->ICSTR;
898 /* Check for receive byte ready */
899 if (I2C_REG_STR_FIELD_RRDY(statusReg))
900 {
901 ushValue = i2cReg->ICDRR & 0x00ff;
902 timeoutCounter = 0;
903 }
904 else
905 { /* rrdy not set */
906 i2cDelay (DELAY_CONST);
907 timeoutCounter += 1;
908 if (timeoutCounter >= I2C_MAX_MASTER_RECEIVE_TIMEOUT)
909 {
910 /* Return to slave receiver, clear nack and bus busy */
911 i2cReg->ICMDR = I2C_VAL_REG_MDR_SLVRCV;
912 i2cReg->ICSTR = I2C_VAL_REG_STR_ON_FAIL;
913 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
915 IFPRINT(platform_write("i2cProbe: I2C Device Timeout - RRDY not set\n"));
916 i2cDelay(CUSTOM_DELAY);
917 i2c_force_release_bus(i2cPortNumber);
918 i2cDelay(CUSTOM_DELAY);
919 return (I2C_RET_IDLE_TIMEOUT);
920 }
921 }
922 } while (timeoutCounter != 0);
924 i2c_force_release_bus(i2cPortNumber);
926 return (I2C_RET_OK);
927 } // i2cProbe
929 #endif /* #if (PLATFORM_I2C_IN) */
930 /* Nothing past this point */