]> www.infradead.org Git - users/hch/misc.git/commitdiff
power: supply: adc-battery-helper: Add support for optional charge_finished GPIO
authorHans de Goede <hansg@kernel.org>
Sun, 31 Aug 2025 12:29:40 +0000 (14:29 +0200)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Fri, 5 Sep 2025 23:50:01 +0000 (01:50 +0200)
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>
drivers/power/supply/adc-battery-helper.c
drivers/power/supply/adc-battery-helper.h
drivers/power/supply/ug3105_battery.c

index f8f6d2f8ec89a5b68189174594e762bb4b8a352d..229b49fef8ad1cade45b47b0f2e7db29ec82fa5e 100644 (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)
index 90c7edcb9ab1d18b610a57f983a1fb15743acb99..4e42181c898375ece245e50fb470c81619e49d33 100644 (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
index c4d4ac859fa41fe9b7550d63f631a6431af515f2..210e0f9aa5e0946260c7dee9d09fb77b03de9164 100644 (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;