2021-01-06 22:58:49 +03:00
// SPDX-License-Identifier: GPL-2.0
// BQ256XX Battery Charger Driver
// Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
# include <linux/err.h>
# include <linux/i2c.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/gpio/consumer.h>
# include <linux/power_supply.h>
# include <linux/regmap.h>
# include <linux/types.h>
# include <linux/usb/phy.h>
# include <linux/device.h>
# include <linux/moduleparam.h>
# include <linux/slab.h>
# include <linux/acpi.h>
# define BQ256XX_MANUFACTURER "Texas Instruments"
# define BQ256XX_INPUT_CURRENT_LIMIT 0x00
# define BQ256XX_CHARGER_CONTROL_0 0x01
# define BQ256XX_CHARGE_CURRENT_LIMIT 0x02
# define BQ256XX_PRECHG_AND_TERM_CURR_LIM 0x03
# define BQ256XX_BATTERY_VOLTAGE_LIMIT 0x04
# define BQ256XX_CHARGER_CONTROL_1 0x05
# define BQ256XX_CHARGER_CONTROL_2 0x06
# define BQ256XX_CHARGER_CONTROL_3 0x07
# define BQ256XX_CHARGER_STATUS_0 0x08
# define BQ256XX_CHARGER_STATUS_1 0x09
# define BQ256XX_CHARGER_STATUS_2 0x0a
# define BQ256XX_PART_INFORMATION 0x0b
# define BQ256XX_CHARGER_CONTROL_4 0x0c
# define BQ256XX_IINDPM_MASK GENMASK(4, 0)
# define BQ256XX_IINDPM_STEP_uA 100000
# define BQ256XX_IINDPM_OFFSET_uA 100000
# define BQ256XX_IINDPM_MIN_uA 100000
# define BQ256XX_IINDPM_MAX_uA 3200000
# define BQ256XX_IINDPM_DEF_uA 2400000
# define BQ256XX_VINDPM_MASK GENMASK(3, 0)
# define BQ256XX_VINDPM_STEP_uV 100000
# define BQ256XX_VINDPM_OFFSET_uV 3900000
# define BQ256XX_VINDPM_MIN_uV 3900000
# define BQ256XX_VINDPM_MAX_uV 5400000
# define BQ256XX_VINDPM_DEF_uV 4500000
# define BQ256XX_VBATREG_MASK GENMASK(7, 3)
# define BQ2560X_VBATREG_STEP_uV 32000
# define BQ2560X_VBATREG_OFFSET_uV 3856000
# define BQ2560X_VBATREG_MIN_uV 3856000
# define BQ2560X_VBATREG_MAX_uV 4624000
# define BQ2560X_VBATREG_DEF_uV 4208000
# define BQ25601D_VBATREG_OFFSET_uV 3847000
# define BQ25601D_VBATREG_MIN_uV 3847000
# define BQ25601D_VBATREG_MAX_uV 4615000
# define BQ25601D_VBATREG_DEF_uV 4199000
# define BQ2561X_VBATREG_STEP_uV 10000
# define BQ25611D_VBATREG_MIN_uV 3494000
# define BQ25611D_VBATREG_MAX_uV 4510000
# define BQ25611D_VBATREG_DEF_uV 4190000
# define BQ25618_VBATREG_MIN_uV 3504000
# define BQ25618_VBATREG_MAX_uV 4500000
# define BQ25618_VBATREG_DEF_uV 4200000
# define BQ256XX_VBATREG_BIT_SHIFT 3
# define BQ2561X_VBATREG_THRESH 0x8
# define BQ25611D_VBATREG_THRESH_uV 4290000
# define BQ25618_VBATREG_THRESH_uV 4300000
# define BQ256XX_ITERM_MASK GENMASK(3, 0)
# define BQ256XX_ITERM_STEP_uA 60000
# define BQ256XX_ITERM_OFFSET_uA 60000
# define BQ256XX_ITERM_MIN_uA 60000
# define BQ256XX_ITERM_MAX_uA 780000
# define BQ256XX_ITERM_DEF_uA 180000
# define BQ25618_ITERM_STEP_uA 20000
# define BQ25618_ITERM_OFFSET_uA 20000
# define BQ25618_ITERM_MIN_uA 20000
# define BQ25618_ITERM_MAX_uA 260000
# define BQ25618_ITERM_DEF_uA 60000
# define BQ256XX_IPRECHG_MASK GENMASK(7, 4)
# define BQ256XX_IPRECHG_STEP_uA 60000
# define BQ256XX_IPRECHG_OFFSET_uA 60000
# define BQ256XX_IPRECHG_MIN_uA 60000
# define BQ256XX_IPRECHG_MAX_uA 780000
# define BQ256XX_IPRECHG_DEF_uA 180000
# define BQ25618_IPRECHG_STEP_uA 20000
# define BQ25618_IPRECHG_OFFSET_uA 20000
# define BQ25618_IPRECHG_MIN_uA 20000
# define BQ25618_IPRECHG_MAX_uA 260000
# define BQ25618_IPRECHG_DEF_uA 40000
# define BQ256XX_IPRECHG_BIT_SHIFT 4
# define BQ256XX_ICHG_MASK GENMASK(5, 0)
# define BQ256XX_ICHG_STEP_uA 60000
# define BQ256XX_ICHG_MIN_uA 0
# define BQ256XX_ICHG_MAX_uA 3000000
# define BQ2560X_ICHG_DEF_uA 2040000
# define BQ25611D_ICHG_DEF_uA 1020000
# define BQ25618_ICHG_STEP_uA 20000
# define BQ25618_ICHG_MIN_uA 0
# define BQ25618_ICHG_MAX_uA 1500000
# define BQ25618_ICHG_DEF_uA 340000
# define BQ25618_ICHG_THRESH 0x3c
# define BQ25618_ICHG_THRESH_uA 1180000
# define BQ256XX_VBUS_STAT_MASK GENMASK(7, 5)
# define BQ256XX_VBUS_STAT_NO_INPUT 0
# define BQ256XX_VBUS_STAT_USB_SDP BIT(5)
# define BQ256XX_VBUS_STAT_USB_CDP BIT(6)
# define BQ256XX_VBUS_STAT_USB_DCP (BIT(6) | BIT(5))
# define BQ256XX_VBUS_STAT_USB_OTG (BIT(7) | BIT(6) | BIT(5))
# define BQ256XX_CHRG_STAT_MASK GENMASK(4, 3)
# define BQ256XX_CHRG_STAT_NOT_CHRGING 0
# define BQ256XX_CHRG_STAT_PRECHRGING BIT(3)
# define BQ256XX_CHRG_STAT_FAST_CHRGING BIT(4)
# define BQ256XX_CHRG_STAT_CHRG_TERM (BIT(4) | BIT(3))
# define BQ256XX_PG_STAT_MASK BIT(2)
# define BQ256XX_WDT_FAULT_MASK BIT(7)
# define BQ256XX_CHRG_FAULT_MASK GENMASK(5, 4)
# define BQ256XX_CHRG_FAULT_NORMAL 0
# define BQ256XX_CHRG_FAULT_INPUT BIT(4)
# define BQ256XX_CHRG_FAULT_THERM BIT(5)
# define BQ256XX_CHRG_FAULT_CST_EXPIRE (BIT(5) | BIT(4))
# define BQ256XX_BAT_FAULT_MASK BIT(3)
# define BQ256XX_NTC_FAULT_MASK GENMASK(2, 0)
# define BQ256XX_NTC_FAULT_WARM BIT(1)
# define BQ256XX_NTC_FAULT_COOL (BIT(1) | BIT(0))
# define BQ256XX_NTC_FAULT_COLD (BIT(2) | BIT(0))
# define BQ256XX_NTC_FAULT_HOT (BIT(2) | BIT(1))
2021-01-14 01:53:52 +03:00
# define BQ256XX_NUM_WD_VAL 4
2021-01-06 22:58:49 +03:00
# define BQ256XX_WATCHDOG_MASK GENMASK(5, 4)
# define BQ256XX_WATCHDOG_MAX 1600000
# define BQ256XX_WATCHDOG_DIS 0
# define BQ256XX_WDT_BIT_SHIFT 4
# define BQ256XX_REG_RST BIT(7)
/**
* struct bq256xx_init_data -
* @ ichg : fast charge current
* @ iindpm : input current limit
* @ vbatreg : charge voltage
* @ iterm : termination current
* @ iprechg : precharge current
* @ vindpm : input voltage limit
* @ ichg_max : maximum fast charge current
* @ vbatreg_max : maximum charge voltage
*/
struct bq256xx_init_data {
u32 ichg ;
u32 iindpm ;
u32 vbatreg ;
u32 iterm ;
u32 iprechg ;
u32 vindpm ;
u32 ichg_max ;
u32 vbatreg_max ;
} ;
/**
* struct bq256xx_state -
* @ vbus_stat : VBUS status according to BQ256XX_CHARGER_STATUS_0
* @ chrg_stat : charging status according to BQ256XX_CHARGER_STATUS_0
* @ online : PG status according to BQ256XX_CHARGER_STATUS_0
*
* @ wdt_fault : watchdog fault according to BQ256XX_CHARGER_STATUS_1
* @ bat_fault : battery fault according to BQ256XX_CHARGER_STATUS_1
* @ chrg_fault : charging fault according to BQ256XX_CHARGER_STATUS_1
* @ ntc_fault : TS fault according to BQ256XX_CHARGER_STATUS_1
*/
struct bq256xx_state {
u8 vbus_stat ;
u8 chrg_stat ;
bool online ;
u8 wdt_fault ;
u8 bat_fault ;
u8 chrg_fault ;
u8 ntc_fault ;
} ;
enum bq256xx_id {
BQ25600 ,
BQ25600D ,
BQ25601 ,
BQ25601D ,
BQ25618 ,
BQ25619 ,
BQ25611D ,
} ;
/**
* struct bq256xx_device -
* @ client : i2c client structure
* @ regmap : register map structure
* @ dev : device structure
2021-04-19 19:33:36 +03:00
* @ charger : power supply registered for the charger
* @ battery : power supply registered for the battery
2021-01-06 22:58:49 +03:00
* @ lock : mutex lock structure
*
* @ usb2_phy : usb_phy identifier
* @ usb3_phy : usb_phy identifier
* @ usb_nb : notifier block
* @ usb_work : usb work queue
* @ usb_event : usb_event code
*
* @ model_name : i2c name string
*
* @ init_data : initialization data
* @ chip_info : device variant information
* @ state : device status and faults
* @ watchdog_timer : watchdog timer value in milliseconds
*/
struct bq256xx_device {
struct i2c_client * client ;
struct device * dev ;
struct power_supply * charger ;
struct power_supply * battery ;
struct mutex lock ;
struct regmap * regmap ;
struct usb_phy * usb2_phy ;
struct usb_phy * usb3_phy ;
struct notifier_block usb_nb ;
struct work_struct usb_work ;
unsigned long usb_event ;
char model_name [ I2C_NAME_SIZE ] ;
struct bq256xx_init_data init_data ;
const struct bq256xx_chip_info * chip_info ;
struct bq256xx_state state ;
int watchdog_timer ;
} ;
/**
* struct bq256xx_chip_info -
* @ model_id : device instance
*
* @ bq256xx_regmap_config : regmap configuration struct
* @ bq256xx_get_ichg : pointer to instance specific get_ichg function
* @ bq256xx_get_iindpm : pointer to instance specific get_iindpm function
* @ bq256xx_get_vbatreg : pointer to instance specific get_vbatreg function
* @ bq256xx_get_iterm : pointer to instance specific get_iterm function
* @ bq256xx_get_iprechg : pointer to instance specific get_iprechg function
* @ bq256xx_get_vindpm : pointer to instance specific get_vindpm function
*
* @ bq256xx_set_ichg : pointer to instance specific set_ichg function
* @ bq256xx_set_iindpm : pointer to instance specific set_iindpm function
* @ bq256xx_set_vbatreg : pointer to instance specific set_vbatreg function
* @ bq256xx_set_iterm : pointer to instance specific set_iterm function
* @ bq256xx_set_iprechg : pointer to instance specific set_iprechg function
* @ bq256xx_set_vindpm : pointer to instance specific set_vindpm function
*
* @ bq256xx_def_ichg : default ichg value in microamps
* @ bq256xx_def_iindpm : default iindpm value in microamps
* @ bq256xx_def_vbatreg : default vbatreg value in microvolts
* @ bq256xx_def_iterm : default iterm value in microamps
* @ bq256xx_def_iprechg : default iprechg value in microamps
* @ bq256xx_def_vindpm : default vindpm value in microvolts
*
* @ bq256xx_max_ichg : maximum charge current in microamps
* @ bq256xx_max_vbatreg : maximum battery regulation voltage in microvolts
*
* @ has_usb_detect : indicates whether device has BC1 .2 detection
*/
struct bq256xx_chip_info {
int model_id ;
const struct regmap_config * bq256xx_regmap_config ;
int ( * bq256xx_get_ichg ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_get_iindpm ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_get_vbatreg ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_get_iterm ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_get_iprechg ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_get_vindpm ) ( struct bq256xx_device * bq ) ;
int ( * bq256xx_set_ichg ) ( struct bq256xx_device * bq , int ichg ) ;
int ( * bq256xx_set_iindpm ) ( struct bq256xx_device * bq , int iindpm ) ;
int ( * bq256xx_set_vbatreg ) ( struct bq256xx_device * bq , int vbatreg ) ;
int ( * bq256xx_set_iterm ) ( struct bq256xx_device * bq , int iterm ) ;
int ( * bq256xx_set_iprechg ) ( struct bq256xx_device * bq , int iprechg ) ;
int ( * bq256xx_set_vindpm ) ( struct bq256xx_device * bq , int vindpm ) ;
int bq256xx_def_ichg ;
int bq256xx_def_iindpm ;
int bq256xx_def_vbatreg ;
int bq256xx_def_iterm ;
int bq256xx_def_iprechg ;
int bq256xx_def_vindpm ;
int bq256xx_max_ichg ;
int bq256xx_max_vbatreg ;
bool has_usb_detect ;
} ;
static int bq256xx_watchdog_time [ BQ256XX_NUM_WD_VAL ] = {
0 , 40000 , 80000 , 1600000
} ;
static const int bq25611d_vbatreg_values [ ] = {
3494000 , 3590000 , 3686000 , 3790000 , 3894000 , 3990000 , 4090000 , 4140000 ,
4190000
} ;
static const int bq25618_619_vbatreg_values [ ] = {
3504000 , 3600000 , 3696000 , 3800000 , 3904000 , 4000000 , 4100000 , 4150000 ,
4200000
} ;
static const int bq25618_619_ichg_values [ ] = {
1290000 , 1360000 , 1430000 , 1500000
} ;
static enum power_supply_usb_type bq256xx_usb_type [ ] = {
POWER_SUPPLY_USB_TYPE_SDP ,
POWER_SUPPLY_USB_TYPE_CDP ,
POWER_SUPPLY_USB_TYPE_DCP ,
POWER_SUPPLY_USB_TYPE_UNKNOWN ,
POWER_SUPPLY_USB_TYPE_ACA ,
} ;
static int bq256xx_array_parse ( int array_size , int val , const int array [ ] )
{
int i = 0 ;
if ( val < array [ i ] )
return i - 1 ;
if ( val > = array [ array_size - 1 ] )
return array_size - 1 ;
for ( i = 1 ; i < array_size ; i + + ) {
if ( val = = array [ i ] )
return i ;
if ( val > array [ i - 1 ] & & val < array [ i ] ) {
if ( val < array [ i ] )
return i - 1 ;
else
return i ;
}
}
return - EINVAL ;
}
static int bq256xx_usb_notifier ( struct notifier_block * nb , unsigned long val ,
void * priv )
{
struct bq256xx_device * bq =
container_of ( nb , struct bq256xx_device , usb_nb ) ;
bq - > usb_event = val ;
queue_work ( system_power_efficient_wq , & bq - > usb_work ) ;
return NOTIFY_OK ;
}
static void bq256xx_usb_work ( struct work_struct * data )
{
struct bq256xx_device * bq =
container_of ( data , struct bq256xx_device , usb_work ) ;
switch ( bq - > usb_event ) {
case USB_EVENT_ID :
break ;
case USB_EVENT_NONE :
power_supply_changed ( bq - > charger ) ;
break ;
default :
dev_err ( bq - > dev , " Error switching to charger mode. \n " ) ;
break ;
}
}
static struct reg_default bq2560x_reg_defs [ ] = {
{ BQ256XX_INPUT_CURRENT_LIMIT , 0x17 } ,
{ BQ256XX_CHARGER_CONTROL_0 , 0x1a } ,
{ BQ256XX_CHARGE_CURRENT_LIMIT , 0xa2 } ,
{ BQ256XX_PRECHG_AND_TERM_CURR_LIM , 0x22 } ,
{ BQ256XX_BATTERY_VOLTAGE_LIMIT , 0x58 } ,
{ BQ256XX_CHARGER_CONTROL_1 , 0x9f } ,
{ BQ256XX_CHARGER_CONTROL_2 , 0x66 } ,
{ BQ256XX_CHARGER_CONTROL_3 , 0x4c } ,
} ;
static struct reg_default bq25611d_reg_defs [ ] = {
{ BQ256XX_INPUT_CURRENT_LIMIT , 0x17 } ,
{ BQ256XX_CHARGER_CONTROL_0 , 0x1a } ,
{ BQ256XX_CHARGE_CURRENT_LIMIT , 0x91 } ,
{ BQ256XX_PRECHG_AND_TERM_CURR_LIM , 0x12 } ,
{ BQ256XX_BATTERY_VOLTAGE_LIMIT , 0x40 } ,
{ BQ256XX_CHARGER_CONTROL_1 , 0x9e } ,
{ BQ256XX_CHARGER_CONTROL_2 , 0xe6 } ,
{ BQ256XX_CHARGER_CONTROL_3 , 0x4c } ,
{ BQ256XX_PART_INFORMATION , 0x54 } ,
{ BQ256XX_CHARGER_CONTROL_4 , 0x75 } ,
} ;
static struct reg_default bq25618_619_reg_defs [ ] = {
{ BQ256XX_INPUT_CURRENT_LIMIT , 0x17 } ,
{ BQ256XX_CHARGER_CONTROL_0 , 0x1a } ,
{ BQ256XX_CHARGE_CURRENT_LIMIT , 0x91 } ,
{ BQ256XX_PRECHG_AND_TERM_CURR_LIM , 0x12 } ,
{ BQ256XX_BATTERY_VOLTAGE_LIMIT , 0x40 } ,
{ BQ256XX_CHARGER_CONTROL_1 , 0x9e } ,
{ BQ256XX_CHARGER_CONTROL_2 , 0xe6 } ,
{ BQ256XX_CHARGER_CONTROL_3 , 0x4c } ,
{ BQ256XX_PART_INFORMATION , 0x2c } ,
{ BQ256XX_CHARGER_CONTROL_4 , 0x75 } ,
} ;
static int bq256xx_get_state ( struct bq256xx_device * bq ,
struct bq256xx_state * state )
{
unsigned int charger_status_0 ;
unsigned int charger_status_1 ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_CHARGER_STATUS_0 ,
& charger_status_0 ) ;
if ( ret )
return ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_CHARGER_STATUS_1 ,
& charger_status_1 ) ;
if ( ret )
return ret ;
state - > vbus_stat = charger_status_0 & BQ256XX_VBUS_STAT_MASK ;
state - > chrg_stat = charger_status_0 & BQ256XX_CHRG_STAT_MASK ;
state - > online = charger_status_0 & BQ256XX_PG_STAT_MASK ;
state - > wdt_fault = charger_status_1 & BQ256XX_WDT_FAULT_MASK ;
state - > bat_fault = charger_status_1 & BQ256XX_BAT_FAULT_MASK ;
state - > chrg_fault = charger_status_1 & BQ256XX_CHRG_FAULT_MASK ;
state - > ntc_fault = charger_status_1 & BQ256XX_NTC_FAULT_MASK ;
return 0 ;
}
static int bq256xx_get_ichg_curr ( struct bq256xx_device * bq )
{
unsigned int charge_current_limit ;
unsigned int ichg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_CHARGE_CURRENT_LIMIT ,
& charge_current_limit ) ;
if ( ret )
return ret ;
ichg_reg_code = charge_current_limit & BQ256XX_ICHG_MASK ;
return ichg_reg_code * BQ256XX_ICHG_STEP_uA ;
}
static int bq25618_619_get_ichg_curr ( struct bq256xx_device * bq )
{
unsigned int charge_current_limit ;
unsigned int ichg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_CHARGE_CURRENT_LIMIT ,
& charge_current_limit ) ;
if ( ret )
return ret ;
ichg_reg_code = charge_current_limit & BQ256XX_ICHG_MASK ;
if ( ichg_reg_code < BQ25618_ICHG_THRESH )
return ichg_reg_code * BQ25618_ICHG_STEP_uA ;
return bq25618_619_ichg_values [ ichg_reg_code - BQ25618_ICHG_THRESH ] ;
}
static int bq256xx_set_ichg_curr ( struct bq256xx_device * bq , int ichg )
{
unsigned int ichg_reg_code ;
int ichg_max = bq - > init_data . ichg_max ;
ichg = clamp ( ichg , BQ256XX_ICHG_MIN_uA , ichg_max ) ;
ichg_reg_code = ichg / BQ256XX_ICHG_STEP_uA ;
return regmap_update_bits ( bq - > regmap , BQ256XX_CHARGE_CURRENT_LIMIT ,
BQ256XX_ICHG_MASK , ichg_reg_code ) ;
}
static int bq25618_619_set_ichg_curr ( struct bq256xx_device * bq , int ichg )
{
int array_size = ARRAY_SIZE ( bq25618_619_ichg_values ) ;
unsigned int ichg_reg_code ;
int ichg_max = bq - > init_data . ichg_max ;
ichg = clamp ( ichg , BQ25618_ICHG_MIN_uA , ichg_max ) ;
if ( ichg < = BQ25618_ICHG_THRESH_uA ) {
ichg_reg_code = ichg / BQ25618_ICHG_STEP_uA ;
} else {
ichg_reg_code = bq256xx_array_parse ( array_size , ichg ,
bq25618_619_ichg_values ) + BQ25618_ICHG_THRESH ;
}
return regmap_update_bits ( bq - > regmap , BQ256XX_CHARGE_CURRENT_LIMIT ,
BQ256XX_ICHG_MASK , ichg_reg_code ) ;
}
static int bq25618_619_get_chrg_volt ( struct bq256xx_device * bq )
{
unsigned int battery_volt_lim ;
unsigned int vbatreg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
& battery_volt_lim ) ;
if ( ret )
return ret ;
vbatreg_reg_code = ( battery_volt_lim & BQ256XX_VBATREG_MASK ) > >
BQ256XX_VBATREG_BIT_SHIFT ;
if ( vbatreg_reg_code > BQ2561X_VBATREG_THRESH )
return ( ( vbatreg_reg_code - BQ2561X_VBATREG_THRESH ) *
BQ2561X_VBATREG_STEP_uV ) +
BQ25618_VBATREG_THRESH_uV ;
return bq25618_619_vbatreg_values [ vbatreg_reg_code ] ;
}
static int bq25611d_get_chrg_volt ( struct bq256xx_device * bq )
{
unsigned int battery_volt_lim ;
unsigned int vbatreg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
& battery_volt_lim ) ;
if ( ret )
return ret ;
vbatreg_reg_code = ( battery_volt_lim & BQ256XX_VBATREG_MASK ) > >
BQ256XX_VBATREG_BIT_SHIFT ;
if ( vbatreg_reg_code > BQ2561X_VBATREG_THRESH )
return ( ( vbatreg_reg_code - BQ2561X_VBATREG_THRESH ) *
BQ2561X_VBATREG_STEP_uV ) +
BQ25611D_VBATREG_THRESH_uV ;
return bq25611d_vbatreg_values [ vbatreg_reg_code ] ;
}
static int bq2560x_get_chrg_volt ( struct bq256xx_device * bq )
{
unsigned int battery_volt_lim ;
unsigned int vbatreg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
& battery_volt_lim ) ;
if ( ret )
return ret ;
vbatreg_reg_code = ( battery_volt_lim & BQ256XX_VBATREG_MASK ) > >
BQ256XX_VBATREG_BIT_SHIFT ;
return ( vbatreg_reg_code * BQ2560X_VBATREG_STEP_uV )
+ BQ2560X_VBATREG_OFFSET_uV ;
}
static int bq25601d_get_chrg_volt ( struct bq256xx_device * bq )
{
unsigned int battery_volt_lim ;
unsigned int vbatreg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
& battery_volt_lim ) ;
if ( ret )
return ret ;
vbatreg_reg_code = ( battery_volt_lim & BQ256XX_VBATREG_MASK ) > >
BQ256XX_VBATREG_BIT_SHIFT ;
return ( vbatreg_reg_code * BQ2560X_VBATREG_STEP_uV )
+ BQ25601D_VBATREG_OFFSET_uV ;
}
static int bq25618_619_set_chrg_volt ( struct bq256xx_device * bq , int vbatreg )
{
int array_size = ARRAY_SIZE ( bq25618_619_vbatreg_values ) ;
unsigned int vbatreg_reg_code ;
int vbatreg_max = bq - > init_data . vbatreg_max ;
vbatreg = clamp ( vbatreg , BQ25618_VBATREG_MIN_uV , vbatreg_max ) ;
if ( vbatreg > BQ25618_VBATREG_THRESH_uV )
vbatreg_reg_code = ( ( vbatreg -
BQ25618_VBATREG_THRESH_uV ) /
( BQ2561X_VBATREG_STEP_uV ) ) + BQ2561X_VBATREG_THRESH ;
else {
vbatreg_reg_code = bq256xx_array_parse ( array_size , vbatreg ,
bq25618_619_vbatreg_values ) ;
}
return regmap_update_bits ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
BQ256XX_VBATREG_MASK , vbatreg_reg_code < <
BQ256XX_VBATREG_BIT_SHIFT ) ;
}
static int bq25611d_set_chrg_volt ( struct bq256xx_device * bq , int vbatreg )
{
int array_size = ARRAY_SIZE ( bq25611d_vbatreg_values ) ;
unsigned int vbatreg_reg_code ;
int vbatreg_max = bq - > init_data . vbatreg_max ;
vbatreg = clamp ( vbatreg , BQ25611D_VBATREG_MIN_uV , vbatreg_max ) ;
if ( vbatreg > BQ25611D_VBATREG_THRESH_uV )
vbatreg_reg_code = ( ( vbatreg -
BQ25611D_VBATREG_THRESH_uV ) /
( BQ2561X_VBATREG_STEP_uV ) ) + BQ2561X_VBATREG_THRESH ;
else {
vbatreg_reg_code = bq256xx_array_parse ( array_size , vbatreg ,
bq25611d_vbatreg_values ) ;
}
return regmap_update_bits ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
BQ256XX_VBATREG_MASK , vbatreg_reg_code < <
BQ256XX_VBATREG_BIT_SHIFT ) ;
}
static int bq2560x_set_chrg_volt ( struct bq256xx_device * bq , int vbatreg )
{
unsigned int vbatreg_reg_code ;
int vbatreg_max = bq - > init_data . vbatreg_max ;
vbatreg = clamp ( vbatreg , BQ2560X_VBATREG_MIN_uV , vbatreg_max ) ;
vbatreg_reg_code = ( vbatreg - BQ2560X_VBATREG_OFFSET_uV ) /
BQ2560X_VBATREG_STEP_uV ;
return regmap_update_bits ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
BQ256XX_VBATREG_MASK , vbatreg_reg_code < <
BQ256XX_VBATREG_BIT_SHIFT ) ;
}
static int bq25601d_set_chrg_volt ( struct bq256xx_device * bq , int vbatreg )
{
unsigned int vbatreg_reg_code ;
int vbatreg_max = bq - > init_data . vbatreg_max ;
vbatreg = clamp ( vbatreg , BQ25601D_VBATREG_MIN_uV , vbatreg_max ) ;
vbatreg_reg_code = ( vbatreg - BQ25601D_VBATREG_OFFSET_uV ) /
BQ2560X_VBATREG_STEP_uV ;
return regmap_update_bits ( bq - > regmap , BQ256XX_BATTERY_VOLTAGE_LIMIT ,
BQ256XX_VBATREG_MASK , vbatreg_reg_code < <
BQ256XX_VBATREG_BIT_SHIFT ) ;
}
static int bq256xx_get_prechrg_curr ( struct bq256xx_device * bq )
{
unsigned int prechg_and_term_curr_lim ;
unsigned int iprechg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
& prechg_and_term_curr_lim ) ;
if ( ret )
return ret ;
iprechg_reg_code = ( prechg_and_term_curr_lim & BQ256XX_IPRECHG_MASK )
> > BQ256XX_IPRECHG_BIT_SHIFT ;
return ( iprechg_reg_code * BQ256XX_IPRECHG_STEP_uA ) +
BQ256XX_IPRECHG_OFFSET_uA ;
}
static int bq256xx_set_prechrg_curr ( struct bq256xx_device * bq , int iprechg )
{
unsigned int iprechg_reg_code ;
iprechg = clamp ( iprechg , BQ256XX_IPRECHG_MIN_uA ,
BQ256XX_IPRECHG_MAX_uA ) ;
iprechg_reg_code = ( ( iprechg - BQ256XX_IPRECHG_OFFSET_uA ) /
BQ256XX_IPRECHG_STEP_uA ) < < BQ256XX_IPRECHG_BIT_SHIFT ;
return regmap_update_bits ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
BQ256XX_IPRECHG_MASK , iprechg_reg_code ) ;
}
static int bq25618_619_get_prechrg_curr ( struct bq256xx_device * bq )
{
unsigned int prechg_and_term_curr_lim ;
unsigned int iprechg_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
& prechg_and_term_curr_lim ) ;
if ( ret )
return ret ;
iprechg_reg_code = ( prechg_and_term_curr_lim & BQ256XX_IPRECHG_MASK )
> > BQ256XX_IPRECHG_BIT_SHIFT ;
return ( iprechg_reg_code * BQ25618_IPRECHG_STEP_uA ) +
BQ25618_IPRECHG_OFFSET_uA ;
}
static int bq25618_619_set_prechrg_curr ( struct bq256xx_device * bq , int iprechg )
{
unsigned int iprechg_reg_code ;
iprechg = clamp ( iprechg , BQ25618_IPRECHG_MIN_uA ,
BQ25618_IPRECHG_MAX_uA ) ;
iprechg_reg_code = ( ( iprechg - BQ25618_IPRECHG_OFFSET_uA ) /
BQ25618_IPRECHG_STEP_uA ) < < BQ256XX_IPRECHG_BIT_SHIFT ;
return regmap_update_bits ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
BQ256XX_IPRECHG_MASK , iprechg_reg_code ) ;
}
static int bq256xx_get_term_curr ( struct bq256xx_device * bq )
{
unsigned int prechg_and_term_curr_lim ;
unsigned int iterm_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
& prechg_and_term_curr_lim ) ;
if ( ret )
return ret ;
iterm_reg_code = prechg_and_term_curr_lim & BQ256XX_ITERM_MASK ;
return ( iterm_reg_code * BQ256XX_ITERM_STEP_uA ) +
BQ256XX_ITERM_OFFSET_uA ;
}
static int bq256xx_set_term_curr ( struct bq256xx_device * bq , int iterm )
{
unsigned int iterm_reg_code ;
iterm = clamp ( iterm , BQ256XX_ITERM_MIN_uA , BQ256XX_ITERM_MAX_uA ) ;
iterm_reg_code = ( iterm - BQ256XX_ITERM_OFFSET_uA ) /
BQ256XX_ITERM_STEP_uA ;
return regmap_update_bits ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
BQ256XX_ITERM_MASK , iterm_reg_code ) ;
}
static int bq25618_619_get_term_curr ( struct bq256xx_device * bq )
{
unsigned int prechg_and_term_curr_lim ;
unsigned int iterm_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
& prechg_and_term_curr_lim ) ;
if ( ret )
return ret ;
iterm_reg_code = prechg_and_term_curr_lim & BQ256XX_ITERM_MASK ;
return ( iterm_reg_code * BQ25618_ITERM_STEP_uA ) +
BQ25618_ITERM_OFFSET_uA ;
}
static int bq25618_619_set_term_curr ( struct bq256xx_device * bq , int iterm )
{
unsigned int iterm_reg_code ;
iterm = clamp ( iterm , BQ25618_ITERM_MIN_uA , BQ25618_ITERM_MAX_uA ) ;
iterm_reg_code = ( iterm - BQ25618_ITERM_OFFSET_uA ) /
BQ25618_ITERM_STEP_uA ;
return regmap_update_bits ( bq - > regmap , BQ256XX_PRECHG_AND_TERM_CURR_LIM ,
BQ256XX_ITERM_MASK , iterm_reg_code ) ;
}
static int bq256xx_get_input_volt_lim ( struct bq256xx_device * bq )
{
unsigned int charger_control_2 ;
unsigned int vindpm_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_CHARGER_CONTROL_2 ,
& charger_control_2 ) ;
if ( ret )
return ret ;
vindpm_reg_code = charger_control_2 & BQ256XX_VINDPM_MASK ;
return ( vindpm_reg_code * BQ256XX_VINDPM_STEP_uV ) +
BQ256XX_VINDPM_OFFSET_uV ;
}
static int bq256xx_set_input_volt_lim ( struct bq256xx_device * bq , int vindpm )
{
unsigned int vindpm_reg_code ;
vindpm = clamp ( vindpm , BQ256XX_VINDPM_MIN_uV , BQ256XX_VINDPM_MAX_uV ) ;
vindpm_reg_code = ( vindpm - BQ256XX_VINDPM_OFFSET_uV ) /
BQ256XX_VINDPM_STEP_uV ;
return regmap_update_bits ( bq - > regmap , BQ256XX_CHARGER_CONTROL_2 ,
BQ256XX_VINDPM_MASK , vindpm_reg_code ) ;
}
static int bq256xx_get_input_curr_lim ( struct bq256xx_device * bq )
{
unsigned int input_current_limit ;
unsigned int iindpm_reg_code ;
int ret ;
ret = regmap_read ( bq - > regmap , BQ256XX_INPUT_CURRENT_LIMIT ,
& input_current_limit ) ;
if ( ret )
return ret ;
iindpm_reg_code = input_current_limit & BQ256XX_IINDPM_MASK ;
return ( iindpm_reg_code * BQ256XX_IINDPM_STEP_uA ) +
BQ256XX_IINDPM_OFFSET_uA ;
}
static int bq256xx_set_input_curr_lim ( struct bq256xx_device * bq , int iindpm )
{
unsigned int iindpm_reg_code ;
iindpm = clamp ( iindpm , BQ256XX_IINDPM_MIN_uA , BQ256XX_IINDPM_MAX_uA ) ;
iindpm_reg_code = ( iindpm - BQ256XX_IINDPM_OFFSET_uA ) /
BQ256XX_IINDPM_STEP_uA ;
return regmap_update_bits ( bq - > regmap , BQ256XX_INPUT_CURRENT_LIMIT ,
BQ256XX_IINDPM_MASK , iindpm_reg_code ) ;
}
static void bq256xx_charger_reset ( void * data )
{
struct bq256xx_device * bq = data ;
regmap_update_bits ( bq - > regmap , BQ256XX_PART_INFORMATION ,
BQ256XX_REG_RST , BQ256XX_REG_RST ) ;
if ( ! IS_ERR_OR_NULL ( bq - > usb2_phy ) )
usb_unregister_notifier ( bq - > usb2_phy , & bq - > usb_nb ) ;
if ( ! IS_ERR_OR_NULL ( bq - > usb3_phy ) )
usb_unregister_notifier ( bq - > usb3_phy , & bq - > usb_nb ) ;
}
static int bq256xx_set_charger_property ( struct power_supply * psy ,
enum power_supply_property prop ,
const union power_supply_propval * val )
{
struct bq256xx_device * bq = power_supply_get_drvdata ( psy ) ;
int ret = - EINVAL ;
switch ( prop ) {
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT :
ret = bq - > chip_info - > bq256xx_set_iindpm ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
case POWER_SUPPLY_PROP_STATUS :
break ;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE :
ret = bq - > chip_info - > bq256xx_set_vbatreg ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT :
ret = bq - > chip_info - > bq256xx_set_ichg ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT :
ret = bq - > chip_info - > bq256xx_set_iprechg ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT :
ret = bq - > chip_info - > bq256xx_set_iterm ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT :
ret = bq - > chip_info - > bq256xx_set_vindpm ( bq , val - > intval ) ;
if ( ret )
return ret ;
break ;
default :
break ;
}
return ret ;
}
static int bq256xx_get_battery_property ( struct power_supply * psy ,
enum power_supply_property psp ,
union power_supply_propval * val )
{
struct bq256xx_device * bq = power_supply_get_drvdata ( psy ) ;
switch ( psp ) {
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX :
val - > intval = bq - > init_data . ichg_max ;
break ;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX :
val - > intval = bq - > init_data . vbatreg_max ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int bq256xx_get_charger_property ( struct power_supply * psy ,
enum power_supply_property psp ,
union power_supply_propval * val )
{
struct bq256xx_device * bq = power_supply_get_drvdata ( psy ) ;
struct bq256xx_state state ;
int ret = 0 ;
mutex_lock ( & bq - > lock ) ;
ret = bq256xx_get_state ( bq , & state ) ;
mutex_unlock ( & bq - > lock ) ;
if ( ret )
return ret ;
switch ( psp ) {
case POWER_SUPPLY_PROP_STATUS :
if ( state . vbus_stat = = BQ256XX_VBUS_STAT_NO_INPUT | |
state . vbus_stat = = BQ256XX_VBUS_STAT_USB_OTG )
val - > intval = POWER_SUPPLY_STATUS_DISCHARGING ;
else if ( state . chrg_stat = = BQ256XX_CHRG_STAT_NOT_CHRGING )
val - > intval = POWER_SUPPLY_STATUS_NOT_CHARGING ;
else if ( state . chrg_stat = = BQ256XX_CHRG_STAT_CHRG_TERM )
val - > intval = POWER_SUPPLY_STATUS_FULL ;
else
val - > intval = POWER_SUPPLY_STATUS_CHARGING ;
break ;
case POWER_SUPPLY_PROP_HEALTH :
val - > intval = POWER_SUPPLY_HEALTH_UNKNOWN ;
if ( state . wdt_fault ) {
val - > intval =
POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE ;
} else if ( state . bat_fault ) {
val - > intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE ;
} else {
switch ( state . chrg_stat ) {
case BQ256XX_CHRG_FAULT_INPUT :
val - > intval =
POWER_SUPPLY_HEALTH_UNSPEC_FAILURE ;
break ;
case BQ256XX_CHRG_FAULT_THERM :
val - > intval = POWER_SUPPLY_HEALTH_OVERHEAT ;
break ;
case BQ256XX_CHRG_FAULT_CST_EXPIRE :
val - > intval =
POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE ;
break ;
default :
break ;
}
switch ( state . ntc_fault ) {
case BQ256XX_NTC_FAULT_WARM :
val - > intval = POWER_SUPPLY_HEALTH_WARM ;
break ;
case BQ256XX_NTC_FAULT_COOL :
val - > intval = POWER_SUPPLY_HEALTH_COOL ;
break ;
case BQ256XX_NTC_FAULT_COLD :
val - > intval = POWER_SUPPLY_HEALTH_COLD ;
break ;
case BQ256XX_NTC_FAULT_HOT :
val - > intval = POWER_SUPPLY_HEALTH_HOT ;
break ;
default :
val - > intval = POWER_SUPPLY_HEALTH_GOOD ;
break ;
}
}
break ;
case POWER_SUPPLY_PROP_USB_TYPE :
if ( bq - > chip_info - > has_usb_detect ) {
switch ( state . vbus_stat ) {
case BQ256XX_VBUS_STAT_USB_SDP :
val - > intval = POWER_SUPPLY_USB_TYPE_SDP ;
break ;
case BQ256XX_VBUS_STAT_USB_CDP :
val - > intval = POWER_SUPPLY_USB_TYPE_CDP ;
break ;
case BQ256XX_VBUS_STAT_USB_DCP :
val - > intval = POWER_SUPPLY_USB_TYPE_DCP ;
break ;
case BQ256XX_VBUS_STAT_USB_OTG :
val - > intval = POWER_SUPPLY_USB_TYPE_ACA ;
break ;
default :
val - > intval = POWER_SUPPLY_USB_TYPE_UNKNOWN ;
break ;
}
} else {
switch ( state . vbus_stat ) {
case BQ256XX_VBUS_STAT_USB_SDP :
val - > intval = POWER_SUPPLY_USB_TYPE_SDP ;
break ;
case BQ256XX_VBUS_STAT_USB_OTG :
val - > intval = POWER_SUPPLY_USB_TYPE_ACA ;
break ;
default :
val - > intval = POWER_SUPPLY_USB_TYPE_UNKNOWN ;
break ;
}
}
break ;
case POWER_SUPPLY_PROP_CHARGE_TYPE :
switch ( state . chrg_stat ) {
case BQ256XX_CHRG_STAT_NOT_CHRGING :
val - > intval = POWER_SUPPLY_CHARGE_TYPE_NONE ;
break ;
case BQ256XX_CHRG_STAT_PRECHRGING :
val - > intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE ;
break ;
case BQ256XX_CHRG_STAT_FAST_CHRGING :
val - > intval = POWER_SUPPLY_CHARGE_TYPE_FAST ;
break ;
case BQ256XX_CHRG_STAT_CHRG_TERM :
val - > intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE ;
break ;
default :
val - > intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN ;
}
break ;
case POWER_SUPPLY_PROP_MANUFACTURER :
val - > strval = BQ256XX_MANUFACTURER ;
break ;
case POWER_SUPPLY_PROP_MODEL_NAME :
val - > strval = bq - > model_name ;
break ;
case POWER_SUPPLY_PROP_ONLINE :
val - > intval = state . online ;
break ;
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT :
ret = bq - > chip_info - > bq256xx_get_vindpm ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT :
ret = bq - > chip_info - > bq256xx_get_iindpm ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE :
ret = bq - > chip_info - > bq256xx_get_vbatreg ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT :
ret = bq - > chip_info - > bq256xx_get_ichg ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT :
ret = bq - > chip_info - > bq256xx_get_iprechg ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT :
ret = bq - > chip_info - > bq256xx_get_iterm ( bq ) ;
if ( ret < 0 )
return ret ;
val - > intval = ret ;
break ;
default :
return - EINVAL ;
}
return ret ;
}
static bool bq256xx_state_changed ( struct bq256xx_device * bq ,
struct bq256xx_state * new_state )
{
struct bq256xx_state old_state ;
mutex_lock ( & bq - > lock ) ;
old_state = bq - > state ;
mutex_unlock ( & bq - > lock ) ;
return memcmp ( & old_state , new_state , sizeof ( struct bq256xx_state ) ) ! = 0 ;
}
static irqreturn_t bq256xx_irq_handler_thread ( int irq , void * private )
{
struct bq256xx_device * bq = private ;
struct bq256xx_state state ;
int ret ;
ret = bq256xx_get_state ( bq , & state ) ;
if ( ret < 0 )
goto irq_out ;
if ( ! bq256xx_state_changed ( bq , & state ) )
goto irq_out ;
mutex_lock ( & bq - > lock ) ;
bq - > state = state ;
mutex_unlock ( & bq - > lock ) ;
power_supply_changed ( bq - > charger ) ;
irq_out :
return IRQ_HANDLED ;
}
static enum power_supply_property bq256xx_power_supply_props [ ] = {
POWER_SUPPLY_PROP_MANUFACTURER ,
POWER_SUPPLY_PROP_MODEL_NAME ,
POWER_SUPPLY_PROP_STATUS ,
POWER_SUPPLY_PROP_ONLINE ,
POWER_SUPPLY_PROP_HEALTH ,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT ,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT ,
POWER_SUPPLY_PROP_CHARGE_TYPE ,
POWER_SUPPLY_PROP_USB_TYPE ,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE ,
POWER_SUPPLY_PROP_PRECHARGE_CURRENT ,
POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT ,
} ;
static enum power_supply_property bq256xx_battery_props [ ] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX ,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX ,
} ;
static int bq256xx_property_is_writeable ( struct power_supply * psy ,
enum power_supply_property prop )
{
switch ( prop ) {
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT :
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE :
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT :
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT :
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT :
case POWER_SUPPLY_PROP_STATUS :
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT :
return true ;
default :
return false ;
}
}
static const struct power_supply_desc bq256xx_power_supply_desc = {
. name = " bq256xx-charger " ,
. type = POWER_SUPPLY_TYPE_USB ,
. usb_types = bq256xx_usb_type ,
. num_usb_types = ARRAY_SIZE ( bq256xx_usb_type ) ,
. properties = bq256xx_power_supply_props ,
. num_properties = ARRAY_SIZE ( bq256xx_power_supply_props ) ,
. get_property = bq256xx_get_charger_property ,
. set_property = bq256xx_set_charger_property ,
. property_is_writeable = bq256xx_property_is_writeable ,
} ;
static struct power_supply_desc bq256xx_battery_desc = {
. name = " bq256xx-battery " ,
. type = POWER_SUPPLY_TYPE_BATTERY ,
. get_property = bq256xx_get_battery_property ,
. properties = bq256xx_battery_props ,
. num_properties = ARRAY_SIZE ( bq256xx_battery_props ) ,
. property_is_writeable = bq256xx_property_is_writeable ,
} ;
static bool bq256xx_is_volatile_reg ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case BQ256XX_INPUT_CURRENT_LIMIT :
case BQ256XX_CHARGER_STATUS_0 . . . BQ256XX_CHARGER_STATUS_2 :
return true ;
default :
return false ;
}
}
static const struct regmap_config bq25600_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = BQ256XX_PART_INFORMATION ,
. reg_defaults = bq2560x_reg_defs ,
. num_reg_defaults = ARRAY_SIZE ( bq2560x_reg_defs ) ,
. cache_type = REGCACHE_FLAT ,
. volatile_reg = bq256xx_is_volatile_reg ,
} ;
static const struct regmap_config bq25611d_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = BQ256XX_CHARGER_CONTROL_4 ,
. reg_defaults = bq25611d_reg_defs ,
. num_reg_defaults = ARRAY_SIZE ( bq25611d_reg_defs ) ,
. cache_type = REGCACHE_FLAT ,
. volatile_reg = bq256xx_is_volatile_reg ,
} ;
static const struct regmap_config bq25618_619_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = BQ256XX_CHARGER_CONTROL_4 ,
. reg_defaults = bq25618_619_reg_defs ,
. num_reg_defaults = ARRAY_SIZE ( bq25618_619_reg_defs ) ,
. cache_type = REGCACHE_FLAT ,
. volatile_reg = bq256xx_is_volatile_reg ,
} ;
static const struct bq256xx_chip_info bq256xx_chip_info_tbl [ ] = {
[ BQ25600 ] = {
. model_id = BQ25600 ,
. bq256xx_regmap_config = & bq25600_regmap_config ,
. bq256xx_get_ichg = bq256xx_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq2560x_get_chrg_volt ,
. bq256xx_get_iterm = bq256xx_get_term_curr ,
. bq256xx_get_iprechg = bq256xx_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq256xx_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq2560x_set_chrg_volt ,
. bq256xx_set_iterm = bq256xx_set_term_curr ,
. bq256xx_set_iprechg = bq256xx_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV ,
. has_usb_detect = false ,
} ,
[ BQ25600D ] = {
. model_id = BQ25600D ,
. bq256xx_regmap_config = & bq25600_regmap_config ,
. bq256xx_get_ichg = bq256xx_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq2560x_get_chrg_volt ,
. bq256xx_get_iterm = bq256xx_get_term_curr ,
. bq256xx_get_iprechg = bq256xx_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq256xx_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq2560x_set_chrg_volt ,
. bq256xx_set_iterm = bq256xx_set_term_curr ,
. bq256xx_set_iprechg = bq256xx_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV ,
. has_usb_detect = true ,
} ,
[ BQ25601 ] = {
. model_id = BQ25601 ,
. bq256xx_regmap_config = & bq25600_regmap_config ,
. bq256xx_get_ichg = bq256xx_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq2560x_get_chrg_volt ,
. bq256xx_get_iterm = bq256xx_get_term_curr ,
. bq256xx_get_iprechg = bq256xx_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq256xx_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq2560x_set_chrg_volt ,
. bq256xx_set_iterm = bq256xx_set_term_curr ,
. bq256xx_set_iprechg = bq256xx_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV ,
. has_usb_detect = false ,
} ,
[ BQ25601D ] = {
. model_id = BQ25601D ,
. bq256xx_regmap_config = & bq25600_regmap_config ,
. bq256xx_get_ichg = bq256xx_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq25601d_get_chrg_volt ,
. bq256xx_get_iterm = bq256xx_get_term_curr ,
. bq256xx_get_iprechg = bq256xx_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq256xx_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq25601d_set_chrg_volt ,
. bq256xx_set_iterm = bq256xx_set_term_curr ,
. bq256xx_set_iprechg = bq256xx_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ2560X_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ2560X_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ2560X_VBATREG_MAX_uV ,
. has_usb_detect = true ,
} ,
[ BQ25611D ] = {
. model_id = BQ25611D ,
. bq256xx_regmap_config = & bq25611d_regmap_config ,
. bq256xx_get_ichg = bq256xx_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq25611d_get_chrg_volt ,
. bq256xx_get_iterm = bq256xx_get_term_curr ,
. bq256xx_get_iprechg = bq256xx_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq256xx_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq25611d_set_chrg_volt ,
. bq256xx_set_iterm = bq256xx_set_term_curr ,
. bq256xx_set_iprechg = bq256xx_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ25611D_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ25611D_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ256XX_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ256XX_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ256XX_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ25611D_VBATREG_MAX_uV ,
. has_usb_detect = true ,
} ,
[ BQ25618 ] = {
. model_id = BQ25618 ,
. bq256xx_regmap_config = & bq25618_619_regmap_config ,
. bq256xx_get_ichg = bq25618_619_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq25618_619_get_chrg_volt ,
. bq256xx_get_iterm = bq25618_619_get_term_curr ,
. bq256xx_get_iprechg = bq25618_619_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq25618_619_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq25618_619_set_chrg_volt ,
. bq256xx_set_iterm = bq25618_619_set_term_curr ,
. bq256xx_set_iprechg = bq25618_619_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ25618_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ25618_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ25618_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ25618_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ25618_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ25618_VBATREG_MAX_uV ,
. has_usb_detect = false ,
} ,
[ BQ25619 ] = {
. model_id = BQ25619 ,
. bq256xx_regmap_config = & bq25618_619_regmap_config ,
. bq256xx_get_ichg = bq25618_619_get_ichg_curr ,
. bq256xx_get_iindpm = bq256xx_get_input_curr_lim ,
. bq256xx_get_vbatreg = bq25618_619_get_chrg_volt ,
. bq256xx_get_iterm = bq25618_619_get_term_curr ,
. bq256xx_get_iprechg = bq25618_619_get_prechrg_curr ,
. bq256xx_get_vindpm = bq256xx_get_input_volt_lim ,
. bq256xx_set_ichg = bq25618_619_set_ichg_curr ,
. bq256xx_set_iindpm = bq256xx_set_input_curr_lim ,
. bq256xx_set_vbatreg = bq25618_619_set_chrg_volt ,
. bq256xx_set_iterm = bq25618_619_set_term_curr ,
. bq256xx_set_iprechg = bq25618_619_set_prechrg_curr ,
. bq256xx_set_vindpm = bq256xx_set_input_volt_lim ,
. bq256xx_def_ichg = BQ25618_ICHG_DEF_uA ,
. bq256xx_def_iindpm = BQ256XX_IINDPM_DEF_uA ,
. bq256xx_def_vbatreg = BQ25618_VBATREG_DEF_uV ,
. bq256xx_def_iterm = BQ25618_ITERM_DEF_uA ,
. bq256xx_def_iprechg = BQ25618_IPRECHG_DEF_uA ,
. bq256xx_def_vindpm = BQ256XX_VINDPM_DEF_uV ,
. bq256xx_max_ichg = BQ25618_ICHG_MAX_uA ,
. bq256xx_max_vbatreg = BQ25618_VBATREG_MAX_uV ,
. has_usb_detect = false ,
} ,
} ;
static int bq256xx_power_supply_init ( struct bq256xx_device * bq ,
struct power_supply_config * psy_cfg , struct device * dev )
{
bq - > charger = devm_power_supply_register ( bq - > dev ,
& bq256xx_power_supply_desc ,
psy_cfg ) ;
if ( IS_ERR ( bq - > charger ) ) {
dev_err ( dev , " power supply register charger failed \n " ) ;
return PTR_ERR ( bq - > charger ) ;
}
bq - > battery = devm_power_supply_register ( bq - > dev ,
& bq256xx_battery_desc ,
psy_cfg ) ;
if ( IS_ERR ( bq - > battery ) ) {
dev_err ( dev , " power supply register battery failed \n " ) ;
return PTR_ERR ( bq - > battery ) ;
}
return 0 ;
}
static int bq256xx_hw_init ( struct bq256xx_device * bq )
{
struct power_supply_battery_info bat_info = { } ;
int wd_reg_val = BQ256XX_WATCHDOG_DIS ;
int ret = 0 ;
int i ;
for ( i = 0 ; i < BQ256XX_NUM_WD_VAL ; i + + ) {
2021-01-14 01:53:52 +03:00
if ( bq - > watchdog_timer = = bq256xx_watchdog_time [ i ] ) {
wd_reg_val = i ;
break ;
}
2021-01-06 22:58:49 +03:00
if ( bq - > watchdog_timer > bq256xx_watchdog_time [ i ] & &
bq - > watchdog_timer < bq256xx_watchdog_time [ i + 1 ] )
wd_reg_val = i ;
}
ret = regmap_update_bits ( bq - > regmap , BQ256XX_CHARGER_CONTROL_1 ,
BQ256XX_WATCHDOG_MASK , wd_reg_val < <
BQ256XX_WDT_BIT_SHIFT ) ;
ret = power_supply_get_battery_info ( bq - > charger , & bat_info ) ;
if ( ret ) {
dev_warn ( bq - > dev , " battery info missing, default values will be applied \n " ) ;
bat_info . constant_charge_current_max_ua =
bq - > chip_info - > bq256xx_def_ichg ;
bat_info . constant_charge_voltage_max_uv =
bq - > chip_info - > bq256xx_def_vbatreg ;
bat_info . precharge_current_ua =
bq - > chip_info - > bq256xx_def_iprechg ;
bat_info . charge_term_current_ua =
bq - > chip_info - > bq256xx_def_iterm ;
bq - > init_data . ichg_max =
bq - > chip_info - > bq256xx_max_ichg ;
bq - > init_data . vbatreg_max =
bq - > chip_info - > bq256xx_max_vbatreg ;
} else {
bq - > init_data . ichg_max =
bat_info . constant_charge_current_max_ua ;
bq - > init_data . vbatreg_max =
bat_info . constant_charge_voltage_max_uv ;
}
ret = bq - > chip_info - > bq256xx_set_vindpm ( bq , bq - > init_data . vindpm ) ;
if ( ret )
return ret ;
ret = bq - > chip_info - > bq256xx_set_iindpm ( bq , bq - > init_data . iindpm ) ;
if ( ret )
return ret ;
ret = bq - > chip_info - > bq256xx_set_ichg ( bq ,
bat_info . constant_charge_current_max_ua ) ;
if ( ret )
return ret ;
ret = bq - > chip_info - > bq256xx_set_iprechg ( bq ,
bat_info . precharge_current_ua ) ;
if ( ret )
return ret ;
ret = bq - > chip_info - > bq256xx_set_vbatreg ( bq ,
bat_info . constant_charge_voltage_max_uv ) ;
if ( ret )
return ret ;
ret = bq - > chip_info - > bq256xx_set_iterm ( bq ,
bat_info . charge_term_current_ua ) ;
if ( ret )
return ret ;
power_supply_put_battery_info ( bq - > charger , & bat_info ) ;
return 0 ;
}
static int bq256xx_parse_dt ( struct bq256xx_device * bq ,
struct power_supply_config * psy_cfg , struct device * dev )
{
int ret = 0 ;
psy_cfg - > drv_data = bq ;
psy_cfg - > of_node = dev - > of_node ;
ret = device_property_read_u32 ( bq - > dev , " ti,watchdog-timeout-ms " ,
& bq - > watchdog_timer ) ;
if ( ret )
bq - > watchdog_timer = BQ256XX_WATCHDOG_DIS ;
if ( bq - > watchdog_timer > BQ256XX_WATCHDOG_MAX | |
bq - > watchdog_timer < BQ256XX_WATCHDOG_DIS )
return - EINVAL ;
ret = device_property_read_u32 ( bq - > dev ,
" input-voltage-limit-microvolt " ,
& bq - > init_data . vindpm ) ;
if ( ret )
bq - > init_data . vindpm = bq - > chip_info - > bq256xx_def_vindpm ;
ret = device_property_read_u32 ( bq - > dev ,
" input-current-limit-microamp " ,
& bq - > init_data . iindpm ) ;
if ( ret )
bq - > init_data . iindpm = bq - > chip_info - > bq256xx_def_iindpm ;
return 0 ;
}
static int bq256xx_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct device * dev = & client - > dev ;
struct bq256xx_device * bq ;
struct power_supply_config psy_cfg = { } ;
int ret ;
bq = devm_kzalloc ( dev , sizeof ( * bq ) , GFP_KERNEL ) ;
if ( ! bq )
return - ENOMEM ;
bq - > client = client ;
bq - > dev = dev ;
bq - > chip_info = & bq256xx_chip_info_tbl [ id - > driver_data ] ;
mutex_init ( & bq - > lock ) ;
strncpy ( bq - > model_name , id - > name , I2C_NAME_SIZE ) ;
bq - > regmap = devm_regmap_init_i2c ( client ,
bq - > chip_info - > bq256xx_regmap_config ) ;
if ( IS_ERR ( bq - > regmap ) ) {
dev_err ( dev , " Failed to allocate register map \n " ) ;
return PTR_ERR ( bq - > regmap ) ;
}
i2c_set_clientdata ( client , bq ) ;
ret = bq256xx_parse_dt ( bq , & psy_cfg , dev ) ;
if ( ret ) {
dev_err ( dev , " Failed to read device tree properties%d \n " , ret ) ;
return ret ;
}
ret = devm_add_action_or_reset ( dev , bq256xx_charger_reset , bq ) ;
if ( ret )
return ret ;
/* OTG reporting */
bq - > usb2_phy = devm_usb_get_phy ( dev , USB_PHY_TYPE_USB2 ) ;
if ( ! IS_ERR_OR_NULL ( bq - > usb2_phy ) ) {
INIT_WORK ( & bq - > usb_work , bq256xx_usb_work ) ;
bq - > usb_nb . notifier_call = bq256xx_usb_notifier ;
usb_register_notifier ( bq - > usb2_phy , & bq - > usb_nb ) ;
}
bq - > usb3_phy = devm_usb_get_phy ( dev , USB_PHY_TYPE_USB3 ) ;
if ( ! IS_ERR_OR_NULL ( bq - > usb3_phy ) ) {
INIT_WORK ( & bq - > usb_work , bq256xx_usb_work ) ;
bq - > usb_nb . notifier_call = bq256xx_usb_notifier ;
usb_register_notifier ( bq - > usb3_phy , & bq - > usb_nb ) ;
}
if ( client - > irq ) {
ret = devm_request_threaded_irq ( dev , client - > irq , NULL ,
bq256xx_irq_handler_thread ,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT ,
dev_name ( & client - > dev ) , bq ) ;
if ( ret < 0 ) {
dev_err ( dev , " get irq fail: %d \n " , ret ) ;
return ret ;
}
}
ret = bq256xx_power_supply_init ( bq , & psy_cfg , dev ) ;
if ( ret ) {
dev_err ( dev , " Failed to register power supply \n " ) ;
return ret ;
}
ret = bq256xx_hw_init ( bq ) ;
if ( ret ) {
dev_err ( dev , " Cannot initialize the chip. \n " ) ;
return ret ;
}
return ret ;
}
static const struct i2c_device_id bq256xx_i2c_ids [ ] = {
{ " bq25600 " , BQ25600 } ,
{ " bq25600d " , BQ25600D } ,
{ " bq25601 " , BQ25601 } ,
{ " bq25601d " , BQ25601D } ,
{ " bq25611d " , BQ25611D } ,
{ " bq25618 " , BQ25618 } ,
{ " bq25619 " , BQ25619 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , bq256xx_i2c_ids ) ;
static const struct of_device_id bq256xx_of_match [ ] = {
{ . compatible = " ti,bq25600 " , . data = ( void * ) BQ25600 } ,
{ . compatible = " ti,bq25600d " , . data = ( void * ) BQ25600D } ,
{ . compatible = " ti,bq25601 " , . data = ( void * ) BQ25601 } ,
{ . compatible = " ti,bq25601d " , . data = ( void * ) BQ25601D } ,
{ . compatible = " ti,bq25611d " , . data = ( void * ) BQ25611D } ,
{ . compatible = " ti,bq25618 " , . data = ( void * ) BQ25618 } ,
{ . compatible = " ti,bq25619 " , . data = ( void * ) BQ25619 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , bq256xx_of_match ) ;
static const struct acpi_device_id bq256xx_acpi_match [ ] = {
{ " bq25600 " , BQ25600 } ,
{ " bq25600d " , BQ25600D } ,
{ " bq25601 " , BQ25601 } ,
{ " bq25601d " , BQ25601D } ,
{ " bq25611d " , BQ25611D } ,
{ " bq25618 " , BQ25618 } ,
{ " bq25619 " , BQ25619 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( acpi , bq256xx_acpi_match ) ;
static struct i2c_driver bq256xx_driver = {
. driver = {
. name = " bq256xx-charger " ,
. of_match_table = bq256xx_of_match ,
. acpi_match_table = bq256xx_acpi_match ,
} ,
. probe = bq256xx_probe ,
. id_table = bq256xx_i2c_ids ,
} ;
module_i2c_driver ( bq256xx_driver ) ;
MODULE_AUTHOR ( " Ricardo Rivera-Matos <r-rivera-matos@ti.com> " ) ;
MODULE_DESCRIPTION ( " bq256xx charger driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;