From 2cba36356d6b4ae61040e4e967526c4bca4b0076 Mon Sep 17 00:00:00 2001 From: Arun Murthy Date: Mon, 5 Dec 2011 11:49:10 +0530 Subject: ab5500_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 Linux next: NA ST-Ericsson ID: 357480 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I80d6e770a57affbe7f3af0fdf82052ca1b7fe8b4 Signed-off-by: Arun Murthy Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/40903 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Srinidhi KASAGAR --- drivers/power/ab5500_fg.c | 78 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/power/ab5500_fg.c b/drivers/power/ab5500_fg.c index 0f1dc4a13df..464e4bff6e2 100644 --- a/drivers/power/ab5500_fg.c +++ b/drivers/power/ab5500_fg.c @@ -163,6 +163,7 @@ struct ab5500_fg_flags { * @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 to reset and re-initialize fuel gauge * @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 @@ -198,6 +199,7 @@ struct ab5500_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 delayed_work fg_acc_cur_work; struct mutex cc_lock; @@ -223,6 +225,8 @@ static enum power_supply_property ab5500_fg_props[] = { /* Function Prototype */ static int ab5500_fg_bat_v_trig(int mux); +static int prev_samples, prev_val; + struct ab5500_fg *ab5500_fg_get(void) { struct ab5500_fg *di; @@ -287,6 +291,29 @@ static int ab5500_fg_add_cap_sample(struct ab5500_fg *di, int sample) return avg->avg; } +/** + * ab5500_fg_clear_cap_samples() - Clear average filter + * @di: pointer to the ab5500_fg structure + * + * The capacity filter is is reset to zero. + */ +static void ab5500_fg_clear_cap_samples(struct ab5500_fg *di) +{ + int i; + struct ab5500_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; + } +} + + /** * ab5500_fg_fill_cap_sample() - Fill average filter * @di: pointer to the ab5500_fg structure @@ -446,7 +473,6 @@ static void ab5500_fg_acc_cur_timer_expired(unsigned long data) queue_delayed_work(di->fg_wq, &di->fg_acc_cur_work, 0); } -static int prev_samples, prev_val; /** * ab5500_fg_acc_cur_work() - average battery current * @work: pointer to the work_struct structure @@ -1661,6 +1687,50 @@ static void ab5500_fg_external_power_changed(struct power_supply *psy) &di->fg_psy, ab5500_fg_get_ext_psy_data); } +/** + * abab5500_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 ab5500_fg_reinit_work(struct work_struct *work) +{ + struct ab5500_fg *di = container_of(work, struct ab5500_fg, + fg_reinit_work.work); + + if (di->flags.calibrate == false) { + dev_dbg(di->dev, "Resetting FG state machine to init.\n"); + ab5500_fg_clear_cap_samples(di); + ab5500_fg_calc_cap_discharge_voltage(di, true); + ab5500_fg_charge_state_to(di, AB5500_FG_CHARGE_INIT); + ab5500_fg_discharge_state_to(di, AB5500_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)); + } +} + +/** + * ab5500_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 ab5500_fg_reinit(void) +{ + struct ab5500_fg *di = ab5500_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); +} + #if defined(CONFIG_PM) static int ab5500_fg_resume(struct platform_device *pdev) { @@ -1789,6 +1859,10 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) INIT_DELAYED_WORK_DEFERRABLE(&di->fg_acc_cur_work, ab5500_fg_acc_cur_work); + /* Init work for reinitialising the fg algorithm */ + INIT_DELAYED_WORK_DEFERRABLE(&di->fg_reinit_work, + ab5500_fg_reinit_work); + /* Work delayed Queue to run the state machine */ INIT_DELAYED_WORK_DEFERRABLE(&di->fg_periodic_work, ab5500_fg_periodic_work); @@ -1823,7 +1897,7 @@ static int __devinit ab5500_fg_probe(struct platform_device *pdev) init_timer(&di->avg_current_timer); di->avg_current_timer.function = ab5500_fg_acc_cur_timer_expired; di->avg_current_timer.data = (unsigned long) di; - di->avg_current_timer.expires = 60 * HZ;; + di->avg_current_timer.expires = 60 * HZ; if (!timer_pending(&di->avg_current_timer)) add_timer(&di->avg_current_timer); else -- cgit v1.2.3