Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: supply: rk817: Update battery capacity calibration

The battery capacity calibration function continues to be a source of
bugs for end users, especially when coming out of suspend. This occurs
when the device has incorrect readings for voltage, and causes the
current code to set fully charged capacity incorrectly.

Add checks to ensure we don't attempt a capacity calibration when we
have invalid voltage values or no battery present, and remove the code
that attempts to automatically set the fully charged capacity in lieu of
making the value writeable. This way userspace is able to adjust the
fully charged capacity for a degraded battery.

Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Link: https://lore.kernel.org/r/20240926144346.94630-3-macroalpha82@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Chris Morgan and committed by
Sebastian Reichel
1e5335d0 bded860c

+55 -46
+55 -46
drivers/power/supply/rk817_charger.c
··· 240 240 static int rk817_bat_calib_cap(struct rk817_charger *charger) 241 241 { 242 242 struct rk808 *rk808 = charger->rk808; 243 - int tmp, charge_now, charge_now_adc, volt_avg; 243 + int charge_now, charge_now_adc; 244 244 u8 bulk_reg[4]; 245 + 246 + /* Don't do anything if there's no battery. */ 247 + if (!charger->battery_present) 248 + return 0; 249 + 250 + /* 251 + * When resuming from suspend, sometimes the voltage value would be 252 + * incorrect. BSP would simply wait two seconds and try reading the 253 + * values again. Do not do any sort of calibration activity when the 254 + * reported value is incorrect. The next scheduled update of battery 255 + * vaules should then return valid data and the driver can continue. 256 + * Use 2.7v as the sanity value because per the datasheet the PMIC 257 + * can in no way support a battery voltage lower than this. BSP only 258 + * checked for values too low, but I'm adding in a check for values 259 + * too high just in case; again the PMIC can in no way support 260 + * voltages above 4.45v, so this seems like a good value. 261 + */ 262 + if ((charger->volt_avg_uv < 2700000) || (charger->volt_avg_uv > 4450000)) { 263 + dev_dbg(charger->dev, 264 + "Battery voltage of %d is invalid, ignoring.\n", 265 + charger->volt_avg_uv); 266 + return -EINVAL; 267 + } 245 268 246 269 /* Calibrate the soc and fcc on a fully charged battery */ 247 270 ··· 326 303 bulk_reg, 4); 327 304 } 328 305 } 329 - 330 - /* 331 - * Calibrate the fully charged capacity when we previously had a full 332 - * battery (soc_cal = 1) and are now empty (at or below minimum design 333 - * voltage). If our columb counter is still positive, subtract that 334 - * from our fcc value to get a calibrated fcc, and if our columb 335 - * counter is negative add that to our fcc (but not to exceed our 336 - * design capacity). 337 - */ 338 - regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H, 339 - bulk_reg, 2); 340 - tmp = get_unaligned_be16(bulk_reg); 341 - volt_avg = (charger->voltage_k * tmp) + 1000 * charger->voltage_b; 342 - if (volt_avg <= charger->bat_voltage_min_design_uv && 343 - charger->soc_cal) { 344 - regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3, 345 - bulk_reg, 4); 346 - charge_now_adc = get_unaligned_be32(bulk_reg); 347 - charge_now = ADC_TO_CHARGE_UAH(charge_now_adc, 348 - charger->res_div); 349 - /* 350 - * Note, if charge_now is negative this will add it (what we 351 - * want) and if it's positive this will subtract (also what 352 - * we want). 353 - */ 354 - charger->fcc_mah = charger->fcc_mah - (charge_now / 1000); 355 - 356 - dev_dbg(charger->dev, 357 - "Recalibrating full charge capacity to %d uah\n", 358 - charger->fcc_mah * 1000); 359 - } 360 - 361 - /* 362 - * Set the SOC to 0 if we are below the minimum system voltage. 363 - */ 364 - if (volt_avg <= charger->bat_voltage_min_design_uv) { 365 - charger->soc = 0; 366 - charge_now_adc = CHARGE_TO_ADC(0, charger->res_div); 367 - put_unaligned_be32(charge_now_adc, bulk_reg); 368 - regmap_bulk_write(rk808->regmap, 369 - RK817_GAS_GAUGE_Q_INIT_H3, bulk_reg, 4); 370 - dev_warn(charger->dev, 371 - "Battery voltage %d below minimum voltage %d\n", 372 - volt_avg, charger->bat_voltage_min_design_uv); 373 - } 374 306 375 307 rk817_record_battery_nvram_values(charger); 376 308 ··· 626 648 return IRQ_HANDLED; 627 649 } 628 650 651 + static int rk817_bat_set_prop(struct power_supply *ps, 652 + enum power_supply_property prop, 653 + const union power_supply_propval *val) 654 + { 655 + struct rk817_charger *charger = power_supply_get_drvdata(ps); 656 + 657 + switch (prop) { 658 + case POWER_SUPPLY_PROP_CHARGE_FULL: 659 + if ((val->intval < 500000) || 660 + (val->intval > charger->bat_charge_full_design_uah)) 661 + return -EINVAL; 662 + charger->fcc_mah = val->intval / 1000; 663 + return rk817_bat_calib_cap(charger); 664 + default: 665 + return -EINVAL; 666 + } 667 + } 668 + 629 669 static enum power_supply_property rk817_bat_props[] = { 630 670 POWER_SUPPLY_PROP_PRESENT, 631 671 POWER_SUPPLY_PROP_STATUS, ··· 669 673 POWER_SUPPLY_PROP_VOLTAGE_AVG, 670 674 }; 671 675 676 + static int rk817_bat_prop_writeable(struct power_supply *psy, 677 + enum power_supply_property psp) 678 + { 679 + switch (psp) { 680 + case POWER_SUPPLY_PROP_CHARGE_FULL: 681 + return 1; 682 + default: 683 + return 0; 684 + } 685 + } 686 + 672 687 static const struct power_supply_desc rk817_bat_desc = { 673 688 .name = "rk817-battery", 674 689 .type = POWER_SUPPLY_TYPE_BATTERY, 675 690 .properties = rk817_bat_props, 691 + .property_is_writeable = rk817_bat_prop_writeable, 676 692 .num_properties = ARRAY_SIZE(rk817_bat_props), 677 693 .get_property = rk817_bat_get_prop, 694 + .set_property = rk817_bat_set_prop, 678 695 }; 679 696 680 697 static const struct power_supply_desc rk817_chg_desc = {