power: supply: rk817_battery: Smooth charging/discharging curves

Retain the remainder of the smoothing coefficient calculation
for use in the next iteration to ensure continuity.

Change-Id: Iea5769149a9df4d294a721e43df7c2e6583a8e4f
Signed-off-by: Shengfei Xu <xsf@rock-chips.com>
This commit is contained in:
Shengfei Xu
2025-05-15 15:37:59 +08:00
committed by Tao Huang
parent fedcfc9334
commit cefe8cd2e3

View File

@@ -44,7 +44,6 @@ module_param_named(dbg_level, dbg_enable, int, 0644);
#define BAT_INFO(fmt, args...) pr_info(fmt, ##args)
#define DRIVER_VERSION "1.10"
#define SFT_SET_KB 1
#define DIV(x) ((x) ? (x) : 1)
#define ENABLE 0x01
@@ -74,7 +73,7 @@ module_param_named(dbg_level, dbg_enable, int, 0644);
(adc_value / 1000 * 1720 / 3600 / samp_res)
/* Adjust full capacity to a reduced value */
#define UPDATE_REDUCE_FCC(fcc) ((fcc) * 995 / 1000)
#define UPDATE_REDUCE_FCC(fcc) ((fcc) * 990 / 1000)
/* Raise the maximum capacity value */
#define UPDATE_RAISE_FCC(fcc) ((fcc) * 1005 / 1000)
/* Effective full capacity */
@@ -474,6 +473,7 @@ struct battery_platform_data {
int charge_stay_awake;
int contact_res;
int get_contact_res_by_soft;
int nominal_voltage;
};
struct rk817_battery_device {
@@ -530,6 +530,10 @@ struct rk817_battery_device {
int sm_remain_cap;
int delta_cap_remainder;
int sm_linek;
int charger_ramainder1;
int charger_ramainder2;
int discharger_ramainder1;
int discharger_ramainder2;
int smooth_soc;
unsigned long sleep_dischrg_sec;
unsigned long sleep_sum_sec;
@@ -1805,14 +1809,20 @@ static u8 is_rk817_bat_initialized(struct rk817_battery_device *battery)
static void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery)
{
long expected_voltage = 0, expected_res2voltage;
int linek, linek_step1, linek_step2;
bool is_discharging;
int nominal_voltage;
int expected_rsoc;
int current_avg;
int soc2vol;
int status;
int linek;
status = rk817_bat_get_charge_status(battery);
current_avg = rk817_bat_get_avg_current(battery);
soc2vol = rk817_bat_soc2vol(battery, battery->rsoc);
is_discharging = (status == CHRG_OFF) || ((status == CC_OR_CV_CHRG) && (current_avg < 0)) ||
((status == CHARGE_FINISH) && (current_avg < FINISH_CURR_THRESD));
if (soc2vol > battery->voltage_avg)
expected_voltage = battery->pdata->pwroff_vol +
soc2vol * (soc2vol - battery->voltage_avg) / battery->pdata->pwroff_vol;
@@ -1832,18 +1842,50 @@ static void rk817_bat_calc_sm_linek(struct rk817_battery_device *battery)
DBG("expected_voltage: %ld, RSOC: %d expected_rsoc: %d delta_rsoc: %d\n",
expected_voltage, battery->rsoc, expected_rsoc, battery->delta_rsoc);
if (battery->pdata->nominal_voltage != 0)
nominal_voltage = battery->pdata->nominal_voltage;
else
nominal_voltage = soc2vol;
status = rk817_bat_get_charge_status(battery);
if ((status == CHRG_OFF) || ((status == CC_OR_CV_CHRG) && (current_avg < 0)) ||
((status == CHARGE_FINISH) && (current_avg < FINISH_CURR_THRESD))) {
DBG("nominal_voltage: %d, pdata->nominal_voltage: %d soc2vol: %d\n",
nominal_voltage, battery->pdata->nominal_voltage, soc2vol);
if (is_discharging) {
/* When the discharge current is less than 30A and the charging IC reports a
* full charge status, the system will determine that the current operation is
*in discharge mode.
*/
linek = -(MAX_PERCENTAGE - battery->rsoc + battery->dsoc) * 1000;
linek /= (MAX_PERCENTAGE - battery->delta_rsoc);
linek_step1 = -(MAX_PERCENTAGE - battery->rsoc + battery->dsoc) * 1000;
linek_step2 = (linek_step1 + battery->discharger_ramainder1) / (MAX_PERCENTAGE - battery->delta_rsoc);
battery->discharger_ramainder1 = (linek_step1 + battery->discharger_ramainder1) % (MAX_PERCENTAGE - battery->delta_rsoc);
DBG("discharge: ocv_voltage %d linek_step1: %d linek_step2: %d: discharger_ramainder1: %d\n",
soc2vol, linek_step1, linek_step2, battery->discharger_ramainder1);
linek_step2 *= soc2vol;
linek = (linek_step2 + battery->discharger_ramainder2) / DIV(nominal_voltage);
DBG("discharge: (linek_step2 + battery->discharger_ramainder2): %d, linek_step1: %d, linek_step2: %d, linek: %d\n",
(linek_step2 + battery->discharger_ramainder2), linek_step1, linek_step2, linek);
battery->discharger_ramainder2 = (linek_step2 + battery->discharger_ramainder2) % DIV(nominal_voltage);
DBG("discharge: ocv_voltage %d linek_step2: %d linek: %d: discharger_ramainder2: %d\n",
soc2vol, linek_step2, linek, battery->discharger_ramainder2);
battery->charger_ramainder1 = 0;
battery->charger_ramainder2 = 0;
} else {
linek = MAX_PERCENTAGE * 1000 / (MAX_PERCENTAGE - battery->rsoc + battery->dsoc);
linek_step1 = (battery->charger_ramainder1 + MAX_PERCENTAGE * 1000) / (battery->fake_full_soc + battery->dsoc - battery->rsoc);
battery->charger_ramainder1 = (battery->charger_ramainder1 + MAX_PERCENTAGE * 1000) % (battery->fake_full_soc + battery->dsoc - battery->rsoc);
DBG("charge: ocv_voltage %d linek: %d: charger_ramainder1: %d: fake_full_soc: %d\n",
soc2vol, linek_step1, battery->charger_ramainder1, battery->fake_full_soc);
linek_step1 *= soc2vol;
linek = (linek_step1 + battery->charger_ramainder2) / DIV(nominal_voltage);
battery->charger_ramainder2 = (linek_step1 + battery->charger_ramainder2) % DIV(nominal_voltage);
DBG("charge: ocv_voltage %d linek_step1: %d linek: %d: charger_ramainder2: %d: fake_full_soc: %d\n",
soc2vol, linek_step1, linek, battery->charger_ramainder2, battery->fake_full_soc);
DBG("charge: ocv_voltage %d linek: %d\n", soc2vol, linek);
battery->discharger_ramainder1 = 0;
battery->discharger_ramainder2 = 0;
}
DBG("expected_voltage %ld expected_rsoc: %d\n", expected_voltage, expected_rsoc);
DBG("ocv_voltage %d sd_ocv_voltage: %ld, linek: %d\n", soc2vol, expected_voltage, linek);
@@ -2251,10 +2293,18 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery)
if (ret < 0)
dev_info(dev, "fake_full_soc missing!\n");
else {
if ((pdata->fake_full_soc > 100) || (pdata->fake_full_soc < 0))
if ((pdata->fake_full_soc > 100) || (pdata->fake_full_soc < 89))
pdata->fake_full_soc = 100;
}
ret = of_property_read_u32(np, "nominal_voltage", &pdata->nominal_voltage);
if (ret < 0) {
dev_info(dev, "nominal_voltage missing!\n");
} else {
if ((pdata->nominal_voltage > 4500) || (pdata->nominal_voltage < 3600))
pdata->nominal_voltage = 0;
}
if (battery->chip_id == RK809_ID) {
ret = of_property_read_u32(np, "bat_res_up",
&pdata->bat_res_up);