Commit 926b1443 authored by Hans de Goede's avatar Hans de Goede Committed by Sebastian Reichel
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarHans de Goede <hansg@kernel.org>
Link: https://lore.kernel.org/r/20250831122942.47875-5-hansg@kernel.org


Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
parent eede3f72
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -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)
	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)
+4 −1
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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;