2010-08-11 20:21:03 +04:00
/*
* I2C multiplexer
*
* Copyright ( c ) 2008 - 2009 Rodolfo Giometti < giometti @ linux . it >
* Copyright ( c ) 2008 - 2009 Eurotech S . p . A . < info @ eurotech . it >
*
* This module supports the PCA954x series of I2C multiplexer / switch chips
* made by Philips Semiconductors .
* This includes the :
* PCA9540 , PCA9542 , PCA9543 , PCA9544 , PCA9545 , PCA9546 , PCA9547
* and PCA9548 .
*
* These chips are all controlled via the I2C bus itself , and all have a
* single 8 - bit register . The upstream " parent " bus fans out to two ,
* four , or eight downstream busses or channels ; which of these
* are selected is determined by the chip type and register contents . A
* mux can select only one sub - bus at a time ; a switch can select any
* combination simultaneously .
*
* Based on :
* pca954x . c from Kumar Gala < galak @ kernel . crashing . org >
* Copyright ( C ) 2006
*
* Based on :
* pca954x . c from Ken Harrenstien
* Copyright ( C ) 2004 Google , Inc . ( Ken Harrenstien )
*
* Based on :
* i2c - virtual_cb . c from Brian Kuschak < bkuschak @ yahoo . com >
* and
2014-01-29 23:40:08 +04:00
* pca9540 . c from Jean Delvare < jdelvare @ suse . de > .
2010-08-11 20:21:03 +04:00
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/device.h>
2014-06-04 20:56:32 +04:00
# include <linux/gpio/consumer.h>
2010-08-11 20:21:03 +04:00
# include <linux/i2c.h>
# include <linux/i2c-mux.h>
# include <linux/i2c/pca954x.h>
2013-11-29 04:51:22 +04:00
# include <linux/module.h>
2015-01-23 18:41:29 +03:00
# include <linux/of.h>
2014-07-25 15:57:46 +04:00
# include <linux/pm.h>
2013-11-29 04:51:22 +04:00
# include <linux/slab.h>
2010-08-11 20:21:03 +04:00
# define PCA954X_MAX_NCHANS 8
enum pca_type {
pca_9540 ,
pca_9542 ,
pca_9543 ,
pca_9544 ,
pca_9545 ,
pca_9546 ,
pca_9547 ,
pca_9548 ,
} ;
struct pca954x {
enum pca_type type ;
struct i2c_adapter * virt_adaps [ PCA954X_MAX_NCHANS ] ;
u8 last_chan ; /* last register value */
} ;
struct chip_desc {
u8 nchans ;
u8 enable ; /* used for muxes only */
enum muxtype {
pca954x_ismux = 0 ,
pca954x_isswi
} muxtype ;
} ;
/* Provide specs for the PCA954x types we know about */
static const struct chip_desc chips [ ] = {
[ pca_9540 ] = {
. nchans = 2 ,
. enable = 0x4 ,
. muxtype = pca954x_ismux ,
} ,
[ pca_9543 ] = {
. nchans = 2 ,
. muxtype = pca954x_isswi ,
} ,
[ pca_9544 ] = {
. nchans = 4 ,
. enable = 0x4 ,
. muxtype = pca954x_ismux ,
} ,
[ pca_9545 ] = {
. nchans = 4 ,
. muxtype = pca954x_isswi ,
} ,
[ pca_9547 ] = {
. nchans = 8 ,
. enable = 0x8 ,
. muxtype = pca954x_ismux ,
} ,
[ pca_9548 ] = {
. nchans = 8 ,
. muxtype = pca954x_isswi ,
} ,
} ;
static const struct i2c_device_id pca954x_id [ ] = {
{ " pca9540 " , pca_9540 } ,
{ " pca9542 " , pca_9540 } ,
{ " pca9543 " , pca_9543 } ,
{ " pca9544 " , pca_9544 } ,
{ " pca9545 " , pca_9545 } ,
{ " pca9546 " , pca_9545 } ,
{ " pca9547 " , pca_9547 } ,
{ " pca9548 " , pca_9548 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , pca954x_id ) ;
/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
for this as they will try to lock adapter a second time */
static int pca954x_reg_write ( struct i2c_adapter * adap ,
struct i2c_client * client , u8 val )
{
int ret = - ENODEV ;
if ( adap - > algo - > master_xfer ) {
struct i2c_msg msg ;
char buf [ 1 ] ;
msg . addr = client - > addr ;
msg . flags = 0 ;
msg . len = 1 ;
buf [ 0 ] = val ;
msg . buf = buf ;
ret = adap - > algo - > master_xfer ( adap , & msg , 1 ) ;
} else {
union i2c_smbus_data data ;
ret = adap - > algo - > smbus_xfer ( adap , client - > addr ,
client - > flags ,
I2C_SMBUS_WRITE ,
val , I2C_SMBUS_BYTE , & data ) ;
}
return ret ;
}
static int pca954x_select_chan ( struct i2c_adapter * adap ,
void * client , u32 chan )
{
struct pca954x * data = i2c_get_clientdata ( client ) ;
const struct chip_desc * chip = & chips [ data - > type ] ;
u8 regval ;
int ret = 0 ;
/* we make switches look like muxes, not sure how to be smarter */
if ( chip - > muxtype = = pca954x_ismux )
regval = chan | chip - > enable ;
else
regval = 1 < < chan ;
/* Only select the channel if its different from the last channel */
if ( data - > last_chan ! = regval ) {
ret = pca954x_reg_write ( adap , client , regval ) ;
data - > last_chan = regval ;
}
return ret ;
}
static int pca954x_deselect_mux ( struct i2c_adapter * adap ,
void * client , u32 chan )
{
struct pca954x * data = i2c_get_clientdata ( client ) ;
/* Deselect active channel */
data - > last_chan = 0 ;
return pca954x_reg_write ( adap , client , data - > last_chan ) ;
}
/*
* I2C init / probing / exit functions
*/
2010-10-24 20:16:59 +04:00
static int pca954x_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
2010-08-11 20:21:03 +04:00
{
struct i2c_adapter * adap = to_i2c_adapter ( client - > dev . parent ) ;
2013-07-30 11:59:33 +04:00
struct pca954x_platform_data * pdata = dev_get_platdata ( & client - > dev ) ;
2015-01-23 18:41:29 +03:00
struct device_node * of_node = client - > dev . of_node ;
bool idle_disconnect_dt ;
2014-06-03 15:15:26 +04:00
struct gpio_desc * gpio ;
2012-10-06 00:23:51 +04:00
int num , force , class ;
2010-08-11 20:21:03 +04:00
struct pca954x * data ;
2013-11-29 04:51:23 +04:00
int ret ;
2010-08-11 20:21:03 +04:00
if ( ! i2c_check_functionality ( adap , I2C_FUNC_SMBUS_BYTE ) )
2013-11-29 04:51:23 +04:00
return - ENODEV ;
2010-08-11 20:21:03 +04:00
2013-11-29 04:51:23 +04:00
data = devm_kzalloc ( & client - > dev , sizeof ( struct pca954x ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
2010-08-11 20:21:03 +04:00
i2c_set_clientdata ( client , data ) ;
2014-06-03 15:15:26 +04:00
/* Get the mux out of reset if a reset GPIO is specified. */
gpio = devm_gpiod_get ( & client - > dev , " reset " ) ;
if ( ! IS_ERR ( gpio ) )
gpiod_direction_output ( gpio , 0 ) ;
2013-11-29 04:51:25 +04:00
2011-06-29 13:36:11 +04:00
/* Write the mux register at addr to verify
* that the mux is in fact present . This also
* initializes the mux to disconnected state .
2010-08-11 20:21:03 +04:00
*/
2011-06-29 13:36:11 +04:00
if ( i2c_smbus_write_byte ( client , 0 ) < 0 ) {
2010-08-11 20:21:03 +04:00
dev_warn ( & client - > dev , " probe failed \n " ) ;
2013-11-29 04:51:23 +04:00
return - ENODEV ;
2010-08-11 20:21:03 +04:00
}
data - > type = id - > driver_data ;
data - > last_chan = 0 ; /* force the first selection */
2015-01-23 18:41:29 +03:00
idle_disconnect_dt = of_node & &
of_property_read_bool ( of_node , " i2c-mux-idle-disconnect " ) ;
2010-08-11 20:21:03 +04:00
/* Now create an adapter for each channel */
for ( num = 0 ; num < chips [ data - > type ] . nchans ; num + + ) {
2015-01-23 18:41:29 +03:00
bool idle_disconnect_pd = false ;
2010-08-11 20:21:03 +04:00
force = 0 ; /* dynamic adap number */
2012-10-06 00:23:51 +04:00
class = 0 ; /* no class by default */
2010-08-11 20:21:03 +04:00
if ( pdata ) {
2012-10-06 00:23:51 +04:00
if ( num < pdata - > num_modes ) {
2010-08-11 20:21:03 +04:00
/* force static number */
force = pdata - > modes [ num ] . adap_id ;
2012-10-06 00:23:51 +04:00
class = pdata - > modes [ num ] . class ;
} else
2010-08-11 20:21:03 +04:00
/* discard unconfigured channels */
break ;
2015-01-23 18:41:29 +03:00
idle_disconnect_pd = pdata - > modes [ num ] . deselect_on_exit ;
2010-08-11 20:21:03 +04:00
}
data - > virt_adaps [ num ] =
2012-04-13 01:14:22 +04:00
i2c_add_mux_adapter ( adap , & client - > dev , client ,
2012-10-06 00:23:51 +04:00
force , num , class , pca954x_select_chan ,
2015-01-23 18:41:29 +03:00
( idle_disconnect_pd | | idle_disconnect_dt )
2010-08-11 20:21:03 +04:00
? pca954x_deselect_mux : NULL ) ;
if ( data - > virt_adaps [ num ] = = NULL ) {
ret = - ENODEV ;
dev_err ( & client - > dev ,
" failed to register multiplexed adapter "
" %d as bus %d \n " , num , force ) ;
goto virt_reg_failed ;
}
}
dev_info ( & client - > dev ,
" registered %d multiplexed busses for I2C %s %s \n " ,
num , chips [ data - > type ] . muxtype = = pca954x_ismux
? " mux " : " switch " , client - > name ) ;
return 0 ;
virt_reg_failed :
for ( num - - ; num > = 0 ; num - - )
i2c_del_mux_adapter ( data - > virt_adaps [ num ] ) ;
return ret ;
}
2010-10-24 20:16:59 +04:00
static int pca954x_remove ( struct i2c_client * client )
2010-08-11 20:21:03 +04:00
{
struct pca954x * data = i2c_get_clientdata ( client ) ;
const struct chip_desc * chip = & chips [ data - > type ] ;
2013-03-09 12:16:48 +04:00
int i ;
2010-08-11 20:21:03 +04:00
for ( i = 0 ; i < chip - > nchans ; + + i )
if ( data - > virt_adaps [ i ] ) {
2013-03-09 12:16:48 +04:00
i2c_del_mux_adapter ( data - > virt_adaps [ i ] ) ;
2010-08-11 20:21:03 +04:00
data - > virt_adaps [ i ] = NULL ;
}
return 0 ;
}
2014-07-25 15:57:46 +04:00
# ifdef CONFIG_PM_SLEEP
static int pca954x_resume ( struct device * dev )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
struct pca954x * data = i2c_get_clientdata ( client ) ;
data - > last_chan = 0 ;
return i2c_smbus_write_byte ( client , 0 ) ;
}
# endif
static SIMPLE_DEV_PM_OPS ( pca954x_pm , NULL , pca954x_resume ) ;
2010-08-11 20:21:03 +04:00
static struct i2c_driver pca954x_driver = {
. driver = {
. name = " pca954x " ,
2014-07-25 15:57:46 +04:00
. pm = & pca954x_pm ,
2010-08-11 20:21:03 +04:00
. owner = THIS_MODULE ,
} ,
. probe = pca954x_probe ,
2010-10-24 20:16:59 +04:00
. remove = pca954x_remove ,
2010-08-11 20:21:03 +04:00
. id_table = pca954x_id ,
} ;
2012-03-26 23:47:19 +04:00
module_i2c_driver ( pca954x_driver ) ;
2010-08-11 20:21:03 +04:00
MODULE_AUTHOR ( " Rodolfo Giometti <giometti@linux.it> " ) ;
MODULE_DESCRIPTION ( " PCA954x I2C mux/switch driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;