power: supply: adc-battery-helper: Add support for optional charge_finished GPIO

Charger ICs often have a status pin which indicates when the charger has
finished charging the battery. Sometimes the status of this pin can be
read over a GPIO.

Add support for optionally reading a charge-finished GPIO and when
available use this to determine when to return POWER_SUPPLY_STATUS_FULL.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Hans de Goede <hansg@kernel.org>
Link: https://lore.kernel.org/r/20250831122942.47875-5-hansg@kernel.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
Hans de Goede
2025-08-31 14:29:40 +02:00
committed by Sebastian Reichel
parent eede3f72a9
commit 926b144366
3 changed files with 20 additions and 5 deletions

View File

@@ -51,6 +51,7 @@
#include <linux/cleanup.h>
#include <linux/devm-helpers.h>
#include <linux/gpio/consumer.h>
#include <linux/mutex.h>
#include <linux/power_supply.h>
#include <linux/workqueue.h>
@@ -82,8 +83,17 @@ static int adc_battery_helper_get_status(struct adc_battery_helper *help)
if (help->curr_ua < -CURR_HYST_UA)
return POWER_SUPPLY_STATUS_DISCHARGING;
if (help->supplied && help->ocv_avg_uv > full_uv)
return POWER_SUPPLY_STATUS_FULL;
if (help->supplied) {
bool full;
if (help->charge_finished)
full = gpiod_get_value_cansleep(help->charge_finished);
else
full = help->ocv_avg_uv > full_uv;
if (full)
return POWER_SUPPLY_STATUS_FULL;
}
return POWER_SUPPLY_STATUS_NOT_CHARGING;
}
@@ -255,13 +265,15 @@ static void adc_battery_helper_start_work(struct adc_battery_helper *help)
}
int adc_battery_helper_init(struct adc_battery_helper *help, struct power_supply *psy,
adc_battery_helper_get_func get_voltage_and_current_now)
adc_battery_helper_get_func get_voltage_and_current_now,
struct gpio_desc *charge_finished_gpio)
{
struct device *dev = psy->dev.parent;
int ret;
help->psy = psy;
help->get_voltage_and_current_now = get_voltage_and_current_now;
help->charge_finished = charge_finished_gpio;
ret = devm_mutex_init(dev, &help->lock);
if (ret)

View File

@@ -11,6 +11,7 @@
#define ADC_BAT_HELPER_MOV_AVG_WINDOW_SIZE 8
struct power_supply;
struct gpio_desc;
/*
* The adc battery helper code needs voltage- and current-now to be sampled as
@@ -21,6 +22,7 @@ typedef int (*adc_battery_helper_get_func)(struct power_supply *psy, int *volt,
struct adc_battery_helper {
struct power_supply *psy;
struct gpio_desc *charge_finished;
struct delayed_work work;
struct mutex lock;
adc_battery_helper_get_func get_voltage_and_current_now;
@@ -44,7 +46,8 @@ extern const enum power_supply_property adc_battery_helper_properties[];
#define ADC_HELPER_NUM_PROPERTIES 7
int adc_battery_helper_init(struct adc_battery_helper *help, struct power_supply *psy,
adc_battery_helper_get_func get_voltage_and_current_now);
adc_battery_helper_get_func get_voltage_and_current_now,
struct gpio_desc *charge_finished_gpio);
/*
* The below functions can be directly used as power-supply / suspend-resume
* callbacks. They cast the power_supply_get_drvdata() / dev_get_drvdata() data

View File

@@ -161,7 +161,7 @@ static int ug3105_probe(struct i2c_client *client)
}
ret = adc_battery_helper_init(&chip->helper, chip->psy,
ug3105_get_voltage_and_current_now);
ug3105_get_voltage_and_current_now, NULL);
if (ret)
goto stop;