2010-04-08 11:04:55 +04:00
/*
* tps6507x . c - - TPS6507x chip family multi - function driver
*
* Copyright ( c ) 2010 RidgeRun ( todd . fischer @ ridgerun . com )
*
* Author : Todd Fischer
* todd . fischer @ ridgerun . com
*
* Credits :
*
* Using code from wm831x - * . c , wm8400 - core , Wolfson Microelectronics PLC .
*
* For licencing details see kernel - base / COPYING
*
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/i2c.h>
2013-01-24 14:55:17 +04:00
# include <linux/of_device.h>
2010-04-08 11:04:55 +04:00
# include <linux/mfd/core.h>
# include <linux/mfd/tps6507x.h>
static struct mfd_cell tps6507x_devs [ ] = {
{
. name = " tps6507x-pmic " ,
} ,
2010-04-06 03:53:12 +04:00
{
. name = " tps6507x-ts " ,
} ,
2010-04-08 11:04:55 +04:00
} ;
static int tps6507x_i2c_read_device ( struct tps6507x_dev * tps6507x , char reg ,
int bytes , void * dest )
{
struct i2c_client * i2c = tps6507x - > i2c_client ;
struct i2c_msg xfer [ 2 ] ;
int ret ;
/* Write register */
xfer [ 0 ] . addr = i2c - > addr ;
xfer [ 0 ] . flags = 0 ;
xfer [ 0 ] . len = 1 ;
xfer [ 0 ] . buf = & reg ;
/* Read data */
xfer [ 1 ] . addr = i2c - > addr ;
xfer [ 1 ] . flags = I2C_M_RD ;
xfer [ 1 ] . len = bytes ;
xfer [ 1 ] . buf = dest ;
ret = i2c_transfer ( i2c - > adapter , xfer , 2 ) ;
if ( ret = = 2 )
ret = 0 ;
else if ( ret > = 0 )
ret = - EIO ;
return ret ;
}
static int tps6507x_i2c_write_device ( struct tps6507x_dev * tps6507x , char reg ,
int bytes , void * src )
{
struct i2c_client * i2c = tps6507x - > i2c_client ;
/* we add 1 byte for device register */
u8 msg [ TPS6507X_MAX_REGISTER + 1 ] ;
int ret ;
2010-10-13 06:44:39 +04:00
if ( bytes > TPS6507X_MAX_REGISTER )
2010-04-08 11:04:55 +04:00
return - EINVAL ;
msg [ 0 ] = reg ;
memcpy ( & msg [ 1 ] , src , bytes ) ;
ret = i2c_master_send ( i2c , msg , bytes + 1 ) ;
if ( ret < 0 )
return ret ;
if ( ret ! = bytes + 1 )
return - EIO ;
return 0 ;
}
static int tps6507x_i2c_probe ( struct i2c_client * i2c ,
const struct i2c_device_id * id )
{
struct tps6507x_dev * tps6507x ;
2012-12-09 16:25:55 +04:00
tps6507x = devm_kzalloc ( & i2c - > dev , sizeof ( struct tps6507x_dev ) ,
GFP_KERNEL ) ;
2010-08-09 10:49:46 +04:00
if ( tps6507x = = NULL )
2010-04-08 11:04:55 +04:00
return - ENOMEM ;
i2c_set_clientdata ( i2c , tps6507x ) ;
tps6507x - > dev = & i2c - > dev ;
tps6507x - > i2c_client = i2c ;
tps6507x - > read_dev = tps6507x_i2c_read_device ;
tps6507x - > write_dev = tps6507x_i2c_write_device ;
2012-12-09 16:25:55 +04:00
return mfd_add_devices ( tps6507x - > dev , - 1 , tps6507x_devs ,
ARRAY_SIZE ( tps6507x_devs ) , NULL , 0 , NULL ) ;
2010-04-08 11:04:55 +04:00
}
static int tps6507x_i2c_remove ( struct i2c_client * i2c )
{
struct tps6507x_dev * tps6507x = i2c_get_clientdata ( i2c ) ;
mfd_remove_devices ( tps6507x - > dev ) ;
return 0 ;
}
static const struct i2c_device_id tps6507x_i2c_id [ ] = {
{ " tps6507x " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , tps6507x_i2c_id ) ;
2013-01-24 14:55:17 +04:00
# ifdef CONFIG_OF
static struct of_device_id tps6507x_of_match [ ] = {
{ . compatible = " ti,tps6507x " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , tps6507x_of_match ) ;
# endif
2010-04-08 11:04:55 +04:00
static struct i2c_driver tps6507x_i2c_driver = {
. driver = {
. name = " tps6507x " ,
. owner = THIS_MODULE ,
2013-01-24 14:55:17 +04:00
. of_match_table = of_match_ptr ( tps6507x_of_match ) ,
2010-04-08 11:04:55 +04:00
} ,
. probe = tps6507x_i2c_probe ,
. remove = tps6507x_i2c_remove ,
. id_table = tps6507x_i2c_id ,
} ;
static int __init tps6507x_i2c_init ( void )
{
return i2c_add_driver ( & tps6507x_i2c_driver ) ;
}
/* init early so consumer devices can complete system boot */
subsys_initcall ( tps6507x_i2c_init ) ;
static void __exit tps6507x_i2c_exit ( void )
{
i2c_del_driver ( & tps6507x_i2c_driver ) ;
}
module_exit ( tps6507x_i2c_exit ) ;
MODULE_DESCRIPTION ( " TPS6507x chip family multi-function driver " ) ;
MODULE_LICENSE ( " GPL " ) ;