summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalle Komierowski <karl.komierowski@stericsson.com>2011-08-25 11:16:07 +0200
committerBibek BASU <bibek.basu@stericsson.com>2011-09-22 12:30:51 +0200
commit3c2357fb81f2c93d6386a9c9d31e4868a1187436 (patch)
tree8b21eeaed4ba04ceab3efaa9cfada3aad722c964
parentbca54fab636b5187669048b5ce2f15ed1e4c5812 (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.c81
-rw-r--r--include/linux/mfd/ab8500/bm.h4
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)
{
}