BQ27000/BQ27200 battery monitoring driver for OMAP34xx
This patch provides the battery monitoring driver to monitor batteries with BQ27000(HDQ) or BQ27200(i2C) chips. On omap 3430 sdp BQ27000 battery is tested through the HDQ interface which uses the earlier posted HDQ and BQ slave drivers. The BQ27200 support is an extension to the BQ27000 driver as the register set between BQ27000 and BQ27200 is the same.
Thanks to Klaus.K Pedersen and Mikko Ylinen for the suggestions to add support for BQ27200 chip as part of this driver.
--- drivers/power/Kconfig | 21 + drivers/power/Makefile | 1 drivers/power/bq27x00_battery.c | 556 ++++++++++++++++++++++++++++++++++++++++ drivers/w1/slaves/w1_bq27000.c | 2 4 files changed, 579 insertions(+), 1 deletion(-)
drivers/power/bq27x00_battery.c new file +556 -0
@@ -0,0 +1,556 @@ +/* +* linux/drivers/power/bq27x00_battery.c +* +* BQ27000/BQ27200 battery driver +* +* Copyright (C) 2008 Texas Instruments, Inc. +* +* Author: Texas Instruments +* +* This package 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. +* +* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +* +*/ +#include <linux/module.h> +#include <linux/param.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/power_supply.h> + +#if defined(CONFIG_BATTERY_BQ27000 ) +#define BATTERY_BQ27000 +#include "../w1/w1.h" +#endif +#if defined(CONFIG_BATTERY_BQ27200 ) +#define BATTERY_BQ27200 +#include <linux/i2c.h> +#endif + +#define BQ27x00_REG_TEMP 0x06 +#define BQ27x00_REG_VOLT 0x08 +#define BQ27x00_REG_RSOC 0x0B/* Relative State-of-Charge */ +#define BQ27x00_REG_AI 0x14 +#define BQ27x00_REG_FLAGS 0x0A +#define HIGH_BYTE (A ) ((A) << 8) + +#if defined(BATTERY_BQ27000 ) +extern int w1_bq27000_read (struct device *dev,u8 reg); +#endif + +struct bq27x00_device_info ; +struct bq27x00_access_methods { +int (*read)(u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); +}; + +struct bq27x00_device_info { +struct device *dev; +#if defined(BATTERY_BQ27000 ) +struct device *w1_dev; +#endif +#if defined(BATTERY_BQ27200 ) +struct i2c_client *client; +#endif +unsigned long update_time; +int voltage_uV; +int current_uA; +int temp_C; +int charge_rsoc; +struct bq27x00_access_methods *bus; +struct power_supply bat; +struct delayed_work monitor_work; +}; + +static unsigned int cache_time =60000 ; +module_param (cache_time, uint,0644 ); +MODULE_PARM_DESC (cache_time,"cache time in milliseconds" ); + +static enum power_supply_property bq27x00_battery_props[] = { +POWER_SUPPLY_PROP_PRESENT , +POWER_SUPPLY_PROP_VOLTAGE_NOW , +POWER_SUPPLY_PROP_CURRENT_NOW , +POWER_SUPPLY_PROP_CHARGE_NOW , +POWER_SUPPLY_PROP_CAPACITY , +POWER_SUPPLY_PROP_TEMP , +}; + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); + +#if defined(BATTERY_BQ27000 ) +static int bq27000_battery_probe (struct platform_device *dev); +static int bq27000_battery_remove (struct platform_device *dev); +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *dev, +pm_message_t state); +static int bq27000_battery_resume (struct platform_device *dev); +#endif + +static struct platform_driver bq27000_battery_driver = { + .probe = bq27000_battery_probe, + .remove = bq27000_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27000_battery_suspend, + .resume = bq27000_battery_resume, +#endif + .driver = { + .name ="bq27000-bat" , + }, +}; +#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_battery_probe (struct i2c_client *client); +static int bq27200_battery_remove (struct i2c_client *client); +static int bq27200_battery_suspend (struct i2c_client *client, +pm_message_t mesg); +static int bq27200_battery_resume (struct i2c_client *client); +static struct i2c_driver bq27200_battery_driver = { + .driver = { + .name ="bq27200-bat" , + }, + .probe = bq27200_battery_probe, + .remove = bq27200_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27200_battery_suspend, + .resume = bq27200_battery_resume, +#endif +}; +#endif + +/* +* Return the battery temperature in Celcius degrees +* Or < 0 if something fails. +*/ +static int bq27x00_battery_temperature (struct bq27x00_device_info *di) +{ +int ret, temp =0 ; + + ret =bq27x00_read (BQ27x00_REG_TEMP, &temp,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading temperature from the battery\n" ); +return ret; + } + +return (temp >>2 ) -273 ; +} + +/* +* Return the battery Voltage in milivolts +* Or < 0 if something fails. +*/ +static int bq27x00_battery_voltage (struct bq27x00_device_info *di) +{ +int ret, volt =0 ; + + ret =bq27x00_read (BQ27x00_REG_VOLT, &volt,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery voltage from the battery\n" ); +return ret; + } + +return volt; +} + +/* +* Return the battery average current +* Note that current can be negative signed as well +* Or 0 if something fails. +*/ +static int bq27x00_battery_current (struct bq27x00_device_info *di) +{ +int ret, curr =0 , flags =0 ; + + ret =bq27x00_read (BQ27x00_REG_AI, &curr,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading current from the battery\n" ); +return 0 ; + } + ret =bq27x00_read (BQ27x00_REG_FLAGS, &flags,0 , di); +if (ret <0 ) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery flags\n" ); +return 0 ; + } +if ((flags & (1 <<7 )) !=0 ) { +pr_debug ("Negative current\n" ); +return -curr; + }else { +return curr; + } +} + +/* +* Return the battery Relative State-of-Charge +* Or < 0 if something fails. +*/ +static int bq27x00_battery_rsoc (struct bq27x00_device_info *di) +{ +int ret, rsoc =0 ; + + ret =bq27x00_read (BQ27x00_REG_RSOC, &rsoc,1 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery Relative" +"State-of-Charge\n" ); +return ret; + } +return rsoc; +} + +#if defined(BATTERY_BQ27000 ) +static int bq27000_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +u8 val; + + val =w1_bq27000_read (di->w1_dev, reg); + *rt_value = val; + +if (!b_single) { + val =0 ; + val =w1_bq27000_read (di->w1_dev, reg +1 ); + *rt_value +=HIGH_BYTE ((int ) val); + } + +return 0 ; +} +#else +#define bq27000_read NULL +#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +struct i2c_client *client = di->client; +struct i2c_msg msg[1 ]; +unsigned char data[2 ]; +int err; + +if (!client->adapter) +return -ENODEV ; + + msg->addr = client->addr; + msg->flags =0 ; + msg->len =1 ; + msg->buf = data; + + data[0 ] = reg; + err =i2c_transfer (client->adapter, msg,1 ); + +if (err >=0 ) { +if (!b_single) + msg->len =2 ; +else + msg->len =1 ; + + msg->flags =I2C_M_RD ; + err =i2c_transfer (client->adapter, msg,1 ); +if (err >=0 ) { +if (!b_single) + *rt_value = data[1 ] |HIGH_BYTE (data[0 ]); +else + *rt_value = data[0 ]; + +return 0 ; + }else { +pr_err ("BQ27200 I2C read failed\n" ); +return err; + } + }else { +pr_err ("BQ27200 I2C write failed\n" ); +return err; + } +} +#else +#define bq27200_read NULL +#endif + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +int ret; + + ret = di->bus->read (reg, rt_value, b_single, di); +return ret; +} + +/* +* Read the battery temp, voltage, current and relative state of charge. +*/ +static void bq27x00_battery_read_status (struct bq27x00_device_info *di) +{ +if (di->update_time &&time_before (jiffies, di->update_time + +msecs_to_jiffies (cache_time))) +return ; + + di->temp_C =bq27x00_battery_temperature (di); + di->voltage_uV =bq27x00_battery_voltage (di); + di->current_uA =bq27x00_battery_current (di); + di->charge_rsoc =bq27x00_battery_rsoc (di); + + di->update_time = jiffies; + +return ; +} + +static void bq27x00_battery_work (struct delayed_work *work) +{ +struct bq27x00_device_info *di =container_of (work, + struct bq27x00_device_info, monitor_work); + +bq27x00_battery_read_status (di); +schedule_delayed_work (&di->monitor_work,100 ); +return ; +} + +#define to_bq27x00_device_info (x) container_of((x), \ + struct bq27x00_device_info, bat); + +static int bq27x00_battery_get_property (struct power_supply *psy, +enum power_supply_property psp, +union power_supply_propval *val) +{ +struct bq27x00_device_info *di =to_bq27x00_device_info (psy); + +switch (psp) { +case POWER_SUPPLY_PROP_VOLTAGE_NOW : + val->intval = di->voltage_uV; +break ; +case POWER_SUPPLY_PROP_CURRENT_NOW : + val->intval = di->current_uA; +break ; +case POWER_SUPPLY_PROP_CHARGE_NOW : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_TEMP : + val->intval = di->temp_C; +break ; +case POWER_SUPPLY_PROP_CAPACITY : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_PRESENT : +if (di->voltage_uV ==0 ) + val->intval =0 ; +else + val->intval =1 ; +break ; +default : +return -EINVAL ; + } + +return 0 ; +} + +static void bq27x00_powersupply_init (struct bq27x00_device_info *di) +{ + di->bat.type =POWER_SUPPLY_TYPE_BATTERY ; + di->bat.properties = bq27x00_battery_props; + di->bat.num_properties =ARRAY_SIZE (bq27x00_battery_props); + di->bat.get_property = bq27x00_battery_get_property; + di->bat.external_power_changed =NULL ; +return ; +} + +#ifdef BATTERY_BQ27200 +static int bq27200_battery_probe (struct i2c_client *client) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +i2c_set_clientdata (client, di); + di->dev = &client->dev; + di->bat.name ="bq27200" ; + bus->read = &bq27200_read; + di->bus = bus; + di->client = client; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&client->dev, &di->bat); +if (retval) { +pr_err ("BQ27200 battery driver: Failed to register battery\n" ); + goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,100 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27200_battery_remove (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27200_battery_suspend (struct i2c_client *client,pm_message_t mesg) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +} + +static int bq27200_battery_resume (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif + +#ifdef BATTERY_BQ27000 +static int bq27000_battery_probe (struct platform_device *pdev) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +platform_set_drvdata (pdev, di); + + di->dev = &pdev->dev; + di->w1_dev = pdev->dev.parent; + di->bat.name ="bq27000" ; + bus->read = &bq27000_read; + di->bus = bus; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&pdev->dev, &di->bat); +if (retval) { +pr_err ("BQ27000 battery driver: Failed to register battery\n" ); + goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,50 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27000_battery_remove (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +platform_set_drvdata (pdev,NULL ); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *pdev, +pm_message_t state) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +} + +static int bq27000_battery_resume (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif + +static int __init bq27x00_battery_init (void ) +{ +int status =0 ; + +#if defined(BATTERY_BQ27000 ) + status =platform_driver_register (&bq27000_battery_driver); +if (status) +printk (KERN_ERR "Unable to register BQ27000 driver\n" ); +#endif +#if defined(BATTERY_BQ27200 ) + status =i2c_add_driver (&bq27200_battery_driver); +printk (KERN_ERR "Unable to register BQ27200 driver\n" ); +#endif +return status; +} + +static void __exit bq27x00_battery_exit(void) +{ +#if defined(BATTERY_BQ27000 ) +platform_driver_unregister (&bq27000_battery_driver); +#endif +#if defined(BATTERY_BQ27200 ) +i2c_del_driver (&bq27200_battery_driver); +#endif +} + +module_init (bq27x00_battery_init); +module_exit (bq27x00_battery_exit); + +MODULE_AUTHOR ("Texas Instruments" ); +MODULE_DESCRIPTION ("BQ27x00 battery moniter driver" ); +MODULE_LICENSE ("GPL" );
drivers/power/Kconfig +21 -0
@@ -49,4 +49,25 @@ help Say Y to enable support for the battery on the OLPC laptop. +config BATTERY_BQ27x00 + tristate "BQ27x00 battery driver" + help + Say Y here to enable support for batteries with BQ27000 or BQ27200 chip. + +config BATTERY_BQ27000 + bool "BQ27000 battery driver" + depends on BATTERY_BQ27x00 + select W1 + select W1_SLAVE_BQ27000 + help + Say Y here to enable support for batteries with BQ27000(HDQ) chip. + +config BATTERY_BQ27200 + bool "BQ27200 battery driver" + depends on BATTERY_BQ27x00 + select I2C + select I2C_OMAP + help + Say Y here to enable support for batteries with BQ27200(I2C) chip. + endif # POWER_SUPPLY
drivers/power/Makefile +1 -0
@@ -20,3 +20,4 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o +obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
drivers/w1/slaves/w1_bq27000.c +1 -1
@@ -59,7 +59,7 @@int id =1 ;struct platform_device *pdev; - pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);if (!pdev) { ret = -ENOMEM ;return ret;
Some cosmetic comments below
Quoted 1 line · Madhusudhan Chikkature Rajashekar
This patch provides the battery monitoring driver to monitor batteries
with
Quoted 2 lines
BQ27000(HDQ) or BQ27200(i2C) chips.
On omap 3430 sdp BQ27000 battery is tested through the HDQ interface
which
Quoted 42 lines
uses the earlier posted HDQ and BQ slave drivers.
The BQ27200 support is an extension to the BQ27000 driver as the register set between BQ27000 and BQ27200 is the same.Thanks to Klaus.K Pedersen and Mikko Ylinen for the suggestions to add support for BQ27200 chip as part of
this driver.Signed-off-by Madhusudhan Chikkature<[email protected]>--- drivers/power/Kconfig | 21 + drivers/power/Makefile | 1 drivers/power/bq27x00_battery.c | 556 ++++++++++++++++++++++++++++++++++++++++ drivers/w1/slaves/w1_bq27000.c | 2 4 files changed, 579 insertions(+), 1 deletion(-)Index:
linux-omap-2.6/drivers/power/bq27x00_battery.c
===================================================================drivers/power/bq27x00_battery.c new file +0
-010:50:53.631358952 +0530
drivers/power/bq27x00_battery.c new file +17
-0@@ -0,0 +1,556 @@ +/* +* linux/drivers/power/bq27x00_battery.c +* +* BQ27000/BQ27200 battery driver +* +* Copyright (C) 2008 Texas Instruments, Inc. +* +* Author: Texas Instruments +* +* This package 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. +* +* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +*
drivers/power/bq27x00_battery.c line 27
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+*/ +#include <linux/module.h> +#include <linux/param.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/power_supply.h> + +#if defined(CONFIG_BATTERY_BQ27000 )
Here use ifdef
drivers/power/bq27x00_battery.c line 28
Quoted 1 line
drivers/power/bq27x00_battery.c new file +1
-0+#define BATTERY_BQ27000
there's no need to add this one as you can use the Kconfig option
Quoted 17 lines
drivers/power/bq27x00_battery.c new file +17
-0+#include "../w1/w1.h" +#endif +#if defined(CONFIG_BATTERY_BQ27200 ) +#define BATTERY_BQ27200 +#include <linux/i2c.h> +#endif + +#define BQ27x00_REG_TEMP 0x06 +#define BQ27x00_REG_VOLT 0x08 +#define BQ27x00_REG_RSOC 0x0B/* Relative State-of-Charge */ +#define BQ27x00_REG_AI 0x14 +#define BQ27x00_REG_FLAGS 0x0A +#define HIGH_BYTE (A ) ((A) << 8) + +#if defined(BATTERY_BQ27000 ) +extern int w1_bq27000_read (struct device *dev,u8 reg); +#endif
drivers/power/bq27x00_battery.c line 55
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ +struct bq27x00_device_info ; +struct bq27x00_access_methods { +int (*read)(u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); +}; + +struct bq27x00_device_info { +struct device *dev; +#if defined(BATTERY_BQ27000 )
#ifdef CONFIG_BATERRY_BQ27000
drivers/power/bq27x00_battery.c line 58
Quoted 3 lines
drivers/power/bq27x00_battery.c new file +3
-0+struct device *w1_dev; +#endif +#if defined(BATTERY_BQ27200 )
#ifdef CONFIG_BATTERY_BQ27200
Quoted 161 lines
drivers/power/bq27x00_battery.c new file +161
-0+struct i2c_client *client; +#endif +unsigned long update_time; +int voltage_uV; +int current_uA; +int temp_C; +int charge_rsoc; +struct bq27x00_access_methods *bus; +struct power_supply bat; +struct delayed_work monitor_work; +}; + +static unsigned int cache_time =60000 ; +module_param (cache_time, uint,0644 ); +MODULE_PARM_DESC (cache_time,"cache time in milliseconds" ); + +static enum power_supply_property bq27x00_battery_props[] = { +POWER_SUPPLY_PROP_PRESENT , +POWER_SUPPLY_PROP_VOLTAGE_NOW , +POWER_SUPPLY_PROP_CURRENT_NOW , +POWER_SUPPLY_PROP_CHARGE_NOW , +POWER_SUPPLY_PROP_CAPACITY , +POWER_SUPPLY_PROP_TEMP , +}; + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); + +#if defined(BATTERY_BQ27000 ) +static int bq27000_battery_probe (struct platform_device *dev); +static int bq27000_battery_remove (struct platform_device *dev); +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *dev, +pm_message_t state); +static int bq27000_battery_resume (struct platform_device *dev); +#endif + +static struct platform_driver bq27000_battery_driver = { + .probe = bq27000_battery_probe, + .remove = bq27000_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27000_battery_suspend, + .resume = bq27000_battery_resume, +#endif + .driver = { + .name ="bq27000-bat" , + }, +}; +#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_battery_probe (struct i2c_client *client); +static int bq27200_battery_remove (struct i2c_client *client); +static int bq27200_battery_suspend (struct i2c_client *client, +pm_message_t mesg); +static int bq27200_battery_resume (struct i2c_client *client); +static struct i2c_driver bq27200_battery_driver = { + .driver = { + .name ="bq27200-bat" , + }, + .probe = bq27200_battery_probe, + .remove = bq27200_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27200_battery_suspend, + .resume = bq27200_battery_resume, +#endif +}; +#endif + +/* +* Return the battery temperature in Celcius degrees +* Or < 0 if something fails. +*/ +static int bq27x00_battery_temperature (struct bq27x00_device_info *di) +{ +int ret, temp =0 ; + + ret =bq27x00_read (BQ27x00_REG_TEMP, &temp,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading temperature from the battery\n" ); +return ret; + } + +return (temp >>2 ) -273 ; +} + +/* +* Return the battery Voltage in milivolts +* Or < 0 if something fails. +*/ +static int bq27x00_battery_voltage (struct bq27x00_device_info *di) +{ +int ret, volt =0 ; + + ret =bq27x00_read (BQ27x00_REG_VOLT, &volt,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery voltage from the battery\n" ); +return ret; + } + +return volt; +} + +/* +* Return the battery average current +* Note that current can be negative signed as well +* Or 0 if something fails. +*/ +static int bq27x00_battery_current (struct bq27x00_device_info *di) +{ +int ret, curr =0 , flags =0 ; + + ret =bq27x00_read (BQ27x00_REG_AI, &curr,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading current from the battery\n" ); +return 0 ; + } + ret =bq27x00_read (BQ27x00_REG_FLAGS, &flags,0 , di); +if (ret <0 ) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery flags\n" ); +return 0 ; + } +if ((flags & (1 <<7 )) !=0 ) { +pr_debug ("Negative current\n" ); +return -curr; + }else { +return curr; + } +} + +/* +* Return the battery Relative State-of-Charge +* Or < 0 if something fails. +*/ +static int bq27x00_battery_rsoc (struct bq27x00_device_info *di) +{ +int ret, rsoc =0 ; + + ret =bq27x00_read (BQ27x00_REG_RSOC, &rsoc,1 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery Relative" +"State-of-Charge\n" ); +return ret; + } +return rsoc; +} + +#if defined(BATTERY_BQ27000 ) +static int bq27000_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +u8 val; + + val =w1_bq27000_read (di->w1_dev, reg); + *rt_value = val; +
drivers/power/bq27x00_battery.c line 229
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+if (!b_single) { + val =0 ; + val =w1_bq27000_read (di->w1_dev, reg +1 ); + *rt_value +=HIGH_BYTE ((int ) val); + } + + return 0; +} +#else +#define bq27000_read NULL
this should be defined as 0 or an static inline int [...] { return 0; }
Quoted 38 lines
drivers/power/bq27x00_battery.c new file +38
-0+#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +struct i2c_client *client = di->client; +struct i2c_msg msg[1 ]; +unsigned char data[2 ]; +int err; + +if (!client->adapter) +return -ENODEV ; + + msg->addr = client->addr; + msg->flags =0 ; + msg->len =1 ; + msg->buf = data; + + data[0 ] = reg; + err =i2c_transfer (client->adapter, msg,1 ); + +if (err >=0 ) { +if (!b_single) + msg->len =2 ; +else + msg->len =1 ; + + msg->flags =I2C_M_RD ; + err =i2c_transfer (client->adapter, msg,1 ); +if (err >=0 ) { +if (!b_single) + *rt_value = data[1 ] |HIGH_BYTE (data[0 ]); +else + *rt_value = data[0 ]; + +return 0 ; + }else {
drivers/power/bq27x00_battery.c line 277
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+pr_err ("BQ27200 I2C read failed\n" ); + return err; + } + }else { +pr_err ("BQ27200 I2C write failed\n" ); +return err; + } +} +#else +#define bq27200_read NULL
same here
Quoted 156 lines
drivers/power/bq27x00_battery.c new file +149
-0+#endif + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +int ret; + + ret = di->bus->read (reg, rt_value, b_single, di); +return ret; +} + +/* +* Read the battery temp, voltage, current and relative state of charge. +*/ +static void bq27x00_battery_read_status (struct bq27x00_device_info *di) +{ +if (di->update_time &&time_before (jiffies, di->update_time + +msecs_to_jiffies (cache_time))) +return ; + + di->temp_C =bq27x00_battery_temperature (di); + di->voltage_uV =bq27x00_battery_voltage (di); + di->current_uA =bq27x00_battery_current (di); + di->charge_rsoc =bq27x00_battery_rsoc (di); + + di->update_time = jiffies; + +return ; +} + +static void bq27x00_battery_work (struct delayed_work *work) +{ +struct bq27x00_device_info *di =container_of (work, + struct bq27x00_device_info, monitor_work); + +bq27x00_battery_read_status (di); +schedule_delayed_work (&di->monitor_work,100 ); +return ; +} + +#define to_bq27x00_device_info (x) container_of((x), \ + struct bq27x00_device_info, bat); + +static int bq27x00_battery_get_property (struct power_supply *psy, +enum power_supply_property psp, +union power_supply_propval *val) +{ +struct bq27x00_device_info *di =to_bq27x00_device_info (psy); + +switch (psp) { +case POWER_SUPPLY_PROP_VOLTAGE_NOW : + val->intval = di->voltage_uV; +break ; +case POWER_SUPPLY_PROP_CURRENT_NOW : + val->intval = di->current_uA; +break ; +case POWER_SUPPLY_PROP_CHARGE_NOW : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_TEMP : + val->intval = di->temp_C; +break ; +case POWER_SUPPLY_PROP_CAPACITY : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_PRESENT : +if (di->voltage_uV ==0 ) + val->intval =0 ; +else + val->intval =1 ; +break ; +default : +return -EINVAL ; + } + +return 0 ; +} + +static void bq27x00_powersupply_init (struct bq27x00_device_info *di) +{ + di->bat.type =POWER_SUPPLY_TYPE_BATTERY ; + di->bat.properties = bq27x00_battery_props; + di->bat.num_properties =ARRAY_SIZE (bq27x00_battery_props); + di->bat.get_property = bq27x00_battery_get_property; + di->bat.external_power_changed =NULL ; +return ; +} + +#ifdef BATTERY_BQ27200 +static int bq27200_battery_probe (struct i2c_client *client) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +i2c_set_clientdata (client, di); + di->dev = &client->dev; + di->bat.name ="bq27200" ; + bus->read = &bq27200_read; + di->bus = bus; + di->client = client; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&client->dev, &di->bat); +if (retval) { +pr_err ("BQ27200 battery driver: Failed to register battery\n" ); + goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,100 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27200_battery_remove (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27200_battery_suspend(struct i2c_client *client,
pm_message_tmesg)drivers/power/bq27x00_battery.c new file +6
-0+{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +}
drivers/power/bq27x00_battery.c line 442
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ +static int bq27200_battery_resume (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif
put a comment indicating which ifdef you're closing, like:
#endif /* CONFIG_PM */
Quoted 165 lines
drivers/power/bq27x00_battery.c new file +114
-0+ +#ifdef BATTERY_BQ27000 +static int bq27000_battery_probe (struct platform_device *pdev) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +platform_set_drvdata (pdev, di); + + di->dev = &pdev->dev; + di->w1_dev = pdev->dev.parent; + di->bat.name ="bq27000" ; + bus->read = &bq27000_read; + di->bus = bus; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&pdev->dev, &di->bat); +if (retval) { +pr_err ("BQ27000 battery driver: Failed to register battery\n" ); + goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,50 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27000_battery_remove (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +platform_set_drvdata (pdev,NULL ); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *pdev, +pm_message_t state) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +} + +static int bq27000_battery_resume (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif + +static int __init bq27x00_battery_init (void ) +{ +int status =0 ; + +#if defined(BATTERY_BQ27000 ) + status =platform_driver_register (&bq27000_battery_driver); +if (status) +printk (KERN_ERR "Unable to register BQ27000 driver\n" ); +#endif +#if defined(BATTERY_BQ27200 ) + status =i2c_add_driver (&bq27200_battery_driver); +printk (KERN_ERR "Unable to register BQ27200 driver\n" ); +#endif +return status; +} + +static void __exit bq27x00_battery_exit(void) +{ +#if defined(BATTERY_BQ27000 ) +platform_driver_unregister (&bq27000_battery_driver); +#endif +#if defined(BATTERY_BQ27200 ) +i2c_del_driver (&bq27200_battery_driver); +#endif +} + +module_init (bq27x00_battery_init); +module_exit (bq27x00_battery_exit); + +MODULE_AUTHOR ("Texas Instruments" ); +MODULE_DESCRIPTION ("BQ27x00 battery moniter driver" ); +MODULE_LICENSE ("GPL" );Index: linux-omap-2.6/drivers/power/Kconfig
===================================================================
--- linux-omap-2.6.orig/drivers/power/Kconfig 2008-04-08
17:15:04.000000000 +0530
+++ linux-omap-2.6/drivers/power/Kconfig 2008-04-21 08:25:00.000000000
+0530drivers/power/bq27x00_battery.c new file +4
-0@@ -49,4 +49,25 @@help Say Y to enable support for the battery on the OLPC laptop. +config BATTERY_BQ27x00 + tristate "BQ27x00 battery driver" + help + SayY here to enable support for batteries withBQ27000 orBQ27200 chip.
drivers/power/bq27x00_battery.c new file +17
-0+ +config BATTERY_BQ27000 + bool "BQ27000 battery driver" + depends on BATTERY_BQ27x00 + select W1 + select W1_SLAVE_BQ27000 + help + Say Y here to enable support for batteries with BQ27000(HDQ) chip. + +config BATTERY_BQ27200 + bool "BQ27200 battery driver" + depends on BATTERY_BQ27x00 + select I2C + select I2C_OMAP + help + Say Y here to enable support for batteries with BQ27200(I2C) chip. + endif # POWER_SUPPLYIndex: linux-omap-2.6/drivers/power/Makefile
===================================================================
--- linux-omap-2.6.orig/drivers/power/Makefile 2008-04-08
17:15:04.000000000 +0530
+++ linux-omap-2.6/drivers/power/Makefile 2008-04-20 17:03:51.000000000
+0530drivers/power/bq27x00_battery.c new file +1
-0@@ -20,3 +20,4 @@ obj-$ (CONFIG_BATTERY_DS2760 ) += ds2760_battery.o obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o +obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.oIndex:
linux-omap-2.6/drivers/w1/slaves/w1_bq27000.c
===================================================================
---linux-omap-2.6.orig/drivers/w1/slaves/w1_bq27000.c2008-04-08
17:15:05.000000000 +0530
+++linux-omap-2.6/drivers/w1/slaves/w1_bq27000.c2008-04-20
17:08:55.000000000 +0530
drivers/power/bq27x00_battery.c line 62
Quoted 5 lines
drivers/power/bq27x00_battery.c new file +1
-1@@ -59,7 +59,7 @@int id =1 ;struct platform_device *pdev; - pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);
do you really need to change the name here?
It seems that this change doesn't belong to this patch.
Quoted 8 lines
drivers/power/bq27x00_battery.c new file +0
-1if (!pdev) { ret = -ENOMEM ;return ret; --To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 5 lines
Best Regards, Felipe Balbi http://felipebalbi.com [email protected]
Hi Felipe,
Thanks for the comments. I will fix them and resend the patch.
Please note my view on the below point.
Quoted 5 lines
drivers/w1/slaves/w1_bq27000.c line 62
Quoted 2 lines
drivers/w1/slaves/w1_bq27000.c +1
-1- pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);do you really need to change the name here?
It seems that this change doesn't belong to this patch.
I will make this as a separate patch.As BQ27000 chip is not omap specific, I guess the above name is not correct. Hence I intend to make that change.
Regards,
Madhu
Quoted 724 lines
-----Original Message-----
From: Felipe Balbi [mailto:[email protected]]
Sent: Friday, April 25, 2008 4:20 PM
To: Madhusudhan Chikkature Rajashekar
Cc: Tony Lindgren; [email protected]
Subject: Re: [RFC/PATCH] BQ27000/BQ27200 battery monitoring driver for OMAP34xxSome cosmetic comments below
Quoted 1 line · Madhusudhan Chikkature Rajashekar
This patch provides the battery monitoring driver to
monitor batteries
withQuoted 2 lines
BQ27000(HDQ) or BQ27200(i2C) chips.
On omap 3430 sdp BQ27000 battery is tested through the HDQ interfacewhich
Quoted 2 lines
uses the earlier posted HDQ and BQ slave drivers. The BQ27200 support is an extension to the BQ27000 driver
as the register
Quoted 3 lines
set between BQ27000 and BQ27200 is the same.
Thanks to Klaus.K Pedersen and Mikko Ylinen for the
suggestions to add
Quoted 20 lines
support for BQ27200 chip as part of
this driver.Signed-off-by Madhusudhan Chikkature<[email protected]>--- drivers/power/Kconfig | 21 + drivers/power/Makefile | 1 drivers/power/bq27x00_battery.c | 556 ++++++++++++++++++++++++++++++++++++++++ drivers/w1/slaves/w1_bq27000.c | 2 4 files changed, 579 insertions(+), 1 deletion(-)Index:
linux-omap-2.6/drivers/power/bq27x00_battery.c
===================================================================drivers/power/bq27x00_battery.c new file +0
-010:50:53.631358952 +0530
drivers/power/bq27x00_battery.c line 10
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0@@ -0,0 +1,556 @@ +/* +* linux/drivers/power/bq27x00_battery.c +* +* BQ27000/BQ27200 battery driver +* +* Copyright (C) 2008 Texas Instruments, Inc. +* +* Author: Texas Instruments +* +* This package is free software; you can redistribute it and/or modify
drivers/power/bq27x00_battery.c line 11
Quoted 1 line
drivers/power/bq27x00_battery.c new file +1
-0+* it under the terms of the GNU General Public License version 2 as
drivers/power/bq27x00_battery.c
Quoted 5 lines
drivers/power/bq27x00_battery.c new file +5
-0+* published by the Free Software Foundation. +* +* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
drivers/power/bq27x00_battery.c line 27
Quoted 11 lines
drivers/power/bq27x00_battery.c new file +11
-0+* +*/ +#include <linux/module.h> +#include <linux/param.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/power_supply.h> + +#if defined(CONFIG_BATTERY_BQ27000 )Here use ifdef
drivers/power/bq27x00_battery.c line 28
Quoted 1 line
drivers/power/bq27x00_battery.c new file +1
-0+#define BATTERY_BQ27000 there's no need to add this one as you can use the
Kconfigoptiondrivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+#include "../w1/w1.h" +#endif +#if defined(CONFIG_BATTERY_BQ27200 ) +#define BATTERY_BQ27200 +#include <linux/i2c.h> +#endif + +#define BQ27x00_REG_TEMP 0x06 +#define BQ27x00_REG_VOLT 0x08 +#define BQ27x00_REG_RSOC 0x0B/* Relative State-of-Charge */
Quoted 7 lines
drivers/power/bq27x00_battery.c new file +7
-0+#define BQ27x00_REG_AI 0x14 +#define BQ27x00_REG_FLAGS 0x0A +#define HIGH_BYTE (A ) ((A) << 8) + +#if defined(BATTERY_BQ27000 ) +extern int w1_bq27000_read (struct device *dev,u8 reg); +#endif drivers/power/bq27x00_battery.c line 55
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ +struct bq27x00_device_info ; +struct bq27x00_access_methods { +int (*read)(u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); +}; + +struct bq27x00_device_info { +struct device *dev; +#if defined(BATTERY_BQ27000 )#ifdef
CONFIG_BATERRY_BQ27000drivers/power/bq27x00_battery.c line 58
Quoted 3 lines
drivers/power/bq27x00_battery.c new file +3
-0+struct device *w1_dev; +#endif +#if defined(BATTERY_BQ27200 )#ifdef
CONFIG_BATTERY_BQ27200Quoted 64 lines
drivers/power/bq27x00_battery.c new file +64
-0+struct i2c_client *client; +#endif +unsigned long update_time; +int voltage_uV; +int current_uA; +int temp_C; +int charge_rsoc; +struct bq27x00_access_methods *bus; +struct power_supply bat; +struct delayed_work monitor_work; +}; + +static unsigned int cache_time =60000 ; +module_param (cache_time, uint,0644 ); +MODULE_PARM_DESC (cache_time,"cache time in milliseconds" ); + +static enum power_supply_property bq27x00_battery_props[] = { +POWER_SUPPLY_PROP_PRESENT , +POWER_SUPPLY_PROP_VOLTAGE_NOW , +POWER_SUPPLY_PROP_CURRENT_NOW , +POWER_SUPPLY_PROP_CHARGE_NOW , +POWER_SUPPLY_PROP_CAPACITY , +POWER_SUPPLY_PROP_TEMP , +}; + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di); + +#if defined(BATTERY_BQ27000 ) +static int bq27000_battery_probe (struct platform_device *dev); +static int bq27000_battery_remove (struct platform_device *dev); +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *dev, +pm_message_t state); +static int bq27000_battery_resume (struct platform_device *dev); +#endif + +static struct platform_driver bq27000_battery_driver = { + .probe = bq27000_battery_probe, + .remove = bq27000_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27000_battery_suspend, + .resume = bq27000_battery_resume, +#endif + .driver = { + .name ="bq27000-bat" , + }, +}; +#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_battery_probe (struct i2c_client *client); +static int bq27200_battery_remove (struct i2c_client *client); +static int bq27200_battery_suspend (struct i2c_client *client, +pm_message_t mesg); +static int bq27200_battery_resume (struct i2c_client *client); +static struct i2c_driver bq27200_battery_driver = { + .driver = { + .name ="bq27200-bat" , + }, + .probe = bq27200_battery_probe, + .remove = bq27200_battery_remove, +#ifdef CONFIG_PM + .suspend = bq27200_battery_suspend,drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ .resume = bq27200_battery_resume, +#endif +}; +#endif + +/* +* Return the battery temperature in Celcius degrees +* Or < 0 if something fails. +*/ +static int bq27x00_battery_temperature(struct
bq27x00_device_info*di)Quoted 15 lines
drivers/power/bq27x00_battery.c new file +15
-0+{ +int ret, temp =0 ; + + ret =bq27x00_read (BQ27x00_REG_TEMP, &temp,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading temperature from the battery\n" ); +return ret; + } + +return (temp >>2 ) -273 ; +} + +/* +* Return the battery Voltage in milivolts drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+* Or < 0 if something fails. +*/ +static int bq27x00_battery_voltage(struct bq27x00_device_info *di) +{ + int ret, volt = 0; + + ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di); + if (ret) { + pr_err("BQ27x00 battery driver:" + "Error reading battery voltage from thebattery\n");
Quoted 62 lines
drivers/power/bq27x00_battery.c new file +62
-0+return ret; + } + +return volt; +} + +/* +* Return the battery average current +* Note that current can be negative signed as well +* Or 0 if something fails. +*/ +static int bq27x00_battery_current (struct bq27x00_device_info *di) +{ +int ret, curr =0 , flags =0 ; + + ret =bq27x00_read (BQ27x00_REG_AI, &curr,0 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading current from the battery\n" ); +return 0 ; + } + ret =bq27x00_read (BQ27x00_REG_FLAGS, &flags,0 , di); +if (ret <0 ) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery flags\n" ); +return 0 ; + } +if ((flags & (1 <<7 )) !=0 ) { +pr_debug ("Negative current\n" ); +return -curr; + }else { +return curr; + } +} + +/* +* Return the battery Relative State-of-Charge +* Or < 0 if something fails. +*/ +static int bq27x00_battery_rsoc (struct bq27x00_device_info *di) +{ +int ret, rsoc =0 ; + + ret =bq27x00_read (BQ27x00_REG_RSOC, &rsoc,1 , di); +if (ret) { +pr_err ("BQ27x00 battery driver:" +"Error reading battery Relative" +"State-of-Charge\n" ); +return ret; + } +return rsoc; +} + +#if defined(BATTERY_BQ27000 ) +static int bq27000_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +u8 val; + + val =w1_bq27000_read (di->w1_dev, reg); + *rt_value = val; +drivers/power/bq27x00_battery.c line 229
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+if (!b_single) { + val =0 ; + val =w1_bq27000_read (di->w1_dev, reg +1 ); + *rt_value +=HIGH_BYTE ((int ) val); + } + + return 0; +} +#else +#define bq27000_read NULLthis should be defined as 0 or an static inline int [...] { return 0; }
Quoted 23 lines
drivers/power/bq27x00_battery.c new file +23
-0+#endif + +#if defined(BATTERY_BQ27200 ) +static int bq27200_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +struct i2c_client *client = di->client; +struct i2c_msg msg[1 ]; +unsigned char data[2 ]; +int err; + +if (!client->adapter) +return -ENODEV ; + + msg->addr = client->addr; + msg->flags =0 ; + msg->len =1 ; + msg->buf = data; + + data[0 ] = reg; + err =i2c_transfer (client->adapter, msg,1 ); + +if (err >=0 ) {drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+if (!b_single) + msg->len =2 ; +else + msg->len =1 ; + + msg->flags =I2C_M_RD ; + err =i2c_transfer (client->adapter, msg,1 ); +if (err >=0 ) { +if (!b_single) + *rt_value = data[1] |
HIGH_BYTE(data[0]);Quoted 5 lines
drivers/power/bq27x00_battery.c new file +5
-0+else + *rt_value = data[0 ]; + +return 0 ; + }else {drivers/power/bq27x00_battery.c line 277
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+pr_err ("BQ27200 I2C read failed\n" ); + return err; + } + }else { +pr_err ("BQ27200 I2C write failed\n" ); +return err; + } +} +#else +#define bq27200_read NULLsame here
drivers/power/bq27x00_battery.c
Quoted 13 lines
drivers/power/bq27x00_battery.c new file +13
-0+#endif + +static int bq27x00_read (u8 reg,int *rt_value,int b_single, +struct bq27x00_device_info *di) +{ +int ret; + + ret = di->bus->read (reg, rt_value, b_single, di); +return ret; +} + +/* +* Read the battery temp, voltage, current and relative state of charge.
drivers/power/bq27x00_battery.c line 292
Quoted 2 lines
drivers/power/bq27x00_battery.c new file +2
-0+*/ +static void bq27x00_battery_read_status(struct
bq27x00_device_info*di)Quoted 54 lines
drivers/power/bq27x00_battery.c new file +54
-0+{ +if (di->update_time &&time_before (jiffies, di->update_time + +msecs_to_jiffies (cache_time))) +return ; + + di->temp_C =bq27x00_battery_temperature (di); + di->voltage_uV =bq27x00_battery_voltage (di); + di->current_uA =bq27x00_battery_current (di); + di->charge_rsoc =bq27x00_battery_rsoc (di); + + di->update_time = jiffies; + +return ; +} + +static void bq27x00_battery_work (struct delayed_work *work) +{ +struct bq27x00_device_info *di =container_of (work, + struct bq27x00_device_info, monitor_work); + +bq27x00_battery_read_status (di); +schedule_delayed_work (&di->monitor_work,100 ); +return ; +} + +#define to_bq27x00_device_info (x) container_of((x), \ + struct bq27x00_device_info, bat); + +static int bq27x00_battery_get_property (struct power_supply *psy, +enum power_supply_property psp, +union power_supply_propval *val) +{ +struct bq27x00_device_info *di =to_bq27x00_device_info (psy); + +switch (psp) { +case POWER_SUPPLY_PROP_VOLTAGE_NOW : + val->intval = di->voltage_uV; +break ; +case POWER_SUPPLY_PROP_CURRENT_NOW : + val->intval = di->current_uA; +break ; +case POWER_SUPPLY_PROP_CHARGE_NOW : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_TEMP : + val->intval = di->temp_C; +break ; +case POWER_SUPPLY_PROP_CAPACITY : + val->intval = di->charge_rsoc; +break ; +case POWER_SUPPLY_PROP_PRESENT : +if (di->voltage_uV ==0 ) + val->intval =0 ; +else drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ val->intval =1 ; +break ; +default : +return -EINVAL ; + } + +return 0 ; +} + +static void bq27x00_powersupply_init(struct
bq27x00_device_info*di)Quoted 33 lines
drivers/power/bq27x00_battery.c new file +33
-0+{ + di->bat.type =POWER_SUPPLY_TYPE_BATTERY ; + di->bat.properties = bq27x00_battery_props; + di->bat.num_properties =ARRAY_SIZE (bq27x00_battery_props); + di->bat.get_property = bq27x00_battery_get_property; + di->bat.external_power_changed =NULL ; +return ; +} + +#ifdef BATTERY_BQ27200 +static int bq27200_battery_probe (struct i2c_client *client) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +i2c_set_clientdata (client, di); + di->dev = &client->dev;drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ di->bat.name ="bq27200" ; + bus->read = &bq27200_read; + di->bus = bus; + di->client = client; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&client->dev, &di->bat); +if (retval) { + pr_err("BQ27200 battery driver: Failed toregister battery\n");
Quoted 34 lines
drivers/power/bq27x00_battery.c new file +27
-0+ goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,100 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27200_battery_remove (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27200_battery_suspend(struct i2c_client *client,
pm_message_tmesg)drivers/power/bq27x00_battery.c new file +6
-0+{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +}drivers/power/bq27x00_battery.c line 442
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ +static int bq27200_battery_resume (struct i2c_client *client) +{ +struct bq27x00_device_info *di =i2c_get_clientdata (client); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif put a comment indicating which ifdef you're closing, like:
#endif /*
CONFIG_PM*/Quoted 26 lines
drivers/power/bq27x00_battery.c new file +26
-0+ +#ifdef BATTERY_BQ27000 +static int bq27000_battery_probe (struct platform_device *pdev) +{ +struct bq27x00_device_info *di; +struct bq27x00_access_methods *bus; +int retval =0 ; + + di =kzalloc (sizeof (*di),GFP_KERNEL ); +if (!di) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate device info structure\n" ); +return -ENOMEM ; + } + + bus =kzalloc (sizeof (*bus),GFP_KERNEL ); +if (!bus) { +pr_err ("BQ27000 battery driver:" +"Failed to allocate access method structure\n" ); +kfree (di); +return -ENOMEM ; + } + +platform_set_drvdata (pdev, di); + + di->dev = &pdev->dev;drivers/power/bq27x00_battery.c
Quoted 10 lines
drivers/power/bq27x00_battery.c new file +10
-0+ di->w1_dev = pdev->dev.parent; + di->bat.name ="bq27000" ; + bus->read = &bq27000_read; + di->bus = bus; + +bq27x00_powersupply_init (di); + + retval =power_supply_register (&pdev->dev, &di->bat); +if (retval) { + pr_err("BQ27000 battery driver: Failed toregister battery\n");
Quoted 78 lines
drivers/power/bq27x00_battery.c new file +78
-0+ goto batt_failed; + } + +INIT_DELAYED_WORK (&di->monitor_work, bq27x00_battery_work); +schedule_delayed_work (&di->monitor_work,50 ); + +return 0 ; + +batt_failed: +kfree (bus); +kfree (di); +return retval; +} + +static int bq27000_battery_remove (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +flush_scheduled_work (); +power_supply_unregister (&di->bat); +platform_set_drvdata (pdev,NULL ); +kfree (di); + +return 0 ; +} + +#ifdef CONFIG_PM +static int bq27000_battery_suspend (struct platform_device *pdev, +pm_message_t state) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +cancel_delayed_work (&di->monitor_work); +return 0 ; +} + +static int bq27000_battery_resume (struct platform_device *pdev) +{ +struct bq27x00_device_info *di =platform_get_drvdata (pdev); + +schedule_delayed_work (&di->monitor_work,0 ); +return 0 ; +} +#endif +#endif + +static int __init bq27x00_battery_init (void ) +{ +int status =0 ; + +#if defined(BATTERY_BQ27000 ) + status =platform_driver_register (&bq27000_battery_driver); +if (status) +printk (KERN_ERR "Unable to register BQ27000 driver\n" ); +#endif +#if defined(BATTERY_BQ27200 ) + status =i2c_add_driver (&bq27200_battery_driver); +printk (KERN_ERR "Unable to register BQ27200 driver\n" ); +#endif +return status; +} + +static void __exit bq27x00_battery_exit(void) +{ +#if defined(BATTERY_BQ27000 ) +platform_driver_unregister (&bq27000_battery_driver); +#endif +#if defined(BATTERY_BQ27200 ) +i2c_del_driver (&bq27200_battery_driver); +#endif +} + +module_init (bq27x00_battery_init); +module_exit (bq27x00_battery_exit); + +MODULE_AUTHOR ("Texas Instruments" ); +MODULE_DESCRIPTION ("BQ27x00 battery moniter driver" ); +MODULE_LICENSE ("GPL" );Quoted 5 lines
Index: linux-omap-2.6/drivers/power/Kconfig
===================================================================
--- linux-omap-2.6.orig/drivers/power/Kconfig 2008-04-08
17:15:04.000000000 +0530
+++ linux-omap-2.6/drivers/power/Kconfig 2008-04-2108:25:00.000000000
drivers/power/bq27x00_battery.c line 55
Quoted 9 lines
+0530
drivers/power/bq27x00_battery.c new file +4
-0@@ -49,4 +49,25 @@help Say Y to enable support for the battery on the OLPC laptop. +config BATTERY_BQ27x00 + tristate "BQ27x00 battery driver" + help + SayY here to enable support for batteries withBQ27000 or BQ27200
drivers/power/bq27x00_battery.c
Quoted 9 lines
chip.
drivers/power/bq27x00_battery.c new file +8
-0+ +config BATTERY_BQ27000 + bool "BQ27000 battery driver" + depends on BATTERY_BQ27x00 + selectW1 + selectW1_SLAVE_BQ27000 + help + SayY here to enable support for batteries withBQ27000(HDQ) chip.
drivers/power/bq27x00_battery.c
Quoted 8 lines
drivers/power/bq27x00_battery.c new file +8
-0+ +config BATTERY_BQ27200 + bool "BQ27200 battery driver" + depends on BATTERY_BQ27x00 + selectI2C + selectI2C_OMAP + help + SayY here to enable support for batteries withBQ27200(I2C) chip.
Quoted 7 lines
+
endif #POWER_SUPPLY
Index: linux-omap-2.6/drivers/power/Makefile
===================================================================
--- linux-omap-2.6.orig/drivers/power/Makefile 2008-04-08
17:15:04.000000000 +0530
+++ linux-omap-2.6/drivers/power/Makefile 2008-04-2017:03:51.000000000
Quoted 9 lines
+0530
drivers/power/bq27x00_battery.c new file +1
-0@@ -20,3 +20,4 @@ obj-$ (CONFIG_BATTERY_DS2760 ) += ds2760_battery.o obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o +obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.oIndex:
linux-omap-2.6/drivers/w1/slaves/w1_bq27000.c
===================================================================
---linux-omap-2.6.orig/drivers/w1/slaves/w1_bq27000.c2008-04-08
drivers/power/bq27x00_battery.c line 62
Quoted 9 lines
17:15:05.000000000 +0530
+++linux-omap-2.6/drivers/w1/slaves/w1_bq27000.c2008-04-20
17:08:55.000000000 +0530drivers/power/bq27x00_battery.c new file +1
-1@@ -59,7 +59,7 @@int id =1 ;struct platform_device *pdev; - pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);do you really need to change the name here?
It seems that this change doesn't belong to this patch.Quoted 6 lines
drivers/power/bq27x00_battery.c new file +0
-1if (!pdev) { ret = -ENOMEM ;return ret; --To unsubscribe from this list: send the line "unsubscribe
linux-omap" in
Quoted 2 lines
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlSignature · 5 lines
Best Regards, Felipe Balbi http://felipebalbi.com [email protected]
Quoted 6 lines · Madhusudhan Chikkature Rajashekar
Hi Felipe,
Thanks for the comments. I will fix them and resend the patch.
Please note my view on the below point.
Quoted 7 lines
Quoted 5 lines
drivers/w1/slaves/w1_bq27000.c line 62
Quoted 2 lines
drivers/w1/slaves/w1_bq27000.c +1
-1- pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);do you really need to change the name here?
It seems that this change doesn't belong to this patch.I will make this as a separate patch.As BQ27000 chip is not omap
specific,
Quoted 1 line
I guess the above name is not correct. Hence I intend to make that
change.
Ok, works for me :-)
I guess bq2700-battery is ok, just remove omap- from the previous name??
Signature · 5 lines
Best Regards, Felipe Balbi http://felipebalbi.com [email protected]
Quoted 28 lines
-----Original Message-----
From: Felipe Balbi [mailto:[email protected]]
Sent: Monday, April 28, 2008 5:17 PM
To: Madhusudhan Chikkature Rajashekar
Cc: Tony Lindgren; [email protected]
Subject: RE: [RFC/PATCH] BQ27000/BQ27200 battery monitoring driver for OMAP34xxQuoted 6 lines · Madhusudhan Chikkature Rajashekar
Hi Felipe,
Thanks for the comments. I will fix them and resend the patch.
Please note my view on the below point.
Quoted 7 lines
Quoted 5 lines
drivers/w1/slaves/w1_bq27000.c line 62
Quoted 2 lines
drivers/w1/slaves/w1_bq27000.c +1
-1- pdev =platform_device_alloc ("omap-bq2700-battery" , id); + pdev =platform_device_alloc ("bq27000-bat" , id);do you really need to change the name here?
It seems that this change doesn't belong to this patch.I will make this as a separate patch.As BQ27000 chip is not omap
Quoted 8 lines
specific,
Quoted 1 line
I guess the above name is not correct. Hence I intend to make that
change.
Ok, works for me :-)
I guess bq2700-battery is ok, just remove omap- from the previous name??
Yes. I will correct the name and resend the patch. I will send this one as a separate patch and followed by it will be the battery driver patch.
Quoted 10 lines
Signature · 6 lines
-- Best Regards, Felipe Balbi http://felipebalbi.com [email protected]