2005-04-16 15:20:36 -07:00
/*
2008-04-22 22:16:46 +02:00
* i2c - algo - pca . c i2c driver algorithms for PCA9564 adapters
2005-04-16 15:20:36 -07:00
* Copyright ( C ) 2004 Arcom Control Systems
2008-04-22 22:16:46 +02:00
* Copyright ( C ) 2008 Pengutronix
2005-04-16 15:20:36 -07:00
*
* 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 .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/delay.h>
2009-03-28 21:34:45 +01:00
# include <linux/jiffies.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/i2c.h>
# include <linux/i2c-algo-pca.h>
2009-03-28 21:34:44 +01:00
# define DEB1(fmt, args...) do { if (i2c_debug >= 1) \
printk ( KERN_DEBUG fmt , # # args ) ; } while ( 0 )
# define DEB2(fmt, args...) do { if (i2c_debug >= 2) \
printk ( KERN_DEBUG fmt , # # args ) ; } while ( 0 )
# define DEB3(fmt, args...) do { if (i2c_debug >= 3) \
printk ( KERN_DEBUG fmt , # # args ) ; } while ( 0 )
2005-04-16 15:20:36 -07:00
2005-09-25 16:23:07 +02:00
static int i2c_debug ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
# define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
# define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
2005-04-16 15:20:36 -07:00
# define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
2008-04-22 22:16:46 +02:00
# define pca_clock(adap) adap->i2c_clock
2005-04-16 15:20:36 -07:00
# define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
# define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
2008-04-22 22:16:46 +02:00
# define pca_wait(adap) adap->wait_for_completion(adap->data)
# define pca_reset(adap) adap->reset_chip(adap->data)
2005-04-16 15:20:36 -07:00
2009-03-28 21:34:44 +01:00
static void pca9665_reset ( void * pd )
{
struct i2c_algo_pca_data * adap = pd ;
pca_outw ( adap , I2C_PCA_INDPTR , I2C_PCA_IPRESET ) ;
pca_outw ( adap , I2C_PCA_IND , 0xA5 ) ;
pca_outw ( adap , I2C_PCA_IND , 0x5A ) ;
}
2005-04-16 15:20:36 -07:00
/*
* Generate a start condition on the i2c bus .
*
2005-05-03 18:21:25 -06:00
* returns after the start condition has occurred
2005-04-16 15:20:36 -07:00
*/
2009-03-28 21:34:45 +01:00
static int pca_start ( struct i2c_algo_pca_data * adap )
2005-04-16 15:20:36 -07:00
{
int sta = pca_get_con ( adap ) ;
DEB2 ( " === START \n " ) ;
sta | = I2C_PCA_CON_STA ;
sta & = ~ ( I2C_PCA_CON_STO | I2C_PCA_CON_SI ) ;
pca_set_con ( adap , sta ) ;
2009-03-28 21:34:45 +01:00
return pca_wait ( adap ) ;
2005-04-16 15:20:36 -07:00
}
/*
2005-05-19 22:27:23 +02:00
* Generate a repeated start condition on the i2c bus
2005-04-16 15:20:36 -07:00
*
2005-05-03 18:21:25 -06:00
* return after the repeated start condition has occurred
2005-04-16 15:20:36 -07:00
*/
2009-03-28 21:34:45 +01:00
static int pca_repeated_start ( struct i2c_algo_pca_data * adap )
2005-04-16 15:20:36 -07:00
{
int sta = pca_get_con ( adap ) ;
DEB2 ( " === REPEATED START \n " ) ;
sta | = I2C_PCA_CON_STA ;
sta & = ~ ( I2C_PCA_CON_STO | I2C_PCA_CON_SI ) ;
pca_set_con ( adap , sta ) ;
2009-03-28 21:34:45 +01:00
return pca_wait ( adap ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Generate a stop condition on the i2c bus
*
* returns after the stop condition has been generated
*
* STOPs do not generate an interrupt or set the SI flag , since the
2005-05-19 22:27:23 +02:00
* part returns the idle state ( 0xf8 ) . Hence we don ' t need to
2005-04-16 15:20:36 -07:00
* pca_wait here .
*/
static void pca_stop ( struct i2c_algo_pca_data * adap )
{
int sta = pca_get_con ( adap ) ;
DEB2 ( " === STOP \n " ) ;
sta | = I2C_PCA_CON_STO ;
sta & = ~ ( I2C_PCA_CON_STA | I2C_PCA_CON_SI ) ;
pca_set_con ( adap , sta ) ;
}
/*
* Send the slave address and R / W bit
*
* returns after the address has been sent
*/
2009-03-28 21:34:45 +01:00
static int pca_address ( struct i2c_algo_pca_data * adap ,
2005-04-16 15:20:36 -07:00
struct i2c_msg * msg )
{
int sta = pca_get_con ( adap ) ;
int addr ;
addr = ( ( 0x7f & msg - > addr ) < < 1 ) ;
if ( msg - > flags & I2C_M_RD )
addr | = 1 ;
2008-04-22 22:16:46 +02:00
DEB2 ( " === SLAVE ADDRESS %#04x+%c=%#04x \n " ,
2005-04-16 15:20:36 -07:00
msg - > addr , msg - > flags & I2C_M_RD ? ' R ' : ' W ' , addr ) ;
2008-04-22 22:16:46 +02:00
2005-04-16 15:20:36 -07:00
pca_outw ( adap , I2C_PCA_DAT , addr ) ;
sta & = ~ ( I2C_PCA_CON_STO | I2C_PCA_CON_STA | I2C_PCA_CON_SI ) ;
pca_set_con ( adap , sta ) ;
2009-03-28 21:34:45 +01:00
return pca_wait ( adap ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Transmit a byte .
*
* Returns after the byte has been transmitted
*/
2009-03-28 21:34:45 +01:00
static int pca_tx_byte ( struct i2c_algo_pca_data * adap ,
2005-04-16 15:20:36 -07:00
__u8 b )
{
int sta = pca_get_con ( adap ) ;
DEB2 ( " === WRITE %#04x \n " , b ) ;
pca_outw ( adap , I2C_PCA_DAT , b ) ;
sta & = ~ ( I2C_PCA_CON_STO | I2C_PCA_CON_STA | I2C_PCA_CON_SI ) ;
pca_set_con ( adap , sta ) ;
2009-03-28 21:34:45 +01:00
return pca_wait ( adap ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Receive a byte
*
* returns immediately .
*/
2008-04-22 22:16:46 +02:00
static void pca_rx_byte ( struct i2c_algo_pca_data * adap ,
2005-04-16 15:20:36 -07:00
__u8 * b , int ack )
{
* b = pca_inw ( adap , I2C_PCA_DAT ) ;
DEB2 ( " === READ %#04x %s \n " , * b , ack ? " ACK " : " NACK " ) ;
}
2008-04-22 22:16:46 +02:00
/*
2005-04-16 15:20:36 -07:00
* Setup ACK or NACK for next received byte and wait for it to arrive .
*
* Returns after next byte has arrived .
*/
2009-03-28 21:34:45 +01:00
static int pca_rx_ack ( struct i2c_algo_pca_data * adap ,
2005-04-16 15:20:36 -07:00
int ack )
{
int sta = pca_get_con ( adap ) ;
sta & = ~ ( I2C_PCA_CON_STO | I2C_PCA_CON_STA | I2C_PCA_CON_SI | I2C_PCA_CON_AA ) ;
if ( ack )
sta | = I2C_PCA_CON_AA ;
pca_set_con ( adap , sta ) ;
2009-03-28 21:34:45 +01:00
return pca_wait ( adap ) ;
2005-04-16 15:20:36 -07:00
}
static int pca_xfer ( struct i2c_adapter * i2c_adap ,
struct i2c_msg * msgs ,
int num )
{
struct i2c_algo_pca_data * adap = i2c_adap - > algo_data ;
struct i2c_msg * msg = NULL ;
int curmsg ;
int numbytes = 0 ;
int state ;
int ret ;
2009-03-28 21:34:45 +01:00
int completed = 1 ;
2009-03-28 21:34:45 +01:00
unsigned long timeout = jiffies + i2c_adap - > timeout ;
while ( pca_status ( adap ) ! = 0xf8 ) {
if ( time_before ( jiffies , timeout ) ) {
msleep ( 10 ) ;
} else {
dev_dbg ( & i2c_adap - > dev , " bus is not idle. status is "
" %#04x \n " , state ) ;
return - EAGAIN ;
}
2005-04-16 15:20:36 -07:00
}
DEB1 ( " {{{ XFER %d messages \n " , num ) ;
if ( i2c_debug > = 2 ) {
for ( curmsg = 0 ; curmsg < num ; curmsg + + ) {
int addr , i ;
msg = & msgs [ curmsg ] ;
2008-04-22 22:16:46 +02:00
2005-04-16 15:20:36 -07:00
addr = ( 0x7f & msg - > addr ) ;
2008-04-22 22:16:46 +02:00
2005-04-16 15:20:36 -07:00
if ( msg - > flags & I2C_M_RD )
2008-04-22 22:16:46 +02:00
printk ( KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...] \n " ,
2005-04-16 15:20:36 -07:00
curmsg , msg - > len , addr , ( addr < < 1 ) | 1 ) ;
else {
2008-04-22 22:16:46 +02:00
printk ( KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s " ,
2005-04-16 15:20:36 -07:00
curmsg , msg - > len , addr , addr < < 1 ,
msg - > len = = 0 ? " " : " , " ) ;
for ( i = 0 ; i < msg - > len ; i + + )
printk ( " %#04x%s " , msg - > buf [ i ] , i = = msg - > len - 1 ? " " : " , " ) ;
printk ( " ] \n " ) ;
}
}
}
curmsg = 0 ;
ret = - EREMOTEIO ;
while ( curmsg < num ) {
state = pca_status ( adap ) ;
DEB3 ( " STATE is 0x%02x \n " , state ) ;
msg = & msgs [ curmsg ] ;
switch ( state ) {
case 0xf8 : /* On reset or stop the bus is idle */
2009-03-28 21:34:45 +01:00
completed = pca_start ( adap ) ;
2005-04-16 15:20:36 -07:00
break ;
case 0x08 : /* A START condition has been transmitted */
case 0x10 : /* A repeated start condition has been transmitted */
2009-03-28 21:34:45 +01:00
completed = pca_address ( adap , msg ) ;
2005-04-16 15:20:36 -07:00
break ;
2008-04-22 22:16:46 +02:00
2005-04-16 15:20:36 -07:00
case 0x18 : /* SLA+W has been transmitted; ACK has been received */
case 0x28 : /* Data byte in I2CDAT has been transmitted; ACK has been received */
if ( numbytes < msg - > len ) {
2009-03-28 21:34:45 +01:00
completed = pca_tx_byte ( adap ,
msg - > buf [ numbytes ] ) ;
2005-04-16 15:20:36 -07:00
numbytes + + ;
break ;
}
curmsg + + ; numbytes = 0 ;
if ( curmsg = = num )
pca_stop ( adap ) ;
else
2009-03-28 21:34:45 +01:00
completed = pca_repeated_start ( adap ) ;
2005-04-16 15:20:36 -07:00
break ;
case 0x20 : /* SLA+W has been transmitted; NOT ACK has been received */
DEB2 ( " NOT ACK received after SLA+W \n " ) ;
pca_stop ( adap ) ;
goto out ;
case 0x40 : /* SLA+R has been transmitted; ACK has been received */
2009-03-28 21:34:45 +01:00
completed = pca_rx_ack ( adap , msg - > len > 1 ) ;
2005-04-16 15:20:36 -07:00
break ;
case 0x50 : /* Data bytes has been received; ACK has been returned */
if ( numbytes < msg - > len ) {
pca_rx_byte ( adap , & msg - > buf [ numbytes ] , 1 ) ;
numbytes + + ;
2009-03-28 21:34:45 +01:00
completed = pca_rx_ack ( adap ,
numbytes < msg - > len - 1 ) ;
2005-04-16 15:20:36 -07:00
break ;
}
curmsg + + ; numbytes = 0 ;
if ( curmsg = = num )
pca_stop ( adap ) ;
else
2009-03-28 21:34:45 +01:00
completed = pca_repeated_start ( adap ) ;
2005-04-16 15:20:36 -07:00
break ;
case 0x48 : /* SLA+R has been transmitted; NOT ACK has been received */
DEB2 ( " NOT ACK received after SLA+R \n " ) ;
pca_stop ( adap ) ;
goto out ;
case 0x30 : /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
DEB2 ( " NOT ACK received after data byte \n " ) ;
goto out ;
case 0x38 : /* Arbitration lost during SLA+W, SLA+R or data bytes */
DEB2 ( " Arbitration lost \n " ) ;
goto out ;
2008-04-22 22:16:46 +02:00
2005-04-16 15:20:36 -07:00
case 0x58 : /* Data byte has been received; NOT ACK has been returned */
if ( numbytes = = msg - > len - 1 ) {
pca_rx_byte ( adap , & msg - > buf [ numbytes ] , 0 ) ;
curmsg + + ; numbytes = 0 ;
if ( curmsg = = num )
pca_stop ( adap ) ;
else
2009-03-28 21:34:45 +01:00
completed = pca_repeated_start ( adap ) ;
2005-04-16 15:20:36 -07:00
} else {
DEB2 ( " NOT ACK sent after data byte received. "
" Not final byte. numbytes %d. len %d \n " ,
numbytes , msg - > len ) ;
pca_stop ( adap ) ;
goto out ;
}
break ;
case 0x70 : /* Bus error - SDA stuck low */
DEB2 ( " BUS ERROR - SDA Stuck low \n " ) ;
pca_reset ( adap ) ;
goto out ;
case 0x90 : /* Bus error - SCL stuck low */
DEB2 ( " BUS ERROR - SCL Stuck low \n " ) ;
pca_reset ( adap ) ;
goto out ;
case 0x00 : /* Bus error during master or slave mode due to illegal START or STOP condition */
DEB2 ( " BUS ERROR - Illegal START or STOP \n " ) ;
pca_reset ( adap ) ;
goto out ;
default :
2008-04-22 22:16:46 +02:00
dev_err ( & i2c_adap - > dev , " unhandled SIO state 0x%02x \n " , state ) ;
2005-04-16 15:20:36 -07:00
break ;
}
2008-04-22 22:16:46 +02:00
2009-03-28 21:34:45 +01:00
if ( ! completed )
goto out ;
2005-04-16 15:20:36 -07:00
}
ret = curmsg ;
out :
2009-03-28 21:34:44 +01:00
DEB1 ( " }}} transfered %d/%d messages. "
2008-04-22 22:16:46 +02:00
" status is %#04x. control is %#04x \n " ,
2005-04-16 15:20:36 -07:00
curmsg , num , pca_status ( adap ) ,
pca_get_con ( adap ) ) ;
return ret ;
}
static u32 pca_func ( struct i2c_adapter * adap )
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL ;
}
2008-04-22 22:16:46 +02:00
static const struct i2c_algorithm pca_algo = {
. master_xfer = pca_xfer ,
. functionality = pca_func ,
} ;
2009-03-28 21:34:44 +01:00
static unsigned int pca_probe_chip ( struct i2c_adapter * adap )
2005-04-16 15:20:36 -07:00
{
2008-04-22 22:16:46 +02:00
struct i2c_algo_pca_data * pca_data = adap - > algo_data ;
2009-03-28 21:34:44 +01:00
/* The trick here is to check if there is an indirect register
* available . If there is one , we will read the value we first
* wrote on I2C_PCA_IADR . Otherwise , we will read the last value
* we wrote on I2C_PCA_ADR
*/
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_IADR ) ;
pca_outw ( pca_data , I2C_PCA_IND , 0xAA ) ;
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_ITO ) ;
pca_outw ( pca_data , I2C_PCA_IND , 0x00 ) ;
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_IADR ) ;
if ( pca_inw ( pca_data , I2C_PCA_IND ) = = 0xAA ) {
printk ( KERN_INFO " %s: PCA9665 detected. \n " , adap - > name ) ;
return I2C_PCA_CHIP_9665 ;
} else {
printk ( KERN_INFO " %s: PCA9564 detected. \n " , adap - > name ) ;
return I2C_PCA_CHIP_9564 ;
2008-04-22 22:16:46 +02:00
}
2009-03-28 21:34:44 +01:00
}
static int pca_init ( struct i2c_adapter * adap )
{
struct i2c_algo_pca_data * pca_data = adap - > algo_data ;
2008-04-22 22:16:46 +02:00
adap - > algo = & pca_algo ;
2005-04-16 15:20:36 -07:00
2009-03-28 21:34:44 +01:00
if ( pca_probe_chip ( adap ) = = I2C_PCA_CHIP_9564 ) {
static int freqs [ ] = { 330 , 288 , 217 , 146 , 88 , 59 , 44 , 36 } ;
int clock ;
if ( pca_data - > i2c_clock > 7 ) {
switch ( pca_data - > i2c_clock ) {
case 330000 :
pca_data - > i2c_clock = I2C_PCA_CON_330kHz ;
break ;
case 288000 :
pca_data - > i2c_clock = I2C_PCA_CON_288kHz ;
break ;
case 217000 :
pca_data - > i2c_clock = I2C_PCA_CON_217kHz ;
break ;
case 146000 :
pca_data - > i2c_clock = I2C_PCA_CON_146kHz ;
break ;
case 88000 :
pca_data - > i2c_clock = I2C_PCA_CON_88kHz ;
break ;
case 59000 :
pca_data - > i2c_clock = I2C_PCA_CON_59kHz ;
break ;
case 44000 :
pca_data - > i2c_clock = I2C_PCA_CON_44kHz ;
break ;
case 36000 :
pca_data - > i2c_clock = I2C_PCA_CON_36kHz ;
break ;
default :
printk ( KERN_WARNING
" %s: Invalid I2C clock speed selected. "
" Using default 59kHz. \n " , adap - > name ) ;
pca_data - > i2c_clock = I2C_PCA_CON_59kHz ;
}
} else {
printk ( KERN_WARNING " %s: "
" Choosing the clock frequency based on "
" index is deprecated. "
" Use the nominal frequency. \n " , adap - > name ) ;
}
pca_reset ( pca_data ) ;
clock = pca_clock ( pca_data ) ;
printk ( KERN_INFO " %s: Clock frequency is %dkHz \n " ,
adap - > name , freqs [ clock ] ) ;
pca_set_con ( pca_data , I2C_PCA_CON_ENSIO | clock ) ;
} else {
int clock ;
int mode ;
int tlow , thi ;
/* Values can be found on PCA9665 datasheet section 7.3.2.6 */
int min_tlow , min_thi ;
/* These values are the maximum raise and fall values allowed
* by the I2C operation mode ( Standard , Fast or Fast + )
* They are used ( added ) below to calculate the clock dividers
* of PCA9665 . Note that they are slightly different of the
* real maximum , to allow the change on mode exactly on the
* maximum clock rate for each mode
*/
int raise_fall_time ;
struct i2c_algo_pca_data * pca_data = adap - > algo_data ;
/* Ignore the reset function from the module,
* we can use the parallel bus reset
*/
pca_data - > reset_chip = pca9665_reset ;
if ( pca_data - > i2c_clock > 1265800 ) {
printk ( KERN_WARNING " %s: I2C clock speed too high. "
" Using 1265.8kHz. \n " , adap - > name ) ;
pca_data - > i2c_clock = 1265800 ;
}
if ( pca_data - > i2c_clock < 60300 ) {
printk ( KERN_WARNING " %s: I2C clock speed too low. "
" Using 60.3kHz. \n " , adap - > name ) ;
pca_data - > i2c_clock = 60300 ;
}
/* To avoid integer overflow, use clock/100 for calculations */
clock = pca_clock ( pca_data ) / 100 ;
if ( pca_data - > i2c_clock > 10000 ) {
mode = I2C_PCA_MODE_TURBO ;
min_tlow = 14 ;
min_thi = 5 ;
raise_fall_time = 22 ; /* Raise 11e-8s, Fall 11e-8s */
} else if ( pca_data - > i2c_clock > 4000 ) {
mode = I2C_PCA_MODE_FASTP ;
min_tlow = 17 ;
min_thi = 9 ;
raise_fall_time = 22 ; /* Raise 11e-8s, Fall 11e-8s */
} else if ( pca_data - > i2c_clock > 1000 ) {
mode = I2C_PCA_MODE_FAST ;
min_tlow = 44 ;
min_thi = 20 ;
raise_fall_time = 58 ; /* Raise 29e-8s, Fall 29e-8s */
} else {
mode = I2C_PCA_MODE_STD ;
min_tlow = 157 ;
min_thi = 134 ;
raise_fall_time = 127 ; /* Raise 29e-8s, Fall 98e-8s */
}
/* The minimum clock that respects the thi/tlow = 134/157 is
* 64800 Hz . Below that , we have to fix the tlow to 255 and
* calculate the thi factor .
*/
if ( clock < 648 ) {
tlow = 255 ;
thi = 1000000 - clock * raise_fall_time ;
thi / = ( I2C_PCA_OSC_PER * clock ) - tlow ;
} else {
tlow = ( 1000000 - clock * raise_fall_time ) * min_tlow ;
tlow / = I2C_PCA_OSC_PER * clock * ( min_thi + min_tlow ) ;
thi = tlow * min_thi / min_tlow ;
}
pca_reset ( pca_data ) ;
2005-04-16 15:20:36 -07:00
2009-03-28 21:34:44 +01:00
printk ( KERN_INFO
" %s: Clock frequency is %dHz \n " , adap - > name , clock * 100 ) ;
2005-04-16 15:20:36 -07:00
2009-03-28 21:34:44 +01:00
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_IMODE ) ;
pca_outw ( pca_data , I2C_PCA_IND , mode ) ;
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_ISCLL ) ;
pca_outw ( pca_data , I2C_PCA_IND , tlow ) ;
pca_outw ( pca_data , I2C_PCA_INDPTR , I2C_PCA_ISCLH ) ;
pca_outw ( pca_data , I2C_PCA_IND , thi ) ;
pca_set_con ( pca_data , I2C_PCA_CON_ENSIO ) ;
}
2008-04-22 22:16:46 +02:00
udelay ( 500 ) ; /* 500 us for oscilator to stabilise */
2005-04-16 15:20:36 -07:00
return 0 ;
}
2008-04-22 22:16:46 +02:00
/*
* registering functions to load algorithms at runtime
2005-04-16 15:20:36 -07:00
*/
int i2c_pca_add_bus ( struct i2c_adapter * adap )
{
int rval ;
2008-04-22 22:16:46 +02:00
rval = pca_init ( adap ) ;
if ( rval )
return rval ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
return i2c_add_adapter ( adap ) ;
}
EXPORT_SYMBOL ( i2c_pca_add_bus ) ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
int i2c_pca_add_numbered_bus ( struct i2c_adapter * adap )
{
int rval ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
rval = pca_init ( adap ) ;
if ( rval )
return rval ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
return i2c_add_numbered_adapter ( adap ) ;
2005-04-16 15:20:36 -07:00
}
2008-04-22 22:16:46 +02:00
EXPORT_SYMBOL ( i2c_pca_add_numbered_bus ) ;
2005-04-16 15:20:36 -07:00
2008-04-22 22:16:46 +02:00
MODULE_AUTHOR ( " Ian Campbell <icampbell@arcom.com>, "
" Wolfram Sang <w.sang@pengutronix.de> " ) ;
2009-03-28 21:34:44 +01:00
MODULE_DESCRIPTION ( " I2C-Bus PCA9564/PCA9665 algorithm " ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;
module_param ( i2c_debug , int , 0 ) ;