2020-07-30 17:31:21 +03:00
// SPDX-License-Identifier: GPL-2.0
2008-11-13 00:27:11 +03:00
/*
2017-07-19 20:04:07 +03:00
* BQ27xxx battery monitor HDQ / 1 - wire driver
2008-11-13 00:27:11 +03:00
*
2020-07-13 22:16:38 +03:00
* Copyright ( C ) 2007 - 2017 Texas Instruments Incorporated - https : //www.ti.com/
2008-11-13 00:27:11 +03:00
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/types.h>
# include <linux/platform_device.h>
# include <linux/mutex.h>
2015-09-22 22:35:06 +03:00
# include <linux/power/bq27xxx_battery.h>
2008-11-13 00:27:11 +03:00
2017-06-05 16:52:08 +03:00
# include <linux/w1.h>
# define W1_FAMILY_BQ27000 0x01
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
# define HDQ_CMD_READ (0 << 7)
# define HDQ_CMD_WRITE (1 << 7)
2008-11-13 00:27:11 +03:00
static int F_ID ;
2017-05-16 23:02:12 +03:00
module_param ( F_ID , int , S_IRUSR ) ;
2017-07-19 20:04:07 +03:00
MODULE_PARM_DESC ( F_ID , " 1-wire slave FID for BQ27xxx device " ) ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
static int w1_bq27000_read ( struct w1_slave * sl , unsigned int reg )
2008-11-13 00:27:11 +03:00
{
u8 val ;
2012-05-18 09:59:52 +04:00
mutex_lock ( & sl - > master - > bus_mutex ) ;
2008-11-13 00:27:11 +03:00
w1_write_8 ( sl - > master , HDQ_CMD_READ | reg ) ;
val = w1_read_8 ( sl - > master ) ;
2012-05-18 09:59:52 +04:00
mutex_unlock ( & sl - > master - > bus_mutex ) ;
2008-11-13 00:27:11 +03:00
return val ;
}
2012-02-15 21:21:42 +04:00
2017-07-19 20:04:07 +03:00
static int bq27xxx_battery_hdq_read ( struct bq27xxx_device_info * di , u8 reg ,
bool single )
2008-11-13 00:27:11 +03:00
{
2017-07-19 20:04:07 +03:00
struct w1_slave * sl = dev_to_w1_slave ( di - > dev ) ;
unsigned int timeout = 3 ;
int upper , lower ;
int temp ;
if ( ! single ) {
/*
* Make sure the value has not changed in between reading the
* lower and the upper part
*/
upper = w1_bq27000_read ( sl , reg + 1 ) ;
do {
temp = upper ;
if ( upper < 0 )
return upper ;
lower = w1_bq27000_read ( sl , reg ) ;
if ( lower < 0 )
return lower ;
upper = w1_bq27000_read ( sl , reg + 1 ) ;
} while ( temp ! = upper & & - - timeout ) ;
if ( timeout = = 0 )
return - EIO ;
return ( upper < < 8 ) | lower ;
2008-11-13 00:27:11 +03:00
}
2017-07-19 20:04:07 +03:00
return w1_bq27000_read ( sl , reg ) ;
}
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
static int bq27xxx_battery_hdq_add_slave ( struct w1_slave * sl )
{
struct bq27xxx_device_info * di ;
di = devm_kzalloc ( & sl - > dev , sizeof ( * di ) , GFP_KERNEL ) ;
if ( ! di )
return - ENOMEM ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
dev_set_drvdata ( & sl - > dev , di ) ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
di - > dev = & sl - > dev ;
di - > chip = BQ27000 ;
di - > name = " bq27000-battery " ;
di - > bus . read = bq27xxx_battery_hdq_read ;
return bq27xxx_battery_setup ( di ) ;
2008-11-13 00:27:11 +03:00
}
2017-07-19 20:04:07 +03:00
static void bq27xxx_battery_hdq_remove_slave ( struct w1_slave * sl )
2008-11-13 00:27:11 +03:00
{
2017-07-19 20:04:07 +03:00
struct bq27xxx_device_info * di = dev_get_drvdata ( & sl - > dev ) ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
bq27xxx_battery_teardown ( di ) ;
2008-11-13 00:27:11 +03:00
}
2020-10-04 22:32:02 +03:00
static const struct w1_family_ops bq27xxx_battery_hdq_fops = {
2017-07-19 20:04:07 +03:00
. add_slave = bq27xxx_battery_hdq_add_slave ,
. remove_slave = bq27xxx_battery_hdq_remove_slave ,
2008-11-13 00:27:11 +03:00
} ;
2017-07-19 20:04:07 +03:00
static struct w1_family bq27xxx_battery_hdq_family = {
2014-11-19 06:04:20 +03:00
. fid = W1_FAMILY_BQ27000 ,
2017-07-19 20:04:07 +03:00
. fops = & bq27xxx_battery_hdq_fops ,
2008-11-13 00:27:11 +03:00
} ;
2017-07-19 20:04:07 +03:00
static int __init bq27xxx_battery_hdq_init ( void )
2008-11-13 00:27:11 +03:00
{
if ( F_ID )
2017-07-19 20:04:07 +03:00
bq27xxx_battery_hdq_family . fid = F_ID ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
return w1_register_family ( & bq27xxx_battery_hdq_family ) ;
2008-11-13 00:27:11 +03:00
}
2017-07-19 20:04:07 +03:00
module_init ( bq27xxx_battery_hdq_init ) ;
2008-11-13 00:27:11 +03:00
2017-07-19 20:04:07 +03:00
static void __exit bq27xxx_battery_hdq_exit ( void )
2008-11-13 00:27:11 +03:00
{
2017-07-19 20:04:07 +03:00
w1_unregister_family ( & bq27xxx_battery_hdq_family ) ;
2008-11-13 00:27:11 +03:00
}
2017-07-19 20:04:07 +03:00
module_exit ( bq27xxx_battery_hdq_exit ) ;
2008-11-13 00:27:11 +03:00
MODULE_AUTHOR ( " Texas Instruments Ltd " ) ;
2017-07-19 20:04:07 +03:00
MODULE_DESCRIPTION ( " BQ27xxx battery monitor HDQ/1-wire driver " ) ;
2017-05-16 23:02:12 +03:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " w1-family- " __stringify ( W1_FAMILY_BQ27000 ) ) ;