]> Gentwo Git Trees - linux/.git/commitdiff
power: supply: max77705_charger: implement aicl feature
authorDzmitry Sankouski <dsankouski@gmail.com>
Thu, 25 Sep 2025 19:09:56 +0000 (22:09 +0300)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Sun, 2 Nov 2025 23:02:30 +0000 (00:02 +0100)
Adaptive input current allows charger to reduce it's current
consumption, when source is not able to provide enough power.

Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
Link: https://patch.msgid.link/20250925-max77705_77976_charger_improvement-v6-1-972c716c17d1@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/max77705_charger.c
include/linux/power/max77705_charger.h

index b1a227bf72e26ffcce3cd91b640349e5461289ca..35cdb10a0e895436f858d3bbe9bdde70ac92c6ff 100644 (file)
@@ -40,6 +40,39 @@ static enum power_supply_property max77705_charger_props[] = {
        POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 };
 
+static irqreturn_t max77705_aicl_irq(int irq, void *irq_drv_data)
+{
+       struct max77705_charger_data *chg = irq_drv_data;
+       unsigned int regval, irq_status;
+       int err;
+
+       err = regmap_read(chg->regmap, MAX77705_CHG_REG_INT_OK, &irq_status);
+       if (err < 0)
+               return IRQ_HANDLED;
+
+       // irq is fiered at the end of current decrease sequence too
+       // early check AICL_I bit to guard against that excess irq call
+       while (!(irq_status & BIT(MAX77705_AICL_I))) {
+               err = regmap_field_read(chg->rfield[MAX77705_CHG_CHGIN_LIM], &regval);
+               if (err < 0)
+                       return IRQ_HANDLED;
+
+               regval--;
+
+               err = regmap_field_write(chg->rfield[MAX77705_CHG_CHGIN_LIM], regval);
+               if (err < 0)
+                       return IRQ_HANDLED;
+
+               msleep(AICL_WORK_DELAY_MS);
+
+               err = regmap_read(chg->regmap, MAX77705_CHG_REG_INT_OK, &irq_status);
+               if (err < 0)
+                       return IRQ_HANDLED;
+       }
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data)
 {
        struct max77705_charger_data *chg = irq_drv_data;
@@ -632,6 +665,15 @@ static int max77705_charger_probe(struct i2c_client *i2c)
                goto destroy_wq;
        }
 
+       ret = devm_request_threaded_irq(dev, regmap_irq_get_virq(irq_data, MAX77705_AICL_I),
+                                       NULL, max77705_aicl_irq,
+                                       IRQF_TRIGGER_NONE,
+                                       "aicl-irq", chg);
+       if (ret) {
+               dev_err_probe(dev, ret, "Failed to Request aicl IRQ\n");
+               goto destroy_wq;
+       }
+
        ret = max77705_charger_enable(chg);
        if (ret) {
                dev_err_probe(dev, ret, "failed to enable charge\n");
index 6653abfdf7470d89d83a2623769928ec684ba29d..b3950ce0625e1abe96457cb65fd477da4a27cafd 100644 (file)
 #define MAX77705_DISABLE_SKIP          1
 #define MAX77705_AUTO_SKIP             0
 
+#define AICL_WORK_DELAY_MS             100
+
 /* uA */
 #define MAX77705_CURRENT_CHGIN_STEP    25000
 #define MAX77705_CURRENT_CHG_STEP      50000