summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorPritesh Raithatha <praithatha@nvidia.com>2011-12-28 19:21:44 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2012-01-04 11:44:26 +0530
commitd42874773d71b8f71225adba714f6d12ccacd31f (patch)
tree483f4823179afc414bdfa61b46e48c5b525c8c98 /drivers/power
parentc2f7bb5e2296f227d4fe0afcf71d8ce1bfca6ee8 (diff)
power: bq27x00: add charging status update delay
bq27x00 takes 3 to 4 second to update charging/discharging status so it requires to schedule work after 4 second on external powersupply change. Bug 902678 Change-Id: Ic5b42804ee3cd98ffab762c042bad447934eba85 Signed-off-by: Pritesh Raithatha <praithatha@nvidia.com> Reviewed-on: http://git-master/r/72411 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/bq27x00_battery.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index fc2923dc03d6..e392f4dc77de 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -78,6 +78,8 @@
#define BQ27510_CNTL_SET_SLEEP 0x0013
#define BQ27510_CNTL_CLEAR_SLEEP 0x0014
+/* bq27x00 requires 3 to 4 second to update charging status */
+#define CHARGING_STATUS_UPDATE_DELAY_SECS 4
struct bq27x00_device_info;
struct bq27x00_access_methods {
@@ -113,12 +115,14 @@ struct bq27x00_device_info {
unsigned long last_update;
struct delayed_work work;
+ struct delayed_work external_power_changed_work;
struct power_supply bat;
struct bq27x00_access_methods bus;
struct mutex lock;
+ struct mutex update_lock;
};
static enum power_supply_property bq27x00_battery_props[] = {
@@ -319,6 +323,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
struct bq27x00_reg_cache cache = {0, };
bool is_bq27500 = (di->chip == BQ27500 || di->chip == BQ27510);
+ mutex_lock(&di->update_lock);
cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
if (cache.flags >= 0) {
cache.capacity = bq27x00_battery_read_rsoc(di);
@@ -345,6 +350,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)
}
di->last_update = jiffies;
+ mutex_unlock(&di->update_lock);
}
static void bq27x00_battery_poll(struct work_struct *work)
@@ -361,6 +367,14 @@ static void bq27x00_battery_poll(struct work_struct *work)
}
}
+static void bq27x00_external_power_changed_work(struct work_struct *work)
+{
+ struct bq27x00_device_info *di =
+ container_of(work, struct bq27x00_device_info,
+ external_power_changed_work.work);
+
+ bq27x00_update(di);
+}
/*
* Return the battery temperature in tenths of degree Celsius
@@ -631,12 +645,19 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
return ret;
}
+static unsigned int charging_update_delay_secs =
+ CHARGING_STATUS_UPDATE_DELAY_SECS;
+module_param(charging_update_delay_secs, uint, 0644);
+MODULE_PARM_DESC(charging_update_delay_secs, "battery charging " \
+ "status update delay in seconds");
+
static void bq27x00_external_power_changed(struct power_supply *psy)
{
struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
- cancel_delayed_work_sync(&di->work);
- schedule_delayed_work(&di->work, 0);
+ cancel_delayed_work_sync(&di->external_power_changed_work);
+ schedule_delayed_work(&di->external_power_changed_work,
+ charging_update_delay_secs * HZ);
}
static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
@@ -650,7 +671,10 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
di->bat.external_power_changed = bq27x00_external_power_changed;
INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
+ INIT_DELAYED_WORK(&di->external_power_changed_work,
+ bq27x00_external_power_changed_work);
mutex_init(&di->lock);
+ mutex_init(&di->update_lock);
ret = power_supply_register(di->dev, &di->bat);
if (ret) {
@@ -668,10 +692,11 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
{
cancel_delayed_work_sync(&di->work);
-
+ cancel_delayed_work_sync(&di->external_power_changed_work);
power_supply_unregister(&di->bat);
mutex_destroy(&di->lock);
+ mutex_destroy(&di->update_lock);
}