From d12af32690fe61d676d97ee931846c9533bbce9c Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AE=8B=E7=A7=80=E6=9D=B0?= Date: Wed, 2 Mar 2011 23:55:48 -0800 Subject: [PATCH] modify fuel gauge bq27510's function --- arch/arm/mach-rk29/board-rk29sdk.c | 20 +++ arch/arm/mach-rk29/include/mach/board.h | 6 + drivers/power/bq27510_battery.c | 179 ++++++++++++++++++------ 3 files changed, 161 insertions(+), 44 deletions(-) mode change 100644 => 100755 drivers/power/bq27510_battery.c diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index f36b9c3dfa36..3d98ca14de31 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -402,6 +402,25 @@ static struct mma8452_platform_data mma8452_info = { }; #endif +#if defined (CONFIG_BATTERY_BQ27510) +#define DC_CHECK_PIN RK29_PIN4_PA1 +#define LI_LION_BAT_NUM 2 +static int bq27510_init_dc_check_pin(void){ + if(gpio_request(DC_CHECK_PIN,"dc_check") != 0){ + gpio_free(DC_CHECK_PIN); + printk("bq27510 init dc check pin request error\n"); + return -EIO; + } + gpio_direction_input(DC_CHECK_PIN); + return 0; +} + +struct bq27510_platform_data bq27510_info = { + .init_dc_check_pin = bq27510_init_dc_check_pin, + .dc_check_pin = DC_CHECK_PIN, + .bat_num = LI_LION_BAT_NUM, +}; +#endif /***************************************************************************************** @@ -506,6 +525,7 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .type = "bq27510", .addr = 0x55, .flags = 0, + .platform_data = &bq27510_info, }, #endif #if defined (CONFIG_RTC_HYM8563) diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index d740f1378fe2..d5f29c1eb933 100755 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -116,6 +116,12 @@ struct rk29_i2c_platform_data { int (*io_deinit)(void); }; +struct bq27510_platform_data { + int (*init_dc_check_pin)(void); + unsigned int dc_check_pin; + unsigned int bat_num; +}; + /*i2s*/ struct rk29_i2s_platform_data { int (*io_init)(void); diff --git a/drivers/power/bq27510_battery.c b/drivers/power/bq27510_battery.c old mode 100644 new mode 100755 index bd72a27db557..1e5d17017d92 --- a/drivers/power/bq27510_battery.c +++ b/drivers/power/bq27510_battery.c @@ -22,9 +22,12 @@ #include #include #include +#include +#include +#include -#define DRIVER_VERSION "1.1.0" +#define DRIVER_VERSION "1.1.0" #define BQ27x00_REG_TEMP 0x06 #define BQ27x00_REG_VOLT 0x08 #define BQ27x00_REG_AI 0x14 @@ -32,19 +35,20 @@ #define BQ27x00_REG_TTE 0x16 #define BQ27x00_REG_TTF 0x18 #define BQ27x00_REG_TTECP 0x26 - #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ -#define BQ27000_FLAG_CHGS BIT(7) - #define BQ27500_REG_SOC 0x2c + #define BQ27500_FLAG_DSC BIT(0) +#define BQ27000_FLAG_CHGS BIT(8) #define BQ27500_FLAG_FC BIT(9) +#define BQ27500_FLAG_OTD BIT(14) +#define BQ27500_FLAG_OTC BIT(15) #define BQ27510_SPEED 300 * 1000 +int virtual_battery_enable = 0; +extern int dwc_vbus_status(void); -#define DC_CHECK_PIN RK29_PIN4_PA1 - -#if 0 +#if 1 #define DBG(x...) printk(KERN_INFO x) #else #define DBG(x...) do { } while (0) @@ -58,10 +62,12 @@ static DEFINE_MUTEX(battery_mutex); struct bq27510_device_info { struct device *dev; struct power_supply bat; - ///struct power_supply ac; + struct power_supply ac; struct delayed_work work; - unsigned int interval; struct i2c_client *client; + unsigned int interval; + unsigned int dc_check_pin; + unsigned int bat_num; }; static enum power_supply_property bq27510_battery_props[] = { @@ -71,6 +77,8 @@ static enum power_supply_property bq27510_battery_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_HEALTH, //POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, //POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, //POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, @@ -80,6 +88,34 @@ static enum power_supply_property rk29_ac_props[] = { POWER_SUPPLY_PROP_ONLINE, }; +static ssize_t battery_proc_write(struct file *file,const char __user *buffer, + unsigned long count,void *data) +{ + char c; + int rc; + printk("USER:\n"); + printk("echo x >/proc/driver/power\n"); + printk("x=1,means just print log ||x=2,means log and data ||x= other,means close log\n"); + + rc = get_user(c,buffer); + if(rc) + return rc; + if(c == '1') + virtual_battery_enable = 1; + else if(c == '2') + virtual_battery_enable = 2; + else if(c == '3') + virtual_battery_enable = 3; + else + virtual_battery_enable = 0; + printk("%s,count(%d),virtual_battery_enable(%d)\n",__FUNCTION__,(int)count,virtual_battery_enable); + return count; +} + +static const struct file_operations battery_proc_fops = { + .owner = THIS_MODULE, + .write = battery_proc_write, +}; /* * Common code for BQ27510 devices read @@ -107,9 +143,8 @@ static int bq27510_battery_temperature(struct bq27510_device_info *di) int ret; int temp = 0; u8 buf[2]; - #if CONFIG_NO_BATTERY_IC - return 258; - #endif + if(virtual_battery_enable == 1) + return 125/*258*/; ret = bq27510_read(di->client,BQ27x00_REG_TEMP,buf,2); if (ret<0) { dev_err(di->dev, "error reading temperature\n"); @@ -130,16 +165,23 @@ static int bq27510_battery_voltage(struct bq27510_device_info *di) int ret; u8 buf[2]; int volt = 0; - #if CONFIG_NO_BATTERY_IC - return 4000000; - #endif + if(virtual_battery_enable == 1) + return 2000000/*4000000*/; + ret = bq27510_read(di->client,BQ27x00_REG_VOLT,buf,2); if (ret<0) { dev_err(di->dev, "error reading voltage\n"); return ret; } volt = get_unaligned_le16(buf); - volt = volt * 1000; + + //bp27510 can only measure one li-lion bat + if(di->bat_num == 2){ + volt = volt * 1000 * 2; + }else{ + volt = volt * 1000; + } + DBG("Enter:%s %d--volt = %d\n",__FUNCTION__,__LINE__,volt); return volt; } @@ -154,9 +196,8 @@ static int bq27510_battery_current(struct bq27510_device_info *di) int ret; int curr = 0; u8 buf[2]; - #if CONFIG_NO_BATTERY_IC - return 22000; - #endif + if(virtual_battery_enable == 1) + return 11000/*22000*/; ret = bq27510_read(di->client,BQ27x00_REG_AI,buf,2); if (ret<0) { dev_err(di->dev, "error reading current\n"); @@ -184,9 +225,9 @@ static int bq27510_battery_rsoc(struct bq27510_device_info *di) int nvcap = 0,facap = 0,remcap=0,fccap=0,full=0,cnt=0; #endif u8 buf[2]; - #if CONFIG_NO_BATTERY_IC - return 100; - #endif + if(virtual_battery_enable == 1) + return 50/*100*/; + ret = bq27510_read(di->client,BQ27500_REG_SOC,buf,2); if (ret<0) { dev_err(di->dev, "error reading relative State-of-Charge\n"); @@ -194,9 +235,6 @@ static int bq27510_battery_rsoc(struct bq27510_device_info *di) } rsoc = get_unaligned_le16(buf); DBG("Enter:%s %d--rsoc = %d\n",__FUNCTION__,__LINE__,rsoc); - #if CONFIG_NO_BATTERY_IC - rsoc = 100; - #endif #if 0 ret = bq27510_read(di->client,0x0c,buf,2); nvcap = get_unaligned_le16(buf); @@ -227,16 +265,18 @@ static int bq27510_battery_status(struct bq27510_device_info *di, int flags = 0; int status; int ret; - #if CONFIG_NO_BATTERY_IC - val->intval = POWER_SUPPLY_STATUS_FULL; - return 0; - #endif + if(virtual_battery_enable == 1) + { + val->intval = POWER_SUPPLY_STATUS_FULL; + return 0; + } ret = bq27510_read(di->client,BQ27x00_REG_FLAGS, buf, 2); if (ret < 0) { dev_err(di->dev, "error reading flags\n"); return ret; } flags = get_unaligned_le16(buf); + DBG("Enter:%s %d--status = %x\n",__FUNCTION__,__LINE__,flags); if (flags & BQ27500_FLAG_FC) status = POWER_SUPPLY_STATUS_FULL; else if (flags & BQ27500_FLAG_DSC) @@ -248,6 +288,35 @@ static int bq27510_battery_status(struct bq27510_device_info *di, return 0; } +static int bq27510_health_status(struct bq27510_device_info *di, + union power_supply_propval *val) +{ + u8 buf[2]; + int flags = 0; + int status; + int ret; + if(virtual_battery_enable == 1) + { + val->intval = POWER_SUPPLY_HEALTH_GOOD; + return 0; + } + ret = bq27510_read(di->client,BQ27x00_REG_FLAGS, buf, 2); + if (ret < 0) { + dev_err(di->dev, "error reading flags\n"); + return ret; + } + flags = get_unaligned_le16(buf); + DBG("Enter:%s %d--status = %x\n",__FUNCTION__,__LINE__,flags); + if ((flags & BQ27500_FLAG_OTD)||(flags & BQ27500_FLAG_OTC)) + status = POWER_SUPPLY_HEALTH_OVERHEAT; + else + status = POWER_SUPPLY_HEALTH_GOOD; + + val->intval = status; + return 0; +} + + /* * Read a time register. * Return < 0 if something fails. @@ -283,8 +352,10 @@ static int bq27510_battery_get_property(struct power_supply *psy, { int ret = 0; struct bq27510_device_info *di = to_bq27510_device_info(psy); - + DBG("Enter:%s %d psp= %d\n",__FUNCTION__,__LINE__,psp); + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: ret = bq27510_battery_status(di, val); break; @@ -303,6 +374,12 @@ static int bq27510_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_TEMP: val->intval = bq27510_battery_temperature(di); break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case POWER_SUPPLY_PROP_HEALTH: + ret = bq27510_health_status(di, val); + break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: ret = bq27510_battery_time(di, BQ27x00_REG_TTE, val); break; @@ -324,13 +401,15 @@ static int rk29_ac_get_property(struct power_supply *psy, union power_supply_propval *val) { int ret = 0; + struct bq27510_device_info *di = container_of(psy, struct bq27510_device_info, ac); + switch (psp) { case POWER_SUPPLY_PROP_ONLINE: if (psy->type == POWER_SUPPLY_TYPE_MAINS){ - if(gpio_get_value(DC_CHECK_PIN)) - val->intval = 0; + if(gpio_get_value(di->dc_check_pin)) + val->intval = 0; /*discharging*/ else - val->intval = 1; + val->intval = 1; /*charging*/ } DBG("%s:%d val->intval = %d\n",__FUNCTION__,__LINE__,val->intval); break; @@ -349,10 +428,11 @@ static void bq27510_powersupply_init(struct bq27510_device_info *di) di->bat.num_properties = ARRAY_SIZE(bq27510_battery_props); di->bat.get_property = bq27510_battery_get_property; - /*di->ac.type = POWER_SUPPLY_TYPE_MAINS; + di->ac.name = "ac"; + di->ac.type = POWER_SUPPLY_TYPE_MAINS; di->ac.properties = rk29_ac_props; di->ac.num_properties = ARRAY_SIZE(rk29_ac_props); - di->ac.get_property = rk29_ac_get_property;*/ + di->ac.get_property = rk29_ac_get_property; } @@ -374,11 +454,14 @@ static int bq27510_battery_probe(struct i2c_client *client, { struct bq27510_device_info *di; int retval = 0; + struct bq27510_platform_data *pdata; #ifdef CONFIG_CHECK_BATT_CAPACITY u8 buf[2]; #endif - + + pdata = client->dev.platform_data; + di = kzalloc(sizeof(*di), GFP_KERNEL); if (!di) { dev_err(&client->dev, "failed to allocate device info data\n"); @@ -392,8 +475,12 @@ static int bq27510_battery_probe(struct i2c_client *client, /* 4 seconds between monotor runs interval */ di->interval = msecs_to_jiffies(4 * 1000); - gpio_request(DC_CHECK_PIN,"dc_check"); - gpio_direction_input(DC_CHECK_PIN); + di->bat_num = pdata->bat_num; + di->dc_check_pin = pdata->dc_check_pin; + + if (pdata->init_dc_check_pin) + pdata->init_dc_check_pin( ); + bq27510_powersupply_init(di); #ifdef CONFIG_CHECK_BATT_CAPACITY buf[0] = 0x41; @@ -408,10 +495,15 @@ static int bq27510_battery_probe(struct i2c_client *client, dev_err(&client->dev, "failed to register battery\n"); goto batt_failed_4; } + retval = power_supply_register(&client->dev, &di->ac); + if (retval) { + dev_err(&client->dev, "failed to register ac\n"); + goto batt_failed_4; + } + INIT_DELAYED_WORK(&di->work, bq27510_battery_work); schedule_delayed_work(&di->work, di->interval); dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION); - return 0; batt_failed_4: @@ -430,10 +522,6 @@ static int bq27510_battery_remove(struct i2c_client *client) return 0; } -/* - * Module stuff - */ - static const struct i2c_device_id bq27510_id[] = { { "bq27510", 0 }, }; @@ -450,10 +538,13 @@ static struct i2c_driver bq27510_battery_driver = { static int __init bq27510_battery_init(void) { int ret; - + struct proc_dir_entry * battery_proc_entry; + ret = i2c_add_driver(&bq27510_battery_driver); if (ret) printk(KERN_ERR "Unable to register BQ27510 driver\n"); + + battery_proc_entry = proc_create("driver/power",0777,NULL,&battery_proc_fops); return ret; } module_init(bq27510_battery_init); -- 2.34.1