chinook-compat: add new toolchain options and stick to util-linux
[openembedded.git] / recipes / i2c-tools / picodlp-control / i2c-api.c
blobcfc41565a40fe0aeda2819ff9ce31b2aa1df02c1
1 /****************************************************************************
3 * Copyright (c) 2006 Dave Hylands <dhylands@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
14 ****************************************************************************/
15 /**
17 * @file i2c-api.c
19 * @brief This file contains the implementation for performing I2C operations
20 * on the gumstix.
22 ****************************************************************************/
24 // ---- Include Files -------------------------------------------------------
26 #include <string.h>
27 #include <errno.h>
29 #include "i2c.h"
30 #include "i2c-dev.h"
31 #include "i2c-api.h"
33 #include "Crc8.h"
34 #include "DumpMem.h"
35 #include "Log.h"
37 // ---- Public Variables ----------------------------------------------------
39 // ---- Private Constants and Types -----------------------------------------
41 // ---- Private Variables ---------------------------------------------------
43 static I2C_Addr_t gI2cAddr;
44 static int gUseCrc;
46 // ---- Private Function Prototypes -----------------------------------------
48 // ---- Functions -----------------------------------------------------------
50 //***************************************************************************
51 /**
53 * Sets the I2C address that we'll be communicating with, as well as whether
54 * the device uses smbus PEC (CRC).
57 void I2cSetSlaveAddress( int i2cDev, I2C_Addr_t i2cAddr, int useCrc )
59 gI2cAddr = i2cAddr;
60 gUseCrc = useCrc;
62 LogDebug( "----- I2cSetSlaveAddress i2cAddr:0x%02x useCrc:%d -----\n",
63 i2cAddr, useCrc );
65 // Indicate which slave we wish to speak to
67 if ( ioctl( i2cDev, I2C_SLAVE, gI2cAddr ) < 0 )
69 LogError( "I2cSetSlaveAddress: Error trying to set slave address to 0x%02x (%d %s)\n",
70 gI2cAddr, errno, strerror( errno ));
73 // We do the CRC calculation ourself, so we don't need to tell the driver
74 // that we're using it.
76 #if 0
77 // Indicate that we use PEC (aka CRCs)
79 if ( ioctl( i2cDev, I2C_PEC, 1 ) < 0 )
81 LogError( "I2cSetSlaveAddress: Error trying to set PEC mode\n" );
83 #endif
85 } // I2cSetSlaveAddress
87 //***************************************************************************
88 /**
89 * Transfer data to/from an i2c device.
91 * This function implements the equivalent of the smbus functions using
92 * I2C_RDWR.
94 * The PXA driver doesn't support the smbus transfers.
96 * This function can perform the following SMBUS transactions:
98 * Write Byte: wrLen == 1, rdLen == 0
99 * Read Byte: wrLen == 0, rdLen == 1
100 * Write Word: wrLen == 2, rdLen == 0
101 * Read Word: wrLen == 0, rdLen == 2
102 * Process Call: wrLen == 2, rdLen == 2
103 * Write Block: wrLen == 0x80 + numBytes, rdLen == 0
104 * Read Block: wrLen == 0, rdLen == 0x80 + numBytes
105 * Process Block: wrLen == 0x80 + numBytes, rdLen == 0x80 + numBytes
108 int I2cTransfer
110 int i2cDev, ///< Handle to i2c-dev file
111 uint8_t cmd, ///< Command to send
112 const void *wrData, ///< Data to write
113 uint8_t wrLen, ///< Number of bytes to write (or in 0x80 for a block write)
114 void *rdData, ///< Place to store data read
115 uint8_t rdLen, ///< Number of bytes to read (or in 0x80 for a block read)
116 uint8_t *bytesReadp ///< Place to store number of bytes read
119 struct i2c_rdwr_ioctl_data rdwr;
120 struct i2c_msg msg[ 2 ];
121 uint8_t wrBuf[ I2C_MAX_DATA_LEN + 3 ]; // +1 for cmd, +1 for len, +1 for CRC
122 uint8_t rdBuf[ I2C_MAX_DATA_LEN + 2 ]; // +1 for len, +1 for CRC
123 uint8_t crc = 0;
124 uint8_t wrBlock = (( wrLen & 0x80 ) != 0 );
125 uint8_t rdBlock = (( rdLen & 0x80 ) != 0 );
126 int rc = 0;
128 LogDebug( "----- I2cTransfer: cmd:0x%02x wrLen:0x%02x rdLen:0x%02x wrBlock:%d rdBlock:%d -----\n",
129 cmd, wrLen, rdLen, wrBlock, rdBlock );
130 if ( wrData != NULL )
132 LogDebug( "----- wrData:0x%08x *wrData:0x%02x -----\n", wrData, *(const uint8_t *)wrData );
135 rdLen &= 0x7f;
136 wrLen &= 0x7f;
138 if ( bytesReadp != NULL )
140 *bytesReadp = 0;
143 if ( wrLen > I2C_MAX_DATA_LEN )
145 LogError( "I2cTransfer: wrLen too big: %d, max is %d\n",
146 wrLen, I2C_MAX_DATA_LEN );
147 errno = ENOBUFS;
148 return -1;
151 if ( rdLen > I2C_MAX_DATA_LEN )
153 LogError( "I2cTransfer: rdLen too big: %d, max is %d\n",
154 rdLen, I2C_MAX_DATA_LEN );
155 errno = ENOBUFS;
156 return -1;
159 // Whether we're doing a read or a write, we always send
160 // the command.
162 msg[ 0 ].addr = gI2cAddr;
163 msg[ 0 ].flags = 0;
164 msg[ 0 ].len = wrLen + 1 + wrBlock; // +1 for cmd
165 msg[ 0 ].buf = (char *)&wrBuf[ 0 ];
167 if ( gUseCrc )
169 crc = Crc8( 0, gI2cAddr << 1 );
170 crc = Crc8( crc, cmd );
173 wrBuf[ 0 ] = cmd;
175 if ( wrLen > 0 )
177 // We have some data to send down to the device
179 if ( wrBlock )
181 wrBuf[ 1 ] = wrLen;
182 memcpy( &wrBuf[ 2 ], wrData, wrLen );
183 wrLen++; // Add in cmd to the length
185 else
187 memcpy( &wrBuf[ 1 ], wrData, wrLen );
189 if ( gUseCrc )
191 crc = Crc8Block( crc, &wrBuf[ 1 ], wrLen );
193 if ( rdLen == 0 )
195 // This is a write-only, so we need to send the CRC
197 wrBuf[ wrLen + 1 ] = crc;
198 msg[ 0 ].len++;
203 if ( gDebug )
205 Log( "msg[ 0 ].addr = 0x%02x\n", msg[ 0 ].addr );
206 Log( "msg[ 0 ].flags = 0x%04x\n", msg[ 0 ].flags );
207 Log( "msg[ 0 ].len = %d\n", msg[ 0 ].len );
208 DumpMem( "I2cTransfer W", 0, &wrBuf[ 0 ], msg[ 0 ].len );
211 rdwr.msgs = msg;
212 rdwr.nmsgs = 1;
214 if ( rdLen > 0 )
216 // We're expecting some data to come back
218 msg[ 1 ].addr = gI2cAddr;
219 msg[ 1 ].flags = I2C_M_RD;
220 msg[ 1 ].len = rdLen + rdBlock + gUseCrc;
221 msg[ 1 ].buf = (char *)&rdBuf[ 0 ];
223 rdwr.nmsgs = 2;
225 if ( gUseCrc )
227 crc = Crc8( crc, ( gI2cAddr << 1 ) | 1 );
230 if ( gDebug )
232 Log( "msg[ 1 ].addr = 0x%02x\n", msg[ 1 ].addr );
233 Log( "msg[ 1 ].flags = 0x%04x\n", msg[ 1 ].flags );
234 Log( "msg[ 1 ].len = %d\n", msg[ 1 ].len );
238 if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 )
240 LogError( "I2cTransfer: ioctl failed: %s (%d)\n", strerror( errno ), errno );
241 return -1;
244 if ( rdLen > 0 )
246 if ( rdBlock )
248 if ( rdBuf[ 0 ] > rdLen )
250 LogError( "I2cTransfer: length is too big: %d max: %d\n", rdBuf[ 0 ], rdLen );
252 rc = EMSGSIZE;
254 else
256 rdLen = rdBuf[ 0 ];
260 if ( gUseCrc )
262 crc = Crc8Block( crc, &rdBuf[ 0 ], rdLen + rdBlock );
264 if ( crc != rdBuf[ rdLen + rdBlock ] )
266 LogError( "I2cTransfer: CRC failed: Rcvd: 0x%02x, expecting: 0x%02x\n",
267 rdBuf[ rdLen + rdBlock ], crc );
268 rc = EBADMSG;
272 if ( gDebug )
274 DumpMem( "I2cTransfer R", 0, &rdBuf[ 0 ], msg[ 1 ].len );
276 memcpy( rdData, &rdBuf[ rdBlock ], rdLen );
278 if ( bytesReadp != NULL )
280 *bytesReadp = rdLen;
283 return rc;
285 } // I2cTransfer
287 //***************************************************************************
289 * Uses the SMBUS Process-Block protocol to read data from a device.
292 int I2cProcessBlock
294 int i2cDev, ///< Handle to i2c-dev file
295 uint8_t cmd, ///< Command to send
296 const void *wrData, ///< Data to write
297 uint8_t wrLen, ///< Number of bytes to write
298 void *rdData, ///< Place to store data read
299 uint8_t rdLen, ///< Number of bytes to read
300 uint8_t *bytesReadp ///< Place to store number of bytes read
303 LogDebug( "----- I2cProcessBlock cmd: 0x%02x wrLen:0x%02x rdLen:0x%02x -----\n", cmd, wrLen, rdLen );
305 return I2cTransfer( i2cDev, cmd, wrData, 0x80 | wrLen, rdData, 0x80 | rdLen, bytesReadp );
307 } // I2cProcessBlock
309 //***************************************************************************
311 * Uses the SMBUS Read-Block protocol to read data from a device.
314 int I2cReadBlock
316 int i2cDev, ///< Handle to i2c-dev file
317 uint8_t cmd, ///< Command to send
318 void *rdData, ///< Place to store data read
319 uint8_t rdLen, ///< Number of bytes to read
320 uint8_t *bytesReadp ///< Place to store number of bytes read
323 LogDebug( "----- I2cReadBlock cmd: 0x%02x rdLen:0x%02x -----\n", cmd, rdLen );
325 return I2cTransfer( i2cDev, cmd, NULL, 0, rdData, 0x80 | rdLen, bytesReadp );
327 } // I2cReadBlock
329 //***************************************************************************
331 * Uses the SMBUS Read-Byte protocol to read a byte.
334 int I2cReadByte
336 int i2cDev, ///< Handle to i2c-dev file
337 uint8_t cmd, ///< Command to send
338 uint8_t *rdByte ///< Place to store byte read
341 LogDebug( "----- I2cReadByte cmd: 0x%02x -----\n", cmd );
343 return I2cTransfer( i2cDev, cmd, NULL, 0, rdByte, 1, NULL );
345 } // I2cReadByte
347 //***************************************************************************
349 * Reads an array of bytes usinng i2c (not compatible with SMBUS)
352 int I2cReadBytes
354 int i2cDev, ///< Handle to i2c-dev file
355 uint8_t cmd, ///< Command to send
356 void *rdByte, ///< Place to store bytes read
357 uint8_t rdLen ///< Number of bytes to read
360 LogDebug( "----- I2cReadBytes cmd: 0x%02x rdLen: 0x%02x -----\n", cmd, rdLen );
362 return I2cTransfer( i2cDev, cmd, NULL, 0, rdByte, rdLen, NULL );
364 } // I2cReadBytes
366 //***************************************************************************
368 * Uses the SMBUS Write-Block protocol to write data from a device.
371 int I2cWriteBlock
373 int i2cDev, ///< Handle to i2c-dev file
374 uint8_t cmd, ///< Command to send
375 const void *wrData, ///< Data to write
376 uint8_t wrLen ///< Number of bytes to write
379 LogDebug( "----- I2cWriteBlock cmd: 0x%02x wrLen:0x%02x -----\n", cmd, wrLen );
381 return I2cTransfer( i2cDev, cmd, wrData, 0x80 | wrLen, NULL, 0, NULL );
383 } // I2cWriteBlock
385 //***************************************************************************
387 * Uses the SMBUS Write-Byte protocol to write a byte.
390 int I2cWriteByte
392 int i2cDev, ///< Handle to i2c-dev file
393 uint8_t cmd, ///< Command to send
394 uint8_t wrByte ///< Byte to write
397 LogDebug( "----- I2cWriteByte cmd: 0x%02x wrByte:0x%02x -----\n", cmd, wrByte );
398 LogDebug( "----- &wrByte = 0x%08x wrByte = 0x%02x -----\n", &wrByte, *&wrByte );
400 return I2cTransfer( i2cDev, cmd, &wrByte, 1, NULL, 0, NULL );
402 } // I2cWriteByte
404 //***************************************************************************
406 * Writes an array of bytes using i2c (not compatible with SMBUS)
409 int I2cWriteBytes
411 int i2cDev, ///< Handle to i2c-dev file
412 uint8_t cmd, ///< Command to send
413 const void *wrByte, ///< Bytes to write
414 uint8_t wrLen ///< Number of bytes to write
417 LogDebug( "----- I2cWriteBytes cmd: 0x%02x wrLen: 0x%02x -----\n", cmd, wrLen );
419 return I2cTransfer( i2cDev, cmd, wrByte, wrLen, NULL, 0, NULL );
421 } // I2cWriteBytes
423 //***************************************************************************
425 * Uses the SMBUS Receive-Byte protocol to read a byte.
428 int I2cReceiveByte
430 int i2cDev, ///< Handle to i2c-dev file
431 uint8_t *rdByte ///< Place to store byte read
434 return I2cReceiveBytes( i2cDev, rdByte, 1 );
436 } // I2cReceiveByte
438 //***************************************************************************
440 * Uses the SMBUS Receive-Byte protocol to read multiple (or one or zero) bytes.
443 int I2cReceiveBytes
445 int i2cDev, ///< Handle to i2c-dev file
446 uint8_t *rdData, ///< Place to store data read
447 uint8_t rdLen ///< Number of bytes to read
450 struct i2c_rdwr_ioctl_data rdwr;
451 struct i2c_msg msg;
453 LogDebug( "----- I2cReceiveBytes -----\n" );
455 msg.addr = gI2cAddr;
456 msg.flags = I2C_M_RD;
457 msg.len = rdLen;
458 msg.buf = (char *)rdData;
460 rdwr.msgs = &msg;
461 rdwr.nmsgs = 1;
463 if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 )
465 LogError( "I2cReceiveBytes: ioctl failed: %s (%d)\n", strerror( errno ), errno );
466 return -1;
469 return 0;
471 } // I2cReceiveBytes
473 //***************************************************************************
475 * Uses the SMBUS Send-Byte protocol to write a byte.
478 int I2cSendByte
480 int i2cDev, ///< Handle to i2c-dev file
481 uint8_t wrByte ///< Byte to write
484 return I2cSendBytes( i2cDev, &wrByte, 1 );
486 } // I2cSendByte
488 //***************************************************************************
490 * Uses the SMBUS Send-Byte protocol to write multiple (or zero or one) bytes.
493 int I2cSendBytes
495 int i2cDev, ///< Handle to i2c-dev file
496 uint8_t *wrData, ///< Pointer to data to write
497 uint8_t wrLen ///< NUmber of bytes to write
500 struct i2c_rdwr_ioctl_data rdwr;
501 struct i2c_msg msg;
503 LogDebug( "----- I2cSendBytes wrLen = 0x%02x -----\n", wrLen );
505 msg.addr = gI2cAddr;
506 msg.flags = 0;
507 msg.len = wrLen;
508 msg.buf = (char *)wrData;
510 rdwr.msgs = &msg;
511 rdwr.nmsgs = 1;
513 if ( ioctl( i2cDev, I2C_RDWR, &rdwr ) < 0 )
515 LogError( "I2cSendBytes: ioctl failed: %s (%d)\n", strerror( errno ), errno );
516 return -1;
519 return 0;
521 } // I2cSendBytes