Skip to content

Commit 5806652

Browse files
Yuanjiang Yusre
authored andcommitted
power: supply: sc27xx: Optimize the battery capacity calibration
This patch factors out the capacity calibration into one single function to calibrate the battery capacity, and adding more abnormal cases to calibrate the capacity when the OCV value is not matchable with current capacity. Moreover we also allow to calibrate the capacity when charger magager tries to get current capacity to make sure we give a correct capacity for userspace. Signed-off-by: Yuanjiang Yu <[email protected]> Signed-off-by: Baolin Wang <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent ff062d0 commit 5806652

File tree

1 file changed

+92
-35
lines changed

1 file changed

+92
-35
lines changed

drivers/power/supply/sc27xx_fuel_gauge.c

Lines changed: 92 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ struct sc27xx_fgu_data {
109109
};
110110

111111
static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity);
112+
static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data,
113+
int cap, bool int_mode);
112114

113115
static const char * const sc27xx_charger_supply_name[] = {
114116
"sc2731_charger",
@@ -389,6 +391,9 @@ static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap)
389391
delta_cap = DIV_ROUND_CLOSEST(temp * 100, data->total_cap);
390392
*cap = delta_cap + data->init_cap;
391393

394+
/* Calibrate the battery capacity in a normal range. */
395+
sc27xx_fgu_capacity_calibration(data, *cap, false);
396+
392397
return 0;
393398
}
394399

@@ -661,50 +666,62 @@ static const struct power_supply_desc sc27xx_fgu_desc = {
661666

662667
static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap)
663668
{
669+
int ret;
670+
664671
data->init_cap = cap;
665-
data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, data->init_cap);
672+
ret = sc27xx_fgu_get_clbcnt(data, &data->init_clbcnt);
673+
if (ret)
674+
dev_err(data->dev, "failed to get init coulomb counter\n");
666675
}
667676

668-
static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
677+
static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data,
678+
int cap, bool int_mode)
669679
{
670-
struct sc27xx_fgu_data *data = dev_id;
671-
int ret, cap, ocv, adc;
672-
u32 status;
673-
674-
mutex_lock(&data->lock);
680+
int ret, ocv, chg_sts, adc;
675681

676-
ret = regmap_read(data->regmap, data->base + SC27XX_FGU_INT_STS,
677-
&status);
678-
if (ret)
679-
goto out;
682+
ret = sc27xx_fgu_get_vbat_ocv(data, &ocv);
683+
if (ret) {
684+
dev_err(data->dev, "get battery ocv error.\n");
685+
return;
686+
}
680687

681-
ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR,
682-
status, status);
683-
if (ret)
684-
goto out;
688+
ret = sc27xx_fgu_get_status(data, &chg_sts);
689+
if (ret) {
690+
dev_err(data->dev, "get charger status error.\n");
691+
return;
692+
}
685693

686694
/*
687-
* When low overload voltage interrupt happens, we should calibrate the
688-
* battery capacity in lower voltage stage.
695+
* If we are in charging mode, then we do not need to calibrate the
696+
* lower capacity.
689697
*/
690-
if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT))
691-
goto out;
698+
if (chg_sts == POWER_SUPPLY_STATUS_CHARGING)
699+
return;
692700

693-
ret = sc27xx_fgu_get_capacity(data, &cap);
694-
if (ret)
695-
goto out;
696-
697-
ret = sc27xx_fgu_get_vbat_ocv(data, &ocv);
698-
if (ret)
699-
goto out;
700-
701-
/*
702-
* If current OCV value is less than the minimum OCV value in OCV table,
703-
* which means now battery capacity is 0%, and we should adjust the
704-
* inititial capacity to 0.
705-
*/
706-
if (ocv <= data->cap_table[data->table_len - 1].ocv) {
701+
if ((ocv > data->cap_table[0].ocv && cap < 100) || cap > 100) {
702+
/*
703+
* If current OCV value is larger than the max OCV value in
704+
* OCV table, or the current capacity is larger than 100,
705+
* we should force the inititial capacity to 100.
706+
*/
707+
sc27xx_fgu_adjust_cap(data, 100);
708+
} else if (ocv <= data->cap_table[data->table_len - 1].ocv) {
709+
/*
710+
* If current OCV value is leass than the minimum OCV value in
711+
* OCV table, we should force the inititial capacity to 0.
712+
*/
707713
sc27xx_fgu_adjust_cap(data, 0);
714+
} else if ((ocv > data->cap_table[data->table_len - 1].ocv && cap <= 0) ||
715+
(ocv > data->min_volt && cap <= data->alarm_cap)) {
716+
/*
717+
* If current OCV value is not matchable with current capacity,
718+
* we should re-calculate current capacity by looking up the
719+
* OCV table.
720+
*/
721+
int cur_cap = power_supply_ocv2cap_simple(data->cap_table,
722+
data->table_len, ocv);
723+
724+
sc27xx_fgu_adjust_cap(data, cur_cap);
708725
} else if (ocv <= data->min_volt) {
709726
/*
710727
* If current OCV value is less than the low alarm voltage, but
@@ -713,7 +730,7 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
713730
*/
714731
if (cap > data->alarm_cap) {
715732
sc27xx_fgu_adjust_cap(data, data->alarm_cap);
716-
} else if (cap <= 0) {
733+
} else {
717734
int cur_cap;
718735

719736
/*
@@ -728,15 +745,55 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
728745
sc27xx_fgu_adjust_cap(data, cur_cap);
729746
}
730747

748+
if (!int_mode)
749+
return;
750+
731751
/*
732752
* After adjusting the battery capacity, we should set the
733753
* lowest alarm voltage instead.
734754
*/
735755
data->min_volt = data->cap_table[data->table_len - 1].ocv;
756+
data->alarm_cap = power_supply_ocv2cap_simple(data->cap_table,
757+
data->table_len,
758+
data->min_volt);
759+
736760
adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000);
737-
regmap_update_bits(data->regmap, data->base + SC27XX_FGU_LOW_OVERLOAD,
761+
regmap_update_bits(data->regmap,
762+
data->base + SC27XX_FGU_LOW_OVERLOAD,
738763
SC27XX_FGU_LOW_OVERLOAD_MASK, adc);
739764
}
765+
}
766+
767+
static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id)
768+
{
769+
struct sc27xx_fgu_data *data = dev_id;
770+
int ret, cap;
771+
u32 status;
772+
773+
mutex_lock(&data->lock);
774+
775+
ret = regmap_read(data->regmap, data->base + SC27XX_FGU_INT_STS,
776+
&status);
777+
if (ret)
778+
goto out;
779+
780+
ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR,
781+
status, status);
782+
if (ret)
783+
goto out;
784+
785+
/*
786+
* When low overload voltage interrupt happens, we should calibrate the
787+
* battery capacity in lower voltage stage.
788+
*/
789+
if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT))
790+
goto out;
791+
792+
ret = sc27xx_fgu_get_capacity(data, &cap);
793+
if (ret)
794+
goto out;
795+
796+
sc27xx_fgu_capacity_calibration(data, cap, true);
740797

741798
out:
742799
mutex_unlock(&data->lock);

0 commit comments

Comments
 (0)