2012-01-04 08:27:43 +04:00
/*
2012-01-27 10:59:08 +04:00
* Driver for LP8727 Micro / Mini USB IC with integrated charger
2012-01-04 08:27:43 +04:00
*
2012-01-30 05:28:18 +04:00
* Copyright ( C ) 2011 Texas Instruments
2012-01-04 08:27:43 +04:00
* Copyright ( C ) 2011 National Semiconductor
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
# include <linux/i2c.h>
# include <linux/power_supply.h>
2012-07-03 05:19:03 +04:00
# include <linux/platform_data/lp8727.h>
2012-01-04 08:27:43 +04:00
2012-08-31 13:24:09 +04:00
# define LP8788_NUM_INTREGS 2
2012-08-31 13:23:25 +04:00
# define DEFAULT_DEBOUNCE_MSEC 270
2012-01-04 08:27:43 +04:00
/* Registers */
2012-08-31 13:24:51 +04:00
# define LP8727_CTRL1 0x1
# define LP8727_CTRL2 0x2
# define LP8727_SWCTRL 0x3
# define LP8727_INT1 0x4
# define LP8727_INT2 0x5
# define LP8727_STATUS1 0x6
# define LP8727_STATUS2 0x7
# define LP8727_CHGCTRL2 0x9
2012-01-04 08:27:43 +04:00
/* CTRL1 register */
2012-08-31 13:24:51 +04:00
# define LP8727_CP_EN BIT(0)
# define LP8727_ADC_EN BIT(1)
# define LP8727_ID200_EN BIT(4)
2012-01-04 08:27:43 +04:00
/* CTRL2 register */
2012-08-31 13:24:51 +04:00
# define LP8727_CHGDET_EN BIT(1)
# define LP8727_INT_EN BIT(6)
2012-01-04 08:27:43 +04:00
/* SWCTRL register */
2012-08-31 13:24:51 +04:00
# define LP8727_SW_DM1_DM (0x0 << 0)
# define LP8727_SW_DM1_HiZ (0x7 << 0)
# define LP8727_SW_DP2_DP (0x0 << 3)
# define LP8727_SW_DP2_HiZ (0x7 << 3)
2012-01-04 08:27:43 +04:00
/* INT1 register */
2012-08-31 13:24:51 +04:00
# define LP8727_IDNO (0xF << 0)
# define LP8727_VBUS BIT(4)
2012-01-04 08:27:43 +04:00
/* STATUS1 register */
2012-08-31 13:24:51 +04:00
# define LP8727_CHGSTAT (3 << 4)
# define LP8727_CHPORT BIT(6)
# define LP8727_DCPORT BIT(7)
# define LP8727_STAT_EOC 0x30
2012-01-04 08:27:43 +04:00
/* STATUS2 register */
2012-08-31 13:24:51 +04:00
# define LP8727_TEMP_STAT (3 << 5)
# define LP8727_TEMP_SHIFT 5
2012-01-04 08:27:43 +04:00
2012-08-31 13:25:07 +04:00
/* CHGCTRL2 register */
# define LP8727_ICHG_SHIFT 4
2012-01-04 08:27:43 +04:00
enum lp8727_dev_id {
2012-08-31 13:24:51 +04:00
LP8727_ID_NONE ,
LP8727_ID_TA ,
LP8727_ID_DEDICATED_CHG ,
LP8727_ID_USB_CHG ,
LP8727_ID_USB_DS ,
LP8727_ID_MAX ,
2012-01-04 08:27:43 +04:00
} ;
2012-08-31 13:24:28 +04:00
enum lp8727_die_temp {
LP8788_TEMP_75C ,
LP8788_TEMP_95C ,
LP8788_TEMP_115C ,
LP8788_TEMP_135C ,
} ;
2012-01-04 08:27:43 +04:00
struct lp8727_psy {
struct power_supply ac ;
struct power_supply usb ;
struct power_supply batt ;
} ;
struct lp8727_chg {
struct device * dev ;
struct i2c_client * client ;
struct mutex xfer_lock ;
struct lp8727_psy * psy ;
2012-08-31 13:27:04 +04:00
struct lp8727_platform_data * pdata ;
/* Charger Data */
2012-01-04 08:27:43 +04:00
enum lp8727_dev_id devid ;
2012-08-31 13:27:04 +04:00
struct lp8727_chg_param * chg_param ;
/* Interrupt Handling */
2012-08-31 13:23:57 +04:00
int irq ;
2012-08-31 13:27:04 +04:00
struct delayed_work work ;
unsigned long debounce_jiffies ;
2012-01-04 08:27:43 +04:00
} ;
2012-01-27 10:58:39 +04:00
static int lp8727_read_bytes ( struct lp8727_chg * pchg , u8 reg , u8 * data , u8 len )
2012-01-04 08:27:43 +04:00
{
s32 ret ;
mutex_lock ( & pchg - > xfer_lock ) ;
ret = i2c_smbus_read_i2c_block_data ( pchg - > client , reg , len , data ) ;
mutex_unlock ( & pchg - > xfer_lock ) ;
return ( ret ! = len ) ? - EIO : 0 ;
}
2012-01-27 10:58:39 +04:00
static inline int lp8727_read_byte ( struct lp8727_chg * pchg , u8 reg , u8 * data )
2012-01-04 08:27:43 +04:00
{
2012-01-27 10:58:39 +04:00
return lp8727_read_bytes ( pchg , reg , data , 1 ) ;
}
static int lp8727_write_byte ( struct lp8727_chg * pchg , u8 reg , u8 data )
{
int ret ;
2012-01-04 08:27:43 +04:00
mutex_lock ( & pchg - > xfer_lock ) ;
2012-01-27 10:58:39 +04:00
ret = i2c_smbus_write_byte_data ( pchg - > client , reg , data ) ;
2012-01-04 08:27:43 +04:00
mutex_unlock ( & pchg - > xfer_lock ) ;
return ret ;
}
2012-08-31 13:25:22 +04:00
static bool lp8727_is_charger_attached ( const char * name , int id )
2012-01-04 08:27:43 +04:00
{
2012-08-31 13:25:22 +04:00
if ( ! strcmp ( name , " ac " ) )
return id = = LP8727_ID_TA | | id = = LP8727_ID_DEDICATED_CHG ;
else if ( ! strcmp ( name , " usb " ) )
return id = = LP8727_ID_USB_CHG ;
return id > = LP8727_ID_TA & & id < = LP8727_ID_USB_CHG ;
2012-01-04 08:27:43 +04:00
}
2012-01-27 10:58:30 +04:00
static int lp8727_init_device ( struct lp8727_chg * pchg )
2012-01-04 08:27:43 +04:00
{
u8 val ;
2012-01-27 10:58:30 +04:00
int ret ;
2012-08-31 13:24:09 +04:00
u8 intstat [ LP8788_NUM_INTREGS ] ;
/* clear interrupts */
2012-08-31 13:24:51 +04:00
ret = lp8727_read_bytes ( pchg , LP8727_INT1 , intstat , LP8788_NUM_INTREGS ) ;
2012-08-31 13:24:09 +04:00
if ( ret )
return ret ;
2012-08-31 13:24:51 +04:00
val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN ;
ret = lp8727_write_byte ( pchg , LP8727_CTRL1 , val ) ;
2012-01-27 10:58:30 +04:00
if ( ret )
return ret ;
2012-01-04 08:27:43 +04:00
2012-08-31 13:24:51 +04:00
val = LP8727_INT_EN | LP8727_CHGDET_EN ;
2012-08-31 13:25:34 +04:00
return lp8727_write_byte ( pchg , LP8727_CTRL2 , val ) ;
2012-01-04 08:27:43 +04:00
}
static int lp8727_is_dedicated_charger ( struct lp8727_chg * pchg )
{
u8 val ;
2012-08-31 13:27:22 +04:00
2012-08-31 13:24:51 +04:00
lp8727_read_byte ( pchg , LP8727_STATUS1 , & val ) ;
return val & LP8727_DCPORT ;
2012-01-04 08:27:43 +04:00
}
static int lp8727_is_usb_charger ( struct lp8727_chg * pchg )
{
u8 val ;
2012-08-31 13:27:22 +04:00
2012-08-31 13:24:51 +04:00
lp8727_read_byte ( pchg , LP8727_STATUS1 , & val ) ;
return val & LP8727_CHPORT ;
2012-01-04 08:27:43 +04:00
}
2012-08-31 13:25:45 +04:00
static inline void lp8727_ctrl_switch ( struct lp8727_chg * pchg , u8 sw )
2012-01-04 08:27:43 +04:00
{
2012-08-31 13:24:51 +04:00
lp8727_write_byte ( pchg , LP8727_SWCTRL , sw ) ;
2012-01-04 08:27:43 +04:00
}
static void lp8727_id_detection ( struct lp8727_chg * pchg , u8 id , int vbusin )
{
2012-08-31 13:23:12 +04:00
struct lp8727_platform_data * pdata = pchg - > pdata ;
2012-08-31 13:24:51 +04:00
u8 devid = LP8727_ID_NONE ;
u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ ;
2012-01-04 08:27:43 +04:00
switch ( id ) {
case 0x5 :
2012-08-31 13:24:51 +04:00
devid = LP8727_ID_TA ;
2012-08-31 13:26:49 +04:00
pchg - > chg_param = pdata ? pdata - > ac : NULL ;
2012-01-04 08:27:43 +04:00
break ;
case 0xB :
if ( lp8727_is_dedicated_charger ( pchg ) ) {
2012-08-31 13:26:49 +04:00
pchg - > chg_param = pdata ? pdata - > ac : NULL ;
2012-08-31 13:24:51 +04:00
devid = LP8727_ID_DEDICATED_CHG ;
2012-01-04 08:27:43 +04:00
} else if ( lp8727_is_usb_charger ( pchg ) ) {
2012-08-31 13:26:49 +04:00
pchg - > chg_param = pdata ? pdata - > usb : NULL ;
2012-08-31 13:24:51 +04:00
devid = LP8727_ID_USB_CHG ;
swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP ;
2012-01-04 08:27:43 +04:00
} else if ( vbusin ) {
2012-08-31 13:24:51 +04:00
devid = LP8727_ID_USB_DS ;
swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP ;
2012-01-04 08:27:43 +04:00
}
break ;
default :
2012-08-31 13:24:51 +04:00
devid = LP8727_ID_NONE ;
2012-08-31 13:26:49 +04:00
pchg - > chg_param = NULL ;
2012-01-04 08:27:43 +04:00
break ;
}
pchg - > devid = devid ;
lp8727_ctrl_switch ( pchg , swctrl ) ;
}
static void lp8727_enable_chgdet ( struct lp8727_chg * pchg )
{
u8 val ;
2012-08-31 13:24:51 +04:00
lp8727_read_byte ( pchg , LP8727_CTRL2 , & val ) ;
val | = LP8727_CHGDET_EN ;
lp8727_write_byte ( pchg , LP8727_CTRL2 , val ) ;
2012-01-04 08:27:43 +04:00
}
static void lp8727_delayed_func ( struct work_struct * _work )
{
2012-08-31 13:26:33 +04:00
struct lp8727_chg * pchg = container_of ( _work , struct lp8727_chg ,
work . work ) ;
u8 intstat [ LP8788_NUM_INTREGS ] ;
u8 idno ;
u8 vbus ;
2012-01-04 08:27:43 +04:00
2012-08-31 13:25:07 +04:00
if ( lp8727_read_bytes ( pchg , LP8727_INT1 , intstat , LP8788_NUM_INTREGS ) ) {
2012-01-04 08:27:43 +04:00
dev_err ( pchg - > dev , " can not read INT registers \n " ) ;
return ;
}
2012-08-31 13:24:51 +04:00
idno = intstat [ 0 ] & LP8727_IDNO ;
vbus = intstat [ 0 ] & LP8727_VBUS ;
2012-01-04 08:27:43 +04:00
lp8727_id_detection ( pchg , idno , vbus ) ;
lp8727_enable_chgdet ( pchg ) ;
power_supply_changed ( & pchg - > psy - > ac ) ;
power_supply_changed ( & pchg - > psy - > usb ) ;
power_supply_changed ( & pchg - > psy - > batt ) ;
}
static irqreturn_t lp8727_isr_func ( int irq , void * ptr )
{
struct lp8727_chg * pchg = ptr ;
2012-08-31 13:23:41 +04:00
schedule_delayed_work ( & pchg - > work , pchg - > debounce_jiffies ) ;
2012-01-04 08:27:43 +04:00
return IRQ_HANDLED ;
}
2012-08-31 13:23:57 +04:00
static int lp8727_setup_irq ( struct lp8727_chg * pchg )
2012-01-04 08:27:43 +04:00
{
2012-08-31 13:23:57 +04:00
int ret ;
int irq = pchg - > client - > irq ;
2012-08-31 13:23:25 +04:00
unsigned delay_msec = pchg - > pdata ? pchg - > pdata - > debounce_msec :
DEFAULT_DEBOUNCE_MSEC ;
2012-01-04 08:27:43 +04:00
INIT_DELAYED_WORK ( & pchg - > work , lp8727_delayed_func ) ;
2012-08-31 13:23:57 +04:00
if ( irq < = 0 ) {
dev_warn ( pchg - > dev , " invalid irq number: %d \n " , irq ) ;
return 0 ;
}
2012-08-31 13:23:25 +04:00
2012-08-31 13:23:57 +04:00
ret = request_threaded_irq ( irq , NULL , lp8727_isr_func ,
2012-08-23 15:42:29 +04:00
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
2012-08-31 13:23:57 +04:00
" lp8727_irq " , pchg ) ;
if ( ret )
return ret ;
pchg - > irq = irq ;
pchg - > debounce_jiffies = msecs_to_jiffies ( delay_msec ) ;
return 0 ;
}
static void lp8727_release_irq ( struct lp8727_chg * pchg )
{
cancel_delayed_work_sync ( & pchg - > work ) ;
if ( pchg - > irq )
free_irq ( pchg - > irq , pchg ) ;
2012-01-04 08:27:43 +04:00
}
static enum power_supply_property lp8727_charger_prop [ ] = {
POWER_SUPPLY_PROP_ONLINE ,
} ;
static enum power_supply_property lp8727_battery_prop [ ] = {
POWER_SUPPLY_PROP_STATUS ,
POWER_SUPPLY_PROP_HEALTH ,
POWER_SUPPLY_PROP_PRESENT ,
POWER_SUPPLY_PROP_VOLTAGE_NOW ,
POWER_SUPPLY_PROP_CAPACITY ,
POWER_SUPPLY_PROP_TEMP ,
} ;
static char * battery_supplied_to [ ] = {
" main_batt " ,
} ;
static int lp8727_charger_get_property ( struct power_supply * psy ,
enum power_supply_property psp ,
union power_supply_propval * val )
{
struct lp8727_chg * pchg = dev_get_drvdata ( psy - > dev - > parent ) ;
2012-08-31 13:25:55 +04:00
if ( psp ! = POWER_SUPPLY_PROP_ONLINE )
return - EINVAL ;
val - > intval = lp8727_is_charger_attached ( psy - > name , pchg - > devid ) ;
2012-01-04 08:27:43 +04:00
return 0 ;
}
2012-08-31 13:24:28 +04:00
static bool lp8727_is_high_temperature ( enum lp8727_die_temp temp )
{
switch ( temp ) {
case LP8788_TEMP_95C :
case LP8788_TEMP_115C :
case LP8788_TEMP_135C :
return true ;
default :
return false ;
}
}
2012-01-04 08:27:43 +04:00
static int lp8727_battery_get_property ( struct power_supply * psy ,
enum power_supply_property psp ,
union power_supply_propval * val )
{
struct lp8727_chg * pchg = dev_get_drvdata ( psy - > dev - > parent ) ;
2012-08-31 13:23:12 +04:00
struct lp8727_platform_data * pdata = pchg - > pdata ;
2012-08-31 13:24:28 +04:00
enum lp8727_die_temp temp ;
2012-01-04 08:27:43 +04:00
u8 read ;
switch ( psp ) {
case POWER_SUPPLY_PROP_STATUS :
2012-08-31 13:26:06 +04:00
if ( ! lp8727_is_charger_attached ( psy - > name , pchg - > devid ) ) {
val - > intval = POWER_SUPPLY_STATUS_DISCHARGING ;
return 0 ;
}
lp8727_read_byte ( pchg , LP8727_STATUS1 , & read ) ;
2012-08-31 13:24:37 +04:00
2012-08-31 13:26:06 +04:00
val - > intval = ( read & LP8727_CHGSTAT ) = = LP8727_STAT_EOC ?
2012-08-31 13:24:37 +04:00
POWER_SUPPLY_STATUS_FULL :
POWER_SUPPLY_STATUS_CHARGING ;
2012-01-04 08:27:43 +04:00
break ;
case POWER_SUPPLY_PROP_HEALTH :
2012-08-31 13:24:51 +04:00
lp8727_read_byte ( pchg , LP8727_STATUS2 , & read ) ;
temp = ( read & LP8727_TEMP_STAT ) > > LP8727_TEMP_SHIFT ;
2012-08-31 13:24:28 +04:00
val - > intval = lp8727_is_high_temperature ( temp ) ?
POWER_SUPPLY_HEALTH_OVERHEAT :
POWER_SUPPLY_HEALTH_GOOD ;
2012-01-04 08:27:43 +04:00
break ;
case POWER_SUPPLY_PROP_PRESENT :
2012-08-31 13:23:12 +04:00
if ( ! pdata )
return - EINVAL ;
if ( pdata - > get_batt_present )
2012-01-04 08:27:43 +04:00
val - > intval = pchg - > pdata - > get_batt_present ( ) ;
break ;
case POWER_SUPPLY_PROP_VOLTAGE_NOW :
2012-08-31 13:23:12 +04:00
if ( ! pdata )
return - EINVAL ;
if ( pdata - > get_batt_level )
2012-01-04 08:27:43 +04:00
val - > intval = pchg - > pdata - > get_batt_level ( ) ;
break ;
case POWER_SUPPLY_PROP_CAPACITY :
2012-08-31 13:23:12 +04:00
if ( ! pdata )
return - EINVAL ;
if ( pdata - > get_batt_capacity )
2012-01-04 08:27:43 +04:00
val - > intval = pchg - > pdata - > get_batt_capacity ( ) ;
break ;
case POWER_SUPPLY_PROP_TEMP :
2012-08-31 13:23:12 +04:00
if ( ! pdata )
return - EINVAL ;
if ( pdata - > get_batt_temp )
2012-01-04 08:27:43 +04:00
val - > intval = pchg - > pdata - > get_batt_temp ( ) ;
break ;
default :
break ;
}
return 0 ;
}
static void lp8727_charger_changed ( struct power_supply * psy )
{
struct lp8727_chg * pchg = dev_get_drvdata ( psy - > dev - > parent ) ;
2012-08-31 13:26:22 +04:00
u8 eoc_level ;
u8 ichg ;
2012-01-04 08:27:43 +04:00
u8 val ;
2012-08-31 13:26:22 +04:00
/* skip if no charger exists */
if ( ! lp8727_is_charger_attached ( psy - > name , pchg - > devid ) )
return ;
/* update charging parameters */
2012-08-31 13:26:49 +04:00
if ( pchg - > chg_param ) {
eoc_level = pchg - > chg_param - > eoc_level ;
ichg = pchg - > chg_param - > ichg ;
2012-08-31 13:26:22 +04:00
val = ( ichg < < LP8727_ICHG_SHIFT ) | eoc_level ;
lp8727_write_byte ( pchg , LP8727_CHGCTRL2 , val ) ;
2012-01-04 08:27:43 +04:00
}
}
static int lp8727_register_psy ( struct lp8727_chg * pchg )
{
struct lp8727_psy * psy ;
2012-08-31 13:22:46 +04:00
psy = devm_kzalloc ( pchg - > dev , sizeof ( * psy ) , GFP_KERNEL ) ;
2012-01-04 08:27:43 +04:00
if ( ! psy )
2012-07-29 21:46:55 +04:00
return - ENOMEM ;
2012-01-04 08:27:43 +04:00
pchg - > psy = psy ;
psy - > ac . name = " ac " ;
psy - > ac . type = POWER_SUPPLY_TYPE_MAINS ;
psy - > ac . properties = lp8727_charger_prop ;
psy - > ac . num_properties = ARRAY_SIZE ( lp8727_charger_prop ) ;
psy - > ac . get_property = lp8727_charger_get_property ;
psy - > ac . supplied_to = battery_supplied_to ;
psy - > ac . num_supplicants = ARRAY_SIZE ( battery_supplied_to ) ;
if ( power_supply_register ( pchg - > dev , & psy - > ac ) )
2012-07-29 21:46:55 +04:00
goto err_psy_ac ;
2012-01-04 08:27:43 +04:00
psy - > usb . name = " usb " ;
psy - > usb . type = POWER_SUPPLY_TYPE_USB ;
psy - > usb . properties = lp8727_charger_prop ;
psy - > usb . num_properties = ARRAY_SIZE ( lp8727_charger_prop ) ;
psy - > usb . get_property = lp8727_charger_get_property ;
psy - > usb . supplied_to = battery_supplied_to ;
psy - > usb . num_supplicants = ARRAY_SIZE ( battery_supplied_to ) ;
if ( power_supply_register ( pchg - > dev , & psy - > usb ) )
2012-07-29 21:46:55 +04:00
goto err_psy_usb ;
2012-01-04 08:27:43 +04:00
psy - > batt . name = " main_batt " ;
psy - > batt . type = POWER_SUPPLY_TYPE_BATTERY ;
psy - > batt . properties = lp8727_battery_prop ;
psy - > batt . num_properties = ARRAY_SIZE ( lp8727_battery_prop ) ;
psy - > batt . get_property = lp8727_battery_get_property ;
psy - > batt . external_power_changed = lp8727_charger_changed ;
if ( power_supply_register ( pchg - > dev , & psy - > batt ) )
2012-07-29 21:46:55 +04:00
goto err_psy_batt ;
2012-01-04 08:27:43 +04:00
return 0 ;
2012-07-29 21:46:55 +04:00
err_psy_batt :
power_supply_unregister ( & psy - > usb ) ;
err_psy_usb :
power_supply_unregister ( & psy - > ac ) ;
err_psy_ac :
2012-01-04 08:27:43 +04:00
return - EPERM ;
}
static void lp8727_unregister_psy ( struct lp8727_chg * pchg )
{
struct lp8727_psy * psy = pchg - > psy ;
2012-01-04 09:03:18 +04:00
if ( ! psy )
return ;
power_supply_unregister ( & psy - > ac ) ;
power_supply_unregister ( & psy - > usb ) ;
power_supply_unregister ( & psy - > batt ) ;
2012-01-04 08:27:43 +04:00
}
static int lp8727_probe ( struct i2c_client * cl , const struct i2c_device_id * id )
{
struct lp8727_chg * pchg ;
int ret ;
2011-11-18 09:43:06 +04:00
if ( ! i2c_check_functionality ( cl - > adapter , I2C_FUNC_SMBUS_I2C_BLOCK ) )
return - EIO ;
2012-08-31 13:22:46 +04:00
pchg = devm_kzalloc ( & cl - > dev , sizeof ( * pchg ) , GFP_KERNEL ) ;
2012-01-04 08:27:43 +04:00
if ( ! pchg )
return - ENOMEM ;
pchg - > client = cl ;
pchg - > dev = & cl - > dev ;
pchg - > pdata = cl - > dev . platform_data ;
i2c_set_clientdata ( cl , pchg ) ;
mutex_init ( & pchg - > xfer_lock ) ;
2012-01-27 10:58:30 +04:00
ret = lp8727_init_device ( pchg ) ;
if ( ret ) {
dev_err ( pchg - > dev , " i2c communication err: %d " , ret ) ;
2012-08-31 13:23:03 +04:00
return ret ;
2012-01-27 10:58:30 +04:00
}
2012-08-31 13:23:03 +04:00
ret = lp8727_register_psy ( pchg ) ;
2012-01-27 10:58:30 +04:00
if ( ret ) {
2012-08-31 13:23:03 +04:00
dev_err ( pchg - > dev , " power supplies register err: %d " , ret ) ;
return ret ;
2012-01-27 10:58:30 +04:00
}
2012-01-04 08:27:43 +04:00
2012-08-31 13:23:57 +04:00
ret = lp8727_setup_irq ( pchg ) ;
2012-01-27 10:58:30 +04:00
if ( ret ) {
2012-08-31 13:23:03 +04:00
dev_err ( pchg - > dev , " irq handler err: %d " , ret ) ;
lp8727_unregister_psy ( pchg ) ;
return ret ;
2012-01-27 10:58:30 +04:00
}
2012-01-04 08:27:43 +04:00
return 0 ;
}
static int __devexit lp8727_remove ( struct i2c_client * cl )
{
struct lp8727_chg * pchg = i2c_get_clientdata ( cl ) ;
2012-08-31 13:23:57 +04:00
lp8727_release_irq ( pchg ) ;
2012-08-31 13:23:03 +04:00
lp8727_unregister_psy ( pchg ) ;
2012-01-04 08:27:43 +04:00
return 0 ;
}
static const struct i2c_device_id lp8727_ids [ ] = {
{ " lp8727 " , 0 } ,
2012-01-16 09:48:20 +04:00
{ }
2012-01-04 08:27:43 +04:00
} ;
2012-01-12 16:45:02 +04:00
MODULE_DEVICE_TABLE ( i2c , lp8727_ids ) ;
2012-01-04 08:27:43 +04:00
static struct i2c_driver lp8727_driver = {
. driver = {
. name = " lp8727 " ,
} ,
. probe = lp8727_probe ,
2012-11-19 22:20:40 +04:00
. remove = lp8727_remove ,
2012-01-04 08:27:43 +04:00
. id_table = lp8727_ids ,
} ;
2012-01-21 10:42:54 +04:00
module_i2c_driver ( lp8727_driver ) ;
2012-01-04 08:27:43 +04:00
2012-01-30 05:28:18 +04:00
MODULE_DESCRIPTION ( " TI/National Semiconductor LP8727 charger driver " ) ;
2012-08-31 13:27:12 +04:00
MODULE_AUTHOR ( " Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com> " ) ;
2012-01-04 08:27:43 +04:00
MODULE_LICENSE ( " GPL " ) ;