* [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers
@ 2025-09-11 17:57 Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
` (8 more replies)
0 siblings, 9 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
This series consists of:
- max77705: interrupt handling fix
- max77705: make input current limit and charge current limit properties
writable
- max77705: add adaptive input current limit feature
- max77705: switch to regfields
- max77705: refactoring
- max77976: change property for current charge limit value
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes in v3:
- move interrupt request before interrupt handler work initialization
- Link to v2: https://lore.kernel.org/r/20250909-max77705_77976_charger_improvement-v2-0-a8d2fba47159@gmail.com
Changes in v2:
- fix charger register protection unlock
- Link to v1: https://lore.kernel.org/r/20250830-max77705_77976_charger_improvement-v1-0-e976db3fd432@gmail.com
---
Dzmitry Sankouski (9):
power: supply: max77705_charger: move active discharge setting to mfd parent
power: supply: max77705_charger: refactoring: rename charger to chg
power: supply: max77705_charger: use regfields for config registers
power: supply: max77705_charger: return error when config fails
power: supply: max77705_charger: add writable properties
power: supply: max77705_charger: rework interrupts
power: supply: max77705_charger: use REGMAP_IRQ_REG_LINE macro
power: supply: max77705_charger: implement aicl feature
power: supply: max77976_charger: fix constant current reporting
drivers/mfd/max77705.c | 3 +
drivers/power/supply/max77705_charger.c | 396 ++++++++++++++++++++++----------
drivers/power/supply/max77976_charger.c | 12 +-
include/linux/power/max77705_charger.h | 149 ++++++------
4 files changed, 355 insertions(+), 205 deletions(-)
---
base-commit: be5d4872e528796df9d7425f2bd9b3893eb3a42c
change-id: 20250830-max77705_77976_charger_improvement-e3f417bfaa56
Best regards,
--
Dzmitry Sankouski <dsankouski@gmail.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-15 15:42 ` [PATCH v3 1/9] mfd: max77705: " Sebastian Reichel
2025-09-16 8:43 ` [PATCH v3 1/9] power: supply: " Lee Jones
2025-09-11 17:57 ` [PATCH v3 2/9] power: supply: max77705_charger: refactoring: rename charger to chg Dzmitry Sankouski
` (7 subsequent siblings)
8 siblings, 2 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Active discharge setting is a part of MFD top level i2c device, hence
cannot be controlled by charger. Writing to MAX77705_PMIC_REG_MAINCTRL1
register from charger driver is a mistake.
Move active discharge setting to MFD parent driver.
Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/mfd/max77705.c | 3 +++
drivers/power/supply/max77705_charger.c | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/max77705.c b/drivers/mfd/max77705.c
index 6b263bacb8c2..ff07d0e0d5f8 100644
--- a/drivers/mfd/max77705.c
+++ b/drivers/mfd/max77705.c
@@ -108,6 +108,9 @@ static int max77705_i2c_probe(struct i2c_client *i2c)
if (pmic_rev != MAX77705_PASS3)
return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
+ /* Active Discharge Enable */
+ regmap_update_bits(max77705->regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
+
ret = devm_regmap_add_irq_chip(dev, max77705->regmap,
i2c->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 329b430d0e50..3b75c82b9b9e 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -487,9 +487,6 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
MAX77705_WDTEN_MASK, 0);
- /* Active Discharge Enable */
- regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
-
/* VBYPSET=5.0V */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 2/9] power: supply: max77705_charger: refactoring: rename charger to chg
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 3/9] power: supply: max77705_charger: use regfields for config registers Dzmitry Sankouski
` (6 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Rename struct max77705_charger_data variable to chg for consistency.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/power/supply/max77705_charger.c | 80 ++++++++++++++++-----------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 3b75c82b9b9e..7855f890e0a9 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -42,9 +42,9 @@ static enum power_supply_property max77705_charger_props[] = {
static int max77705_chgin_irq(void *irq_drv_data)
{
- struct max77705_charger_data *charger = irq_drv_data;
+ struct max77705_charger_data *chg = irq_drv_data;
- queue_work(charger->wqueue, &charger->chgin_work);
+ queue_work(chg->wqueue, &chg->chgin_work);
return 0;
}
@@ -109,19 +109,19 @@ static int max77705_get_online(struct regmap *regmap, int *val)
return 0;
}
-static int max77705_check_battery(struct max77705_charger_data *charger, int *val)
+static int max77705_check_battery(struct max77705_charger_data *chg, int *val)
{
unsigned int reg_data;
unsigned int reg_data2;
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
regmap_read(regmap, MAX77705_CHG_REG_INT_OK, ®_data);
- dev_dbg(charger->dev, "CHG_INT_OK(0x%x)\n", reg_data);
+ dev_dbg(chg->dev, "CHG_INT_OK(0x%x)\n", reg_data);
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_00, ®_data2);
- dev_dbg(charger->dev, "CHG_DETAILS00(0x%x)\n", reg_data2);
+ dev_dbg(chg->dev, "CHG_DETAILS00(0x%x)\n", reg_data2);
if ((reg_data & MAX77705_BATP_OK) || !(reg_data2 & MAX77705_BATP_DTLS))
*val = true;
@@ -131,9 +131,9 @@ static int max77705_check_battery(struct max77705_charger_data *charger, int *va
return 0;
}
-static int max77705_get_charge_type(struct max77705_charger_data *charger, int *val)
+static int max77705_get_charge_type(struct max77705_charger_data *chg, int *val)
{
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
unsigned int reg_data;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
@@ -159,9 +159,9 @@ static int max77705_get_charge_type(struct max77705_charger_data *charger, int *
return 0;
}
-static int max77705_get_status(struct max77705_charger_data *charger, int *val)
+static int max77705_get_status(struct max77705_charger_data *chg, int *val)
{
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
unsigned int reg_data;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
@@ -234,10 +234,10 @@ static int max77705_get_vbus_state(struct regmap *regmap, int *value)
return 0;
}
-static int max77705_get_battery_health(struct max77705_charger_data *charger,
+static int max77705_get_battery_health(struct max77705_charger_data *chg,
int *value)
{
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
unsigned int bat_dtls;
regmap_read(regmap, MAX77705_CHG_REG_DETAILS_01, &bat_dtls);
@@ -245,16 +245,16 @@ static int max77705_get_battery_health(struct max77705_charger_data *charger,
switch (bat_dtls) {
case MAX77705_BATTERY_NOBAT:
- dev_dbg(charger->dev, "%s: No battery and the charger is suspended\n",
+ dev_dbg(chg->dev, "%s: No battery and the chg is suspended\n",
__func__);
*value = POWER_SUPPLY_HEALTH_NO_BATTERY;
break;
case MAX77705_BATTERY_PREQUALIFICATION:
- dev_dbg(charger->dev, "%s: battery is okay but its voltage is low(~VPQLB)\n",
+ dev_dbg(chg->dev, "%s: battery is okay but its voltage is low(~VPQLB)\n",
__func__);
break;
case MAX77705_BATTERY_DEAD:
- dev_dbg(charger->dev, "%s: battery dead\n", __func__);
+ dev_dbg(chg->dev, "%s: battery dead\n", __func__);
*value = POWER_SUPPLY_HEALTH_DEAD;
break;
case MAX77705_BATTERY_GOOD:
@@ -262,11 +262,11 @@ static int max77705_get_battery_health(struct max77705_charger_data *charger,
*value = POWER_SUPPLY_HEALTH_GOOD;
break;
case MAX77705_BATTERY_OVERVOLTAGE:
- dev_dbg(charger->dev, "%s: battery ovp\n", __func__);
+ dev_dbg(chg->dev, "%s: battery ovp\n", __func__);
*value = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
break;
default:
- dev_dbg(charger->dev, "%s: battery unknown\n", __func__);
+ dev_dbg(chg->dev, "%s: battery unknown\n", __func__);
*value = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
break;
}
@@ -274,9 +274,9 @@ static int max77705_get_battery_health(struct max77705_charger_data *charger,
return 0;
}
-static int max77705_get_health(struct max77705_charger_data *charger, int *val)
+static int max77705_get_health(struct max77705_charger_data *chg, int *val)
{
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
int ret, is_online = 0;
ret = max77705_get_online(regmap, &is_online);
@@ -287,15 +287,15 @@ static int max77705_get_health(struct max77705_charger_data *charger, int *val)
if (ret || (*val != POWER_SUPPLY_HEALTH_GOOD))
return ret;
}
- return max77705_get_battery_health(charger, val);
+ return max77705_get_battery_health(chg, val);
}
-static int max77705_get_input_current(struct max77705_charger_data *charger,
+static int max77705_get_input_current(struct max77705_charger_data *chg,
int *val)
{
unsigned int reg_data;
int get_current = 0;
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
@@ -313,11 +313,11 @@ static int max77705_get_input_current(struct max77705_charger_data *charger,
return 0;
}
-static int max77705_get_charge_current(struct max77705_charger_data *charger,
+static int max77705_get_charge_current(struct max77705_charger_data *chg,
int *val)
{
unsigned int reg_data;
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_02, ®_data);
reg_data &= MAX77705_CHG_CC;
@@ -327,12 +327,12 @@ static int max77705_get_charge_current(struct max77705_charger_data *charger,
return 0;
}
-static int max77705_set_float_voltage(struct max77705_charger_data *charger,
+static int max77705_set_float_voltage(struct max77705_charger_data *chg,
int float_voltage)
{
int float_voltage_mv;
unsigned int reg_data = 0;
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
float_voltage_mv = float_voltage / 1000;
reg_data = float_voltage_mv <= 4000 ? 0x0 :
@@ -345,12 +345,12 @@ static int max77705_set_float_voltage(struct max77705_charger_data *charger,
(reg_data << MAX77705_CHG_CV_PRM_SHIFT));
}
-static int max77705_get_float_voltage(struct max77705_charger_data *charger,
+static int max77705_get_float_voltage(struct max77705_charger_data *chg,
int *val)
{
unsigned int reg_data = 0;
int voltage_mv;
- struct regmap *regmap = charger->regmap;
+ struct regmap *regmap = chg->regmap;
regmap_read(regmap, MAX77705_CHG_REG_CNFG_04, ®_data);
reg_data &= MAX77705_CHG_PRM_MASK;
@@ -365,28 +365,28 @@ static int max77705_chg_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
- struct max77705_charger_data *charger = power_supply_get_drvdata(psy);
- struct regmap *regmap = charger->regmap;
+ struct max77705_charger_data *chg = power_supply_get_drvdata(psy);
+ struct regmap *regmap = chg->regmap;
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
return max77705_get_online(regmap, &val->intval);
case POWER_SUPPLY_PROP_PRESENT:
- return max77705_check_battery(charger, &val->intval);
+ return max77705_check_battery(chg, &val->intval);
case POWER_SUPPLY_PROP_STATUS:
- return max77705_get_status(charger, &val->intval);
+ return max77705_get_status(chg, &val->intval);
case POWER_SUPPLY_PROP_CHARGE_TYPE:
- return max77705_get_charge_type(charger, &val->intval);
+ return max77705_get_charge_type(chg, &val->intval);
case POWER_SUPPLY_PROP_HEALTH:
- return max77705_get_health(charger, &val->intval);
+ return max77705_get_health(chg, &val->intval);
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
- return max77705_get_input_current(charger, &val->intval);
+ return max77705_get_input_current(chg, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
- return max77705_get_charge_current(charger, &val->intval);
+ return max77705_get_charge_current(chg, &val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
- return max77705_get_float_voltage(charger, &val->intval);
+ return max77705_get_float_voltage(chg, &val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
- val->intval = charger->bat_info->voltage_max_design_uv;
+ val->intval = chg->bat_info->voltage_max_design_uv;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = max77705_charger_model;
@@ -410,10 +410,10 @@ static const struct power_supply_desc max77705_charger_psy_desc = {
static void max77705_chgin_isr_work(struct work_struct *work)
{
- struct max77705_charger_data *charger =
+ struct max77705_charger_data *chg =
container_of(work, struct max77705_charger_data, chgin_work);
- power_supply_changed(charger->psy_chg);
+ power_supply_changed(chg->psy_chg);
}
static void max77705_charger_initialize(struct max77705_charger_data *chg)
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 3/9] power: supply: max77705_charger: use regfields for config registers
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 2/9] power: supply: max77705_charger: refactoring: rename charger to chg Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 4/9] power: supply: max77705_charger: return error when config fails Dzmitry Sankouski
` (5 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Using regfields allows to cleanup masks and register offset definition,
allowing to access register info by it's functional name.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes to v2:
- fix MAX77705_CHGPROT_UNLOCKED value: GENMASK(3, 2) -> 3, because it's
now used in regfield
- remove MAX77705_CHGPROT_MASK because it's unused now
---
drivers/power/supply/max77705_charger.c | 105 ++++++++++++--------------------
include/linux/power/max77705_charger.h | 102 ++++++++++++++++---------------
2 files changed, 93 insertions(+), 114 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 7855f890e0a9..2d2201a6ba68 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -74,8 +74,7 @@ static int max77705_charger_enable(struct max77705_charger_data *chg)
{
int rv;
- rv = regmap_update_bits(chg->regmap, MAX77705_CHG_REG_CNFG_09,
- MAX77705_CHG_EN_MASK, MAX77705_CHG_EN_MASK);
+ rv = regmap_field_write(chg->rfield[MAX77705_CHG_EN], 1);
if (rv)
dev_err(chg->dev, "unable to enable the charger: %d\n", rv);
@@ -87,10 +86,7 @@ static void max77705_charger_disable(void *data)
struct max77705_charger_data *chg = data;
int rv;
- rv = regmap_update_bits(chg->regmap,
- MAX77705_CHG_REG_CNFG_09,
- MAX77705_CHG_EN_MASK,
- MAX77705_CHG_DISABLE);
+ rv = regmap_field_write(chg->rfield[MAX77705_CHG_EN], MAX77705_CHG_DISABLE);
if (rv)
dev_err(chg->dev, "unable to disable the charger: %d\n", rv);
}
@@ -134,10 +130,10 @@ static int max77705_check_battery(struct max77705_charger_data *chg, int *val)
static int max77705_get_charge_type(struct max77705_charger_data *chg, int *val)
{
struct regmap *regmap = chg->regmap;
- unsigned int reg_data;
+ unsigned int reg_data, chg_en;
- regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
- if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
+ regmap_field_read(chg->rfield[MAX77705_CHG_EN], &chg_en);
+ if (!chg_en) {
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
@@ -162,10 +158,10 @@ static int max77705_get_charge_type(struct max77705_charger_data *chg, int *val)
static int max77705_get_status(struct max77705_charger_data *chg, int *val)
{
struct regmap *regmap = chg->regmap;
- unsigned int reg_data;
+ unsigned int reg_data, chg_en;
- regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
- if (!MAX77705_CHARGER_CHG_CHARGING(reg_data)) {
+ regmap_field_read(chg->rfield[MAX77705_CHG_EN], &chg_en);
+ if (!chg_en) {
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
@@ -295,16 +291,11 @@ static int max77705_get_input_current(struct max77705_charger_data *chg,
{
unsigned int reg_data;
int get_current = 0;
- struct regmap *regmap = chg->regmap;
- regmap_read(regmap, MAX77705_CHG_REG_CNFG_09, ®_data);
-
- reg_data &= MAX77705_CHG_CHGIN_LIM_MASK;
+ regmap_field_read(chg->rfield[MAX77705_CHG_CHGIN_LIM], ®_data);
if (reg_data <= 3)
get_current = MAX77705_CURRENT_CHGIN_MIN;
- else if (reg_data >= MAX77705_CHG_CHGIN_LIM_MASK)
- get_current = MAX77705_CURRENT_CHGIN_MAX;
else
get_current = (reg_data + 1) * MAX77705_CURRENT_CHGIN_STEP;
@@ -317,10 +308,8 @@ static int max77705_get_charge_current(struct max77705_charger_data *chg,
int *val)
{
unsigned int reg_data;
- struct regmap *regmap = chg->regmap;
- regmap_read(regmap, MAX77705_CHG_REG_CNFG_02, ®_data);
- reg_data &= MAX77705_CHG_CC;
+ regmap_field_read(chg->rfield[MAX77705_CHG_CC_LIM], ®_data);
*val = reg_data <= 0x2 ? MAX77705_CURRENT_CHGIN_MIN : reg_data * MAX77705_CURRENT_CHG_STEP;
@@ -332,7 +321,6 @@ static int max77705_set_float_voltage(struct max77705_charger_data *chg,
{
int float_voltage_mv;
unsigned int reg_data = 0;
- struct regmap *regmap = chg->regmap;
float_voltage_mv = float_voltage / 1000;
reg_data = float_voltage_mv <= 4000 ? 0x0 :
@@ -340,9 +328,7 @@ static int max77705_set_float_voltage(struct max77705_charger_data *chg,
(float_voltage_mv <= 4200) ? (float_voltage_mv - 4000) / 50 :
(((float_voltage_mv - 4200) / 10) + 0x04);
- return regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_04,
- MAX77705_CHG_CV_PRM_MASK,
- (reg_data << MAX77705_CHG_CV_PRM_SHIFT));
+ return regmap_field_write(chg->rfield[MAX77705_CHG_CV_PRM], reg_data);
}
static int max77705_get_float_voltage(struct max77705_charger_data *chg,
@@ -350,10 +336,8 @@ static int max77705_get_float_voltage(struct max77705_charger_data *chg,
{
unsigned int reg_data = 0;
int voltage_mv;
- struct regmap *regmap = chg->regmap;
- regmap_read(regmap, MAX77705_CHG_REG_CNFG_04, ®_data);
- reg_data &= MAX77705_CHG_PRM_MASK;
+ regmap_field_read(chg->rfield[MAX77705_CHG_CV_PRM], ®_data);
voltage_mv = reg_data <= 0x04 ? reg_data * 50 + 4000 :
(reg_data - 4) * 10 + 4200;
*val = voltage_mv * 1000;
@@ -418,7 +402,6 @@ static void max77705_chgin_isr_work(struct work_struct *work)
static void max77705_charger_initialize(struct max77705_charger_data *chg)
{
- u8 reg_data;
struct power_supply_battery_info *info;
struct regmap *regmap = chg->regmap;
@@ -429,45 +412,31 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
/* unlock charger setting protect */
/* slowest LX slope */
- reg_data = MAX77705_CHGPROT_MASK | MAX77705_SLOWEST_LX_SLOPE;
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_06, reg_data,
- reg_data);
+ regmap_field_write(chg->rfield[MAX77705_CHGPROT], MAX77705_CHGPROT_UNLOCKED);
+ regmap_field_write(chg->rfield[MAX77705_LX_SLOPE], MAX77705_SLOWEST_LX_SLOPE);
/* fast charge timer disable */
/* restart threshold disable */
/* pre-qual charge disable */
- reg_data = (MAX77705_FCHGTIME_DISABLE << MAX77705_FCHGTIME_SHIFT) |
- (MAX77705_CHG_RSTRT_DISABLE << MAX77705_CHG_RSTRT_SHIFT) |
- (MAX77705_CHG_PQEN_DISABLE << MAX77705_PQEN_SHIFT);
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_01,
- (MAX77705_FCHGTIME_MASK |
- MAX77705_CHG_RSTRT_MASK |
- MAX77705_PQEN_MASK),
- reg_data);
-
- /* OTG off(UNO on), boost off */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
- MAX77705_OTG_CTRL, 0);
+ regmap_field_write(chg->rfield[MAX77705_FCHGTIME], MAX77705_FCHGTIME_DISABLE);
+ regmap_field_write(chg->rfield[MAX77705_CHG_RSTRT], MAX77705_CHG_RSTRT_DISABLE);
+ regmap_field_write(chg->rfield[MAX77705_CHG_PQEN], MAX77705_CHG_PQEN_DISABLE);
+
+ regmap_field_write(chg->rfield[MAX77705_MODE],
+ MAX77705_CHG_MASK | MAX77705_BUCK_MASK);
/* charge current 450mA(default) */
/* otg current limit 900mA */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_02,
- MAX77705_OTG_ILIM_MASK,
- MAX77705_OTG_ILIM_900 << MAX77705_OTG_ILIM_SHIFT);
+ regmap_field_write(chg->rfield[MAX77705_OTG_ILIM], MAX77705_OTG_ILIM_900);
/* BAT to SYS OCP 4.80A */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_05,
- MAX77705_REG_B2SOVRC_MASK,
- MAX77705_B2SOVRC_4_8A << MAX77705_REG_B2SOVRC_SHIFT);
+ regmap_field_write(chg->rfield[MAX77705_REG_B2SOVRC], MAX77705_B2SOVRC_4_8A);
+
/* top off current 150mA */
/* top off timer 30min */
- reg_data = (MAX77705_TO_ITH_150MA << MAX77705_TO_ITH_SHIFT) |
- (MAX77705_TO_TIME_30M << MAX77705_TO_TIME_SHIFT) |
- (MAX77705_SYS_TRACK_DISABLE << MAX77705_SYS_TRACK_DIS_SHIFT);
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_03,
- (MAX77705_TO_ITH_MASK |
- MAX77705_TO_TIME_MASK |
- MAX77705_SYS_TRACK_DIS_MASK), reg_data);
+ regmap_field_write(chg->rfield[MAX77705_TO], MAX77705_TO_ITH_150MA);
+ regmap_field_write(chg->rfield[MAX77705_TO_TIME], MAX77705_TO_TIME_30M);
+ regmap_field_write(chg->rfield[MAX77705_SYS_TRACK], MAX77705_SYS_TRACK_DISABLE);
/* cv voltage 4.2V or 4.35V */
/* MINVSYS 3.6V(default) */
@@ -478,25 +447,21 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
max77705_set_float_voltage(chg, info->voltage_max_design_uv);
}
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
- MAX77705_VCHGIN_REG_MASK, MAX77705_VCHGIN_4_5);
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12,
- MAX77705_WCIN_REG_MASK, MAX77705_WCIN_4_5);
+ regmap_field_write(chg->rfield[MAX77705_VCHGIN], MAX77705_VCHGIN_4_5);
+ regmap_field_write(chg->rfield[MAX77705_WCIN], MAX77705_WCIN_4_5);
/* Watchdog timer */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
MAX77705_WDTEN_MASK, 0);
/* VBYPSET=5.0V */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
+ regmap_field_write(chg->rfield[MAX77705_VBYPSET], 0);
/* Switching Frequency : 1.5MHz */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_08, MAX77705_REG_FSW_MASK,
- (MAX77705_CHG_FSW_1_5MHz << MAX77705_REG_FSW_SHIFT));
+ regmap_field_write(chg->rfield[MAX77705_REG_FSW], MAX77705_CHG_FSW_1_5MHz);
/* Auto skip mode */
- regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_12, MAX77705_REG_DISKIP_MASK,
- (MAX77705_AUTO_SKIP << MAX77705_REG_DISKIP_SHIFT));
+ regmap_field_write(chg->rfield[MAX77705_REG_DISKIP], MAX77705_AUTO_SKIP);
}
static int max77705_charger_probe(struct i2c_client *i2c)
@@ -520,6 +485,14 @@ static int max77705_charger_probe(struct i2c_client *i2c)
if (IS_ERR(chg->regmap))
return PTR_ERR(chg->regmap);
+ for (int i = 0; i < MAX77705_N_REGMAP_FIELDS; i++) {
+ chg->rfield[i] = devm_regmap_field_alloc(dev, chg->regmap,
+ max77705_reg_field[i]);
+ if (IS_ERR(chg->rfield[i]))
+ return dev_err_probe(dev, PTR_ERR(chg->rfield[i]),
+ "cannot allocate regmap field\n");
+ }
+
ret = regmap_update_bits(chg->regmap,
MAX77705_CHG_REG_INT_MASK,
MAX77705_CHGIN_IM, 0);
diff --git a/include/linux/power/max77705_charger.h b/include/linux/power/max77705_charger.h
index fdec9af9c541..a612795577b6 100644
--- a/include/linux/power/max77705_charger.h
+++ b/include/linux/power/max77705_charger.h
@@ -9,6 +9,8 @@
#ifndef __MAX77705_CHARGER_H
#define __MAX77705_CHARGER_H __FILE__
+#include <linux/regmap.h>
+
/* MAX77705_CHG_REG_CHG_INT */
#define MAX77705_BYP_I BIT(0)
#define MAX77705_INP_LIMIT_I BIT(1)
@@ -63,7 +65,6 @@
#define MAX77705_BUCK_SHIFT 2
#define MAX77705_BOOST_SHIFT 3
#define MAX77705_WDTEN_SHIFT 4
-#define MAX77705_MODE_MASK GENMASK(3, 0)
#define MAX77705_CHG_MASK BIT(MAX77705_CHG_SHIFT)
#define MAX77705_UNO_MASK BIT(MAX77705_UNO_SHIFT)
#define MAX77705_OTG_MASK BIT(MAX77705_OTG_SHIFT)
@@ -74,34 +75,19 @@
#define MAX77705_OTG_CTRL (MAX77705_OTG_MASK | MAX77705_BOOST_MASK)
/* MAX77705_CHG_REG_CNFG_01 */
-#define MAX77705_FCHGTIME_SHIFT 0
-#define MAX77705_FCHGTIME_MASK GENMASK(2, 0)
-#define MAX77705_CHG_RSTRT_SHIFT 4
-#define MAX77705_CHG_RSTRT_MASK GENMASK(5, 4)
#define MAX77705_FCHGTIME_DISABLE 0
#define MAX77705_CHG_RSTRT_DISABLE 0x3
-#define MAX77705_PQEN_SHIFT 7
-#define MAX77705_PQEN_MASK BIT(7)
#define MAX77705_CHG_PQEN_DISABLE 0
#define MAX77705_CHG_PQEN_ENABLE 1
/* MAX77705_CHG_REG_CNFG_02 */
-#define MAX77705_OTG_ILIM_SHIFT 6
-#define MAX77705_OTG_ILIM_MASK GENMASK(7, 6)
#define MAX77705_OTG_ILIM_500 0
#define MAX77705_OTG_ILIM_900 1
#define MAX77705_OTG_ILIM_1200 2
#define MAX77705_OTG_ILIM_1500 3
-#define MAX77705_CHG_CC GENMASK(5, 0)
/* MAX77705_CHG_REG_CNFG_03 */
-#define MAX77705_TO_ITH_SHIFT 0
-#define MAX77705_TO_ITH_MASK GENMASK(2, 0)
-#define MAX77705_TO_TIME_SHIFT 3
-#define MAX77705_TO_TIME_MASK GENMASK(5, 3)
-#define MAX77705_SYS_TRACK_DIS_SHIFT 7
-#define MAX77705_SYS_TRACK_DIS_MASK BIT(7)
#define MAX77705_TO_ITH_150MA 0
#define MAX77705_TO_TIME_30M 3
#define MAX77705_SYS_TRACK_ENABLE 0
@@ -110,15 +96,8 @@
/* MAX77705_CHG_REG_CNFG_04 */
#define MAX77705_CHG_MINVSYS_SHIFT 6
#define MAX77705_CHG_MINVSYS_MASK GENMASK(7, 6)
-#define MAX77705_CHG_PRM_SHIFT 0
-#define MAX77705_CHG_PRM_MASK GENMASK(5, 0)
-
-#define MAX77705_CHG_CV_PRM_SHIFT 0
-#define MAX77705_CHG_CV_PRM_MASK GENMASK(5, 0)
/* MAX77705_CHG_REG_CNFG_05 */
-#define MAX77705_REG_B2SOVRC_SHIFT 0
-#define MAX77705_REG_B2SOVRC_MASK GENMASK(3, 0)
#define MAX77705_B2SOVRC_DISABLE 0
#define MAX77705_B2SOVRC_4_5A 6
#define MAX77705_B2SOVRC_4_8A 8
@@ -128,9 +107,8 @@
#define MAX77705_WDTCLR_SHIFT 0
#define MAX77705_WDTCLR_MASK GENMASK(1, 0)
#define MAX77705_WDTCLR 1
-#define MAX77705_CHGPROT_MASK GENMASK(3, 2)
-#define MAX77705_CHGPROT_UNLOCKED GENMASK(3, 2)
-#define MAX77705_SLOWEST_LX_SLOPE GENMASK(6, 5)
+#define MAX77705_CHGPROT_UNLOCKED 3
+#define MAX77705_SLOWEST_LX_SLOPE 3
/* MAX77705_CHG_REG_CNFG_07 */
#define MAX77705_CHG_FMBST 4
@@ -140,36 +118,14 @@
#define MAX77705_REG_FGSRC_MASK BIT(MAX77705_REG_FGSRC_SHIFT)
/* MAX77705_CHG_REG_CNFG_08 */
-#define MAX77705_REG_FSW_SHIFT 0
-#define MAX77705_REG_FSW_MASK GENMASK(1, 0)
#define MAX77705_CHG_FSW_3MHz 0
#define MAX77705_CHG_FSW_2MHz 1
#define MAX77705_CHG_FSW_1_5MHz 2
/* MAX77705_CHG_REG_CNFG_09 */
-#define MAX77705_CHG_CHGIN_LIM_MASK GENMASK(6, 0)
-#define MAX77705_CHG_EN_MASK BIT(7)
#define MAX77705_CHG_DISABLE 0
-#define MAX77705_CHARGER_CHG_CHARGING(_reg) \
- (((_reg) & MAX77705_CHG_EN_MASK) > 1)
-
-
-/* MAX77705_CHG_REG_CNFG_10 */
-#define MAX77705_CHG_WCIN_LIM GENMASK(5, 0)
-
-/* MAX77705_CHG_REG_CNFG_11 */
-#define MAX77705_VBYPSET_SHIFT 0
-#define MAX77705_VBYPSET_MASK GENMASK(6, 0)
/* MAX77705_CHG_REG_CNFG_12 */
-#define MAX77705_CHGINSEL_SHIFT 5
-#define MAX77705_CHGINSEL_MASK BIT(MAX77705_CHGINSEL_SHIFT)
-#define MAX77705_WCINSEL_SHIFT 6
-#define MAX77705_WCINSEL_MASK BIT(MAX77705_WCINSEL_SHIFT)
-#define MAX77705_VCHGIN_REG_MASK GENMASK(4, 3)
-#define MAX77705_WCIN_REG_MASK GENMASK(2, 1)
-#define MAX77705_REG_DISKIP_SHIFT 0
-#define MAX77705_REG_DISKIP_MASK BIT(MAX77705_REG_DISKIP_SHIFT)
/* REG=4.5V, UVLO=4.7V */
#define MAX77705_VCHGIN_4_5 0
/* REG=4.5V, UVLO=4.7V */
@@ -183,9 +139,59 @@
#define MAX77705_CURRENT_CHGIN_MIN 100000
#define MAX77705_CURRENT_CHGIN_MAX 3200000
+enum max77705_field_idx {
+ MAX77705_CHGPROT,
+ MAX77705_CHG_EN,
+ MAX77705_CHG_CC_LIM,
+ MAX77705_CHG_CHGIN_LIM,
+ MAX77705_CHG_CV_PRM,
+ MAX77705_CHG_PQEN,
+ MAX77705_CHG_RSTRT,
+ MAX77705_CHG_WCIN,
+ MAX77705_FCHGTIME,
+ MAX77705_LX_SLOPE,
+ MAX77705_MODE,
+ MAX77705_OTG_ILIM,
+ MAX77705_REG_B2SOVRC,
+ MAX77705_REG_DISKIP,
+ MAX77705_REG_FSW,
+ MAX77705_SYS_TRACK,
+ MAX77705_TO,
+ MAX77705_TO_TIME,
+ MAX77705_VBYPSET,
+ MAX77705_VCHGIN,
+ MAX77705_WCIN,
+ MAX77705_N_REGMAP_FIELDS,
+};
+
+static const struct reg_field max77705_reg_field[MAX77705_N_REGMAP_FIELDS] = {
+ [MAX77705_MODE] = REG_FIELD(MAX77705_CHG_REG_CNFG_00, 0, 3),
+ [MAX77705_FCHGTIME] = REG_FIELD(MAX77705_CHG_REG_CNFG_01, 0, 2),
+ [MAX77705_CHG_RSTRT] = REG_FIELD(MAX77705_CHG_REG_CNFG_01, 4, 5),
+ [MAX77705_CHG_PQEN] = REG_FIELD(MAX77705_CHG_REG_CNFG_01, 7, 7),
+ [MAX77705_CHG_CC_LIM] = REG_FIELD(MAX77705_CHG_REG_CNFG_02, 0, 5),
+ [MAX77705_OTG_ILIM] = REG_FIELD(MAX77705_CHG_REG_CNFG_02, 6, 7),
+ [MAX77705_TO] = REG_FIELD(MAX77705_CHG_REG_CNFG_03, 0, 2),
+ [MAX77705_TO_TIME] = REG_FIELD(MAX77705_CHG_REG_CNFG_03, 3, 5),
+ [MAX77705_SYS_TRACK] = REG_FIELD(MAX77705_CHG_REG_CNFG_03, 7, 7),
+ [MAX77705_CHG_CV_PRM] = REG_FIELD(MAX77705_CHG_REG_CNFG_04, 0, 5),
+ [MAX77705_REG_B2SOVRC] = REG_FIELD(MAX77705_CHG_REG_CNFG_05, 0, 3),
+ [MAX77705_CHGPROT] = REG_FIELD(MAX77705_CHG_REG_CNFG_06, 2, 3),
+ [MAX77705_LX_SLOPE] = REG_FIELD(MAX77705_CHG_REG_CNFG_06, 5, 6),
+ [MAX77705_REG_FSW] = REG_FIELD(MAX77705_CHG_REG_CNFG_08, 0, 1),
+ [MAX77705_CHG_CHGIN_LIM] = REG_FIELD(MAX77705_CHG_REG_CNFG_09, 0, 6),
+ [MAX77705_CHG_EN] = REG_FIELD(MAX77705_CHG_REG_CNFG_09, 7, 7),
+ [MAX77705_CHG_WCIN] = REG_FIELD(MAX77705_CHG_REG_CNFG_10, 0, 5),
+ [MAX77705_VBYPSET] = REG_FIELD(MAX77705_CHG_REG_CNFG_11, 0, 6),
+ [MAX77705_REG_DISKIP] = REG_FIELD(MAX77705_CHG_REG_CNFG_12, 0, 0),
+ [MAX77705_WCIN] = REG_FIELD(MAX77705_CHG_REG_CNFG_12, 1, 2),
+ [MAX77705_VCHGIN] = REG_FIELD(MAX77705_CHG_REG_CNFG_12, 3, 4),
+};
+
struct max77705_charger_data {
struct device *dev;
struct regmap *regmap;
+ struct regmap_field *rfield[MAX77705_N_REGMAP_FIELDS];
struct power_supply_battery_info *bat_info;
struct workqueue_struct *wqueue;
struct work_struct chgin_work;
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 4/9] power: supply: max77705_charger: return error when config fails
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (2 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 3/9] power: supply: max77705_charger: use regfields for config registers Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 5/9] power: supply: max77705_charger: add writable properties Dzmitry Sankouski
` (4 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Handle error, returned from register writes in init function.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/power/supply/max77705_charger.c | 90 +++++++++++++++++++++++++--------
1 file changed, 70 insertions(+), 20 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 2d2201a6ba68..93d055458849 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -400,43 +400,72 @@ static void max77705_chgin_isr_work(struct work_struct *work)
power_supply_changed(chg->psy_chg);
}
-static void max77705_charger_initialize(struct max77705_charger_data *chg)
+static int max77705_charger_initialize(struct max77705_charger_data *chg)
{
struct power_supply_battery_info *info;
struct regmap *regmap = chg->regmap;
+ int err;
- if (power_supply_get_battery_info(chg->psy_chg, &info) < 0)
- return;
+ err = power_supply_get_battery_info(chg->psy_chg, &info);
+ if (err)
+ return dev_err_probe(chg->dev, err, "error on getting battery info");
chg->bat_info = info;
/* unlock charger setting protect */
/* slowest LX slope */
- regmap_field_write(chg->rfield[MAX77705_CHGPROT], MAX77705_CHGPROT_UNLOCKED);
- regmap_field_write(chg->rfield[MAX77705_LX_SLOPE], MAX77705_SLOWEST_LX_SLOPE);
+ err = regmap_field_write(chg->rfield[MAX77705_CHGPROT], MAX77705_CHGPROT_UNLOCKED);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_LX_SLOPE], MAX77705_SLOWEST_LX_SLOPE);
+ if (err)
+ goto err;
/* fast charge timer disable */
/* restart threshold disable */
/* pre-qual charge disable */
- regmap_field_write(chg->rfield[MAX77705_FCHGTIME], MAX77705_FCHGTIME_DISABLE);
- regmap_field_write(chg->rfield[MAX77705_CHG_RSTRT], MAX77705_CHG_RSTRT_DISABLE);
- regmap_field_write(chg->rfield[MAX77705_CHG_PQEN], MAX77705_CHG_PQEN_DISABLE);
+ err = regmap_field_write(chg->rfield[MAX77705_FCHGTIME], MAX77705_FCHGTIME_DISABLE);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_CHG_RSTRT], MAX77705_CHG_RSTRT_DISABLE);
+ if (err)
+ goto err;
- regmap_field_write(chg->rfield[MAX77705_MODE],
+ err = regmap_field_write(chg->rfield[MAX77705_CHG_PQEN], MAX77705_CHG_PQEN_DISABLE);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_MODE],
MAX77705_CHG_MASK | MAX77705_BUCK_MASK);
+ if (err)
+ goto err;
/* charge current 450mA(default) */
/* otg current limit 900mA */
- regmap_field_write(chg->rfield[MAX77705_OTG_ILIM], MAX77705_OTG_ILIM_900);
+ err = regmap_field_write(chg->rfield[MAX77705_OTG_ILIM], MAX77705_OTG_ILIM_900);
+ if (err)
+ goto err;
/* BAT to SYS OCP 4.80A */
- regmap_field_write(chg->rfield[MAX77705_REG_B2SOVRC], MAX77705_B2SOVRC_4_8A);
+ err = regmap_field_write(chg->rfield[MAX77705_REG_B2SOVRC], MAX77705_B2SOVRC_4_8A);
+ if (err)
+ goto err;
/* top off current 150mA */
/* top off timer 30min */
- regmap_field_write(chg->rfield[MAX77705_TO], MAX77705_TO_ITH_150MA);
- regmap_field_write(chg->rfield[MAX77705_TO_TIME], MAX77705_TO_TIME_30M);
- regmap_field_write(chg->rfield[MAX77705_SYS_TRACK], MAX77705_SYS_TRACK_DISABLE);
+ err = regmap_field_write(chg->rfield[MAX77705_TO], MAX77705_TO_ITH_150MA);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_TO_TIME], MAX77705_TO_TIME_30M);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_SYS_TRACK], MAX77705_SYS_TRACK_DISABLE);
+ if (err)
+ goto err;
/* cv voltage 4.2V or 4.35V */
/* MINVSYS 3.6V(default) */
@@ -447,21 +476,38 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
max77705_set_float_voltage(chg, info->voltage_max_design_uv);
}
- regmap_field_write(chg->rfield[MAX77705_VCHGIN], MAX77705_VCHGIN_4_5);
- regmap_field_write(chg->rfield[MAX77705_WCIN], MAX77705_WCIN_4_5);
+ err = regmap_field_write(chg->rfield[MAX77705_VCHGIN], MAX77705_VCHGIN_4_5);
+ if (err)
+ goto err;
+
+ err = regmap_field_write(chg->rfield[MAX77705_WCIN], MAX77705_WCIN_4_5);
+ if (err)
+ goto err;
/* Watchdog timer */
regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
MAX77705_WDTEN_MASK, 0);
/* VBYPSET=5.0V */
- regmap_field_write(chg->rfield[MAX77705_VBYPSET], 0);
+ err = regmap_field_write(chg->rfield[MAX77705_VBYPSET], 0);
+ if (err)
+ goto err;
/* Switching Frequency : 1.5MHz */
- regmap_field_write(chg->rfield[MAX77705_REG_FSW], MAX77705_CHG_FSW_1_5MHz);
+ err = regmap_field_write(chg->rfield[MAX77705_REG_FSW], MAX77705_CHG_FSW_1_5MHz);
+ if (err)
+ goto err;
/* Auto skip mode */
- regmap_field_write(chg->rfield[MAX77705_REG_DISKIP], MAX77705_AUTO_SKIP);
+ err = regmap_field_write(chg->rfield[MAX77705_REG_DISKIP], MAX77705_AUTO_SKIP);
+ if (err)
+ goto err;
+
+ return 0;
+
+err:
+ return dev_err_probe(chg->dev, err, "error while configuring");
+
}
static int max77705_charger_probe(struct i2c_client *i2c)
@@ -524,7 +570,11 @@ static int max77705_charger_probe(struct i2c_client *i2c)
goto destroy_wq;
}
- max77705_charger_initialize(chg);
+ ret = max77705_charger_initialize(chg);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to initialize charger IC\n");
+ goto destroy_wq;
+ }
ret = max77705_charger_enable(chg);
if (ret) {
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 5/9] power: supply: max77705_charger: add writable properties
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (3 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 4/9] power: supply: max77705_charger: return error when config fails Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts Dzmitry Sankouski
` (3 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Add INPUT_CURRENT_LIMIT, CONSTANT_CHARGE_CURRENT properties as writeable
to be able to control input power consumption and charging speed.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/power/supply/max77705_charger.c | 54 +++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 93d055458849..d6a3cd98c898 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -105,6 +105,17 @@ static int max77705_get_online(struct regmap *regmap, int *val)
return 0;
}
+static int max77705_set_integer(struct max77705_charger_data *chg, enum max77705_field_idx fidx,
+ unsigned int clamp_min, unsigned int clamp_max,
+ unsigned int div, int val)
+{
+ unsigned int regval;
+
+ regval = clamp_val(val, clamp_min, clamp_max) / div;
+
+ return regmap_field_write(chg->rfield[fidx], regval);
+}
+
static int max77705_check_battery(struct max77705_charger_data *chg, int *val)
{
unsigned int reg_data;
@@ -384,12 +395,55 @@ static int max77705_chg_get_property(struct power_supply *psy,
return 0;
}
+static int max77705_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct max77705_charger_data *charger = power_supply_get_drvdata(psy);
+ int err = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ err = max77705_set_integer(charger, MAX77705_CHG_CC_LIM,
+ MAX77705_CURRENT_CHGIN_MIN,
+ MAX77705_CURRENT_CHGIN_MAX,
+ MAX77705_CURRENT_CHG_STEP,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ err = max77705_set_integer(charger, MAX77705_CHG_CHGIN_LIM,
+ MAX77705_CURRENT_CHGIN_MIN,
+ MAX77705_CURRENT_CHGIN_MAX,
+ MAX77705_CURRENT_CHGIN_STEP,
+ val->intval);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ return err;
+};
+
+static int max77705_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const struct power_supply_desc max77705_charger_psy_desc = {
.name = "max77705-charger",
.type = POWER_SUPPLY_TYPE_USB,
.properties = max77705_charger_props,
+ .property_is_writeable = max77705_property_is_writeable,
.num_properties = ARRAY_SIZE(max77705_charger_props),
.get_property = max77705_chg_get_property,
+ .set_property = max77705_set_property,
};
static void max77705_chgin_isr_work(struct work_struct *work)
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (4 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 5/9] power: supply: max77705_charger: add writable properties Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-15 15:34 ` Sebastian Reichel
2025-09-11 17:57 ` [PATCH v3 7/9] power: supply: max77705_charger: use REGMAP_IRQ_REG_LINE macro Dzmitry Sankouski
` (2 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Current implementation uses handle_post_irq to actually handle chgin
irq. This is not how things are meant to work in regmap-irq.
Remove handle_post_irq, and request a threaded interrupt for chgin.
Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
Changes to v3:
- move irq initialization after workqueue and charger initialization
---
drivers/power/supply/max77705_charger.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index d6a3cd98c898..5f831c25b150 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -40,13 +40,13 @@ static enum power_supply_property max77705_charger_props[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
-static int max77705_chgin_irq(void *irq_drv_data)
+static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data)
{
struct max77705_charger_data *chg = irq_drv_data;
queue_work(chg->wqueue, &chg->chgin_work);
- return 0;
+ return IRQ_HANDLED;
}
static const struct regmap_irq max77705_charger_irqs[] = {
@@ -64,7 +64,6 @@ static struct regmap_irq_chip max77705_charger_irq_chip = {
.name = "max77705-charger",
.status_base = MAX77705_CHG_REG_INT,
.mask_base = MAX77705_CHG_REG_INT_MASK,
- .handle_post_irq = max77705_chgin_irq,
.num_regs = 1,
.irqs = max77705_charger_irqs,
.num_irqs = ARRAY_SIZE(max77705_charger_irqs),
@@ -593,12 +592,6 @@ static int max77705_charger_probe(struct i2c_client *i2c)
"cannot allocate regmap field\n");
}
- ret = regmap_update_bits(chg->regmap,
- MAX77705_CHG_REG_INT_MASK,
- MAX77705_CHGIN_IM, 0);
- if (ret)
- return ret;
-
pscfg.fwnode = dev_fwnode(dev);
pscfg.drv_data = chg;
@@ -630,6 +623,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_CHGIN_I),
+ NULL, max77705_chgin_irq,
+ IRQF_TRIGGER_HIGH,
+ "chgin-irq", chg);
+ if (ret) {
+ pr_err("%s: Failed to Request IRQ (%d)\n", __func__, ret);
+ goto destroy_wq;
+ }
+
ret = max77705_charger_enable(chg);
if (ret) {
dev_err_probe(dev, ret, "failed to enable charge\n");
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 7/9] power: supply: max77705_charger: use REGMAP_IRQ_REG_LINE macro
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (5 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 8/9] power: supply: max77705_charger: implement aicl feature Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting Dzmitry Sankouski
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
Refactor regmap_irq declarations with REGMAP_IRQ_REG_LINE saves a few
lines on definitions.
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/power/supply/max77705_charger.c | 16 ++++++-------
include/linux/power/max77705_charger.h | 42 +++++++++++++--------------------
2 files changed, 24 insertions(+), 34 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 5f831c25b150..940cf3bf6d1a 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -50,14 +50,14 @@ static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data)
}
static const struct regmap_irq max77705_charger_irqs[] = {
- { .mask = MAX77705_BYP_IM, },
- { .mask = MAX77705_INP_LIMIT_IM, },
- { .mask = MAX77705_BATP_IM, },
- { .mask = MAX77705_BAT_IM, },
- { .mask = MAX77705_CHG_IM, },
- { .mask = MAX77705_WCIN_IM, },
- { .mask = MAX77705_CHGIN_IM, },
- { .mask = MAX77705_AICL_IM, },
+ REGMAP_IRQ_REG_LINE(MAX77705_BYP_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_INP_LIMIT_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_BATP_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_BAT_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_CHG_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_WCIN_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_CHGIN_I, BITS_PER_BYTE),
+ REGMAP_IRQ_REG_LINE(MAX77705_AICL_I, BITS_PER_BYTE),
};
static struct regmap_irq_chip max77705_charger_irq_chip = {
diff --git a/include/linux/power/max77705_charger.h b/include/linux/power/max77705_charger.h
index a612795577b6..6653abfdf747 100644
--- a/include/linux/power/max77705_charger.h
+++ b/include/linux/power/max77705_charger.h
@@ -12,34 +12,24 @@
#include <linux/regmap.h>
/* MAX77705_CHG_REG_CHG_INT */
-#define MAX77705_BYP_I BIT(0)
-#define MAX77705_INP_LIMIT_I BIT(1)
-#define MAX77705_BATP_I BIT(2)
-#define MAX77705_BAT_I BIT(3)
-#define MAX77705_CHG_I BIT(4)
-#define MAX77705_WCIN_I BIT(5)
-#define MAX77705_CHGIN_I BIT(6)
-#define MAX77705_AICL_I BIT(7)
-
-/* MAX77705_CHG_REG_CHG_INT_MASK */
-#define MAX77705_BYP_IM BIT(0)
-#define MAX77705_INP_LIMIT_IM BIT(1)
-#define MAX77705_BATP_IM BIT(2)
-#define MAX77705_BAT_IM BIT(3)
-#define MAX77705_CHG_IM BIT(4)
-#define MAX77705_WCIN_IM BIT(5)
-#define MAX77705_CHGIN_IM BIT(6)
-#define MAX77705_AICL_IM BIT(7)
+#define MAX77705_BYP_I (0)
+#define MAX77705_INP_LIMIT_I (1)
+#define MAX77705_BATP_I (2)
+#define MAX77705_BAT_I (3)
+#define MAX77705_CHG_I (4)
+#define MAX77705_WCIN_I (5)
+#define MAX77705_CHGIN_I (6)
+#define MAX77705_AICL_I (7)
/* MAX77705_CHG_REG_CHG_INT_OK */
-#define MAX77705_BYP_OK BIT(0)
-#define MAX77705_DISQBAT_OK BIT(1)
-#define MAX77705_BATP_OK BIT(2)
-#define MAX77705_BAT_OK BIT(3)
-#define MAX77705_CHG_OK BIT(4)
-#define MAX77705_WCIN_OK BIT(5)
-#define MAX77705_CHGIN_OK BIT(6)
-#define MAX77705_AICL_OK BIT(7)
+#define MAX77705_BYP_OK BIT(MAX77705_BYP_I)
+#define MAX77705_DISQBAT_OK BIT(MAX77705_INP_LIMIT_I)
+#define MAX77705_BATP_OK BIT(MAX77705_BATP_I)
+#define MAX77705_BAT_OK BIT(MAX77705_BAT_I)
+#define MAX77705_CHG_OK BIT(MAX77705_CHG_I)
+#define MAX77705_WCIN_OK BIT(MAX77705_WCIN_I)
+#define MAX77705_CHGIN_OK BIT(MAX77705_CHGIN_I)
+#define MAX77705_AICL_OK BIT(MAX77705_AICL_I)
/* MAX77705_CHG_REG_DETAILS_00 */
#define MAX77705_BATP_DTLS BIT(0)
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 8/9] power: supply: max77705_charger: implement aicl feature
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (6 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 7/9] power: supply: max77705_charger: use REGMAP_IRQ_REG_LINE macro Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting Dzmitry Sankouski
8 siblings, 0 replies; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
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>
---
drivers/power/supply/max77705_charger.c | 70 +++++++++++++++++++++++++++++++++
include/linux/power/max77705_charger.h | 5 +++
2 files changed, 75 insertions(+)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
index 940cf3bf6d1a..a943efc67546 100644
--- a/drivers/power/supply/max77705_charger.c
+++ b/drivers/power/supply/max77705_charger.c
@@ -40,6 +40,16 @@ 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;
+
+ queue_delayed_work(chg->wqueue, &chg->aicl_work,
+ msecs_to_jiffies(AICL_WORK_DELAY));
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data)
{
struct max77705_charger_data *chg = irq_drv_data;
@@ -445,6 +455,40 @@ static const struct power_supply_desc max77705_charger_psy_desc = {
.set_property = max77705_set_property,
};
+static void max77705_aicl_isr_work(struct work_struct *work)
+{
+ unsigned int regval, irq_status;
+ int err;
+ struct max77705_charger_data *chg =
+ container_of(work, struct max77705_charger_data, aicl_work.work);
+
+ regmap_read(chg->regmap, MAX77705_CHG_REG_INT_OK, &irq_status);
+ if (!chg->is_aicl_irq_disabled) {
+ disable_irq(chg->aicl_irq);
+ chg->is_aicl_irq_disabled = true;
+ }
+
+ if (!(irq_status & BIT(MAX77705_AICL_I))) {
+ err = regmap_field_read(chg->rfield[MAX77705_CHG_CHGIN_LIM], ®val);
+ if (err < 0)
+ return;
+
+ regval--;
+
+ pr_info("aicl call. regval: %d\n", regval);
+ err = regmap_field_write(chg->rfield[MAX77705_CHG_CHGIN_LIM], regval);
+ if (err < 0)
+ return;
+
+ queue_delayed_work(chg->wqueue, &chg->aicl_work,
+ msecs_to_jiffies(AICL_WORK_DELAY));
+ } else {
+ pr_info("aicl finish\n");
+ enable_irq(chg->aicl_irq);
+ chg->is_aicl_irq_disabled = false;
+ }
+}
+
static void max77705_chgin_isr_work(struct work_struct *work)
{
struct max77705_charger_data *chg =
@@ -607,6 +651,16 @@ static int max77705_charger_probe(struct i2c_client *i2c)
if (ret)
return dev_err_probe(dev, ret, "failed to add irq chip\n");
+ ret = devm_request_threaded_irq(dev, regmap_irq_get_virq(irq_data, MAX77705_CHGIN_I),
+ NULL, max77705_chgin_irq,
+ IRQF_TRIGGER_HIGH,
+ "chgin-irq", chg);
+ if (ret) {
+ pr_err("%s: Failed to Request IRQ (%d)\n", __func__, ret);
+ return ret;
+ }
+
+
chg->wqueue = create_singlethread_workqueue(dev_name(dev));
if (!chg->wqueue)
return dev_err_probe(dev, -ENOMEM, "failed to create workqueue\n");
@@ -617,6 +671,12 @@ static int max77705_charger_probe(struct i2c_client *i2c)
goto destroy_wq;
}
+ ret = devm_delayed_work_autocancel(dev, &chg->aicl_work, max77705_aicl_isr_work);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to initialize interrupt work\n");
+ goto destroy_wq;
+ }
+
ret = max77705_charger_initialize(chg);
if (ret) {
dev_err_probe(dev, ret, "failed to initialize charger IC\n");
@@ -632,6 +692,16 @@ static int max77705_charger_probe(struct i2c_client *i2c)
goto destroy_wq;
}
+ chg->aicl_irq = regmap_irq_get_virq(irq_data, MAX77705_AICL_I);
+ ret = devm_request_threaded_irq(dev, chg->aicl_irq,
+ NULL, max77705_aicl_irq,
+ IRQF_TRIGGER_HIGH,
+ "aicl-irq", chg);
+ if (ret) {
+ pr_err("%s: Failed to Request IRQ (%d)\n", __func__, ret);
+ 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..92fef95e4ac4 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 100
+
/* uA */
#define MAX77705_CURRENT_CHGIN_STEP 25000
#define MAX77705_CURRENT_CHG_STEP 50000
@@ -185,7 +187,10 @@ struct max77705_charger_data {
struct power_supply_battery_info *bat_info;
struct workqueue_struct *wqueue;
struct work_struct chgin_work;
+ struct delayed_work aicl_work;
struct power_supply *psy_chg;
+ int is_aicl_irq_disabled;
+ int aicl_irq;
};
#endif /* __MAX77705_CHARGER_H */
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
` (7 preceding siblings ...)
2025-09-11 17:57 ` [PATCH v3 8/9] power: supply: max77705_charger: implement aicl feature Dzmitry Sankouski
@ 2025-09-11 17:57 ` Dzmitry Sankouski
2025-09-15 15:25 ` Sebastian Reichel
8 siblings, 1 reply; 15+ messages in thread
From: Dzmitry Sankouski @ 2025-09-11 17:57 UTC (permalink / raw)
To: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Sebastian Reichel,
Luca Ceresoli
Cc: Krzysztof Kozlowski, Sebastian Reichel, linux-kernel, linux-pm,
Dzmitry Sankouski
CHARGE_CONTROL_LIMIT is a wrong property to report charge current limit,
because `CHARGE_*` attributes represents capacity, not current. The
correct attribute to report and set charge current limit is
CONSTANT_CHARGE_CURRENT.
Rename CHARGE_CONTROL_LIMIT to CONSTANT_CHARGE_CURRENT.
Fixes: 715ecbc10d6a ("power: supply: max77976: add Maxim MAX77976 charger driver")
Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
---
drivers/power/supply/max77976_charger.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c
index e6fe68cebc32..3d6ff4005533 100644
--- a/drivers/power/supply/max77976_charger.c
+++ b/drivers/power/supply/max77976_charger.c
@@ -292,10 +292,10 @@ static int max77976_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_ONLINE:
err = max77976_get_online(chg, &val->intval);
break;
- case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
val->intval = MAX77976_CHG_CC_MAX;
break;
- case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
err = max77976_get_integer(chg, CHG_CC,
MAX77976_CHG_CC_MIN,
MAX77976_CHG_CC_MAX,
@@ -330,7 +330,7 @@ static int max77976_set_property(struct power_supply *psy,
int err = 0;
switch (psp) {
- case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
err = max77976_set_integer(chg, CHG_CC,
MAX77976_CHG_CC_MIN,
MAX77976_CHG_CC_MAX,
@@ -355,7 +355,7 @@ static int max77976_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
switch (psp) {
- case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return true;
default:
@@ -368,8 +368,8 @@ static enum power_supply_property max77976_psy_props[] = {
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_ONLINE,
- POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
- POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
--
2.39.5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting
2025-09-11 17:57 ` [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting Dzmitry Sankouski
@ 2025-09-15 15:25 ` Sebastian Reichel
0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Reichel @ 2025-09-15 15:25 UTC (permalink / raw)
To: Dzmitry Sankouski
Cc: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Luca Ceresoli,
Krzysztof Kozlowski, linux-kernel, linux-pm
[-- Attachment #1: Type: text/plain, Size: 2840 bytes --]
Hi,
On Thu, Sep 11, 2025 at 08:57:17PM +0300, Dzmitry Sankouski wrote:
> CHARGE_CONTROL_LIMIT is a wrong property to report charge current limit,
> because `CHARGE_*` attributes represents capacity, not current. The
> correct attribute to report and set charge current limit is
> CONSTANT_CHARGE_CURRENT.
>
> Rename CHARGE_CONTROL_LIMIT to CONSTANT_CHARGE_CURRENT.
>
> Fixes: 715ecbc10d6a ("power: supply: max77976: add Maxim MAX77976 charger driver")
>
^^^ this newline does not belong here. Also you should reorder the
patches in this series, so that Fixes (i.e. this patch) are at the
beginning.
Greetings,
-- Sebastian
> Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> ---
> drivers/power/supply/max77976_charger.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c
> index e6fe68cebc32..3d6ff4005533 100644
> --- a/drivers/power/supply/max77976_charger.c
> +++ b/drivers/power/supply/max77976_charger.c
> @@ -292,10 +292,10 @@ static int max77976_get_property(struct power_supply *psy,
> case POWER_SUPPLY_PROP_ONLINE:
> err = max77976_get_online(chg, &val->intval);
> break;
> - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
> val->intval = MAX77976_CHG_CC_MAX;
> break;
> - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
> err = max77976_get_integer(chg, CHG_CC,
> MAX77976_CHG_CC_MIN,
> MAX77976_CHG_CC_MAX,
> @@ -330,7 +330,7 @@ static int max77976_set_property(struct power_supply *psy,
> int err = 0;
>
> switch (psp) {
> - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
> err = max77976_set_integer(chg, CHG_CC,
> MAX77976_CHG_CC_MIN,
> MAX77976_CHG_CC_MAX,
> @@ -355,7 +355,7 @@ static int max77976_property_is_writeable(struct power_supply *psy,
> enum power_supply_property psp)
> {
> switch (psp) {
> - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
> + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
> case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> return true;
> default:
> @@ -368,8 +368,8 @@ static enum power_supply_property max77976_psy_props[] = {
> POWER_SUPPLY_PROP_CHARGE_TYPE,
> POWER_SUPPLY_PROP_HEALTH,
> POWER_SUPPLY_PROP_ONLINE,
> - POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
> - POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
> + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
> + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
> POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
> POWER_SUPPLY_PROP_MODEL_NAME,
> POWER_SUPPLY_PROP_MANUFACTURER,
>
> --
> 2.39.5
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts
2025-09-11 17:57 ` [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts Dzmitry Sankouski
@ 2025-09-15 15:34 ` Sebastian Reichel
0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Reichel @ 2025-09-15 15:34 UTC (permalink / raw)
To: Dzmitry Sankouski
Cc: Chanwoo Choi, Krzysztof Kozlowski, Lee Jones, Luca Ceresoli,
Krzysztof Kozlowski, linux-kernel, linux-pm
[-- Attachment #1: Type: text/plain, Size: 2951 bytes --]
Hi,
On Thu, Sep 11, 2025 at 08:57:14PM +0300, Dzmitry Sankouski wrote:
> Current implementation uses handle_post_irq to actually handle chgin
> irq. This is not how things are meant to work in regmap-irq.
>
> Remove handle_post_irq, and request a threaded interrupt for chgin.
>
> Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
>
There shouldn't be a newline between Fixes and SoB line.
> Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> ---
> Changes to v3:
> - move irq initialization after workqueue and charger initialization
> ---
> drivers/power/supply/max77705_charger.c | 20 +++++++++++---------
> 1 file changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
> index d6a3cd98c898..5f831c25b150 100644
> --- a/drivers/power/supply/max77705_charger.c
> +++ b/drivers/power/supply/max77705_charger.c
> @@ -40,13 +40,13 @@ static enum power_supply_property max77705_charger_props[] = {
> POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
> };
>
> -static int max77705_chgin_irq(void *irq_drv_data)
> +static irqreturn_t max77705_chgin_irq(int irq, void *irq_drv_data)
> {
> struct max77705_charger_data *chg = irq_drv_data;
>
> queue_work(chg->wqueue, &chg->chgin_work);
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static const struct regmap_irq max77705_charger_irqs[] = {
> @@ -64,7 +64,6 @@ static struct regmap_irq_chip max77705_charger_irq_chip = {
> .name = "max77705-charger",
> .status_base = MAX77705_CHG_REG_INT,
> .mask_base = MAX77705_CHG_REG_INT_MASK,
> - .handle_post_irq = max77705_chgin_irq,
> .num_regs = 1,
> .irqs = max77705_charger_irqs,
> .num_irqs = ARRAY_SIZE(max77705_charger_irqs),
> @@ -593,12 +592,6 @@ static int max77705_charger_probe(struct i2c_client *i2c)
> "cannot allocate regmap field\n");
> }
>
> - ret = regmap_update_bits(chg->regmap,
> - MAX77705_CHG_REG_INT_MASK,
> - MAX77705_CHGIN_IM, 0);
> - if (ret)
> - return ret;
> -
> pscfg.fwnode = dev_fwnode(dev);
> pscfg.drv_data = chg;
>
> @@ -630,6 +623,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_CHGIN_I),
> + NULL, max77705_chgin_irq,
> + IRQF_TRIGGER_HIGH,
I guess IRQF_TRIGGER_NONE considering this is not a physical IRQ?
> + "chgin-irq", chg);
wrong indent
> + if (ret) {
> + pr_err("%s: Failed to Request IRQ (%d)\n", __func__, ret);
dev_err_probe() and no need to print __func__, see how it works in
other drivers.
Greetings,
-- Sebastian
> + goto destroy_wq;
> + }
> +
> ret = max77705_charger_enable(chg);
> if (ret) {
> dev_err_probe(dev, ret, "failed to enable charge\n");
>
> --
> 2.39.5
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/9] mfd: max77705: max77705_charger: move active discharge setting to mfd parent
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
@ 2025-09-15 15:42 ` Sebastian Reichel
2025-09-16 8:45 ` Lee Jones
2025-09-16 8:43 ` [PATCH v3 1/9] power: supply: " Lee Jones
1 sibling, 1 reply; 15+ messages in thread
From: Sebastian Reichel @ 2025-09-15 15:42 UTC (permalink / raw)
To: Dzmitry Sankouski, Lee Jones
Cc: Chanwoo Choi, Krzysztof Kozlowski, Luca Ceresoli,
Krzysztof Kozlowski, linux-kernel, linux-pm
[-- Attachment #1: Type: text/plain, Size: 2513 bytes --]
Hi,
On Thu, Sep 11, 2025 at 08:57:09PM +0300, Dzmitry Sankouski wrote:
> Active discharge setting is a part of MFD top level i2c device, hence
> cannot be controlled by charger. Writing to MAX77705_PMIC_REG_MAINCTRL1
> register from charger driver is a mistake.
>
> Move active discharge setting to MFD parent driver.
This is quite confusing to read without knowing the driver. I think
it's betterly described like this:
Active discharge setting is a part of MFD top level register range,
hence cannot be controlled by the charger regmap, which only offers
access to the charger registers.
Move active discharge setting to MFD parent driver to fix the issue.
>
> Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
>
No newline after Fixes:
> Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> ---
> drivers/mfd/max77705.c | 3 +++
> drivers/power/supply/max77705_charger.c | 3 ---
> 2 files changed, 3 insertions(+), 3 deletions(-)
I think it's sensible to use 'mfd: max77705:' prefix for this patch,
otherwise Lee easily misses that this patchset has anything to do
with his subsystem :)
Greetings,
-- Sebastian
>
> diff --git a/drivers/mfd/max77705.c b/drivers/mfd/max77705.c
> index 6b263bacb8c2..ff07d0e0d5f8 100644
> --- a/drivers/mfd/max77705.c
> +++ b/drivers/mfd/max77705.c
> @@ -108,6 +108,9 @@ static int max77705_i2c_probe(struct i2c_client *i2c)
> if (pmic_rev != MAX77705_PASS3)
> return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
>
> + /* Active Discharge Enable */
> + regmap_update_bits(max77705->regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
> +
> ret = devm_regmap_add_irq_chip(dev, max77705->regmap,
> i2c->irq,
> IRQF_ONESHOT | IRQF_SHARED, 0,
> diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
> index 329b430d0e50..3b75c82b9b9e 100644
> --- a/drivers/power/supply/max77705_charger.c
> +++ b/drivers/power/supply/max77705_charger.c
> @@ -487,9 +487,6 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
> regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
> MAX77705_WDTEN_MASK, 0);
>
> - /* Active Discharge Enable */
> - regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
> -
> /* VBYPSET=5.0V */
> regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
>
>
> --
> 2.39.5
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
2025-09-15 15:42 ` [PATCH v3 1/9] mfd: max77705: " Sebastian Reichel
@ 2025-09-16 8:43 ` Lee Jones
1 sibling, 0 replies; 15+ messages in thread
From: Lee Jones @ 2025-09-16 8:43 UTC (permalink / raw)
To: Dzmitry Sankouski
Cc: Chanwoo Choi, Krzysztof Kozlowski, Sebastian Reichel,
Luca Ceresoli, Krzysztof Kozlowski, Sebastian Reichel,
linux-kernel, linux-pm
On Thu, 11 Sep 2025, Dzmitry Sankouski wrote:
> Active discharge setting is a part of MFD top level i2c device, hence
> cannot be controlled by charger. Writing to MAX77705_PMIC_REG_MAINCTRL1
> register from charger driver is a mistake.
>
> Move active discharge setting to MFD parent driver.
>
> Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
>
> Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> ---
> drivers/mfd/max77705.c | 3 +++
> drivers/power/supply/max77705_charger.c | 3 ---
> 2 files changed, 3 insertions(+), 3 deletions(-)
Acked-by: Lee Jones <lee@kernel.org>
> diff --git a/drivers/mfd/max77705.c b/drivers/mfd/max77705.c
> index 6b263bacb8c2..ff07d0e0d5f8 100644
> --- a/drivers/mfd/max77705.c
> +++ b/drivers/mfd/max77705.c
> @@ -108,6 +108,9 @@ static int max77705_i2c_probe(struct i2c_client *i2c)
> if (pmic_rev != MAX77705_PASS3)
> return dev_err_probe(dev, -ENODEV, "Rev.0x%x is not tested\n", pmic_rev);
>
> + /* Active Discharge Enable */
> + regmap_update_bits(max77705->regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
> +
> ret = devm_regmap_add_irq_chip(dev, max77705->regmap,
> i2c->irq,
> IRQF_ONESHOT | IRQF_SHARED, 0,
> diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c
> index 329b430d0e50..3b75c82b9b9e 100644
> --- a/drivers/power/supply/max77705_charger.c
> +++ b/drivers/power/supply/max77705_charger.c
> @@ -487,9 +487,6 @@ static void max77705_charger_initialize(struct max77705_charger_data *chg)
> regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_00,
> MAX77705_WDTEN_MASK, 0);
>
> - /* Active Discharge Enable */
> - regmap_update_bits(regmap, MAX77705_PMIC_REG_MAINCTRL1, 1, 1);
> -
> /* VBYPSET=5.0V */
> regmap_update_bits(regmap, MAX77705_CHG_REG_CNFG_11, MAX77705_VBYPSET_MASK, 0);
>
>
> --
> 2.39.5
>
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v3 1/9] mfd: max77705: max77705_charger: move active discharge setting to mfd parent
2025-09-15 15:42 ` [PATCH v3 1/9] mfd: max77705: " Sebastian Reichel
@ 2025-09-16 8:45 ` Lee Jones
0 siblings, 0 replies; 15+ messages in thread
From: Lee Jones @ 2025-09-16 8:45 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Dzmitry Sankouski, Chanwoo Choi, Krzysztof Kozlowski,
Luca Ceresoli, Krzysztof Kozlowski, linux-kernel, linux-pm
On Mon, 15 Sep 2025, Sebastian Reichel wrote:
> Hi,
>
> On Thu, Sep 11, 2025 at 08:57:09PM +0300, Dzmitry Sankouski wrote:
> > Active discharge setting is a part of MFD top level i2c device, hence
> > cannot be controlled by charger. Writing to MAX77705_PMIC_REG_MAINCTRL1
> > register from charger driver is a mistake.
> >
> > Move active discharge setting to MFD parent driver.
>
> This is quite confusing to read without knowing the driver. I think
> it's betterly described like this:
>
> Active discharge setting is a part of MFD top level register range,
> hence cannot be controlled by the charger regmap, which only offers
> access to the charger registers.
>
> Move active discharge setting to MFD parent driver to fix the issue.
>
> >
> > Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705")
> >
>
> No newline after Fixes:
>
> > Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> > ---
> > drivers/mfd/max77705.c | 3 +++
> > drivers/power/supply/max77705_charger.c | 3 ---
> > 2 files changed, 3 insertions(+), 3 deletions(-)
>
> I think it's sensible to use 'mfd: max77705:' prefix for this patch,
> otherwise Lee easily misses that this patchset has anything to do
> with his subsystem :)
=:-)
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-09-16 8:46 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-11 17:57 [PATCH v3 0/9] power: supply: fixes and improvements for max77(705,976) chargers Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 1/9] power: supply: max77705_charger: move active discharge setting to mfd parent Dzmitry Sankouski
2025-09-15 15:42 ` [PATCH v3 1/9] mfd: max77705: " Sebastian Reichel
2025-09-16 8:45 ` Lee Jones
2025-09-16 8:43 ` [PATCH v3 1/9] power: supply: " Lee Jones
2025-09-11 17:57 ` [PATCH v3 2/9] power: supply: max77705_charger: refactoring: rename charger to chg Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 3/9] power: supply: max77705_charger: use regfields for config registers Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 4/9] power: supply: max77705_charger: return error when config fails Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 5/9] power: supply: max77705_charger: add writable properties Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 6/9] power: supply: max77705_charger: rework interrupts Dzmitry Sankouski
2025-09-15 15:34 ` Sebastian Reichel
2025-09-11 17:57 ` [PATCH v3 7/9] power: supply: max77705_charger: use REGMAP_IRQ_REG_LINE macro Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 8/9] power: supply: max77705_charger: implement aicl feature Dzmitry Sankouski
2025-09-11 17:57 ` [PATCH v3 9/9] power: supply: max77976_charger: fix constant current reporting Dzmitry Sankouski
2025-09-15 15:25 ` Sebastian Reichel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).