2005-04-17 02:20:36 +04:00
/* ------------------------------------------------------------------------- */
/* i2c-algo-bit.c i2c driver algorithms for bit-shift adapters */
/* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-2000 Simon G. Vogl
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
/* ------------------------------------------------------------------------- */
/* With some changes from Frodo Looijaard <frodol@dds.nl>, Ky<4B> sti M<> lkki
< kmalkki @ cc . hut . fi > and Jean Delvare < khali @ linux - fr . org > */
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/sched.h>
# include <linux/i2c.h>
# include <linux/i2c-algo-bit.h>
/* ----- global defines ----------------------------------------------- */
2007-05-02 01:26:33 +04:00
# ifdef DEBUG
# define bit_dbg(level, dev, format, args...) \
do { \
if ( i2c_debug > = level ) \
dev_dbg ( dev , format , # # args ) ; \
} while ( 0 )
# else
# define bit_dbg(level, dev, format, args...) \
do { } while ( 0 )
# endif /* DEBUG */
2005-04-17 02:20:36 +04:00
/* ----- global variables --------------------------------------------- */
static int bit_test ; /* see if the line-setting functions work */
2007-05-02 01:26:33 +04:00
module_param ( bit_test , bool , 0 ) ;
MODULE_PARM_DESC ( bit_test , " Test the lines of the bus to see if it is stuck " ) ;
# ifdef DEBUG
static int i2c_debug = 1 ;
module_param ( i2c_debug , int , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( i2c_debug ,
" debug level - 0 off; 1 normal; 2 verbose; 3 very verbose " ) ;
# endif
2005-04-17 02:20:36 +04:00
/* --- setting states on the bus with the right timing: --------------- */
# define setsda(adap,val) adap->setsda(adap->data, val)
# define setscl(adap,val) adap->setscl(adap->data, val)
# define getsda(adap) adap->getsda(adap->data)
# define getscl(adap) adap->getscl(adap->data)
static inline void sdalo ( struct i2c_algo_bit_data * adap )
{
setsda ( adap , 0 ) ;
2007-05-02 01:26:33 +04:00
udelay ( ( adap - > udelay + 1 ) / 2 ) ;
2005-04-17 02:20:36 +04:00
}
static inline void sdahi ( struct i2c_algo_bit_data * adap )
{
setsda ( adap , 1 ) ;
2007-05-02 01:26:33 +04:00
udelay ( ( adap - > udelay + 1 ) / 2 ) ;
2005-04-17 02:20:36 +04:00
}
static inline void scllo ( struct i2c_algo_bit_data * adap )
{
setscl ( adap , 0 ) ;
2007-05-02 01:26:33 +04:00
udelay ( adap - > udelay / 2 ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Raise scl line , and do checking for delays . This is necessary for slower
* devices .
*/
2006-09-04 00:22:12 +04:00
static int sclhi ( struct i2c_algo_bit_data * adap )
2005-04-17 02:20:36 +04:00
{
unsigned long start ;
setscl ( adap , 1 ) ;
/* Not all adapters have scl sense line... */
2006-09-04 00:22:12 +04:00
if ( ! adap - > getscl )
goto done ;
2005-04-17 02:20:36 +04:00
start = jiffies ;
while ( ! getscl ( adap ) ) {
/* the hw knows how to read the clock line,
* so we wait until it actually gets high .
* This is safer as some chips may hold it low
* while they are processing data internally .
*/
if ( time_after_eq ( jiffies , start + adap - > timeout ) ) {
return - ETIMEDOUT ;
}
cond_resched ( ) ;
}
2007-05-02 01:26:33 +04:00
# ifdef DEBUG
if ( jiffies ! = start & & i2c_debug > = 3 )
pr_debug ( " i2c-algo-bit: needed %ld jiffies for SCL to go "
" high \n " , jiffies - start ) ;
# endif
2006-09-04 00:22:12 +04:00
done :
2005-04-17 02:20:36 +04:00
udelay ( adap - > udelay ) ;
return 0 ;
}
/* --- other auxiliary functions -------------------------------------- */
static void i2c_start ( struct i2c_algo_bit_data * adap )
{
/* assert: scl, sda are high */
2007-05-02 01:26:33 +04:00
setsda ( adap , 0 ) ;
udelay ( adap - > udelay ) ;
2005-04-17 02:20:36 +04:00
scllo ( adap ) ;
}
static void i2c_repstart ( struct i2c_algo_bit_data * adap )
{
2007-05-02 01:26:33 +04:00
/* assert: scl is low */
sdahi ( adap ) ;
2005-04-17 02:20:36 +04:00
sclhi ( adap ) ;
2007-05-02 01:26:33 +04:00
setsda ( adap , 0 ) ;
udelay ( adap - > udelay ) ;
2005-04-17 02:20:36 +04:00
scllo ( adap ) ;
}
static void i2c_stop ( struct i2c_algo_bit_data * adap )
{
/* assert: scl is low */
sdalo ( adap ) ;
sclhi ( adap ) ;
2007-05-02 01:26:33 +04:00
setsda ( adap , 1 ) ;
udelay ( adap - > udelay ) ;
2005-04-17 02:20:36 +04:00
}
/* send a byte without start cond., look for arbitration,
check ackn . from slave */
/* returns:
* 1 if the device acknowledged
* 0 if the device did not ack
* - ETIMEDOUT if an error occurred ( while raising the scl line )
*/
2007-05-02 01:26:33 +04:00
static int i2c_outb ( struct i2c_adapter * i2c_adap , unsigned char c )
2005-04-17 02:20:36 +04:00
{
int i ;
int sb ;
int ack ;
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
/* assert: scl is low */
for ( i = 7 ; i > = 0 ; i - - ) {
2007-05-02 01:26:33 +04:00
sb = ( c > > i ) & 1 ;
2005-04-17 02:20:36 +04:00
setsda ( adap , sb ) ;
2007-05-02 01:26:33 +04:00
udelay ( ( adap - > udelay + 1 ) / 2 ) ;
2005-04-17 02:20:36 +04:00
if ( sclhi ( adap ) < 0 ) { /* timed out */
2007-05-02 01:26:33 +04:00
bit_dbg ( 1 , & i2c_adap - > dev , " i2c_outb: 0x%02x, "
" timeout at bit #%d \n " , ( int ) c , i ) ;
2005-04-17 02:20:36 +04:00
return - ETIMEDOUT ;
} ;
/* do arbitration here:
* if ( sb & & ! getsda ( adap ) ) - > ouch ! Get out of here .
*/
2007-05-02 01:26:33 +04:00
scllo ( adap ) ;
2005-04-17 02:20:36 +04:00
}
sdahi ( adap ) ;
if ( sclhi ( adap ) < 0 ) { /* timeout */
2007-05-02 01:26:33 +04:00
bit_dbg ( 1 , & i2c_adap - > dev , " i2c_outb: 0x%02x, "
" timeout at ack \n " , ( int ) c ) ;
return - ETIMEDOUT ;
2005-04-17 02:20:36 +04:00
} ;
/* read ack: SDA should be pulled down by slave */
2007-05-02 01:26:33 +04:00
ack = ! getsda ( adap ) ; /* ack: sda is pulled low -> success */
bit_dbg ( 2 , & i2c_adap - > dev , " i2c_outb: 0x%02x %s \n " , ( int ) c ,
ack ? " A " : " NA " ) ;
2005-04-17 02:20:36 +04:00
scllo ( adap ) ;
2007-05-02 01:26:33 +04:00
return ack ;
2005-04-17 02:20:36 +04:00
/* assert: scl is low (sda undef) */
}
static int i2c_inb ( struct i2c_adapter * i2c_adap )
{
/* read byte via i2c port, without start/stop sequence */
/* acknowledge is sent in i2c_read. */
int i ;
unsigned char indata = 0 ;
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
/* assert: scl is low */
sdahi ( adap ) ;
for ( i = 0 ; i < 8 ; i + + ) {
if ( sclhi ( adap ) < 0 ) { /* timeout */
2007-05-02 01:26:33 +04:00
bit_dbg ( 1 , & i2c_adap - > dev , " i2c_inb: timeout at bit "
" #%d \n " , 7 - i ) ;
2005-04-17 02:20:36 +04:00
return - ETIMEDOUT ;
} ;
indata * = 2 ;
if ( getsda ( adap ) )
indata | = 0x01 ;
2007-05-02 01:26:33 +04:00
setscl ( adap , 0 ) ;
udelay ( i = = 7 ? adap - > udelay / 2 : adap - > udelay ) ;
2005-04-17 02:20:36 +04:00
}
/* assert: scl is low */
2007-05-02 01:26:33 +04:00
return indata ;
2005-04-17 02:20:36 +04:00
}
/*
* Sanity check for the adapter hardware - check the reaction of
* the bus lines only if it seems to be idle .
*/
static int test_bus ( struct i2c_algo_bit_data * adap , char * name ) {
int scl , sda ;
if ( adap - > getscl = = NULL )
2007-05-02 01:26:33 +04:00
pr_info ( " %s: Testing SDA only, SCL is not readable \n " , name ) ;
2005-04-17 02:20:36 +04:00
sda = getsda ( adap ) ;
scl = ( adap - > getscl = = NULL ? 1 : getscl ( adap ) ) ;
if ( ! scl | | ! sda ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: bus seems to be busy \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
sdalo ( adap ) ;
sda = getsda ( adap ) ;
scl = ( adap - > getscl = = NULL ? 1 : getscl ( adap ) ) ;
if ( 0 ! = sda ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SDA stuck high! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
if ( 0 = = scl ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SCL unexpected low "
" while pulling SDA low! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
sdahi ( adap ) ;
sda = getsda ( adap ) ;
scl = ( adap - > getscl = = NULL ? 1 : getscl ( adap ) ) ;
if ( 0 = = sda ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SDA stuck low! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
if ( 0 = = scl ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SCL unexpected low "
" while pulling SDA high! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
scllo ( adap ) ;
sda = getsda ( adap ) ;
scl = ( adap - > getscl = = NULL ? 0 : getscl ( adap ) ) ;
if ( 0 ! = scl ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SCL stuck high! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
if ( 0 = = sda ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SDA unexpected low "
" while pulling SCL low! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
sclhi ( adap ) ;
sda = getsda ( adap ) ;
scl = ( adap - > getscl = = NULL ? 1 : getscl ( adap ) ) ;
if ( 0 = = scl ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SCL stuck low! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
if ( 0 = = sda ) {
2007-05-02 01:26:33 +04:00
printk ( KERN_WARNING " %s: SDA unexpected low "
" while pulling SCL high! \n " , name ) ;
2005-04-17 02:20:36 +04:00
goto bailout ;
}
2007-05-02 01:26:33 +04:00
pr_info ( " %s: Test OK \n " , name ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
bailout :
sdahi ( adap ) ;
sclhi ( adap ) ;
return - ENODEV ;
}
/* ----- Utility functions
*/
/* try_address tries to contact a chip for a number of
* times before it gives up .
* return values :
* 1 chip answered
* 0 chip did not answer
* - x transmission error
*/
2006-09-04 00:22:12 +04:00
static int try_address ( struct i2c_adapter * i2c_adap ,
2005-04-17 02:20:36 +04:00
unsigned char addr , int retries )
{
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
int i , ret = - 1 ;
for ( i = 0 ; i < = retries ; i + + ) {
ret = i2c_outb ( i2c_adap , addr ) ;
2007-05-02 01:26:28 +04:00
if ( ret = = 1 | | i = = retries )
break ;
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting stop condition \n " ) ;
2005-04-17 02:20:36 +04:00
i2c_stop ( adap ) ;
udelay ( adap - > udelay ) ;
2007-05-02 01:26:33 +04:00
yield ( ) ;
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting start condition \n " ) ;
2007-05-02 01:26:33 +04:00
i2c_start ( adap ) ;
2005-04-17 02:20:36 +04:00
}
2007-05-02 01:26:33 +04:00
if ( i & & ret )
bit_dbg ( 1 , & i2c_adap - > dev , " Used %d tries to %s client at "
" 0x%02x: %s \n " , i + 1 ,
addr & 1 ? " read from " : " write to " , addr > > 1 ,
ret = = 1 ? " success " : " failed, timeout? " ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
static int sendbytes ( struct i2c_adapter * i2c_adap , struct i2c_msg * msg )
{
2007-05-02 01:26:33 +04:00
const unsigned char * temp = msg - > buf ;
2005-04-17 02:20:36 +04:00
int count = msg - > len ;
unsigned short nak_ok = msg - > flags & I2C_M_IGNORE_NAK ;
int retval ;
int wrcount = 0 ;
while ( count > 0 ) {
2007-05-02 01:26:33 +04:00
retval = i2c_outb ( i2c_adap , * temp ) ;
2005-04-17 02:20:36 +04:00
if ( ( retval > 0 ) | | ( nak_ok & & ( retval = = 0 ) ) ) { /* ok or ignored NAK */
count - - ;
temp + + ;
wrcount + + ;
} else { /* arbitration or no acknowledge */
dev_err ( & i2c_adap - > dev , " sendbytes: error - bailout. \n " ) ;
return ( retval < 0 ) ? retval : - EFAULT ;
/* got a better one ?? */
}
}
return wrcount ;
}
2007-09-10 00:29:14 +04:00
static int acknak ( struct i2c_adapter * i2c_adap , int is_ack )
{
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
/* assert: sda is high */
if ( is_ack ) /* send ack */
setsda ( adap , 0 ) ;
udelay ( ( adap - > udelay + 1 ) / 2 ) ;
if ( sclhi ( adap ) < 0 ) { /* timeout */
dev_err ( & i2c_adap - > dev , " readbytes: ack/nak timeout \n " ) ;
return - ETIMEDOUT ;
}
scllo ( adap ) ;
return 0 ;
}
2006-09-04 00:22:12 +04:00
static int readbytes ( struct i2c_adapter * i2c_adap , struct i2c_msg * msg )
2005-04-17 02:20:36 +04:00
{
int inval ;
int rdcount = 0 ; /* counts bytes read */
2007-05-02 01:26:33 +04:00
unsigned char * temp = msg - > buf ;
2005-04-17 02:20:36 +04:00
int count = msg - > len ;
2007-09-10 00:29:14 +04:00
const unsigned flags = msg - > flags ;
2005-04-17 02:20:36 +04:00
while ( count > 0 ) {
inval = i2c_inb ( i2c_adap ) ;
if ( inval > = 0 ) {
* temp = inval ;
rdcount + + ;
} else { /* read timed out */
break ;
}
temp + + ;
count - - ;
2007-05-02 01:26:29 +04:00
/* Some SMBus transactions require that we receive the
transaction length as the first read byte . */
2007-09-10 00:29:14 +04:00
if ( rdcount = = 1 & & ( flags & I2C_M_RECV_LEN ) ) {
2007-05-02 01:26:29 +04:00
if ( inval < = 0 | | inval > I2C_SMBUS_BLOCK_MAX ) {
2007-09-10 00:29:14 +04:00
if ( ! ( flags & I2C_M_NO_RD_ACK ) )
acknak ( i2c_adap , 0 ) ;
2007-05-02 01:26:33 +04:00
dev_err ( & i2c_adap - > dev , " readbytes: invalid "
" block length (%d) \n " , inval ) ;
2007-05-02 01:26:29 +04:00
return - EREMOTEIO ;
}
/* The original count value accounts for the extra
bytes , that is , either 1 for a regular transaction ,
or 2 for a PEC transaction . */
count + = inval ;
msg - > len + = inval ;
}
2007-09-10 00:29:14 +04:00
bit_dbg ( 2 , & i2c_adap - > dev , " readbytes: 0x%02x %s \n " ,
inval ,
( flags & I2C_M_NO_RD_ACK )
? " (no ack/nak) "
: ( count ? " A " : " NA " ) ) ;
if ( ! ( flags & I2C_M_NO_RD_ACK ) ) {
inval = acknak ( i2c_adap , count ) ;
if ( inval < 0 )
return inval ;
}
2005-04-17 02:20:36 +04:00
}
return rdcount ;
}
/* doAddress initiates the transfer by generating the start condition (in
* try_address ) and transmits the address in the necessary format to handle
* reads , writes as well as 10 bit - addresses .
* returns :
* 0 everything went okay , the chip ack ' ed , or IGNORE_NAK flag was set
* - x an error occurred ( like : - EREMOTEIO if the device did not answer , or
* - ETIMEDOUT , for example if the lines are stuck . . . )
*/
2006-09-04 00:22:12 +04:00
static int bit_doAddress ( struct i2c_adapter * i2c_adap , struct i2c_msg * msg )
2005-04-17 02:20:36 +04:00
{
unsigned short flags = msg - > flags ;
unsigned short nak_ok = msg - > flags & I2C_M_IGNORE_NAK ;
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
unsigned char addr ;
int ret , retries ;
retries = nak_ok ? 0 : i2c_adap - > retries ;
if ( ( flags & I2C_M_TEN ) ) {
/* a ten bit address */
addr = 0xf0 | ( ( msg - > addr > > 7 ) & 0x03 ) ;
2007-05-02 01:26:33 +04:00
bit_dbg ( 2 , & i2c_adap - > dev , " addr0: %d \n " , addr ) ;
2005-04-17 02:20:36 +04:00
/* try extended address code...*/
ret = try_address ( i2c_adap , addr , retries ) ;
if ( ( ret ! = 1 ) & & ! nak_ok ) {
2007-05-02 01:26:33 +04:00
dev_err ( & i2c_adap - > dev ,
" died at extended address code \n " ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
/* the remaining 8 bit address */
ret = i2c_outb ( i2c_adap , msg - > addr & 0x7f ) ;
if ( ( ret ! = 1 ) & & ! nak_ok ) {
/* the chip did not ack / xmission error occurred */
2007-05-02 01:26:33 +04:00
dev_err ( & i2c_adap - > dev , " died at 2nd address code \n " ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
if ( flags & I2C_M_RD ) {
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting repeated "
" start condition \n " ) ;
2005-04-17 02:20:36 +04:00
i2c_repstart ( adap ) ;
/* okay, now switch into reading mode */
addr | = 0x01 ;
ret = try_address ( i2c_adap , addr , retries ) ;
if ( ( ret ! = 1 ) & & ! nak_ok ) {
2007-05-02 01:26:33 +04:00
dev_err ( & i2c_adap - > dev ,
" died at repeated address code \n " ) ;
2005-04-17 02:20:36 +04:00
return - EREMOTEIO ;
}
}
} else { /* normal 7bit address */
addr = ( msg - > addr < < 1 ) ;
if ( flags & I2C_M_RD )
addr | = 1 ;
if ( flags & I2C_M_REV_DIR_ADDR )
addr ^ = 1 ;
ret = try_address ( i2c_adap , addr , retries ) ;
if ( ( ret ! = 1 ) & & ! nak_ok )
return - EREMOTEIO ;
}
return 0 ;
}
static int bit_xfer ( struct i2c_adapter * i2c_adap ,
struct i2c_msg msgs [ ] , int num )
{
struct i2c_msg * pmsg ;
struct i2c_algo_bit_data * adap = i2c_adap - > algo_data ;
int i , ret ;
unsigned short nak_ok ;
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting start condition \n " ) ;
2005-04-17 02:20:36 +04:00
i2c_start ( adap ) ;
for ( i = 0 ; i < num ; i + + ) {
pmsg = & msgs [ i ] ;
nak_ok = pmsg - > flags & I2C_M_IGNORE_NAK ;
if ( ! ( pmsg - > flags & I2C_M_NOSTART ) ) {
if ( i ) {
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting "
" repeated start condition \n " ) ;
2005-04-17 02:20:36 +04:00
i2c_repstart ( adap ) ;
}
ret = bit_doAddress ( i2c_adap , pmsg ) ;
if ( ( ret ! = 0 ) & & ! nak_ok ) {
2007-05-02 01:26:33 +04:00
bit_dbg ( 1 , & i2c_adap - > dev , " NAK from "
" device addr 0x%02x msg #%d \n " ,
msgs [ i ] . addr , i ) ;
2007-05-02 01:26:28 +04:00
goto bailout ;
2005-04-17 02:20:36 +04:00
}
}
if ( pmsg - > flags & I2C_M_RD ) {
/* read bytes into buffer*/
ret = readbytes ( i2c_adap , pmsg ) ;
2007-05-02 01:26:33 +04:00
if ( ret > = 1 )
bit_dbg ( 2 , & i2c_adap - > dev , " read %d byte%s \n " ,
ret , ret = = 1 ? " " : " s " ) ;
2007-05-02 01:26:28 +04:00
if ( ret < pmsg - > len ) {
if ( ret > = 0 )
ret = - EREMOTEIO ;
goto bailout ;
2005-04-17 02:20:36 +04:00
}
} else {
/* write bytes from buffer */
ret = sendbytes ( i2c_adap , pmsg ) ;
2007-05-02 01:26:33 +04:00
if ( ret > = 1 )
bit_dbg ( 2 , & i2c_adap - > dev , " wrote %d byte%s \n " ,
ret , ret = = 1 ? " " : " s " ) ;
2007-05-02 01:26:28 +04:00
if ( ret < pmsg - > len ) {
if ( ret > = 0 )
ret = - EREMOTEIO ;
goto bailout ;
2005-04-17 02:20:36 +04:00
}
}
}
2007-05-02 01:26:28 +04:00
ret = i ;
bailout :
2007-05-02 01:26:33 +04:00
bit_dbg ( 3 , & i2c_adap - > dev , " emitting stop condition \n " ) ;
2005-04-17 02:20:36 +04:00
i2c_stop ( adap ) ;
2007-05-02 01:26:28 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static u32 bit_func ( struct i2c_adapter * adap )
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
2007-05-02 01:26:29 +04:00
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
2005-04-17 02:20:36 +04:00
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING ;
}
/* -----exported algorithm data: ------------------------------------- */
2006-09-04 00:38:52 +04:00
static const struct i2c_algorithm i2c_bit_algo = {
2005-04-17 02:20:36 +04:00
. master_xfer = bit_xfer ,
. functionality = bit_func ,
} ;
/*
* registering functions to load algorithms at runtime
*/
2007-05-02 01:26:31 +04:00
static int i2c_bit_prepare_bus ( struct i2c_adapter * adap )
2005-04-17 02:20:36 +04:00
{
struct i2c_algo_bit_data * bit_adap = adap - > algo_data ;
if ( bit_test ) {
int ret = test_bus ( bit_adap , adap - > name ) ;
if ( ret < 0 )
return - ENODEV ;
}
/* register new adapter to i2c module... */
adap - > algo = & i2c_bit_algo ;
adap - > timeout = 100 ; /* default values, should */
adap - > retries = 3 ; /* be replaced by defines */
2007-05-02 01:26:31 +04:00
return 0 ;
}
int i2c_bit_add_bus ( struct i2c_adapter * adap )
{
int err ;
err = i2c_bit_prepare_bus ( adap ) ;
if ( err )
return err ;
2006-07-01 19:16:06 +04:00
return i2c_add_adapter ( adap ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( i2c_bit_add_bus ) ;
2007-05-02 01:26:31 +04:00
int i2c_bit_add_numbered_bus ( struct i2c_adapter * adap )
{
int err ;
err = i2c_bit_prepare_bus ( adap ) ;
if ( err )
return err ;
return i2c_add_numbered_adapter ( adap ) ;
}
EXPORT_SYMBOL ( i2c_bit_add_numbered_bus ) ;
2005-04-17 02:20:36 +04:00
MODULE_AUTHOR ( " Simon G. Vogl <simon@tk.uni-linz.ac.at> " ) ;
MODULE_DESCRIPTION ( " I2C-Bus bit-banging algorithm " ) ;
MODULE_LICENSE ( " GPL " ) ;