diff options
| author | Dzmitry Sankouski <dsankouski@gmail.com> | 2025-09-25 22:09:56 +0300 |
|---|---|---|
| committer | Sebastian Reichel <sebastian.reichel@collabora.com> | 2025-11-03 00:02:30 +0100 |
| commit | 8ed6b8842c44a4a716dfd536e7f13aff77039a02 (patch) | |
| tree | 9f3f2bffe4a1dce7fac9f26018a664095bcac713 | |
| parent | b838cecc229122559b3e2e381a9275f714bd4146 (diff) | |
power: supply: max77705_charger: implement aicl feature
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>
| -rw-r--r-- | drivers/power/supply/max77705_charger.c | 42 | ||||
| -rw-r--r-- | include/linux/power/max77705_charger.h | 2 |
2 files changed, 44 insertions, 0 deletions
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c index b1a227bf72e2..35cdb10a0e89 100644 --- a/drivers/power/supply/max77705_charger.c +++ b/drivers/power/supply/max77705_charger.c @@ -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], ®val); + 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"); diff --git a/include/linux/power/max77705_charger.h b/include/linux/power/max77705_charger.h index 6653abfdf747..b3950ce0625e 100644 --- a/include/linux/power/max77705_charger.h +++ b/include/linux/power/max77705_charger.h @@ -123,6 +123,8 @@ #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 |
