diff options
author | Kalle Komierowski <karl.komierowski@stericsson.com> | 2011-08-25 11:16:07 +0200 |
---|---|---|
committer | Bibek BASU <bibek.basu@stericsson.com> | 2011-09-22 12:30:51 +0200 |
commit | 3c2357fb81f2c93d6386a9c9d31e4868a1187436 (patch) | |
tree | 8b21eeaed4ba04ceab3efaa9cfada3aad722c964 | |
parent | bca54fab636b5187669048b5ce2f15ed1e4c5812 (diff) |
power: ab8500_bm: Add interface to reinit FG algorithm
A function has been added to enable reinitialisation of the
fuel gauge algorithm. This can be used to to reinitialise with
a different battery voltage at start-up, for verification reasons.
ST-Ericsson ID: 357480
ST-Ericsson Linux next: Not tested
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I1ba9775e3c26f49fe746e56c01dce0d5ba8384b3
Signed-off-by: Kalle Komierowski <karl.komierowski@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31676
Reviewed-by: Bibek BASU <bibek.basu@stericsson.com>
Tested-by: Bibek BASU <bibek.basu@stericsson.com>
-rw-r--r-- | drivers/power/ab8500_fg.c | 81 | ||||
-rw-r--r-- | include/linux/mfd/ab8500/bm.h | 4 |
2 files changed, 79 insertions, 6 deletions
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 62b4adae0a6..ce7d9606667 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -175,6 +175,7 @@ struct inst_curr_result_list { * @fg_wq: Work queue for running the FG algorithm * @fg_periodic_work: Work to run the FG algorithm periodically * @fg_low_bat_work: Work to check low bat condition + * @fg_reinit_work Work used to reset and reinitialise the FG algorithm * @fg_work: Work to run the FG algorithm instantly * @fg_acc_cur_work: Work to read the FG accumulator * @cc_lock: Mutex for locking the CC @@ -223,6 +224,7 @@ struct ab8500_fg { struct workqueue_struct *fg_wq; struct delayed_work fg_periodic_work; struct delayed_work fg_low_bat_work; + struct delayed_work fg_reinit_work; struct work_struct fg_work; struct work_struct fg_acc_cur_work; struct mutex cc_lock; @@ -404,6 +406,28 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample) } /** + * ab8500_fg_clear_cap_samples() - Clear average filter + * @di: pointer to the ab8500_fg structure + * + * The capacity filter is is reset to zero. + */ +static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di) +{ + int i; + struct ab8500_fg_avg_cap *avg = &di->avg_cap; + + avg->pos = 0; + avg->nbr_samples = 0; + avg->sum = 0; + avg->avg = 0; + + for (i = 0; i < NBR_AVG_SAMPLES; i++) { + avg->samples[i] = 0; + avg->time_stamps[i] = 0; + } +} + +/** * ab8500_fg_fill_cap_sample() - Fill average filter * @di: pointer to the ab8500_fg structure * @sample: the capacity in mAh to fill the filter with @@ -752,8 +776,7 @@ exit: dev_err(di->dev, "Failed to read or write gas gauge registers\n"); mutex_unlock(&di->cc_lock); - queue_work(di->fg_wq, - &di->fg_work); + queue_work(di->fg_wq, &di->fg_work); } /** @@ -1332,8 +1355,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) AB8500_FG_DISCHARGE_RECOVERY); queue_delayed_work(di->fg_wq, - &di->fg_periodic_work, - 0); + &di->fg_periodic_work, 0); break; } @@ -1860,6 +1882,50 @@ static void ab8500_fg_external_power_changed(struct power_supply *psy) &di->fg_psy, ab8500_fg_get_ext_psy_data); } +/** + * abab8500_fg_reinit_work() - work to reset the FG algorithm + * @work: pointer to the work_struct structure + * + * Used to reset the current battery capacity to be able to + * retrigger a new voltage base capacity calculation. For + * test and verification purpose. + */ +static void ab8500_fg_reinit_work(struct work_struct *work) +{ + struct ab8500_fg *di = container_of(work, struct ab8500_fg, + fg_reinit_work.work); + + if (di->flags.calibrate == false) { + dev_dbg(di->dev, "Resetting FG state machine to init.\n"); + ab8500_fg_clear_cap_samples(di); + ab8500_fg_calc_cap_discharge_voltage(di, true); + ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); + ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + } else { + dev_err(di->dev, "Residual offset calibration ongoing " + "retrying..\n"); + /* Wait one second until next try*/ + queue_delayed_work(di->fg_wq, &di->fg_reinit_work, + round_jiffies(1)); + } +} + +/** + * ab8500_fg_reinit() - forces FG algorithm to reinitialize with current values + * + * This function can be used to force the FG algorithm to recalculate a new + * voltage based battery capacity. + */ +void ab8500_fg_reinit(void) +{ + struct ab8500_fg *di = ab8500_fg_get(); + /* User won't be notified if a null pointer returned. */ + if (di != NULL) + queue_delayed_work(di->fg_wq, &di->fg_reinit_work, 0); +} + /* Exposure to the sysfs interface */ struct ab8500_fg_sysfs_entry { @@ -1887,7 +1953,6 @@ static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf, di->bat_cap.max_mah = (int) charge_full; ret = count; } - return ret; } static struct ab8500_fg_sysfs_entry charge_full_attr = @@ -1907,7 +1972,6 @@ ab8500_fg_show(struct kobject *kobj, struct attribute *attr, char *buf) return entry->show(di, buf); } - static ssize_t ab8500_fg_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) @@ -2134,6 +2198,10 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) /* Init work for getting the battery accumulated current */ INIT_WORK(&di->fg_acc_cur_work, ab8500_fg_acc_cur_work); + /* Init work for reinitialising the fg algorithm */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_reinit_work, + ab8500_fg_reinit_work); + /* Work delayed Queue to run the state machine */ INIT_DELAYED_WORK_DEFERRABLE(&di->fg_periodic_work, ab8500_fg_periodic_work); @@ -2189,6 +2257,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) /* Calibrate the fg first time */ di->flags.calibrate = true; di->calib_state = AB8500_FG_CALIB_INIT; + /* Run the FG algorithm */ queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); diff --git a/include/linux/mfd/ab8500/bm.h b/include/linux/mfd/ab8500/bm.h index 0bd8703b2bd..1fb67d25deb 100644 --- a/include/linux/mfd/ab8500/bm.h +++ b/include/linux/mfd/ab8500/bm.h @@ -474,6 +474,7 @@ struct ab8500_btemp; struct ab8500_gpadc; struct ab8500_fg; #ifdef CONFIG_AB8500_BM +void ab8500_fg_reinit(void); void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA); struct ab8500_btemp *ab8500_btemp_get(void); int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp); @@ -481,6 +482,9 @@ struct ab8500_fg *ab8500_fg_get(void); int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev); int ab8500_fg_inst_curr_nonblocking(struct ab8500_fg *dev, int *local_result); #else +static void ab8500_fg_reinit(void) +{ +} static void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA) { } |