2010-05-11 01:39:47 +04:00
/*
* Copyright ( C ) ST - Ericsson SA 2010
*
* License Terms : GNU General Public License , version 2
* Author : Hanumath Prasad < hanumath . prasad @ stericsson . com > for ST - Ericsson
* Author : Rabin Vincent < rabin . vincent @ stericsson . com > for ST - Ericsson
*/
# include <linux/module.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
2012-09-07 15:14:56 +04:00
# include <linux/irqdomain.h>
2010-05-11 01:39:47 +04:00
# include <linux/slab.h>
# include <linux/i2c.h>
2012-09-07 15:14:57 +04:00
# include <linux/of.h>
2014-01-23 16:43:28 +04:00
# include <linux/of_device.h>
2010-05-11 01:39:47 +04:00
# include <linux/mfd/core.h>
2010-12-13 07:03:12 +03:00
# include <linux/mfd/tc3589x.h>
2014-01-23 16:43:28 +04:00
# include <linux/err.h>
2010-05-11 01:39:47 +04:00
2013-10-18 13:51:45 +04:00
/**
* enum tc3589x_version - indicates the TC3589x version
*/
enum tc3589x_version {
TC3589X_TC35890 ,
TC3589X_TC35892 ,
TC3589X_TC35893 ,
TC3589X_TC35894 ,
TC3589X_TC35895 ,
TC3589X_TC35896 ,
TC3589X_UNKNOWN ,
} ;
2010-12-13 07:03:18 +03:00
# define TC3589x_CLKMODE_MODCTL_SLEEP 0x0
# define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0)
2010-05-11 01:39:47 +04:00
/**
2010-12-13 07:03:14 +03:00
* tc3589x_reg_read ( ) - read a single TC3589x register
* @ tc3589x : Device to read from
2010-05-11 01:39:47 +04:00
* @ reg : Register to read
*/
2010-12-13 07:03:14 +03:00
int tc3589x_reg_read ( struct tc3589x * tc3589x , u8 reg )
2010-05-11 01:39:47 +04:00
{
int ret ;
2010-12-13 07:03:14 +03:00
ret = i2c_smbus_read_byte_data ( tc3589x - > i2c , reg ) ;
2010-05-11 01:39:47 +04:00
if ( ret < 0 )
2010-12-13 07:03:14 +03:00
dev_err ( tc3589x - > dev , " failed to read reg %#x: %d \n " ,
2010-05-11 01:39:47 +04:00
reg , ret ) ;
return ret ;
}
2010-12-13 07:03:14 +03:00
EXPORT_SYMBOL_GPL ( tc3589x_reg_read ) ;
2010-05-11 01:39:47 +04:00
/**
2010-12-13 07:03:14 +03:00
* tc3589x_reg_read ( ) - write a single TC3589x register
* @ tc3589x : Device to write to
2010-05-11 01:39:47 +04:00
* @ reg : Register to read
* @ data : Value to write
*/
2010-12-13 07:03:14 +03:00
int tc3589x_reg_write ( struct tc3589x * tc3589x , u8 reg , u8 data )
2010-05-11 01:39:47 +04:00
{
int ret ;
2010-12-13 07:03:14 +03:00
ret = i2c_smbus_write_byte_data ( tc3589x - > i2c , reg , data ) ;
2010-05-11 01:39:47 +04:00
if ( ret < 0 )
2010-12-13 07:03:14 +03:00
dev_err ( tc3589x - > dev , " failed to write reg %#x: %d \n " ,
2010-05-11 01:39:47 +04:00
reg , ret ) ;
return ret ;
}
2010-12-13 07:03:14 +03:00
EXPORT_SYMBOL_GPL ( tc3589x_reg_write ) ;
2010-05-11 01:39:47 +04:00
/**
2010-12-13 07:03:14 +03:00
* tc3589x_block_read ( ) - read multiple TC3589x registers
* @ tc3589x : Device to read from
2010-05-11 01:39:47 +04:00
* @ reg : First register
* @ length : Number of registers
* @ values : Buffer to write to
*/
2010-12-13 07:03:14 +03:00
int tc3589x_block_read ( struct tc3589x * tc3589x , u8 reg , u8 length , u8 * values )
2010-05-11 01:39:47 +04:00
{
int ret ;
2010-12-13 07:03:14 +03:00
ret = i2c_smbus_read_i2c_block_data ( tc3589x - > i2c , reg , length , values ) ;
2010-05-11 01:39:47 +04:00
if ( ret < 0 )
2010-12-13 07:03:14 +03:00
dev_err ( tc3589x - > dev , " failed to read regs %#x: %d \n " ,
2010-05-11 01:39:47 +04:00
reg , ret ) ;
return ret ;
}
2010-12-13 07:03:14 +03:00
EXPORT_SYMBOL_GPL ( tc3589x_block_read ) ;
2010-05-11 01:39:47 +04:00
/**
2010-12-13 07:03:14 +03:00
* tc3589x_block_write ( ) - write multiple TC3589x registers
* @ tc3589x : Device to write to
2010-05-11 01:39:47 +04:00
* @ reg : First register
* @ length : Number of registers
* @ values : Values to write
*/
2010-12-13 07:03:14 +03:00
int tc3589x_block_write ( struct tc3589x * tc3589x , u8 reg , u8 length ,
2010-05-11 01:39:47 +04:00
const u8 * values )
{
int ret ;
2010-12-13 07:03:14 +03:00
ret = i2c_smbus_write_i2c_block_data ( tc3589x - > i2c , reg , length ,
2010-05-11 01:39:47 +04:00
values ) ;
if ( ret < 0 )
2010-12-13 07:03:14 +03:00
dev_err ( tc3589x - > dev , " failed to write regs %#x: %d \n " ,
2010-05-11 01:39:47 +04:00
reg , ret ) ;
return ret ;
}
2010-12-13 07:03:14 +03:00
EXPORT_SYMBOL_GPL ( tc3589x_block_write ) ;
2010-05-11 01:39:47 +04:00
/**
2010-12-13 07:03:14 +03:00
* tc3589x_set_bits ( ) - set the value of a bitfield in a TC3589x register
* @ tc3589x : Device to write to
2010-05-11 01:39:47 +04:00
* @ reg : Register to write
* @ mask : Mask of bits to set
* @ values : Value to set
*/
2010-12-13 07:03:14 +03:00
int tc3589x_set_bits ( struct tc3589x * tc3589x , u8 reg , u8 mask , u8 val )
2010-05-11 01:39:47 +04:00
{
int ret ;
2010-12-13 07:03:14 +03:00
mutex_lock ( & tc3589x - > lock ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
ret = tc3589x_reg_read ( tc3589x , reg ) ;
2010-05-11 01:39:47 +04:00
if ( ret < 0 )
goto out ;
ret & = ~ mask ;
ret | = val ;
2010-12-13 07:03:14 +03:00
ret = tc3589x_reg_write ( tc3589x , reg , ret ) ;
2010-05-11 01:39:47 +04:00
out :
2010-12-13 07:03:14 +03:00
mutex_unlock ( & tc3589x - > lock ) ;
2010-05-11 01:39:47 +04:00
return ret ;
}
2010-12-13 07:03:14 +03:00
EXPORT_SYMBOL_GPL ( tc3589x_set_bits ) ;
2010-05-11 01:39:47 +04:00
static struct resource gpio_resources [ ] = {
{
2010-12-13 07:03:14 +03:00
. start = TC3589x_INT_GPIIRQ ,
. end = TC3589x_INT_GPIIRQ ,
2010-05-11 01:39:47 +04:00
. flags = IORESOURCE_IRQ ,
} ,
} ;
2010-12-21 13:23:31 +03:00
static struct resource keypad_resources [ ] = {
{
. start = TC3589x_INT_KBDIRQ ,
. end = TC3589x_INT_KBDIRQ ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
2013-11-18 17:33:03 +04:00
static const struct mfd_cell tc3589x_dev_gpio [ ] = {
2010-05-11 01:39:47 +04:00
{
2010-12-13 07:03:14 +03:00
. name = " tc3589x-gpio " ,
2010-05-11 01:39:47 +04:00
. num_resources = ARRAY_SIZE ( gpio_resources ) ,
. resources = & gpio_resources [ 0 ] ,
2014-01-23 16:43:28 +04:00
. of_compatible = " toshiba,tc3589x-gpio " ,
2010-05-11 01:39:47 +04:00
} ,
} ;
2013-11-18 17:33:03 +04:00
static const struct mfd_cell tc3589x_dev_keypad [ ] = {
2010-12-21 13:23:31 +03:00
{
. name = " tc3589x-keypad " ,
. num_resources = ARRAY_SIZE ( keypad_resources ) ,
. resources = & keypad_resources [ 0 ] ,
2014-01-23 16:43:28 +04:00
. of_compatible = " toshiba,tc3589x-keypad " ,
2010-12-21 13:23:31 +03:00
} ,
} ;
2010-12-13 07:03:14 +03:00
static irqreturn_t tc3589x_irq ( int irq , void * data )
2010-05-11 01:39:47 +04:00
{
2010-12-13 07:03:14 +03:00
struct tc3589x * tc3589x = data ;
2010-05-11 01:39:47 +04:00
int status ;
2010-12-13 07:03:16 +03:00
again :
2010-12-13 07:03:14 +03:00
status = tc3589x_reg_read ( tc3589x , TC3589x_IRQST ) ;
2010-05-11 01:39:47 +04:00
if ( status < 0 )
return IRQ_NONE ;
while ( status ) {
int bit = __ffs ( status ) ;
2012-09-07 15:14:56 +04:00
int virq = irq_create_mapping ( tc3589x - > domain , bit ) ;
2010-05-11 01:39:47 +04:00
2012-09-07 15:14:56 +04:00
handle_nested_irq ( virq ) ;
2010-05-11 01:39:47 +04:00
status & = ~ ( 1 < < bit ) ;
}
/*
* A dummy read or write ( to any register ) appears to be necessary to
* have the last interrupt clear ( for example , GPIO IC write ) take
2010-12-13 07:03:16 +03:00
* effect . In such a case , recheck for any interrupt which is still
* pending .
2010-05-11 01:39:47 +04:00
*/
2010-12-13 07:03:16 +03:00
status = tc3589x_reg_read ( tc3589x , TC3589x_IRQST ) ;
if ( status )
goto again ;
2010-05-11 01:39:47 +04:00
return IRQ_HANDLED ;
}
2012-09-07 15:14:56 +04:00
static int tc3589x_irq_map ( struct irq_domain * d , unsigned int virq ,
irq_hw_number_t hwirq )
2010-05-11 01:39:47 +04:00
{
2012-09-07 15:14:56 +04:00
struct tc3589x * tc3589x = d - > host_data ;
2010-05-11 01:39:47 +04:00
2012-09-07 15:14:56 +04:00
irq_set_chip_data ( virq , tc3589x ) ;
irq_set_chip_and_handler ( virq , & dummy_irq_chip ,
handle_edge_irq ) ;
irq_set_nested_thread ( virq , 1 ) ;
irq_set_noprobe ( virq ) ;
2010-05-11 01:39:47 +04:00
return 0 ;
}
2012-09-07 15:14:56 +04:00
static void tc3589x_irq_unmap ( struct irq_domain * d , unsigned int virq )
2010-05-11 01:39:47 +04:00
{
2012-09-07 15:14:56 +04:00
irq_set_chip_and_handler ( virq , NULL , NULL ) ;
irq_set_chip_data ( virq , NULL ) ;
}
2015-04-27 15:54:13 +03:00
static const struct irq_domain_ops tc3589x_irq_ops = {
2013-01-02 17:40:14 +04:00
. map = tc3589x_irq_map ,
2012-09-07 15:14:56 +04:00
. unmap = tc3589x_irq_unmap ,
2014-06-10 16:31:32 +04:00
. xlate = irq_domain_xlate_onecell ,
2012-09-07 15:14:56 +04:00
} ;
2012-09-07 15:14:57 +04:00
static int tc3589x_irq_init ( struct tc3589x * tc3589x , struct device_node * np )
2012-09-07 15:14:56 +04:00
{
2013-01-02 17:40:14 +04:00
tc3589x - > domain = irq_domain_add_simple (
2014-10-28 13:06:56 +03:00
np , TC3589x_NR_INTERNAL_IRQS , 0 ,
2013-01-02 17:40:14 +04:00
& tc3589x_irq_ops , tc3589x ) ;
2012-09-07 15:14:56 +04:00
if ( ! tc3589x - > domain ) {
dev_err ( tc3589x - > dev , " Failed to create irqdomain \n " ) ;
return - ENOSYS ;
}
return 0 ;
2010-05-11 01:39:47 +04:00
}
2010-12-13 07:03:14 +03:00
static int tc3589x_chip_init ( struct tc3589x * tc3589x )
2010-05-11 01:39:47 +04:00
{
int manf , ver , ret ;
2010-12-13 07:03:14 +03:00
manf = tc3589x_reg_read ( tc3589x , TC3589x_MANFCODE ) ;
2010-05-11 01:39:47 +04:00
if ( manf < 0 )
return manf ;
2010-12-13 07:03:14 +03:00
ver = tc3589x_reg_read ( tc3589x , TC3589x_VERSION ) ;
2010-05-11 01:39:47 +04:00
if ( ver < 0 )
return ver ;
2010-12-13 07:03:14 +03:00
if ( manf ! = TC3589x_MANFCODE_MAGIC ) {
dev_err ( tc3589x - > dev , " unknown manufacturer: %#x \n " , manf ) ;
2010-05-11 01:39:47 +04:00
return - EINVAL ;
}
2010-12-13 07:03:14 +03:00
dev_info ( tc3589x - > dev , " manufacturer: %#x, version: %#x \n " , manf , ver ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:17 +03:00
/*
* Put everything except the IRQ module into reset ;
* also spare the GPIO module for any pin initialization
* done during pre - kernel boot
*/
2010-12-13 07:03:14 +03:00
ret = tc3589x_reg_write ( tc3589x , TC3589x_RSTCTRL ,
TC3589x_RSTCTRL_TIMRST
| TC3589x_RSTCTRL_ROTRST
2010-12-13 07:03:17 +03:00
| TC3589x_RSTCTRL_KBDRST ) ;
2010-05-11 01:39:47 +04:00
if ( ret < 0 )
return ret ;
/* Clear the reset interrupt. */
2010-12-13 07:03:14 +03:00
return tc3589x_reg_write ( tc3589x , TC3589x_RSTINTCLR , 0x1 ) ;
2010-05-11 01:39:47 +04:00
}
2012-11-19 22:23:04 +04:00
static int tc3589x_device_init ( struct tc3589x * tc3589x )
2010-12-13 07:03:15 +03:00
{
int ret = 0 ;
unsigned int blocks = tc3589x - > pdata - > block ;
if ( blocks & TC3589x_BLOCK_GPIO ) {
ret = mfd_add_devices ( tc3589x - > dev , - 1 , tc3589x_dev_gpio ,
2012-09-11 11:16:36 +04:00
ARRAY_SIZE ( tc3589x_dev_gpio ) , NULL ,
2014-10-28 13:06:56 +03:00
0 , tc3589x - > domain ) ;
2010-12-13 07:03:15 +03:00
if ( ret ) {
dev_err ( tc3589x - > dev , " failed to add gpio child \n " ) ;
return ret ;
}
dev_info ( tc3589x - > dev , " added gpio block \n " ) ;
}
2010-12-21 13:23:31 +03:00
if ( blocks & TC3589x_BLOCK_KEYPAD ) {
ret = mfd_add_devices ( tc3589x - > dev , - 1 , tc3589x_dev_keypad ,
2012-09-11 11:16:36 +04:00
ARRAY_SIZE ( tc3589x_dev_keypad ) , NULL ,
2014-10-28 13:06:56 +03:00
0 , tc3589x - > domain ) ;
2010-12-21 13:23:31 +03:00
if ( ret ) {
dev_err ( tc3589x - > dev , " failed to keypad child \n " ) ;
return ret ;
}
dev_info ( tc3589x - > dev , " added keypad block \n " ) ;
}
2010-12-13 07:03:15 +03:00
2010-12-21 13:23:31 +03:00
return ret ;
2010-12-13 07:03:15 +03:00
}
2014-01-23 16:43:28 +04:00
static const struct of_device_id tc3589x_match [ ] = {
/* Legacy compatible string */
{ . compatible = " tc3589x " , . data = ( void * ) TC3589X_UNKNOWN } ,
{ . compatible = " toshiba,tc35890 " , . data = ( void * ) TC3589X_TC35890 } ,
{ . compatible = " toshiba,tc35892 " , . data = ( void * ) TC3589X_TC35892 } ,
{ . compatible = " toshiba,tc35893 " , . data = ( void * ) TC3589X_TC35893 } ,
{ . compatible = " toshiba,tc35894 " , . data = ( void * ) TC3589X_TC35894 } ,
{ . compatible = " toshiba,tc35895 " , . data = ( void * ) TC3589X_TC35895 } ,
{ . compatible = " toshiba,tc35896 " , . data = ( void * ) TC3589X_TC35896 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , tc3589x_match ) ;
static struct tc3589x_platform_data *
tc3589x_of_probe ( struct device * dev , enum tc3589x_version * version )
2012-09-07 15:14:57 +04:00
{
2014-01-23 16:43:28 +04:00
struct device_node * np = dev - > of_node ;
struct tc3589x_platform_data * pdata ;
2012-09-07 15:14:57 +04:00
struct device_node * child ;
2014-01-23 16:43:28 +04:00
const struct of_device_id * of_id ;
pdata = devm_kzalloc ( dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
if ( ! pdata )
return ERR_PTR ( - ENOMEM ) ;
of_id = of_match_device ( tc3589x_match , dev ) ;
if ( ! of_id )
return ERR_PTR ( - ENODEV ) ;
* version = ( enum tc3589x_version ) of_id - > data ;
2012-09-07 15:14:57 +04:00
for_each_child_of_node ( np , child ) {
2014-01-23 16:43:28 +04:00
if ( of_device_is_compatible ( child , " toshiba,tc3589x-gpio " ) )
2012-09-07 15:14:57 +04:00
pdata - > block | = TC3589x_BLOCK_GPIO ;
2014-01-23 16:43:28 +04:00
if ( of_device_is_compatible ( child , " toshiba,tc3589x-keypad " ) )
2012-09-07 15:14:57 +04:00
pdata - > block | = TC3589x_BLOCK_KEYPAD ;
}
2014-01-23 16:43:28 +04:00
return pdata ;
2012-09-07 15:14:57 +04:00
}
2012-11-19 22:23:04 +04:00
static int tc3589x_probe ( struct i2c_client * i2c ,
2010-05-11 01:39:47 +04:00
const struct i2c_device_id * id )
{
2012-09-07 15:14:57 +04:00
struct device_node * np = i2c - > dev . of_node ;
2014-01-23 16:43:28 +04:00
struct tc3589x_platform_data * pdata = dev_get_platdata ( & i2c - > dev ) ;
2010-12-13 07:03:14 +03:00
struct tc3589x * tc3589x ;
2014-01-23 16:43:28 +04:00
enum tc3589x_version version ;
2010-05-11 01:39:47 +04:00
int ret ;
2012-09-07 15:14:57 +04:00
if ( ! pdata ) {
2014-01-23 16:43:28 +04:00
pdata = tc3589x_of_probe ( & i2c - > dev , & version ) ;
if ( IS_ERR ( pdata ) ) {
2012-09-07 15:14:57 +04:00
dev_err ( & i2c - > dev , " No platform data or DT found \n " ) ;
2014-01-23 16:43:28 +04:00
return PTR_ERR ( pdata ) ;
2012-09-07 15:14:57 +04:00
}
2014-01-23 16:43:28 +04:00
} else {
/* When not probing from device tree we have this ID */
version = id - > driver_data ;
2012-09-07 15:14:57 +04:00
}
2010-05-11 01:39:47 +04:00
if ( ! i2c_check_functionality ( i2c - > adapter , I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK ) )
return - EIO ;
2013-02-20 13:31:52 +04:00
tc3589x = devm_kzalloc ( & i2c - > dev , sizeof ( struct tc3589x ) ,
GFP_KERNEL ) ;
2010-12-13 07:03:14 +03:00
if ( ! tc3589x )
2010-05-11 01:39:47 +04:00
return - ENOMEM ;
2010-12-13 07:03:14 +03:00
mutex_init ( & tc3589x - > lock ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
tc3589x - > dev = & i2c - > dev ;
tc3589x - > i2c = i2c ;
tc3589x - > pdata = pdata ;
2013-10-18 13:51:45 +04:00
2014-01-23 16:43:28 +04:00
switch ( version ) {
2013-10-18 13:51:45 +04:00
case TC3589X_TC35893 :
case TC3589X_TC35895 :
case TC3589X_TC35896 :
tc3589x - > num_gpio = 20 ;
break ;
case TC3589X_TC35890 :
case TC3589X_TC35892 :
case TC3589X_TC35894 :
case TC3589X_UNKNOWN :
default :
tc3589x - > num_gpio = 24 ;
break ;
}
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
i2c_set_clientdata ( i2c , tc3589x ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
ret = tc3589x_chip_init ( tc3589x ) ;
2010-05-11 01:39:47 +04:00
if ( ret )
2013-02-20 13:31:52 +04:00
return ret ;
2010-05-11 01:39:47 +04:00
2012-09-07 15:14:57 +04:00
ret = tc3589x_irq_init ( tc3589x , np ) ;
2010-05-11 01:39:47 +04:00
if ( ret )
2013-02-20 13:31:52 +04:00
return ret ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
ret = request_threaded_irq ( tc3589x - > i2c - > irq , NULL , tc3589x_irq ,
2010-05-11 01:39:47 +04:00
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
2010-12-13 07:03:14 +03:00
" tc3589x " , tc3589x ) ;
2010-05-11 01:39:47 +04:00
if ( ret ) {
2010-12-13 07:03:14 +03:00
dev_err ( tc3589x - > dev , " failed to request IRQ: %d \n " , ret ) ;
2013-02-20 13:31:52 +04:00
return ret ;
2010-05-11 01:39:47 +04:00
}
2010-12-13 07:03:15 +03:00
ret = tc3589x_device_init ( tc3589x ) ;
2010-05-11 01:39:47 +04:00
if ( ret ) {
2010-12-13 07:03:15 +03:00
dev_err ( tc3589x - > dev , " failed to add child devices \n " ) ;
2013-02-20 13:31:52 +04:00
return ret ;
2010-05-11 01:39:47 +04:00
}
return 0 ;
}
2012-11-19 22:26:01 +04:00
static int tc3589x_remove ( struct i2c_client * client )
2010-05-11 01:39:47 +04:00
{
2010-12-13 07:03:14 +03:00
struct tc3589x * tc3589x = i2c_get_clientdata ( client ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
mfd_remove_devices ( tc3589x - > dev ) ;
2010-05-11 01:39:47 +04:00
return 0 ;
}
2012-07-02 13:19:52 +04:00
# ifdef CONFIG_PM_SLEEP
2010-12-13 07:03:18 +03:00
static int tc3589x_suspend ( struct device * dev )
{
struct tc3589x * tc3589x = dev_get_drvdata ( dev ) ;
struct i2c_client * client = tc3589x - > i2c ;
int ret = 0 ;
/* put the system to sleep mode */
if ( ! device_may_wakeup ( & client - > dev ) )
ret = tc3589x_reg_write ( tc3589x , TC3589x_CLKMODE ,
TC3589x_CLKMODE_MODCTL_SLEEP ) ;
return ret ;
}
static int tc3589x_resume ( struct device * dev )
{
struct tc3589x * tc3589x = dev_get_drvdata ( dev ) ;
struct i2c_client * client = tc3589x - > i2c ;
int ret = 0 ;
/* enable the system into operation */
if ( ! device_may_wakeup ( & client - > dev ) )
ret = tc3589x_reg_write ( tc3589x , TC3589x_CLKMODE ,
TC3589x_CLKMODE_MODCTL_OPERATION ) ;
return ret ;
}
2011-08-09 22:37:17 +04:00
# endif
2010-12-13 07:03:18 +03:00
2012-07-02 13:19:52 +04:00
static SIMPLE_DEV_PM_OPS ( tc3589x_dev_pm_ops , tc3589x_suspend , tc3589x_resume ) ;
2010-12-13 07:03:14 +03:00
static const struct i2c_device_id tc3589x_id [ ] = {
2013-10-18 13:51:45 +04:00
{ " tc35890 " , TC3589X_TC35890 } ,
{ " tc35892 " , TC3589X_TC35892 } ,
{ " tc35893 " , TC3589X_TC35893 } ,
{ " tc35894 " , TC3589X_TC35894 } ,
{ " tc35895 " , TC3589X_TC35895 } ,
{ " tc35896 " , TC3589X_TC35896 } ,
{ " tc3589x " , TC3589X_UNKNOWN } ,
2010-05-11 01:39:47 +04:00
{ }
} ;
2010-12-13 07:03:14 +03:00
MODULE_DEVICE_TABLE ( i2c , tc3589x_id ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
static struct i2c_driver tc3589x_driver = {
2014-01-23 16:43:28 +04:00
. driver = {
. name = " tc3589x " ,
. pm = & tc3589x_dev_pm_ops ,
. of_match_table = of_match_ptr ( tc3589x_match ) ,
} ,
2010-12-13 07:03:14 +03:00
. probe = tc3589x_probe ,
2012-11-19 22:20:24 +04:00
. remove = tc3589x_remove ,
2010-12-13 07:03:14 +03:00
. id_table = tc3589x_id ,
2010-05-11 01:39:47 +04:00
} ;
2010-12-13 07:03:14 +03:00
static int __init tc3589x_init ( void )
2010-05-11 01:39:47 +04:00
{
2010-12-13 07:03:14 +03:00
return i2c_add_driver ( & tc3589x_driver ) ;
2010-05-11 01:39:47 +04:00
}
2010-12-13 07:03:14 +03:00
subsys_initcall ( tc3589x_init ) ;
2010-05-11 01:39:47 +04:00
2010-12-13 07:03:14 +03:00
static void __exit tc3589x_exit ( void )
2010-05-11 01:39:47 +04:00
{
2010-12-13 07:03:14 +03:00
i2c_del_driver ( & tc3589x_driver ) ;
2010-05-11 01:39:47 +04:00
}
2010-12-13 07:03:14 +03:00
module_exit ( tc3589x_exit ) ;
2010-05-11 01:39:47 +04:00
MODULE_LICENSE ( " GPL v2 " ) ;
2010-12-13 07:03:14 +03:00
MODULE_DESCRIPTION ( " TC3589x MFD core driver " ) ;
2010-05-11 01:39:47 +04:00
MODULE_AUTHOR ( " Hanumath Prasad, Rabin Vincent " ) ;