From 75a0e1e0b86078687c3c6a05107a98c7e59a65a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 12:18:16 +0200 Subject: power: Drop unused assignment of platform_device_id driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver explicitly set the .driver_data member of struct platform_device_id to zero without relying on that value. Drop this unused assignments. While touching this array unify spacing, use a named initializer for .name and drop trailing commas after the list terminators. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Tzung-Bi Shih Link: https://patch.msgid.link/ba3589f74a12d86fb02ecb9fa2e89532188c22a0.1780048925.git.u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/qemu-virt-ctrl.c | 2 +- drivers/power/supply/charger-manager.c | 4 ++-- drivers/power/supply/cros_charge-control.c | 4 ++-- drivers/power/supply/cros_peripheral_charger.c | 4 ++-- drivers/power/supply/cros_usbpd-charger.c | 4 ++-- drivers/power/supply/max77693_charger.c | 2 +- drivers/power/supply/max8997_charger.c | 2 +- drivers/power/supply/mt6360_charger.c | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/power/reset/qemu-virt-ctrl.c b/drivers/power/reset/qemu-virt-ctrl.c index 01409dfe2265..aa8355270b2c 100644 --- a/drivers/power/reset/qemu-virt-ctrl.c +++ b/drivers/power/reset/qemu-virt-ctrl.c @@ -103,7 +103,7 @@ static int qemu_virt_ctrl_probe(struct platform_device *pdev) } static const struct platform_device_id qemu_virt_ctrl_id[] = { - { "qemu-virt-ctrl", 0 }, + { .name = "qemu-virt-ctrl" }, { } }; MODULE_DEVICE_TABLE(platform, qemu_virt_ctrl_id); diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index c49e0e4d02f7..5dc9cd37d697 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1653,8 +1653,8 @@ static void charger_manager_remove(struct platform_device *pdev) } static const struct platform_device_id charger_manager_id[] = { - { "charger-manager", 0 }, - { }, + { .name = "charger-manager" }, + { } }; MODULE_DEVICE_TABLE(platform, charger_manager_id); diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c index 53e6a77e03fc..b489325be816 100644 --- a/drivers/power/supply/cros_charge-control.c +++ b/drivers/power/supply/cros_charge-control.c @@ -320,8 +320,8 @@ static int cros_chctl_probe(struct platform_device *pdev) } static const struct platform_device_id cros_chctl_id[] = { - { "cros-charge-control", 0 }, - {} + { .name = "cros-charge-control" }, + { } }; static struct platform_driver cros_chctl_driver = { diff --git a/drivers/power/supply/cros_peripheral_charger.c b/drivers/power/supply/cros_peripheral_charger.c index f132fad288cb..9f67a6dbd94e 100644 --- a/drivers/power/supply/cros_peripheral_charger.c +++ b/drivers/power/supply/cros_peripheral_charger.c @@ -369,8 +369,8 @@ static int __maybe_unused cros_pchg_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cros_pchg_pm_ops, NULL, cros_pchg_resume); static const struct platform_device_id cros_pchg_id[] = { - { DRV_NAME, 0 }, - {} + { .name = DRV_NAME }, + { } }; MODULE_DEVICE_TABLE(platform, cros_pchg_id); diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c index 7d3e676a951c..308e1d4e6dd8 100644 --- a/drivers/power/supply/cros_usbpd-charger.c +++ b/drivers/power/supply/cros_usbpd-charger.c @@ -707,8 +707,8 @@ static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL, cros_usbpd_charger_resume); static const struct platform_device_id cros_usbpd_charger_id[] = { - { DRV_NAME, 0 }, - {} + { .name = DRV_NAME }, + { } }; MODULE_DEVICE_TABLE(platform, cros_usbpd_charger_id); diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c index 027d6a539b65..76c58b32a374 100644 --- a/drivers/power/supply/max77693_charger.c +++ b/drivers/power/supply/max77693_charger.c @@ -788,7 +788,7 @@ static void max77693_charger_remove(struct platform_device *pdev) } static const struct platform_device_id max77693_charger_id[] = { - { "max77693-charger", 0, }, + { .name = "max77693-charger" }, { } }; MODULE_DEVICE_TABLE(platform, max77693_charger_id); diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index 1ec3535a257d..19da9eff0372 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c @@ -268,7 +268,7 @@ static int max8997_battery_probe(struct platform_device *pdev) } static const struct platform_device_id max8997_battery_id[] = { - { "max8997-battery", 0 }, + { .name = "max8997-battery" }, { } }; MODULE_DEVICE_TABLE(platform, max8997_battery_id); diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c index 77747eb51667..69955f255091 100644 --- a/drivers/power/supply/mt6360_charger.c +++ b/drivers/power/supply/mt6360_charger.c @@ -841,8 +841,8 @@ static const struct of_device_id __maybe_unused mt6360_charger_of_id[] = { MODULE_DEVICE_TABLE(of, mt6360_charger_of_id); static const struct platform_device_id mt6360_charger_id[] = { - { "mt6360-chg", 0 }, - {}, + { .name = "mt6360-chg" }, + { } }; MODULE_DEVICE_TABLE(platform, mt6360_charger_id); -- cgit v1.2.3 From 37258ad1f3a52ea442c32b3c92ad7146e74050c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 12:18:17 +0200 Subject: power: supply: max14577: Drop driver data in of and platform device id arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These values are not used, the relevant distinction happens in the mfd parent driver. So they can be dropped. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/62e1b01a6591dd59406a78f2bbca619d734a9150.1780048925.git.u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max14577_charger.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c index 63077d38ea30..a15d94942184 100644 --- a/drivers/power/supply/max14577_charger.c +++ b/drivers/power/supply/max14577_charger.c @@ -613,18 +613,16 @@ static void max14577_charger_remove(struct platform_device *pdev) } static const struct platform_device_id max14577_charger_id[] = { - { "max14577-charger", MAXIM_DEVICE_TYPE_MAX14577, }, - { "max77836-charger", MAXIM_DEVICE_TYPE_MAX77836, }, + { .name = "max14577-charger" }, + { .name = "max77836-charger" }, { } }; MODULE_DEVICE_TABLE(platform, max14577_charger_id); static const struct of_device_id of_max14577_charger_dt_match[] = { - { .compatible = "maxim,max14577-charger", - .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, }, - { .compatible = "maxim,max77836-charger", - .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, }, - { }, + { .compatible = "maxim,max14577-charger" }, + { .compatible = "maxim,max77836-charger" }, + { } }; MODULE_DEVICE_TABLE(of, of_max14577_charger_dt_match); -- cgit v1.2.3 From e28f7498dd819878b8acacb89c4c073a646feea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 12:18:19 +0200 Subject: power: Use named initializers for platform_device_id arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Named initializers are better readable and more robust to changes of the struct definition. This robustness is relevant for a planned change to struct platform_device_id replacing .driver_data by an anonymous union. While touching these arrays unify spacing and usage of commas. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Matti Vaittinen Reviewed-by: Joshua Peisach Link: https://patch.msgid.link/1ceacf4f9c3f827bcad85b378aa04cdca1c04635.1780048925.git.u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/spacemit-p1-reboot.c | 4 ++-- drivers/power/reset/tps65086-restart.c | 2 +- drivers/power/supply/bd71828-power.c | 8 ++++---- drivers/power/supply/macsmc-power.c | 2 +- drivers/power/supply/max77759_charger.c | 2 +- drivers/power/supply/max8998_charger.c | 2 +- drivers/power/supply/pf1550-charger.c | 2 +- drivers/power/supply/rt5033_charger.c | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/power/reset/spacemit-p1-reboot.c b/drivers/power/reset/spacemit-p1-reboot.c index 9ec3d1fff8f3..84026b042ea2 100644 --- a/drivers/power/reset/spacemit-p1-reboot.c +++ b/drivers/power/reset/spacemit-p1-reboot.c @@ -70,8 +70,8 @@ static int spacemit_p1_reboot_probe(struct platform_device *pdev) } static const struct platform_device_id spacemit_p1_reboot_id_table[] = { - { "spacemit-p1-reboot", }, - { /* sentinel */ }, + { .name = "spacemit-p1-reboot" }, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, spacemit_p1_reboot_id_table); diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c index 6976dbcac74f..37d248a9df17 100644 --- a/drivers/power/reset/tps65086-restart.c +++ b/drivers/power/reset/tps65086-restart.c @@ -41,7 +41,7 @@ static int tps65086_restart_probe(struct platform_device *pdev) } static const struct platform_device_id tps65086_restart_id_table[] = { - { "tps65086-reset", }, + { .name = "tps65086-reset" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, tps65086_restart_id_table); diff --git a/drivers/power/supply/bd71828-power.c b/drivers/power/supply/bd71828-power.c index 5e78faa0a4aa..5ab514ff5c65 100644 --- a/drivers/power/supply/bd71828-power.c +++ b/drivers/power/supply/bd71828-power.c @@ -1184,10 +1184,10 @@ static int bd71828_power_probe(struct platform_device *pdev) } static const struct platform_device_id bd71828_charger_id[] = { - { "bd71815-power", ROHM_CHIP_TYPE_BD71815 }, - { "bd71828-power", ROHM_CHIP_TYPE_BD71828 }, - { "bd72720-power", ROHM_CHIP_TYPE_BD72720 }, - { }, + { .name = "bd71815-power", .driver_data = ROHM_CHIP_TYPE_BD71815 }, + { .name = "bd71828-power", .driver_data = ROHM_CHIP_TYPE_BD71828 }, + { .name = "bd72720-power", .driver_data = ROHM_CHIP_TYPE_BD72720 }, + { } }; MODULE_DEVICE_TABLE(platform, bd71828_charger_id); diff --git a/drivers/power/supply/macsmc-power.c b/drivers/power/supply/macsmc-power.c index 33ca07460f3a..ced07f71e0a8 100644 --- a/drivers/power/supply/macsmc-power.c +++ b/drivers/power/supply/macsmc-power.c @@ -834,7 +834,7 @@ static void macsmc_power_remove(struct platform_device *pdev) } static const struct platform_device_id macsmc_power_id[] = { - { "macsmc-power" }, + { .name = "macsmc-power" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, macsmc_power_id); diff --git a/drivers/power/supply/max77759_charger.c b/drivers/power/supply/max77759_charger.c index 9bb414599f16..c606d7bafcb8 100644 --- a/drivers/power/supply/max77759_charger.c +++ b/drivers/power/supply/max77759_charger.c @@ -754,7 +754,7 @@ static int max77759_charger_probe(struct platform_device *pdev) } static const struct platform_device_id max77759_charger_id[] = { - { .name = "max77759-charger", }, + { .name = "max77759-charger" }, { } }; MODULE_DEVICE_TABLE(platform, max77759_charger_id); diff --git a/drivers/power/supply/max8998_charger.c b/drivers/power/supply/max8998_charger.c index 418b882b163d..b0eda2b51e7f 100644 --- a/drivers/power/supply/max8998_charger.c +++ b/drivers/power/supply/max8998_charger.c @@ -188,7 +188,7 @@ static int max8998_battery_probe(struct platform_device *pdev) } static const struct platform_device_id max8998_battery_id[] = { - { "max8998-battery", TYPE_MAX8998 }, + { .name = "max8998-battery" }, { } }; MODULE_DEVICE_TABLE(platform, max8998_battery_id); diff --git a/drivers/power/supply/pf1550-charger.c b/drivers/power/supply/pf1550-charger.c index a457862ef461..41036f4cb64a 100644 --- a/drivers/power/supply/pf1550-charger.c +++ b/drivers/power/supply/pf1550-charger.c @@ -622,7 +622,7 @@ static int pf1550_charger_probe(struct platform_device *pdev) } static const struct platform_device_id pf1550_charger_id[] = { - { "pf1550-charger", }, + { .name = "pf1550-charger" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, pf1550_charger_id); diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c index de724f23e453..536ab29b657d 100644 --- a/drivers/power/supply/rt5033_charger.c +++ b/drivers/power/supply/rt5033_charger.c @@ -727,7 +727,7 @@ out: } static const struct platform_device_id rt5033_charger_id[] = { - { "rt5033-charger", }, + { .name = "rt5033-charger" }, { } }; MODULE_DEVICE_TABLE(platform, rt5033_charger_id); -- cgit v1.2.3 From eb7ed650e5960fc303130704d1e29d18a7d0e1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 12:18:20 +0200 Subject: power: supply: mt6360_charger: Use of match table unconditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mt6360_charger_of_id is defined unconditionally, so it doesn't make sense to not use it for the driver's .of_match_table member. Signed-off-by: Uwe Kleine-König (The Capable Hub) Link: https://patch.msgid.link/ff94de5fb3ee6aeb1c0256e1a00c1c5ac350b430.1780048925.git.u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/mt6360_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c index 69955f255091..d3b0731f6562 100644 --- a/drivers/power/supply/mt6360_charger.c +++ b/drivers/power/supply/mt6360_charger.c @@ -849,7 +849,7 @@ MODULE_DEVICE_TABLE(platform, mt6360_charger_id); static struct platform_driver mt6360_charger_driver = { .driver = { .name = "mt6360-chg", - .of_match_table = of_match_ptr(mt6360_charger_of_id), + .of_match_table = mt6360_charger_of_id, }, .probe = mt6360_charger_probe, .id_table = mt6360_charger_id, -- cgit v1.2.3 From e3f669bed32287ae72c05a4ddab4a6687b0e62ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 12:18:21 +0200 Subject: power: Unify code style for platform_device_id arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a single space in the list terminator and remove the trailing comma. Signed-off-by: Uwe Kleine-König (The Capable Hub) Acked-by: Chen-Yu Tsai Link: https://patch.msgid.link/d840a6f83e3736510d7d859bf48c9bce04876b0c.1780048925.git.u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 2 +- drivers/power/supply/axp288_fuel_gauge.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index ea0f5caee8f0..24a8b1ee2fec 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -955,7 +955,7 @@ static int axp288_charger_probe(struct platform_device *pdev) static const struct platform_device_id axp288_charger_id_table[] = { { .name = "axp288_charger" }, - {}, + { } }; MODULE_DEVICE_TABLE(platform, axp288_charger_id_table); diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index a3d71fc72064..5af334c0a980 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -799,7 +799,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev) static const struct platform_device_id axp288_fg_id_table[] = { { .name = DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(platform, axp288_fg_id_table); -- cgit v1.2.3 From b6c7feeb604262f31a4279bd66aa300ad0903255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= Date: Thu, 28 May 2026 18:18:24 +0200 Subject: power: reset: sc27xx: Add platform_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the poweroff driver for SC27xx-series PMICs probe automatically. Since the device representing the poweroff functionality of the SC27xx PMIC is not supposed to have a dedicated device tree node without any corresponding DT resources [1], an of_device_id table cannot be used here. Instead, use a platform_device_id table to match the poweroff sub-device instantiated by the parent MFD driver. [1]: https://lore.kernel.org/all/20251002025344.GA2958334-robh@kernel.org/ Signed-off-by: Otto Pflüger Link: https://patch.msgid.link/20260528-sc27xx-mfd-cells-v3-2-25cd685d2743@abscue.de Signed-off-by: Sebastian Reichel --- drivers/power/reset/sc27xx-poweroff.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c index 393bd1c33b73..6376706bf561 100644 --- a/drivers/power/reset/sc27xx-poweroff.c +++ b/drivers/power/reset/sc27xx-poweroff.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -70,11 +71,18 @@ static int sc27xx_poweroff_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id sc27xx_poweroff_id_table[] = { + { "sc2731-poweroff" }, + { } +}; +MODULE_DEVICE_TABLE(platform, sc27xx_poweroff_id_table); + static struct platform_driver sc27xx_poweroff_driver = { .probe = sc27xx_poweroff_probe, .driver = { .name = "sc27xx-poweroff", }, + .id_table = sc27xx_poweroff_id_table, }; module_platform_driver(sc27xx_poweroff_driver); -- cgit v1.2.3 From 63f2279aa1eca55c0f6403f488739f1ff54d8564 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 6 Apr 2026 16:57:49 -0400 Subject: power: supply: max17042_battery: Put LSB units into defines Signed-off-by: Sebastian Krzyszkowiak Link: https://patch.msgid.link/20260406205759.493288-2-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 38 +++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 167fb3fb3732..103ce1d47aa8 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -52,6 +52,13 @@ #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */ +#define MAX17042_CURRENT_LSB 1562500ll /* 1.5625µV/Rsense */ +#define MAX17042_CAPACITY_LSB 5000000ll /* 5.0µVH/Rsense */ +#define MAX17042_TIME_LSB 5625 / 1000 /* s */ +#define MAX17042_VOLTAGE_LSB 625 / 8 /* µV */ +#define MAX17042_RESISTANCE_LSB 1 / 4096 /* Ω */ +#define MAX17042_TEMPERATURE_LSB 1 / 256 /* °C */ + struct max17042_chip { struct device *dev; struct regmap *regmap; @@ -107,8 +114,7 @@ static int max17042_get_temperature(struct max17042_chip *chip, int *temp) *temp = sign_extend32(data, 15); /* The value is converted into deci-centigrade scale */ - /* Units of LSB = 1 / 256 degree Celsius */ - *temp = *temp * 10 / 256; + *temp = *temp * 10 * MAX17042_TEMPERATURE_LSB; return 0; } @@ -185,7 +191,7 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health) goto health_error; /* bits [0-3] unused */ - vavg = val * 625 / 8; + vavg = val * MAX17042_VOLTAGE_LSB; /* Convert to millivolts */ vavg /= 1000; @@ -194,7 +200,7 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health) goto health_error; /* bits [0-3] unused */ - vbatt = val * 625 / 8; + vbatt = val * MAX17042_VOLTAGE_LSB; /* Convert to millivolts */ vbatt /= 1000; @@ -301,21 +307,21 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - val->intval = data * 625 / 8; + val->intval = data * MAX17042_VOLTAGE_LSB; break; case POWER_SUPPLY_PROP_VOLTAGE_AVG: ret = regmap_read(map, MAX17042_AvgVCELL, &data); if (ret < 0) return ret; - val->intval = data * 625 / 8; + val->intval = data * MAX17042_VOLTAGE_LSB; break; case POWER_SUPPLY_PROP_VOLTAGE_OCV: ret = regmap_read(map, MAX17042_OCVInternal, &data); if (ret < 0) return ret; - val->intval = data * 625 / 8; + val->intval = data * MAX17042_VOLTAGE_LSB; break; case POWER_SUPPLY_PROP_CAPACITY: if (chip->pdata->enable_current_sense) @@ -332,7 +338,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = data * 5000000ll; + data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); do_div(data64, chip->pdata->r_sns); @@ -343,7 +349,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = data * 5000000ll; + data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); do_div(data64, chip->pdata->r_sns); @@ -354,7 +360,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = data * 5000000ll; + data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); do_div(data64, chip->pdata->r_sns); @@ -365,7 +371,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = sign_extend64(data, 15) * 5000000ll; + data64 = sign_extend64(data, 15) * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; data64 = div_s64(data64, MAX17042_DEFAULT_TASK_PERIOD); val->intval = div_s64(data64, chip->pdata->r_sns); @@ -409,7 +415,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = sign_extend64(data, 15) * 1562500ll; + data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB; val->intval = div_s64(data64, chip->pdata->r_sns); } else { return -EINVAL; @@ -421,7 +427,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = sign_extend64(data, 15) * 1562500ll; + data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB; val->intval = div_s64(data64, chip->pdata->r_sns); } else { return -EINVAL; @@ -432,7 +438,7 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - data64 = data * 1562500ll; + data64 = data * MAX17042_CURRENT_LSB; val->intval = div_s64(data64, chip->pdata->r_sns); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: @@ -444,7 +450,7 @@ static int max17042_get_property(struct power_supply *psy, if (data == U16_MAX) return -ENODATA; - val->intval = data * 5625 / 1000; + val->intval = data * MAX17042_TIME_LSB; break; case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055 && @@ -459,7 +465,7 @@ static int max17042_get_property(struct power_supply *psy, if (data == U16_MAX) return -ENODATA; - val->intval = data * 5625 / 1000; + val->intval = data * MAX17042_TIME_LSB; break; default: return -EINVAL; -- cgit v1.2.3 From 0a733cd247eb9bda928049d72ab7ae16b9bff353 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 6 Apr 2026 16:57:50 -0400 Subject: power: supply: max17042_battery: Use Current register in get_status It can take a while for AvgCurrent to adjust after (un)plugging the charger. Use the instantaneous value in order to not confuse the userspace. While at that, don't do unit conversion of the read value. The current code was prone to overflows and we only care about the sign anyway. Signed-off-by: Sebastian Krzyszkowiak Link: https://patch.msgid.link/20260406205759.493288-3-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 103ce1d47aa8..e896cd169a91 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -121,7 +121,7 @@ static int max17042_get_temperature(struct max17042_chip *chip, int *temp) static int max17042_get_status(struct max17042_chip *chip, int *status) { int ret, charge_full, charge_now; - int avg_current; + int current_now; u32 data; ret = power_supply_am_i_supplied(chip->battery); @@ -166,14 +166,13 @@ static int max17042_get_status(struct max17042_chip *chip, int *status) return 0; } - ret = regmap_read(chip->regmap, MAX17042_AvgCurrent, &data); + ret = regmap_read(chip->regmap, MAX17042_Current, &data); if (ret < 0) return ret; - avg_current = sign_extend32(data, 15); - avg_current *= 1562500 / chip->pdata->r_sns; + current_now = sign_extend32(data, 15); - if (avg_current > 0) + if (current_now > 0) *status = POWER_SUPPLY_STATUS_CHARGING; else *status = POWER_SUPPLY_STATUS_DISCHARGING; -- cgit v1.2.3 From 6649d933f5b91284750b4ab98ca3c7035e4f04ee Mon Sep 17 00:00:00 2001 From: Vincent Cloutier Date: Mon, 6 Apr 2026 16:57:52 -0400 Subject: power: supply: max17042_battery: Route MAX17055 SOC alerts through dSOCi Use MAX17055 dSOCi for ordinary 1% state-of-charge notifications and leave SALRT configured for the critical low-battery threshold instead of reprogramming the SALRT window on every alert. Signed-off-by: Vincent Cloutier Link: https://patch.msgid.link/20260406205759.493288-5-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 39 ++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index e896cd169a91..d05202974a71 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -27,6 +27,7 @@ /* Status register bits */ #define STATUS_POR_BIT (1 << 1) #define STATUS_BST_BIT (1 << 3) +#define STATUS_DSOCI_BIT (1 << 7) #define STATUS_VMN_BIT (1 << 8) #define STATUS_TMN_BIT (1 << 9) #define STATUS_SMN_BIT (1 << 10) @@ -38,6 +39,7 @@ /* Interrupt mask bits */ #define CFG_ALRT_BIT_ENBL (1 << 2) +#define CFG2_DSOCI_BIT_ENBL (1 << 7) #define VFSOC0_LOCK 0x0000 #define VFSOC0_UNLOCK 0x0080 @@ -52,6 +54,8 @@ #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */ +#define MAX17042_CRITICAL_SOC 0x03 + #define MAX17042_CURRENT_LSB 1562500ll /* 1.5625µV/Rsense */ #define MAX17042_CAPACITY_LSB 5000000ll /* 5.0µVH/Rsense */ #define MAX17042_TIME_LSB 5625 / 1000 /* s */ @@ -903,6 +907,34 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) regmap_write(map, MAX17042_SALRT_Th, soc_tr); } +static void max17042_set_critical_soc_threshold(struct max17042_chip *chip) +{ + struct regmap *map = chip->regmap; + u32 soc; + + if (chip->pdata->enable_current_sense) + regmap_read(map, MAX17042_RepSOC, &soc); + else + regmap_read(map, MAX17042_VFSOC, &soc); + + regmap_write(map, MAX17042_SALRT_Th, + ((soc >> 8) >= MAX17042_CRITICAL_SOC) ? + 0xff00 + MAX17042_CRITICAL_SOC : 0xff00); +} + +static void max17042_enable_soc_alerts(struct max17042_chip *chip) +{ + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) { + regmap_update_bits(chip->regmap, MAX17055_Config2, + CFG2_DSOCI_BIT_ENBL, + CFG2_DSOCI_BIT_ENBL); + max17042_set_critical_soc_threshold(chip); + return; + } + + max17042_set_soc_threshold(chip, 1); +} + static irqreturn_t max17042_thread_handler(int id, void *dev) { struct max17042_chip *chip = dev; @@ -913,9 +945,10 @@ static irqreturn_t max17042_thread_handler(int id, void *dev) if (ret) return IRQ_HANDLED; - if ((val & STATUS_SMN_BIT) || (val & STATUS_SMX_BIT)) { + if ((val & STATUS_SMN_BIT) || (val & STATUS_SMX_BIT) || + (val & STATUS_DSOCI_BIT)) { dev_dbg(chip->dev, "SOC threshold INTR\n"); - max17042_set_soc_threshold(chip, 1); + max17042_enable_soc_alerts(chip); } /* we implicitly handle all alerts via power_supply_changed */ @@ -1201,7 +1234,7 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq regmap_update_bits(chip->regmap, MAX17042_CONFIG, CFG_ALRT_BIT_ENBL, CFG_ALRT_BIT_ENBL); - max17042_set_soc_threshold(chip, 1); + max17042_enable_soc_alerts(chip); } else { irq = 0; if (ret != -EBUSY) -- cgit v1.2.3 From 601885ffb5e9a0fd30c40a6c8cffeed2a04d695e Mon Sep 17 00:00:00 2001 From: Vincent Cloutier Date: Mon, 6 Apr 2026 16:57:53 -0400 Subject: power: supply: max17042_battery: Keep only critical alerts during suspend Disable MAX17055 dSOCi while the system is suspended so state-of-charge changes do not wake the system repeatedly. Leave SALRT armed for the critical low-battery threshold and restore runtime alert handling on resume. Signed-off-by: Vincent Cloutier Link: https://patch.msgid.link/20260406205759.493288-6-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index d05202974a71..2110b87bdc4b 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -935,6 +935,16 @@ static void max17042_enable_soc_alerts(struct max17042_chip *chip) max17042_set_soc_threshold(chip, 1); } +static void max17042_suspend_soc_alerts(struct max17042_chip *chip) +{ + if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055) + return; + + regmap_update_bits(chip->regmap, MAX17055_Config2, + CFG2_DSOCI_BIT_ENBL, 0); + max17042_set_critical_soc_threshold(chip); +} + static irqreturn_t max17042_thread_handler(int id, void *dev) { struct max17042_chip *chip = dev; @@ -1310,6 +1320,7 @@ static int max17042_suspend(struct device *dev) */ if (chip->irq) { disable_irq(chip->irq); + max17042_suspend_soc_alerts(chip); enable_irq_wake(chip->irq); } @@ -1323,8 +1334,8 @@ static int max17042_resume(struct device *dev) if (chip->irq) { disable_irq_wake(chip->irq); enable_irq(chip->irq); - /* re-program the SOC thresholds to 1% change */ - max17042_set_soc_threshold(chip, 1); + /* re-arm runtime SOC alerts */ + max17042_enable_soc_alerts(chip); } return 0; -- cgit v1.2.3 From d0c54c6f9dab20f93185df7722ed133097aaccb3 Mon Sep 17 00:00:00 2001 From: Vincent Cloutier Date: Mon, 6 Apr 2026 16:57:54 -0400 Subject: power: supply: max17042_battery: Remove unused platform-data plumbing No in-tree user still provides `max17042_platform_data` or `max17042_reg_data`. Move the simple runtime fields into `struct max17042_chip`, populate them directly from DT or the default hardware state, and drop the unused public platform-data interface. While here, write the MAX17047/MAX17050 default `FullSOCThr` value directly in probe instead of carrying it through an `init_data` table. Signed-off-by: Vincent Cloutier Link: https://patch.msgid.link/20260406205759.493288-7-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 204 ++++++++++++++------------------ include/linux/power/max17042_battery.h | 29 ----- 2 files changed, 89 insertions(+), 144 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 2110b87bdc4b..446f8926a8e0 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -68,11 +68,18 @@ struct max17042_chip { struct regmap *regmap; struct power_supply *battery; enum max170xx_chip_type chip_type; - struct max17042_platform_data *pdata; + struct max17042_config_data *config_data; struct work_struct work; int init_complete; int irq; int task_period; + bool enable_current_sense; + bool enable_por_init; + unsigned int r_sns; + int vmin; /* in millivolts */ + int vmax; /* in millivolts */ + int temp_min; /* in tenths of degree Celsius */ + int temp_max; /* in tenths of degree Celsius */ }; static enum power_supply_property max17042_battery_props[] = { @@ -165,7 +172,7 @@ static int max17042_get_status(struct max17042_chip *chip, int *status) * Even though we are supplied, we may still be discharging if the * supply is e.g. only delivering 5V 0.5A. Check current if available. */ - if (!chip->pdata->enable_current_sense) { + if (!chip->enable_current_sense) { *status = POWER_SUPPLY_STATUS_CHARGING; return 0; } @@ -207,12 +214,12 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health) /* Convert to millivolts */ vbatt /= 1000; - if (vavg < chip->pdata->vmin) { + if (vavg < chip->vmin) { *health = POWER_SUPPLY_HEALTH_DEAD; goto out; } - if (vbatt > size_add(chip->pdata->vmax, MAX17042_VMAX_TOLERANCE)) { + if (vbatt > size_add(chip->vmax, MAX17042_VMAX_TOLERANCE)) { *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; goto out; } @@ -221,12 +228,12 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health) if (ret < 0) goto health_error; - if (temp < chip->pdata->temp_min) { + if (temp < chip->temp_min) { *health = POWER_SUPPLY_HEALTH_COLD; goto out; } - if (temp > chip->pdata->temp_max) { + if (temp > chip->temp_max) { *health = POWER_SUPPLY_HEALTH_OVERHEAT; goto out; } @@ -327,7 +334,7 @@ static int max17042_get_property(struct power_supply *psy, val->intval = data * MAX17042_VOLTAGE_LSB; break; case POWER_SUPPLY_PROP_CAPACITY: - if (chip->pdata->enable_current_sense) + if (chip->enable_current_sense) ret = regmap_read(map, MAX17042_RepSOC, &data); else ret = regmap_read(map, MAX17042_VFSOC, &data); @@ -344,7 +351,7 @@ static int max17042_get_property(struct power_supply *psy, data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); - do_div(data64, chip->pdata->r_sns); + do_div(data64, chip->r_sns); val->intval = data64; break; case POWER_SUPPLY_PROP_CHARGE_FULL: @@ -355,7 +362,7 @@ static int max17042_get_property(struct power_supply *psy, data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); - do_div(data64, chip->pdata->r_sns); + do_div(data64, chip->r_sns); val->intval = data64; break; case POWER_SUPPLY_PROP_CHARGE_NOW: @@ -366,7 +373,7 @@ static int max17042_get_property(struct power_supply *psy, data64 = data * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; do_div(data64, MAX17042_DEFAULT_TASK_PERIOD); - do_div(data64, chip->pdata->r_sns); + do_div(data64, chip->r_sns); val->intval = data64; break; case POWER_SUPPLY_PROP_CHARGE_COUNTER: @@ -377,7 +384,7 @@ static int max17042_get_property(struct power_supply *psy, data64 = sign_extend64(data, 15) * MAX17042_CAPACITY_LSB; data64 *= chip->task_period; data64 = div_s64(data64, MAX17042_DEFAULT_TASK_PERIOD); - val->intval = div_s64(data64, chip->pdata->r_sns); + val->intval = div_s64(data64, chip->r_sns); break; case POWER_SUPPLY_PROP_TEMP: ret = max17042_get_temperature(chip, &val->intval); @@ -399,10 +406,10 @@ static int max17042_get_property(struct power_supply *psy, val->intval = sign_extend32(data >> 8, 7) * 10; break; case POWER_SUPPLY_PROP_TEMP_MIN: - val->intval = chip->pdata->temp_min; + val->intval = chip->temp_min; break; case POWER_SUPPLY_PROP_TEMP_MAX: - val->intval = chip->pdata->temp_max; + val->intval = chip->temp_max; break; case POWER_SUPPLY_PROP_HEALTH: ret = max17042_get_battery_health(chip, &val->intval); @@ -413,25 +420,25 @@ static int max17042_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_SCOPE_SYSTEM; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - if (chip->pdata->enable_current_sense) { + if (chip->enable_current_sense) { ret = regmap_read(map, MAX17042_Current, &data); if (ret < 0) return ret; data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB; - val->intval = div_s64(data64, chip->pdata->r_sns); + val->intval = div_s64(data64, chip->r_sns); } else { return -EINVAL; } break; case POWER_SUPPLY_PROP_CURRENT_AVG: - if (chip->pdata->enable_current_sense) { + if (chip->enable_current_sense) { ret = regmap_read(map, MAX17042_AvgCurrent, &data); if (ret < 0) return ret; data64 = sign_extend64(data, 15) * MAX17042_CURRENT_LSB; - val->intval = div_s64(data64, chip->pdata->r_sns); + val->intval = div_s64(data64, chip->r_sns); } else { return -EINVAL; } @@ -442,7 +449,7 @@ static int max17042_get_property(struct power_supply *psy, return ret; data64 = data * MAX17042_CURRENT_LSB; - val->intval = div_s64(data64, chip->pdata->r_sns); + val->intval = div_s64(data64, chip->r_sns); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: ret = regmap_read(map, MAX17042_TTE, &data); @@ -591,7 +598,7 @@ static inline void max17042_write_model_data(struct max17042_chip *chip, for (i = 0; i < size; i++) regmap_write(map, addr + i, - chip->pdata->config_data->cell_char_tbl[i]); + chip->config_data->cell_char_tbl[i]); } static inline void max17042_read_model_data(struct max17042_chip *chip, @@ -626,7 +633,7 @@ static inline int max17042_model_data_compare(struct max17042_chip *chip, static int max17042_init_model(struct max17042_chip *chip) { int ret; - int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); + int table_size = ARRAY_SIZE(chip->config_data->cell_char_tbl); u16 *temp_data; temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); @@ -641,7 +648,7 @@ static int max17042_init_model(struct max17042_chip *chip) ret = max17042_model_data_compare( chip, - chip->pdata->config_data->cell_char_tbl, + chip->config_data->cell_char_tbl, temp_data, table_size); @@ -654,7 +661,7 @@ static int max17042_init_model(struct max17042_chip *chip) static int max17042_verify_model_lock(struct max17042_chip *chip) { int i; - int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); + int table_size = ARRAY_SIZE(chip->config_data->cell_char_tbl); u16 *temp_data; int ret = 0; @@ -674,7 +681,7 @@ static int max17042_verify_model_lock(struct max17042_chip *chip) static void max17042_write_config_regs(struct max17042_chip *chip) { - struct max17042_config_data *config = chip->pdata->config_data; + struct max17042_config_data *config = chip->config_data; struct regmap *map = chip->regmap; regmap_write(map, MAX17042_CONFIG, config->config); @@ -692,7 +699,7 @@ static void max17042_write_config_regs(struct max17042_chip *chip) static void max17042_write_custom_regs(struct max17042_chip *chip) { - struct max17042_config_data *config = chip->pdata->config_data; + struct max17042_config_data *config = chip->config_data; struct regmap *map = chip->regmap; max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0); @@ -716,7 +723,7 @@ static void max17042_write_custom_regs(struct max17042_chip *chip) static void max17042_update_capacity_regs(struct max17042_chip *chip) { - struct max17042_config_data *config = chip->pdata->config_data; + struct max17042_config_data *config = chip->config_data; struct regmap *map = chip->regmap; max17042_write_verify_reg(map, MAX17042_FullCAP, @@ -742,7 +749,7 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip) u32 full_cap0, rep_cap, dq_acc, vfSoc; u32 rem_cap; - struct max17042_config_data *config = chip->pdata->config_data; + struct max17042_config_data *config = chip->config_data; struct regmap *map = chip->regmap; regmap_read(map, MAX17042_FullCAP0, &full_cap0); @@ -774,14 +781,14 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip) } /* - * Block write all the override values coming from platform data. + * Block write all the override values coming from config_data. * This function MUST be called before the POR initialization procedure * specified by maxim. */ static inline void max17042_override_por_values(struct max17042_chip *chip) { struct regmap *map = chip->regmap; - struct max17042_config_data *config = chip->pdata->config_data; + struct max17042_config_data *config = chip->config_data; max17042_override_por(map, MAX17042_TGAIN, config->tgain); max17042_override_por(map, MAX17042_TOFF, config->toff); @@ -896,7 +903,7 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) /* program interrupt thresholds such that we should * get interrupt for every 'off' perc change in the soc */ - if (chip->pdata->enable_current_sense) + if (chip->enable_current_sense) regmap_read(map, MAX17042_RepSOC, &soc); else regmap_read(map, MAX17042_VFSOC, &soc); @@ -912,7 +919,7 @@ static void max17042_set_critical_soc_threshold(struct max17042_chip *chip) struct regmap *map = chip->regmap; u32 soc; - if (chip->pdata->enable_current_sense) + if (chip->enable_current_sense) regmap_read(map, MAX17042_RepSOC, &soc); else regmap_read(map, MAX17042_VFSOC, &soc); @@ -975,8 +982,8 @@ static void max17042_init_worker(struct work_struct *work) struct max17042_chip, work); int ret; - /* Initialize registers according to values from the platform data */ - if (chip->pdata->enable_por_init && chip->pdata->config_data) { + /* Initialize registers according to values from config_data */ + if (chip->enable_por_init && chip->config_data) { ret = max17042_init_chip(chip); if (ret) return; @@ -986,17 +993,10 @@ static void max17042_init_worker(struct work_struct *work) } #ifdef CONFIG_OF -static struct max17042_platform_data * -max17042_get_of_pdata(struct max17042_chip *chip) +static int max17042_parse_dt(struct max17042_chip *chip) { - struct device *dev = chip->dev; - struct device_node *np = dev->of_node; + struct device_node *np = chip->dev->of_node; u32 prop; - struct max17042_platform_data *pdata; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; /* * Require current sense resistor value to be specified for @@ -1007,85 +1007,46 @@ max17042_get_of_pdata(struct max17042_chip *chip) if ((of_property_read_u32(np, "shunt-resistor-micro-ohms", &prop) == 0) || (of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0)) { - pdata->r_sns = prop; - pdata->enable_current_sense = true; + chip->r_sns = prop; + chip->enable_current_sense = true; } - if (of_property_read_s32(np, "maxim,cold-temp", &pdata->temp_min)) - pdata->temp_min = INT_MIN; - if (of_property_read_s32(np, "maxim,over-heat-temp", &pdata->temp_max)) - pdata->temp_max = INT_MAX; - if (of_property_read_s32(np, "maxim,dead-volt", &pdata->vmin)) - pdata->vmin = INT_MIN; - if (of_property_read_s32(np, "maxim,over-volt", &pdata->vmax)) - pdata->vmax = INT_MAX; + if (of_property_read_s32(np, "maxim,cold-temp", &chip->temp_min)) + chip->temp_min = INT_MIN; + if (of_property_read_s32(np, "maxim,over-heat-temp", &chip->temp_max)) + chip->temp_max = INT_MAX; + if (of_property_read_s32(np, "maxim,dead-volt", &chip->vmin)) + chip->vmin = INT_MIN; + if (of_property_read_s32(np, "maxim,over-volt", &chip->vmax)) + chip->vmax = INT_MAX; - return pdata; + return 0; } #endif -static struct max17042_reg_data max17047_default_pdata_init_regs[] = { - /* - * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection - * when the voltage FG reports 95%, as recommended in the datasheet. - */ - { MAX17047_FullSOCThr, MAX17042_BATTERY_FULL << 8 }, -}; - -static struct max17042_platform_data * -max17042_get_default_pdata(struct max17042_chip *chip) +static int max17042_init_defaults(struct max17042_chip *chip) { - struct device *dev = chip->dev; - struct max17042_platform_data *pdata; int ret, misc_cfg; /* - * The MAX17047 gets used on x86 where we might not have pdata, assume + * The MAX17047 gets used on x86 where we might not have DT, assume * the firmware will already have initialized the fuel-gauge and provide * default values for the non init bits to make things work. */ - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return pdata; - - if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || - (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) { - pdata->init_data = max17047_default_pdata_init_regs; - pdata->num_init_data = - ARRAY_SIZE(max17047_default_pdata_init_regs); - } ret = regmap_read(chip->regmap, MAX17042_MiscCFG, &misc_cfg); if (ret < 0) - return NULL; + return ret; /* If bits 0-1 are set to 3 then only Voltage readings are used */ - if ((misc_cfg & 0x3) == 0x3) - pdata->enable_current_sense = false; - else - pdata->enable_current_sense = true; + chip->enable_current_sense = (misc_cfg & 0x3) != 0x3; - pdata->vmin = MAX17042_DEFAULT_VMIN; - pdata->vmax = MAX17042_DEFAULT_VMAX; - pdata->temp_min = MAX17042_DEFAULT_TEMP_MIN; - pdata->temp_max = MAX17042_DEFAULT_TEMP_MAX; + chip->vmin = MAX17042_DEFAULT_VMIN; + chip->vmax = MAX17042_DEFAULT_VMAX; + chip->temp_min = MAX17042_DEFAULT_TEMP_MIN; + chip->temp_max = MAX17042_DEFAULT_TEMP_MAX; - return pdata; -} - -static struct max17042_platform_data * -max17042_get_pdata(struct max17042_chip *chip) -{ - struct device *dev = chip->dev; - -#ifdef CONFIG_OF - if (dev->of_node) - return max17042_get_of_pdata(chip); -#endif - if (dev->platform_data) - return dev->platform_data; - - return max17042_get_default_pdata(chip); + return 0; } static const struct regmap_config max17042_regmap_config = { @@ -1164,8 +1125,8 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq struct power_supply_config psy_cfg = {}; struct max17042_chip *chip; int ret; - int i; u32 val; + bool use_default_config = false; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -EIO; @@ -1186,10 +1147,19 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq return dev_err_probe(dev, PTR_ERR(chip->regmap), "Failed to initialize regmap\n"); - chip->pdata = max17042_get_pdata(chip); - if (!chip->pdata) - return dev_err_probe(dev, -EINVAL, - "no platform data provided\n"); +#ifdef CONFIG_OF + if (dev->of_node) { + ret = max17042_parse_dt(chip); + if (ret) + return ret; + } else +#endif + { + ret = max17042_init_defaults(chip); + if (ret) + return ret; + use_default_config = true; + } dev_set_drvdata(dev, chip); psy_cfg.drv_data = chip; @@ -1197,19 +1167,13 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq /* When current is not measured, * CURRENT_NOW and CURRENT_AVG properties should be invisible. */ - if (!chip->pdata->enable_current_sense) + if (!chip->enable_current_sense) max17042_desc = &max17042_no_current_sense_psy_desc; - if (chip->pdata->r_sns == 0) - chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; + if (chip->r_sns == 0) + chip->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; - if (chip->pdata->init_data) - for (i = 0; i < chip->pdata->num_init_data; i++) - regmap_write(chip->regmap, - chip->pdata->init_data[i].addr, - chip->pdata->init_data[i].data); - - if (!chip->pdata->enable_current_sense) { + if (!chip->enable_current_sense) { regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000); regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003); regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); @@ -1232,6 +1196,16 @@ static int max17042_probe(struct i2c_client *client, struct device *dev, int irq return dev_err_probe(dev, PTR_ERR(chip->battery), "failed: power supply register\n"); + /* + * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection + * when the voltage FG reports 95%, as recommended in the datasheet. + */ + if (use_default_config && + (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047 || + chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) + regmap_write(chip->regmap, MAX17047_FullSOCThr, + MAX17042_BATTERY_FULL << 8); + if (irq) { unsigned int flags = IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED; diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index d5b08313cf11..25dccf908d20 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -198,16 +198,6 @@ enum max170xx_chip_type { MAXIM_DEVICE_TYPE_NUM }; -/* - * used for setting a register to a desired value - * addr : address for a register - * data : setting value for the register - */ -struct max17042_reg_data { - u8 addr; - u16 data; -}; - struct max17042_config_data { /* External current sense resistor value in milli-ohms */ u32 cur_sense_val; @@ -265,23 +255,4 @@ struct max17042_config_data { u16 cell_char_tbl[MAX17042_CHARACTERIZATION_DATA_SIZE]; } __packed; -struct max17042_platform_data { - struct max17042_reg_data *init_data; - struct max17042_config_data *config_data; - int num_init_data; /* Number of enties in init_data array */ - bool enable_current_sense; - bool enable_por_init; /* Use POR init from Maxim appnote */ - - /* - * R_sns in micro-ohms. - * default 10000 (if r_sns = 0) as it is the recommended value by - * the datasheet although it can be changed by board designers. - */ - unsigned int r_sns; - int vmin; /* in millivolts */ - int vmax; /* in millivolts */ - int temp_min; /* in tenths of degree Celsius */ - int temp_max; /* in tenths of degree Celsius */ -}; - #endif /* __MAX17042_BATTERY_H_ */ -- cgit v1.2.3 From b26bc0b97d8d1b7454b7f7ab64f1bda8d1cd4002 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Mon, 6 Apr 2026 16:57:55 -0400 Subject: power: supply: max17042_battery: use ModelCfg refresh on max17055 Unlike other models, max17055 doesn't require cell characterization data and operates on a smaller set of input variables (`DesignCap`, `VEmpty`, `IChgTerm`, and `ModelCfg`). Those values can be filled in through `max17042_override_por_values()`, but the refresh bit has to be set afterward in order to make them apply. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Vincent Cloutier Link: https://patch.msgid.link/20260406205759.493288-8-vincent.cloutier@icloud.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 66 +++++++++++++++++++-------------- include/linux/power/max17042_battery.h | 3 ++ 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 446f8926a8e0..abd276e13475 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -843,6 +843,9 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) (chip->chip_type == MAXIM_DEVICE_TYPE_MAX77759)) { max17042_override_por(map, MAX17047_V_empty, config->vempty); } + + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) + max17042_override_por(map, MAX17055_ModelCfg, config->model_cfg); } static int max17042_init_chip(struct max17042_chip *chip) @@ -851,44 +854,53 @@ static int max17042_init_chip(struct max17042_chip *chip) int ret; max17042_override_por_values(chip); + + if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17055) { + regmap_write_bits(map, MAX17055_ModelCfg, + MAX17055_MODELCFG_REFRESH_BIT, + MAX17055_MODELCFG_REFRESH_BIT); + } + /* After Power up, the MAX17042 requires 500mS in order * to perform signal debouncing and initial SOC reporting */ msleep(500); - /* Initialize configuration */ - max17042_write_config_regs(chip); + if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17055) { + /* Initialize configuration */ + max17042_write_config_regs(chip); - /* write cell characterization data */ - ret = max17042_init_model(chip); - if (ret) { - dev_err(chip->dev, "%s init failed\n", - __func__); - return -EIO; - } + /* write cell characterization data */ + ret = max17042_init_model(chip); + if (ret) { + dev_err(chip->dev, "%s init failed\n", + __func__); + return -EIO; + } - ret = max17042_verify_model_lock(chip); - if (ret) { - dev_err(chip->dev, "%s lock verify failed\n", - __func__); - return -EIO; - } - /* write custom parameters */ - max17042_write_custom_regs(chip); + ret = max17042_verify_model_lock(chip); + if (ret) { + dev_err(chip->dev, "%s lock verify failed\n", + __func__); + return -EIO; + } + /* write custom parameters */ + max17042_write_custom_regs(chip); - /* update capacity params */ - max17042_update_capacity_regs(chip); + /* update capacity params */ + max17042_update_capacity_regs(chip); - /* delay must be atleast 350mS to allow VFSOC - * to be calculated from the new configuration - */ - msleep(350); + /* delay must be atleast 350mS to allow VFSOC + * to be calculated from the new configuration + */ + msleep(350); - /* reset vfsoc0 reg */ - max17042_reset_vfsoc0_reg(chip); + /* reset vfsoc0 reg */ + max17042_reset_vfsoc0_reg(chip); - /* load new capacity params */ - max17042_load_new_capacity_params(chip); + /* load new capacity params */ + max17042_load_new_capacity_params(chip); + } /* Init complete, Clear the POR bit */ regmap_update_bits(map, MAX17042_STATUS, STATUS_POR_BIT, 0x0); diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index 25dccf908d20..13aeab1597c6 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -24,6 +24,8 @@ #define MAX17042_CHARACTERIZATION_DATA_SIZE 48 +#define MAX17055_MODELCFG_REFRESH_BIT BIT(15) + enum max17042_register { MAX17042_STATUS = 0x00, MAX17042_VALRT_Th = 0x01, @@ -219,6 +221,7 @@ struct max17042_config_data { u16 full_soc_thresh; /* 0x13 */ u16 design_cap; /* 0x18 */ u16 ichgt_term; /* 0x1E */ + u16 model_cfg; /* 0xDB */ /* MG3 config */ u16 at_rate; /* 0x04 */ -- cgit v1.2.3 From 8eec545cde69e46e9a1d2b7d915ce4f5df85b3bd Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Tue, 7 Apr 2026 07:30:25 +0000 Subject: power: reset: linkstation-poweroff: fix use-after-free in the linkstation_poweroff_init() Move of_node_put(dn) after the of_match_node() call, which still needs the node pointer. The node reference is correctly released after use. Fixes: e2f471efe1d6 ("power: reset: linkstation-poweroff: prepare for new devices") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang Link: https://patch.msgid.link/20260407073025.271865-1-vulab@iscas.ac.cn Signed-off-by: Sebastian Reichel --- drivers/power/reset/linkstation-poweroff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c index 02f5fdb8ffc4..e56d75bfcc43 100644 --- a/drivers/power/reset/linkstation-poweroff.c +++ b/drivers/power/reset/linkstation-poweroff.c @@ -163,10 +163,10 @@ static int __init linkstation_poweroff_init(void) dn = of_find_matching_node(NULL, ls_poweroff_of_match); if (!dn) return -ENODEV; - of_node_put(dn); match = of_match_node(ls_poweroff_of_match, dn); cfg = match->data; + of_node_put(dn); dn = of_find_node_by_name(NULL, cfg->mdio_node_name); if (!dn) -- cgit v1.2.3 From 68d234144b7dffd1f50b07ba74d0d6e833ef43a4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2026 14:33:38 +0200 Subject: power: supply: max17042: fix OF node reference imbalance The driver reuses the OF node of the parent multi-function device but fails to take another reference to balance the one dropped by the platform bus code when unbinding the MFD and deregistering the child devices. Fix this by using the intended helper for reusing OF nodes. Fixes: 0cd4f1f77ad4 ("power: supply: max17042: add platform driver variant") Cc: stable@vger.kernel.org # 6.14 Cc: Dzmitry Sankouski Signed-off-by: Johan Hovold Link: https://patch.msgid.link/20260407123338.2677375-1-johan@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index abd276e13475..024fa38888f6 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1288,7 +1288,8 @@ static int max17042_platform_probe(struct platform_device *pdev) if (!i2c) return -EINVAL; - dev->of_node = dev->parent->of_node; + device_set_of_node_from_dev(dev, dev->parent); + id = platform_get_device_id(pdev); irq = platform_get_irq(pdev, 0); -- cgit v1.2.3 From a2c14ff63e0e02e3c832385e523e9cc81301171c Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Fri, 24 Apr 2026 09:10:13 +0800 Subject: power: supply: cpcap-battery: Fix missing nvmem_device_put() causing reference leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In cpcap_battery_detect_battery_type(), the reference to an nvmem device obtained via nvmem_device_find() is not released with nvmem_device_put() on the success or read-failure paths, causing a permanent reference leak. The driver’s retry logic on subsequent battery property reads can compound this leak, preventing the nvmem device from ever being freed. Found by code review. Signed-off-by: Ma Ke Cc: stable@vger.kernel.org Fixes: fd46821e85de ("power: supply: cpcap-battery: Add battery type auto detection for mapphone devices") Link: https://patch.msgid.link/20260424011013.879639-1-make24@iscas.ac.cn Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-battery.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index 7b7bdce3162f..59c741993ef8 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -439,10 +439,13 @@ static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata) if (IS_ERR_OR_NULL(nvmem)) { ddata->check_nvmem = true; dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n"); - } else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) { - battery_id = 0; - ddata->check_nvmem = true; - dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n"); + } else { + if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) { + battery_id = 0; + ddata->check_nvmem = true; + dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n"); + } + nvmem_device_put(nvmem); } switch (battery_id) { -- cgit v1.2.3 From b6c6b9260a92dacef6edef8e93bc2767b86b1dfe Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Wed, 3 Jun 2026 00:10:50 +0400 Subject: power: supply: bq257xx: Fix VSYSMIN clamping logic The minimal system voltage (VSYSMIN) is meant to protect the battery from dangerous over-discharge. When the device tree provides a value for the minimum design voltage of the battery, the user should not be allowed to set a lower VSYSMIN, as that would defeat the purpose of this protection. Flip the clamping logic when setting VSYSMIN to ensure that battery design voltage is respected. Cc: stable@vger.kernel.org Fixes: 1cc017b7f9c7 ("power: supply: bq257xx: Add support for BQ257XX charger") Tested-by: Chris Morgan Signed-off-by: Alexey Charkov Link: https://patch.msgid.link/20260603-bq25792-v7-2-d487bed276d0@flipper.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq257xx_charger.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/bq257xx_charger.c index 02c7d8b61e82..7ca4ae610902 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -128,9 +128,8 @@ static int bq25703_get_min_vsys(struct bq257xx_chg *pdata, int *intval) * @vsys: voltage value to set in uV. * * This function takes a requested minimum system voltage value, clamps - * it between the minimum supported value by the charger and a user - * defined minimum system value, and then writes the value to the - * appropriate register. + * it between the user defined minimum system value and the maximum supported + * value by the charger, and then writes the value to the appropriate register. * * Return: Returns 0 on success or error if an error occurs. */ @@ -139,7 +138,7 @@ static int bq25703_set_min_vsys(struct bq257xx_chg *pdata, int vsys) unsigned int reg; int vsys_min = pdata->vsys_min; - vsys = clamp(vsys, BQ25703_MINVSYS_MIN_UV, vsys_min); + vsys = clamp(vsys, vsys_min, BQ25703_MINVSYS_MAX_UV); reg = ((vsys - BQ25703_MINVSYS_MIN_UV) / BQ25703_MINVSYS_STEP_UV); reg = FIELD_PREP(BQ25703_MINVSYS_MASK, reg); -- cgit v1.2.3 From 759aa7d62b55f5910d916b63b88b092395a8c2c9 Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Wed, 3 Jun 2026 00:10:51 +0400 Subject: power: supply: bq257xx: Make the default current limit a per-chip attribute Add a field for the default current limit to the bq257xx_info structure and use it instead of the hardcoded value in the probe function. This prepares the driver for allowing different electrical constraints for different chip variants. Tested-by: Chris Morgan Signed-off-by: Alexey Charkov Link: https://patch.msgid.link/20260603-bq25792-v7-3-d487bed276d0@flipper.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq257xx_charger.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/bq257xx_charger.c index 7ca4ae610902..39718223c3f9 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -18,6 +18,7 @@ struct bq257xx_chg; /** * struct bq257xx_chip_info - chip specific routines + * @default_iindpm_uA: default input current limit in microamps * @bq257xx_hw_init: init function for hw * @bq257xx_hw_shutdown: shutdown function for hw * @bq257xx_get_state: get and update state of hardware @@ -26,6 +27,7 @@ struct bq257xx_chg; * @bq257xx_set_iindpm: set maximum input current (in uA) */ struct bq257xx_chip_info { + int default_iindpm_uA; int (*bq257xx_hw_init)(struct bq257xx_chg *pdata); void (*bq257xx_hw_shutdown)(struct bq257xx_chg *pdata); int (*bq257xx_get_state)(struct bq257xx_chg *pdata); @@ -627,6 +629,7 @@ static const struct power_supply_desc bq257xx_power_supply_desc = { }; static const struct bq257xx_chip_info bq25703_chip_info = { + .default_iindpm_uA = BQ25703_IINDPM_DEFAULT_UA, .bq257xx_hw_init = &bq25703_hw_init, .bq257xx_hw_shutdown = &bq25703_hw_shutdown, .bq257xx_get_state = &bq25703_get_state, @@ -675,7 +678,7 @@ static int bq257xx_parse_dt(struct bq257xx_chg *pdata, "input-current-limit-microamp", &pdata->iindpm_max); if (ret) - pdata->iindpm_max = BQ25703_IINDPM_DEFAULT_UA; + pdata->iindpm_max = pdata->chip->default_iindpm_uA; return 0; } -- cgit v1.2.3 From 528058841022e1bbe468b2246d4fc318881cf1cb Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Wed, 3 Jun 2026 00:10:52 +0400 Subject: power: supply: bq257xx: Consistently use indirect get/set helpers Move the remaining get/set helper functions to indirect calls via the per-chip bq257xx_chip_info struct. This improves the consistency of the code and prepares the driver to support multiple chip variants with different register layouts and bit definitions. Tested-by: Chris Morgan Signed-off-by: Alexey Charkov Link: https://patch.msgid.link/20260603-bq25792-v7-4-d487bed276d0@flipper.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq257xx_charger.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/bq257xx_charger.c index 39718223c3f9..0765673728e4 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -22,18 +22,30 @@ struct bq257xx_chg; * @bq257xx_hw_init: init function for hw * @bq257xx_hw_shutdown: shutdown function for hw * @bq257xx_get_state: get and update state of hardware + * @bq257xx_get_ichg: get maximum charge current (in uA) * @bq257xx_set_ichg: set maximum charge current (in uA) + * @bq257xx_get_vbatreg: get maximum charge voltage (in uV) * @bq257xx_set_vbatreg: set maximum charge voltage (in uV) + * @bq257xx_get_iindpm: get maximum input current (in uA) * @bq257xx_set_iindpm: set maximum input current (in uA) + * @bq257xx_get_cur: get battery current from ADC (in uA) + * @bq257xx_get_vbat: get battery voltage from ADC (in uV) + * @bq257xx_get_min_vsys: get minimum system voltage (in uV) */ struct bq257xx_chip_info { int default_iindpm_uA; int (*bq257xx_hw_init)(struct bq257xx_chg *pdata); void (*bq257xx_hw_shutdown)(struct bq257xx_chg *pdata); int (*bq257xx_get_state)(struct bq257xx_chg *pdata); + int (*bq257xx_get_ichg)(struct bq257xx_chg *pdata, int *intval); int (*bq257xx_set_ichg)(struct bq257xx_chg *pdata, int ichg); + int (*bq257xx_get_vbatreg)(struct bq257xx_chg *pdata, int *intval); int (*bq257xx_set_vbatreg)(struct bq257xx_chg *pdata, int vbatreg); + int (*bq257xx_get_iindpm)(struct bq257xx_chg *pdata, int *intval); int (*bq257xx_set_iindpm)(struct bq257xx_chg *pdata, int iindpm); + int (*bq257xx_get_cur)(struct bq257xx_chg *pdata, int *intval); + int (*bq257xx_get_vbat)(struct bq257xx_chg *pdata, int *intval); + int (*bq257xx_get_min_vsys)(struct bq257xx_chg *pdata, int *intval); }; /** @@ -490,22 +502,22 @@ static int bq257xx_get_charger_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: - return bq25703_get_iindpm(pdata, &val->intval); + return pdata->chip->bq257xx_get_iindpm(pdata, &val->intval); case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: - return bq25703_get_chrg_volt(pdata, &val->intval); + return pdata->chip->bq257xx_get_vbatreg(pdata, &val->intval); case POWER_SUPPLY_PROP_CURRENT_NOW: - return bq25703_get_cur(pdata, &val->intval); + return pdata->chip->bq257xx_get_cur(pdata, &val->intval); case POWER_SUPPLY_PROP_VOLTAGE_NOW: - return bq25703_get_vbat(pdata, &val->intval); + return pdata->chip->bq257xx_get_vbat(pdata, &val->intval); case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: - return bq25703_get_ichg_cur(pdata, &val->intval); + return pdata->chip->bq257xx_get_ichg(pdata, &val->intval); case POWER_SUPPLY_PROP_VOLTAGE_MIN: - return bq25703_get_min_vsys(pdata, &val->intval); + return pdata->chip->bq257xx_get_min_vsys(pdata, &val->intval); case POWER_SUPPLY_PROP_USB_TYPE: val->intval = pdata->usb_type; @@ -633,9 +645,15 @@ static const struct bq257xx_chip_info bq25703_chip_info = { .bq257xx_hw_init = &bq25703_hw_init, .bq257xx_hw_shutdown = &bq25703_hw_shutdown, .bq257xx_get_state = &bq25703_get_state, + .bq257xx_get_ichg = &bq25703_get_ichg_cur, .bq257xx_set_ichg = &bq25703_set_ichg_cur, + .bq257xx_get_vbatreg = &bq25703_get_chrg_volt, .bq257xx_set_vbatreg = &bq25703_set_chrg_volt, + .bq257xx_get_iindpm = &bq25703_get_iindpm, .bq257xx_set_iindpm = &bq25703_set_iindpm, + .bq257xx_get_cur = &bq25703_get_cur, + .bq257xx_get_vbat = &bq25703_get_vbat, + .bq257xx_get_min_vsys = &bq25703_get_min_vsys, }; /** -- cgit v1.2.3 From 5d543bf02965d1c04064acfd5e97d1529268d86f Mon Sep 17 00:00:00 2001 From: Alexey Charkov Date: Wed, 3 Jun 2026 00:10:53 +0400 Subject: power: supply: bq257xx: Add fields for 'charging' and 'overvoltage' states The driver currently reports the 'charging' and 'overvoltage' states based on a logical expression in the get_charger_property() wrapper function. This doesn't scale well to other chip variants, which may have a different number and type of hardware reported conditions which fall into these broad power supply states. Move the logic for determining 'charging' and 'overvoltage' states into chip-specific accessors, which can be overridden by each variant as needed. This helps keep the get_charger_property() wrapper function chip-agnostic while allowing for new chip variants to be added bringing their own logic. Tested-by: Chris Morgan Signed-off-by: Alexey Charkov Link: https://patch.msgid.link/20260603-bq25792-v7-5-d487bed276d0@flipper.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq257xx_charger.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/bq257xx_charger.c b/drivers/power/supply/bq257xx_charger.c index 0765673728e4..9c082865e745 100644 --- a/drivers/power/supply/bq257xx_charger.c +++ b/drivers/power/supply/bq257xx_charger.c @@ -54,8 +54,10 @@ struct bq257xx_chip_info { * @bq: parent MFD device * @charger: power supply device * @online: charger input is present + * @charging: charger is actively charging the battery * @fast_charge: charger is in fast charge mode * @pre_charge: charger is in pre-charge mode + * @overvoltage: overvoltage fault detected * @ov_fault: charger reports over voltage fault * @batoc_fault: charger reports battery over current fault * @oc_fault: charger reports over current fault @@ -71,8 +73,10 @@ struct bq257xx_chg { struct bq257xx_device *bq; struct power_supply *charger; bool online; + bool charging; bool fast_charge; bool pre_charge; + bool overvoltage; bool ov_fault; bool batoc_fault; bool oc_fault; @@ -106,8 +110,10 @@ static int bq25703_get_state(struct bq257xx_chg *pdata) pdata->online = reg & BQ25703_STS_AC_STAT; pdata->fast_charge = reg & BQ25703_STS_IN_FCHRG; pdata->pre_charge = reg & BQ25703_STS_IN_PCHRG; + pdata->charging = pdata->fast_charge || pdata->pre_charge; pdata->ov_fault = reg & BQ25703_STS_FAULT_ACOV; pdata->batoc_fault = reg & BQ25703_STS_FAULT_BATOC; + pdata->overvoltage = pdata->ov_fault || pdata->batoc_fault; pdata->oc_fault = reg & BQ25703_STS_FAULT_ACOC; return 0; @@ -478,14 +484,14 @@ static int bq257xx_get_charger_property(struct power_supply *psy, case POWER_SUPPLY_PROP_STATUS: if (!pdata->online) val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - else if (pdata->fast_charge || pdata->pre_charge) + else if (pdata->charging) val->intval = POWER_SUPPLY_STATUS_CHARGING; else val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; break; case POWER_SUPPLY_PROP_HEALTH: - if (pdata->ov_fault || pdata->batoc_fault) + if (pdata->overvoltage) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; else if (pdata->oc_fault) val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT; -- cgit v1.2.3 From c05383b9074d72d244d3dea34832eeb725317575 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 18 May 2026 17:41:44 -0700 Subject: power: reset: st-poweroff: Use of_device_get_match_data() Use of_device_get_match_data() to fetch the reset syscfg data directly instead of open-coding an of_match_device() lookup. This also lets the driver drop the of_device.h include. Assisted-by: Codex:GPT-5.5 Signed-off-by: Rosen Penev Link: https://patch.msgid.link/20260519004144.626969-1-rosenp@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/st-poweroff.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/power/reset/st-poweroff.c b/drivers/power/reset/st-poweroff.c index 85175066beea..2c0cedd18406 100644 --- a/drivers/power/reset/st-poweroff.c +++ b/drivers/power/reset/st-poweroff.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -73,15 +72,12 @@ static const struct of_device_id st_reset_of_match[] = { static int st_reset_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *match; struct device *dev = &pdev->dev; - match = of_match_device(st_reset_of_match, dev); - if (!match) + st_restart_syscfg = (struct reset_syscfg *)of_device_get_match_data(dev); + if (!st_restart_syscfg) return -ENODEV; - st_restart_syscfg = (struct reset_syscfg *)match->data; - st_restart_syscfg->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); if (IS_ERR(st_restart_syscfg->regmap)) { -- cgit v1.2.3 From 0549c4c01338abe343a4ffaa4733475d0a85d38a Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Fri, 15 May 2026 21:50:41 +0300 Subject: power: supply: Remove unused jz4740-battery.h The last user was removed in commit aea12071d6fc ("power/supply: Drop obsolete JZ4740 driver") and replaced by a self-contained IIO-based driver. No file includes this header. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Costa Shulyupin Link: https://patch.msgid.link/20260515185043.1523363-1-costa.shul@redhat.com Signed-off-by: Sebastian Reichel --- include/linux/power/jz4740-battery.h | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 include/linux/power/jz4740-battery.h diff --git a/include/linux/power/jz4740-battery.h b/include/linux/power/jz4740-battery.h deleted file mode 100644 index 10da211678c8..000000000000 --- a/include/linux/power/jz4740-battery.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2009, Jiejing Zhang - */ - -#ifndef __JZ4740_BATTERY_H -#define __JZ4740_BATTERY_H - -struct jz_battery_platform_data { - struct power_supply_info info; - int gpio_charge; /* GPIO port of Charger state */ - int gpio_charge_active_low; -}; - -#endif -- cgit v1.2.3 From 347fcfcc0758cc7523f440f47594f9a5037c50c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 15 May 2026 12:16:28 +0200 Subject: power: supply: Use named initializers for arrays of i2c_device_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. The mentioned robustness is relevant for a planned change to struct i2c_device_id that replaces .driver_data by an anonymous union. While touching all these arrays, unify usage of whitespace and commas. This patch doesn't modify the compiled arrays, only their representation in source form benefits. The former was confirmed with x86 and arm64 builds. Signed-off-by: Uwe Kleine-König (The Capable Hub) Reviewed-by: Luca Ceresoli # max77976_charger.c Link: https://patch.msgid.link/20260515101629.4132270-2-u.kleine-koenig@baylibre.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/adp5061.c | 2 +- drivers/power/supply/bq2415x_charger.c | 28 +++++------ drivers/power/supply/bq24190_charger.c | 16 +++--- drivers/power/supply/bq24257_charger.c | 8 +-- drivers/power/supply/bq24735-charger.c | 4 +- drivers/power/supply/bq2515x_charger.c | 6 +-- drivers/power/supply/bq256xx_charger.c | 16 +++--- drivers/power/supply/bq25890_charger.c | 10 ++-- drivers/power/supply/bq25980_charger.c | 8 +-- drivers/power/supply/bq27xxx_battery_i2c.c | 64 ++++++++++++------------ drivers/power/supply/cw2015_battery.c | 2 +- drivers/power/supply/ds2782_battery.c | 6 +-- drivers/power/supply/lp8727_charger.c | 2 +- drivers/power/supply/ltc2941-battery-gauge.c | 10 ++-- drivers/power/supply/ltc4162-l-charger.c | 8 +-- drivers/power/supply/max14656_charger_detector.c | 4 +- drivers/power/supply/max17040_battery.c | 18 +++---- drivers/power/supply/max17042_battery.c | 12 ++--- drivers/power/supply/max77976_charger.c | 2 +- drivers/power/supply/max8971_charger.c | 2 +- drivers/power/supply/mm8013.c | 4 +- drivers/power/supply/rt5033_battery.c | 2 +- drivers/power/supply/rt9455_charger.c | 2 +- drivers/power/supply/sbs-battery.c | 8 +-- drivers/power/supply/sbs-charger.c | 2 +- drivers/power/supply/sbs-manager.c | 4 +- drivers/power/supply/smb347-charger.c | 8 +-- drivers/power/supply/stc3117_fuel_gauge.c | 2 +- drivers/power/supply/ug3105_battery.c | 2 +- 29 files changed, 131 insertions(+), 131 deletions(-) diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c index 458fd3024373..7d5754c24553 100644 --- a/drivers/power/supply/adp5061.c +++ b/drivers/power/supply/adp5061.c @@ -727,7 +727,7 @@ static int adp5061_probe(struct i2c_client *client) } static const struct i2c_device_id adp5061_id[] = { - { "adp5061" }, + { .name = "adp5061" }, { } }; MODULE_DEVICE_TABLE(i2c, adp5061_id); diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c index b50a28b9dd38..9f801717bfb0 100644 --- a/drivers/power/supply/bq2415x_charger.c +++ b/drivers/power/supply/bq2415x_charger.c @@ -1738,20 +1738,20 @@ static void bq2415x_remove(struct i2c_client *client) } static const struct i2c_device_id bq2415x_i2c_id_table[] = { - { "bq2415x", BQUNKNOWN }, - { "bq24150", BQ24150 }, - { "bq24150a", BQ24150A }, - { "bq24151", BQ24151 }, - { "bq24151a", BQ24151A }, - { "bq24152", BQ24152 }, - { "bq24153", BQ24153 }, - { "bq24153a", BQ24153A }, - { "bq24155", BQ24155 }, - { "bq24156", BQ24156 }, - { "bq24156a", BQ24156A }, - { "bq24157s", BQ24157S }, - { "bq24158", BQ24158 }, - {}, + { .name = "bq2415x", .driver_data = BQUNKNOWN }, + { .name = "bq24150", .driver_data = BQ24150 }, + { .name = "bq24150a", .driver_data = BQ24150A }, + { .name = "bq24151", .driver_data = BQ24151 }, + { .name = "bq24151a", .driver_data = BQ24151A }, + { .name = "bq24152", .driver_data = BQ24152 }, + { .name = "bq24153", .driver_data = BQ24153 }, + { .name = "bq24153a", .driver_data = BQ24153A }, + { .name = "bq24155", .driver_data = BQ24155 }, + { .name = "bq24156", .driver_data = BQ24156 }, + { .name = "bq24156a", .driver_data = BQ24156A }, + { .name = "bq24157s", .driver_data = BQ24157S }, + { .name = "bq24158", .driver_data = BQ24158 }, + { } }; MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table); diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 55da91bacc3e..6700d578a98f 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -2308,14 +2308,14 @@ static const struct dev_pm_ops bq24190_pm_ops = { }; static const struct i2c_device_id bq24190_i2c_ids[] = { - { "bq24190", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] }, - { "bq24192", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] }, - { "bq24192i", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] }, - { "bq24193", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24193] }, - { "bq24196", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] }, - { "bq24296", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] }, - { "bq24297", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24297] }, - { }, + { .name = "bq24190", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] }, + { .name = "bq24192", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] }, + { .name = "bq24192i", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] }, + { .name = "bq24193", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24193] }, + { .name = "bq24196", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] }, + { .name = "bq24296", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] }, + { .name = "bq24297", .driver_data = (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24297] }, + { } }; MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c index 766eecb35694..72f1bfea8d54 100644 --- a/drivers/power/supply/bq24257_charger.c +++ b/drivers/power/supply/bq24257_charger.c @@ -1133,10 +1133,10 @@ static const struct bq2425x_chip_info bq24257_info = { }; static const struct i2c_device_id bq24257_i2c_ids[] = { - { "bq24250", (kernel_ulong_t)&bq24250_info }, - { "bq24251", (kernel_ulong_t)&bq24251_info }, - { "bq24257", (kernel_ulong_t)&bq24257_info }, - {} + { .name = "bq24250", .driver_data = (kernel_ulong_t)&bq24250_info }, + { .name = "bq24251", .driver_data = (kernel_ulong_t)&bq24251_info }, + { .name = "bq24257", .driver_data = (kernel_ulong_t)&bq24257_info }, + { } }; MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c index 637e0da65f87..99abbaf0470f 100644 --- a/drivers/power/supply/bq24735-charger.c +++ b/drivers/power/supply/bq24735-charger.c @@ -489,8 +489,8 @@ static int bq24735_charger_probe(struct i2c_client *client) } static const struct i2c_device_id bq24735_charger_id[] = { - { "bq24735-charger" }, - {} + { .name = "bq24735-charger" }, + { } }; MODULE_DEVICE_TABLE(i2c, bq24735_charger_id); diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index 437bff5bc420..0208358ebbe4 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -1137,9 +1137,9 @@ static const struct bq2515x_info bq25155 = { }; static const struct i2c_device_id bq2515x_i2c_ids[] = { - { "bq25150", (kernel_ulong_t)&bq25150 }, - { "bq25155", (kernel_ulong_t)&bq25155 }, - {} + { .name = "bq25150", .driver_data = (kernel_ulong_t)&bq25150 }, + { .name = "bq25155", .driver_data = (kernel_ulong_t)&bq25155 }, + { } }; MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids); diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index 563f512709b3..5a6634fde837 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -1768,14 +1768,14 @@ static int bq256xx_probe(struct i2c_client *client) } static const struct i2c_device_id bq256xx_i2c_ids[] = { - { "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] }, - { "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] }, - { "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] }, - { "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] }, - { "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] }, - { "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] }, - { "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] }, - {} + { .name = "bq25600", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] }, + { .name = "bq25600d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] }, + { .name = "bq25601", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] }, + { .name = "bq25601d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] }, + { .name = "bq25611d", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] }, + { .name = "bq25618", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] }, + { .name = "bq25619", .driver_data = (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] }, + { } }; MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids); diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 868e86e1749b..c1c12a447178 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -1617,11 +1617,11 @@ static const struct dev_pm_ops bq25890_pm = { }; static const struct i2c_device_id bq25890_i2c_ids[] = { - { "bq25890" }, - { "bq25892" }, - { "bq25895" }, - { "bq25896" }, - {} + { .name = "bq25890" }, + { .name = "bq25892" }, + { .name = "bq25895" }, + { .name = "bq25896" }, + { } }; MODULE_DEVICE_TABLE(i2c, bq25890_i2c_ids); diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c index 44af3a0c92e5..eced3aecc7d2 100644 --- a/drivers/power/supply/bq25980_charger.c +++ b/drivers/power/supply/bq25980_charger.c @@ -1266,10 +1266,10 @@ static int bq25980_probe(struct i2c_client *client) } static const struct i2c_device_id bq25980_i2c_ids[] = { - { "bq25980", BQ25980 }, - { "bq25975", BQ25975 }, - { "bq25960", BQ25960 }, - {}, + { .name = "bq25980", .driver_data = BQ25980 }, + { .name = "bq25975", .driver_data = BQ25975 }, + { .name = "bq25960", .driver_data = BQ25960 }, + { } }; MODULE_DEVICE_TABLE(i2c, bq25980_i2c_ids); diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index 868e95f0887e..c4e7a9521d08 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c @@ -225,38 +225,38 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id bq27xxx_i2c_id_table[] = { - { "bq27200", BQ27000 }, - { "bq27210", BQ27010 }, - { "bq27500", BQ2750X }, - { "bq27510", BQ2751X }, - { "bq27520", BQ2752X }, - { "bq27500-1", BQ27500 }, - { "bq27510g1", BQ27510G1 }, - { "bq27510g2", BQ27510G2 }, - { "bq27510g3", BQ27510G3 }, - { "bq27520g1", BQ27520G1 }, - { "bq27520g2", BQ27520G2 }, - { "bq27520g3", BQ27520G3 }, - { "bq27520g4", BQ27520G4 }, - { "bq27521", BQ27521 }, - { "bq27530", BQ27530 }, - { "bq27531", BQ27531 }, - { "bq27541", BQ27541 }, - { "bq27542", BQ27542 }, - { "bq27546", BQ27546 }, - { "bq27742", BQ27742 }, - { "bq27545", BQ27545 }, - { "bq27411", BQ27411 }, - { "bq27421", BQ27421 }, - { "bq27425", BQ27425 }, - { "bq27426", BQ27426 }, - { "bq27441", BQ27441 }, - { "bq27621", BQ27621 }, - { "bq27z561", BQ27Z561 }, - { "bq28z610", BQ28Z610 }, - { "bq34z100", BQ34Z100 }, - { "bq78z100", BQ78Z100 }, - {}, + { .name = "bq27200", .driver_data = BQ27000 }, + { .name = "bq27210", .driver_data = BQ27010 }, + { .name = "bq27500", .driver_data = BQ2750X }, + { .name = "bq27510", .driver_data = BQ2751X }, + { .name = "bq27520", .driver_data = BQ2752X }, + { .name = "bq27500-1", .driver_data = BQ27500 }, + { .name = "bq27510g1", .driver_data = BQ27510G1 }, + { .name = "bq27510g2", .driver_data = BQ27510G2 }, + { .name = "bq27510g3", .driver_data = BQ27510G3 }, + { .name = "bq27520g1", .driver_data = BQ27520G1 }, + { .name = "bq27520g2", .driver_data = BQ27520G2 }, + { .name = "bq27520g3", .driver_data = BQ27520G3 }, + { .name = "bq27520g4", .driver_data = BQ27520G4 }, + { .name = "bq27521", .driver_data = BQ27521 }, + { .name = "bq27530", .driver_data = BQ27530 }, + { .name = "bq27531", .driver_data = BQ27531 }, + { .name = "bq27541", .driver_data = BQ27541 }, + { .name = "bq27542", .driver_data = BQ27542 }, + { .name = "bq27546", .driver_data = BQ27546 }, + { .name = "bq27742", .driver_data = BQ27742 }, + { .name = "bq27545", .driver_data = BQ27545 }, + { .name = "bq27411", .driver_data = BQ27411 }, + { .name = "bq27421", .driver_data = BQ27421 }, + { .name = "bq27425", .driver_data = BQ27425 }, + { .name = "bq27426", .driver_data = BQ27426 }, + { .name = "bq27441", .driver_data = BQ27441 }, + { .name = "bq27621", .driver_data = BQ27621 }, + { .name = "bq27z561", .driver_data = BQ27Z561 }, + { .name = "bq28z610", .driver_data = BQ28Z610 }, + { .name = "bq34z100", .driver_data = BQ34Z100 }, + { .name = "bq78z100", .driver_data = BQ78Z100 }, + { } }; MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table); diff --git a/drivers/power/supply/cw2015_battery.c b/drivers/power/supply/cw2015_battery.c index 286524d2318c..7496295d2948 100644 --- a/drivers/power/supply/cw2015_battery.c +++ b/drivers/power/supply/cw2015_battery.c @@ -733,7 +733,7 @@ static int __maybe_unused cw_bat_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cw_bat_pm_ops, cw_bat_suspend, cw_bat_resume); static const struct i2c_device_id cw_bat_id_table[] = { - { "cw2015" }, + { .name = "cw2015" }, { } }; diff --git a/drivers/power/supply/ds2782_battery.c b/drivers/power/supply/ds2782_battery.c index cae95d35d398..ed44837473e7 100644 --- a/drivers/power/supply/ds2782_battery.c +++ b/drivers/power/supply/ds2782_battery.c @@ -423,9 +423,9 @@ static int ds278x_battery_probe(struct i2c_client *client) } static const struct i2c_device_id ds278x_id[] = { - {"ds2782", DS2782}, - {"ds2786", DS2786}, - {}, + { .name = "ds2782", .driver_data = DS2782 }, + { .name = "ds2786", .driver_data = DS2786 }, + { } }; MODULE_DEVICE_TABLE(i2c, ds278x_id); diff --git a/drivers/power/supply/lp8727_charger.c b/drivers/power/supply/lp8727_charger.c index 4186fcd37512..641e0445a410 100644 --- a/drivers/power/supply/lp8727_charger.c +++ b/drivers/power/supply/lp8727_charger.c @@ -584,7 +584,7 @@ static const struct of_device_id lp8727_dt_ids[] __maybe_unused = { MODULE_DEVICE_TABLE(of, lp8727_dt_ids); static const struct i2c_device_id lp8727_ids[] = { - { "lp8727" }, + { .name = "lp8727" }, { } }; MODULE_DEVICE_TABLE(i2c, lp8727_ids); diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index a1ddc4b060ce..5b6760722f38 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -600,11 +600,11 @@ static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops, ltc294x_suspend, ltc294x_resume); static const struct i2c_device_id ltc294x_i2c_id[] = { - { "ltc2941", LTC2941_ID, }, - { "ltc2942", LTC2942_ID, }, - { "ltc2943", LTC2943_ID, }, - { "ltc2944", LTC2944_ID, }, - { }, + { .name = "ltc2941", .driver_data = LTC2941_ID }, + { .name = "ltc2942", .driver_data = LTC2942_ID }, + { .name = "ltc2943", .driver_data = LTC2943_ID }, + { .name = "ltc2944", .driver_data = LTC2944_ID }, + { } }; MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id); diff --git a/drivers/power/supply/ltc4162-l-charger.c b/drivers/power/supply/ltc4162-l-charger.c index 9dd74fa9552d..5c09e0368e6f 100644 --- a/drivers/power/supply/ltc4162-l-charger.c +++ b/drivers/power/supply/ltc4162-l-charger.c @@ -1229,10 +1229,10 @@ static void ltc4162l_alert(struct i2c_client *client, } static const struct i2c_device_id ltc4162l_i2c_id_table[] = { - { "ltc4015", (kernel_ulong_t)<c4015_chip_info }, - { "ltc4162-f", (kernel_ulong_t)<c4162f_chip_info }, - { "ltc4162-l", (kernel_ulong_t)<c4162l_chip_info }, - { "ltc4162-s", (kernel_ulong_t)<c4162s_chip_info }, + { .name = "ltc4015", .driver_data = (kernel_ulong_t)<c4015_chip_info }, + { .name = "ltc4162-f", .driver_data = (kernel_ulong_t)<c4162f_chip_info }, + { .name = "ltc4162-l", .driver_data = (kernel_ulong_t)<c4162l_chip_info }, + { .name = "ltc4162-s", .driver_data = (kernel_ulong_t)<c4162s_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltc4162l_i2c_id_table); diff --git a/drivers/power/supply/max14656_charger_detector.c b/drivers/power/supply/max14656_charger_detector.c index a5b42b42d134..b6c3bc0d9ec1 100644 --- a/drivers/power/supply/max14656_charger_detector.c +++ b/drivers/power/supply/max14656_charger_detector.c @@ -300,8 +300,8 @@ static int max14656_probe(struct i2c_client *client) } static const struct i2c_device_id max14656_id[] = { - { "max14656" }, - {} + { .name = "max14656" }, + { } }; MODULE_DEVICE_TABLE(i2c, max14656_id); diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 48453508688a..e94d53b36aa4 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -598,15 +598,15 @@ static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume); #endif /* CONFIG_PM_SLEEP */ static const struct i2c_device_id max17040_id[] = { - { "max17040", ID_MAX17040 }, - { "max17041", ID_MAX17041 }, - { "max17043", ID_MAX17043 }, - { "max77836-battery", ID_MAX17043 }, - { "max17044", ID_MAX17044 }, - { "max17048", ID_MAX17048 }, - { "max17049", ID_MAX17049 }, - { "max17058", ID_MAX17058 }, - { "max17059", ID_MAX17059 }, + { .name = "max17040", .driver_data = ID_MAX17040 }, + { .name = "max17041", .driver_data = ID_MAX17041 }, + { .name = "max17043", .driver_data = ID_MAX17043 }, + { .name = "max77836-battery", .driver_data = ID_MAX17043 }, + { .name = "max17044", .driver_data = ID_MAX17044 }, + { .name = "max17048", .driver_data = ID_MAX17048 }, + { .name = "max17049", .driver_data = ID_MAX17049 }, + { .name = "max17058", .driver_data = ID_MAX17058 }, + { .name = "max17059", .driver_data = ID_MAX17059 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, max17040_id); diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 024fa38888f6..0fb46c1c203f 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1371,12 +1371,12 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match); #endif static const struct i2c_device_id max17042_id[] = { - { "max17042", MAXIM_DEVICE_TYPE_MAX17042 }, - { "max17047", MAXIM_DEVICE_TYPE_MAX17047 }, - { "max17050", MAXIM_DEVICE_TYPE_MAX17050 }, - { "max17055", MAXIM_DEVICE_TYPE_MAX17055 }, - { "max77759-fg", MAXIM_DEVICE_TYPE_MAX77759 }, - { "max77849-battery", MAXIM_DEVICE_TYPE_MAX17047 }, + { .name = "max17042", .driver_data = MAXIM_DEVICE_TYPE_MAX17042 }, + { .name = "max17047", .driver_data = MAXIM_DEVICE_TYPE_MAX17047 }, + { .name = "max17050", .driver_data = MAXIM_DEVICE_TYPE_MAX17050 }, + { .name = "max17055", .driver_data = MAXIM_DEVICE_TYPE_MAX17055 }, + { .name = "max77759-fg", .driver_data = MAXIM_DEVICE_TYPE_MAX77759 }, + { .name = "max77849-battery", .driver_data = MAXIM_DEVICE_TYPE_MAX17047 }, { } }; MODULE_DEVICE_TABLE(i2c, max17042_id); diff --git a/drivers/power/supply/max77976_charger.c b/drivers/power/supply/max77976_charger.c index 3d6ff4005533..9a8a09d2a55e 100644 --- a/drivers/power/supply/max77976_charger.c +++ b/drivers/power/supply/max77976_charger.c @@ -484,7 +484,7 @@ static int max77976_probe(struct i2c_client *client) } static const struct i2c_device_id max77976_i2c_id[] = { - { MAX77976_DRIVER_NAME }, + { .name = MAX77976_DRIVER_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, max77976_i2c_id); diff --git a/drivers/power/supply/max8971_charger.c b/drivers/power/supply/max8971_charger.c index 26416d26f235..49a05858bef8 100644 --- a/drivers/power/supply/max8971_charger.c +++ b/drivers/power/supply/max8971_charger.c @@ -731,7 +731,7 @@ static const struct of_device_id max8971_match_ids[] = { MODULE_DEVICE_TABLE(of, max8971_match_ids); static const struct i2c_device_id max8971_i2c_id[] = { - { "max8971" }, + { .name = "max8971" }, { } }; MODULE_DEVICE_TABLE(i2c, max8971_i2c_id); diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c index 93c50cff31bc..819667a27cad 100644 --- a/drivers/power/supply/mm8013.c +++ b/drivers/power/supply/mm8013.c @@ -284,8 +284,8 @@ static int mm8013_probe(struct i2c_client *client) } static const struct i2c_device_id mm8013_id_table[] = { - { "mm8013" }, - {} + { .name = "mm8013" }, + { } }; MODULE_DEVICE_TABLE(i2c, mm8013_id_table); diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index b2674adfa30b..63333f6aa819 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -174,7 +174,7 @@ static int rt5033_battery_probe(struct i2c_client *client) } static const struct i2c_device_id rt5033_battery_id[] = { - { "rt5033-battery", }, + { .name = "rt5033-battery" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5033_battery_id); diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c index 5130d2395e88..7045d2908148 100644 --- a/drivers/power/supply/rt9455_charger.c +++ b/drivers/power/supply/rt9455_charger.c @@ -1719,7 +1719,7 @@ static void rt9455_remove(struct i2c_client *client) } static const struct i2c_device_id rt9455_i2c_id_table[] = { - { RT9455_DRIVER_NAME }, + { .name = RT9455_DRIVER_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, rt9455_i2c_id_table); diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index 43c48196c167..017ec06be766 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -1254,10 +1254,10 @@ static SIMPLE_DEV_PM_OPS(sbs_pm_ops, sbs_suspend, NULL); #endif static const struct i2c_device_id sbs_id[] = { - { "bq20z65", SBS_FLAGS_TI_BQ20ZX5 }, - { "bq20z75", SBS_FLAGS_TI_BQ20ZX5 }, - { "sbs-battery", 0 }, - {} + { .name = "bq20z65", .driver_data = SBS_FLAGS_TI_BQ20ZX5 }, + { .name = "bq20z75", .driver_data = SBS_FLAGS_TI_BQ20ZX5 }, + { .name = "sbs-battery", .driver_data = 0 }, + { } }; MODULE_DEVICE_TABLE(i2c, sbs_id); diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c index 7d5e67620580..a00c710601e8 100644 --- a/drivers/power/supply/sbs-charger.c +++ b/drivers/power/supply/sbs-charger.c @@ -244,7 +244,7 @@ MODULE_DEVICE_TABLE(of, sbs_dt_ids); #endif static const struct i2c_device_id sbs_id[] = { - { "sbs-charger" }, + { .name = "sbs-charger" }, { } }; MODULE_DEVICE_TABLE(i2c, sbs_id); diff --git a/drivers/power/supply/sbs-manager.c b/drivers/power/supply/sbs-manager.c index 343ad4ab4082..9ad3fb117a4d 100644 --- a/drivers/power/supply/sbs-manager.c +++ b/drivers/power/supply/sbs-manager.c @@ -389,8 +389,8 @@ static int sbsm_probe(struct i2c_client *client) } static const struct i2c_device_id sbsm_ids[] = { - { "sbs-manager" }, - { "ltc1760" }, + { .name = "sbs-manager" }, + { .name = "ltc1760" }, { } }; MODULE_DEVICE_TABLE(i2c, sbsm_ids); diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index 8b95f7e8712f..d9624b6a898c 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -1609,10 +1609,10 @@ static void smb347_shutdown(struct i2c_client *client) } static const struct i2c_device_id smb347_id[] = { - { "smb345", SMB345 }, - { "smb347", SMB347 }, - { "smb358", SMB358 }, - { }, + { .name = "smb345", .driver_data = SMB345 }, + { .name = "smb347", .driver_data = SMB347 }, + { .name = "smb358", .driver_data = SMB358 }, + { } }; MODULE_DEVICE_TABLE(i2c, smb347_id); diff --git a/drivers/power/supply/stc3117_fuel_gauge.c b/drivers/power/supply/stc3117_fuel_gauge.c index a1bc5970370a..469f2b359920 100644 --- a/drivers/power/supply/stc3117_fuel_gauge.c +++ b/drivers/power/supply/stc3117_fuel_gauge.c @@ -584,7 +584,7 @@ static int stc3117_probe(struct i2c_client *client) } static const struct i2c_device_id stc3117_id[] = { - { "stc3117", 0 }, + { .name = "stc3117", .driver_data = 0 }, { } }; MODULE_DEVICE_TABLE(i2c, stc3117_id); diff --git a/drivers/power/supply/ug3105_battery.c b/drivers/power/supply/ug3105_battery.c index 210e0f9aa5e0..0cbf45856fac 100644 --- a/drivers/power/supply/ug3105_battery.c +++ b/drivers/power/supply/ug3105_battery.c @@ -195,7 +195,7 @@ static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend, ug3105_resume); static const struct i2c_device_id ug3105_id[] = { - { "ug3105" }, + { .name = "ug3105" }, { } }; MODULE_DEVICE_TABLE(i2c, ug3105_id); -- cgit v1.2.3 From 15384402c94a55b05d06a446aedd19e242367b6f Mon Sep 17 00:00:00 2001 From: Md Shofiqul Islam Date: Thu, 7 May 2026 22:18:40 +0300 Subject: power: supply: ab8500_fg: Fix typos in comments Fix spelling mistake in comments: - occured -> occurred (twice) Acked-by: Linus Walleij Signed-off-by: Md Shofiqul Islam Link: https://patch.msgid.link/20260507191840.25941-1-shofiqtest@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_fg.c | 2 +- drivers/power/supply/smb347-charger.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 9dd99722667a..eb5c1ae68e44 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -2037,7 +2037,7 @@ static irqreturn_t ab8500_fg_cc_convend_handler(int irq, void *_di) } /** - * ab8500_fg_batt_ovv_handler() - Battery OVV occured + * ab8500_fg_batt_ovv_handler() - Battery OVV occurred * @irq: interrupt number * @_di: pointer to the ab8500_fg structure * diff --git a/drivers/power/supply/smb347-charger.c b/drivers/power/supply/smb347-charger.c index d9624b6a898c..c1b67dac8ef6 100644 --- a/drivers/power/supply/smb347-charger.c +++ b/drivers/power/supply/smb347-charger.c @@ -1083,7 +1083,7 @@ static int smb347_get_charging_status(struct smb347_charger *smb, } else { /* * in this case no charger error or termination - * occured but charging is not in progress!!! + * occurred but charging is not in progress!!! */ status = POWER_SUPPLY_STATUS_NOT_CHARGING; } -- cgit v1.2.3 From 43401898fde586bdeb73ac2c11d4f949fcba9f77 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 May 2026 12:27:52 +0200 Subject: power: supply: cros_charge-control: Move MODULE_DEVICE_TABLE next to the table itself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By convention MODULE_DEVICE_TABLE() immediately follows the ID table it exports, because this is easier to read and verify. It also makes more sense since #ifdef for ACPI or OF could hide both of them. Most of the privers already have this correctly placed, so adjust the missing ones. No functional impact. Signed-off-by: Krzysztof Kozlowski Acked-by: Thomas Weißschuh Reviewed-by: Tzung-Bi Shih Link: https://patch.msgid.link/20260505102752.182089-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/cros_charge-control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c index b489325be816..e1b8f3b1b7de 100644 --- a/drivers/power/supply/cros_charge-control.c +++ b/drivers/power/supply/cros_charge-control.c @@ -323,6 +323,7 @@ static const struct platform_device_id cros_chctl_id[] = { { .name = "cros-charge-control" }, { } }; +MODULE_DEVICE_TABLE(platform, cros_chctl_id); static struct platform_driver cros_chctl_driver = { .driver.name = "cros-charge-control", @@ -331,7 +332,6 @@ static struct platform_driver cros_chctl_driver = { }; module_platform_driver(cros_chctl_driver); -MODULE_DEVICE_TABLE(platform, cros_chctl_id); MODULE_DESCRIPTION("ChromeOS EC charge control"); MODULE_AUTHOR("Thomas Weißschuh "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a9e36028b688d693d8aefbf84a9899f31a20fcf0 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 5 May 2026 13:05:18 +0300 Subject: power: supply: cpcap-charger: include missing This file uses dev_fwnode() without including the proper header for it, relying on transitive header inclusion from: drivers/power/supply/cpcap-charger.c - include/linux/phy/omap_usb.h - include/linux/usb/phy_companion.h - include/linux/usb/otg.h - include/linux/phy/phy.h - drivers/phy/phy-provider.h - include/linux/of.h - include/linux/property.h With the future removal of drivers/phy/phy-provider.h from include/linux/phy/phy.h, this transitive inclusion would break. Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20260505100523.1922388-27-vladimir.oltean@nxp.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-charger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index d0c3008db534..24221244b45b 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From e92786dd86a24bf02ab4503856799192b7f073c7 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Mon, 4 May 2026 18:40:17 +0200 Subject: power: supply: bd71828: sysfs for auto input current limitation Add the possibility to disable the auto adjustment for input current limitation via sysfs because it gives strange results under certain circumstances e.g. when powering the device with solar panels resulting in no input power usage at all. Signed-off-by: Andreas Kemnade Reviewed-by: Matti Vaittinen Link: https://patch.msgid.link/20260504164017.467679-1-andreas@kemnade.info Signed-off-by: Sebastian Reichel --- .../ABI/testing/sysfs-class-power-bd71828 | 12 ++++ drivers/power/supply/bd71828-power.c | 69 +++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-class-power-bd71828 diff --git a/Documentation/ABI/testing/sysfs-class-power-bd71828 b/Documentation/ABI/testing/sysfs-class-power-bd71828 new file mode 100644 index 000000000000..2d451e1c8336 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-power-bd71828 @@ -0,0 +1,12 @@ +What: /sys/class/power_supply/bd71828_ac/auto_dcin_limit +Description: + Enable/Disable automatic management of input current limit + (ILIM_DCIN_EN bit). + + Possible values are: + + ============ =========================================== + 1 automatic adjustment of input current limit + 0 no adjustment of input current limit. This + helps for more unusual power sources like + solar modules. diff --git a/drivers/power/supply/bd71828-power.c b/drivers/power/supply/bd71828-power.c index 5ab514ff5c65..b671563ead79 100644 --- a/drivers/power/supply/bd71828-power.c +++ b/drivers/power/supply/bd71828-power.c @@ -12,6 +12,7 @@ #include #include #include +#include /* common defines */ #define BD7182x_MASK_VBAT_U 0x1f @@ -25,6 +26,7 @@ #define BD71815_MASK_CONF_XSTB BIT(1) #define BD7182x_MASK_BAT_STAT 0x3f #define BD7182x_MASK_ILIM 0x3f +#define BD71828_MASK_ILIM_DCIN_EN BIT(6) #define BD7182x_MASK_DCIN_STAT 0x07 #define BD7182x_MASK_WDT_AUTO 0x40 @@ -1099,10 +1101,75 @@ static int bd7182x_get_rsens(struct bd71828_power *pwr) return 0; } +static ssize_t auto_dcin_limit_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + int ret; + unsigned int v; + + ret = regmap_read(pwr->regmap, pwr->regs->dcin_set, &v); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", !!(v & BD71828_MASK_ILIM_DCIN_EN)); +} + +static ssize_t auto_dcin_limit_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + int ret; + bool v; + + ret = kstrtobool(buf, &v); + if (ret < 0) + return ret; + + ret = regmap_update_bits(pwr->regmap, BD71828_REG_DCIN_SET, + BD71828_MASK_ILIM_DCIN_EN, + v ? BD71828_MASK_ILIM_DCIN_EN : 0); + if (ret < 0) + return ret; + + return len; +} + +static DEVICE_ATTR_RW(auto_dcin_limit); + +static struct attribute *bd71828_ac_sysfs_attrs[] = { + &dev_attr_auto_dcin_limit.attr, + NULL, +}; + +static bool bd71828_ac_sysfs_group_visible(struct kobject *kobj) +{ + struct device *dev = kobj_to_dev(kobj); + struct bd71828_power *pwr = dev_get_drvdata(dev->parent); + + return !!pwr->regs->dcin_set; +} + +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs); + +static const struct attribute_group bd71828_ac_sysfs_group = { + .attrs = bd71828_ac_sysfs_attrs, + .is_visible = SYSFS_GROUP_VISIBLE(bd71828_ac_sysfs) +}; + +static const struct attribute_group *bd71828_ac_sysfs_groups[] = { + &bd71828_ac_sysfs_group, + NULL +}; + static int bd71828_power_probe(struct platform_device *pdev) { struct bd71828_power *pwr; - struct power_supply_config ac_cfg = {}; + struct power_supply_config ac_cfg = { + .attr_grp = bd71828_ac_sysfs_groups, + }; struct power_supply_config bat_cfg = {}; int ret; -- cgit v1.2.3 From de296b53775cd1ccb6b448b4cc8d843c8858e1df Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Thu, 7 May 2026 16:46:06 +0300 Subject: dt-bindings: embedded-controller: Document Surface RT EC Document Embedded Controller used in Microsoft Surface RT tablets for monitoring battery properties and charger status. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260507134608.76222-2-clamor95@gmail.com Signed-off-by: Sebastian Reichel --- .../microsoft,surface-rt-ec.yaml | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml diff --git a/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml b/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml new file mode 100644 index 000000000000..0fee574a3015 --- /dev/null +++ b/Documentation/devicetree/bindings/embedded-controller/microsoft,surface-rt-ec.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/embedded-controller/microsoft,surface-rt-ec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microsoft Surface RT fuel gauge and charger EC + +maintainers: + - Jonas Schwöbel + - Svyatoslav Ryhel + +description: + An Embedded Controller used in Microsoft Surface RT for monitoring + battery properties and charger status. + +allOf: + - $ref: /schemas/power/supply/power-supply.yaml# + +properties: + compatible: + const: microsoft,surface-rt-ec + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + enable-gpios: + maxItems: 1 + + monitored-battery: true + +required: + - compatible + - reg + - interrupts + - enable-gpios + +additionalProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + embedded-controller@a { + compatible = "microsoft,surface-rt-ec"; + reg = <0x0a>; + + interrupt-parent = <&gpio>; + interrupts = <74 IRQ_TYPE_EDGE_RISING>; + + enable-gpios = <&gpio 88 GPIO_ACTIVE_HIGH>; + monitored-battery = <&battery>; + }; + }; +... -- cgit v1.2.3 From 3d6529b837de49294cea0d4600144353f5f084dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Schw=C3=B6bel?= Date: Thu, 7 May 2026 16:46:07 +0300 Subject: power: supply: Add support for Surface RT battery and charger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for Embedded Controller found in the Microsoft Surface RT and used to monitor battery cell and charger input status and properties. Controller works both for UEFI and APX booting. [wmjb: added POWER_SUPPLY_PROP_CHARGE_NOW support] Signed-off-by: Jethro Bull Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel Link: https://patch.msgid.link/20260507134608.76222-3-clamor95@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 11 + drivers/power/supply/Makefile | 1 + drivers/power/supply/surface-rt-ec.c | 389 +++++++++++++++++++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 drivers/power/supply/surface-rt-ec.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 83392ed6a8da..c56d7ace7d55 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -1135,6 +1135,17 @@ config BATTERY_UG3105 device is off or suspended, the functionality of this driver is limited to reporting capacity only. +config BATTERY_CHARGER_SURFACE_RT + tristate "Battery & Charger driver for Microsoft Surface RT" + depends on I2C && GPIOLIB + help + UEFI/APX driver for the 1st-generation Microsoft Surface RT + battery. Driver supports reading battery properties and + charger status. + + This driver can also be built as a module. If so, the module + will be called surface-rt-ec. + config CHARGER_QCOM_SMB2 tristate "Qualcomm PMI8998 PMIC charger driver" depends on MFD_SPMI_PMIC diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 7ee839dca7f3..b55612d626c8 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -126,6 +126,7 @@ obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o +obj-$(CONFIG_BATTERY_CHARGER_SURFACE_RT) += surface-rt-ec.o obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_smbx.o obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o diff --git a/drivers/power/supply/surface-rt-ec.c b/drivers/power/supply/surface-rt-ec.c new file mode 100644 index 000000000000..a728ae0db858 --- /dev/null +++ b/drivers/power/supply/surface-rt-ec.c @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register Addresses (B=byte; W=word; S=string) */ +#define REGB_STATUS 0x02 +#define REGW_VOLTAGE_NOW 0x20 +#define REGW_CURRENT_NOW 0x24 +#define REGW_CAPACITY 0x28 +#define REGW_CHARGE_NOW 0x2a +#define REGW_CHARGE_FULL 0x2c +#define REGW_CYCLE_COUNT 0x3a +#define REGW_CHARGE_FULL_DESIGN 0x3c +#define REGW_VOLTAGE_MAX_DESIGN 0x3e +#define REGW_SERIAL_NUMBER 0x44 +#define REGS_MANUFACTURER 0x46 +#define REGS_MODEL_NAME 0x52 +#define REGS_TECHNOLOGY 0x5a +#define REGB_ONLINE 0x67 + +struct srt_ec_device { + struct i2c_client *client; + + struct power_supply *bat; + struct power_supply *psy; + + struct gpio_desc *enable_gpiod; + struct delayed_work poll_work; + + unsigned int technology; + unsigned int capacity; + + const char *serial; + char manufacturer[13]; + char model_name[10]; +}; + +static const enum power_supply_property srt_bat_power_supply_props[] = { + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CYCLE_COUNT, + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_SERIAL_NUMBER, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +static const enum power_supply_property srt_psy_power_supply_props[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_PRESENT, +}; + +static int srt_bat_get_value(struct i2c_client *client, int reg, int *val) +{ + int ret; + + switch (reg) { + case REGW_CHARGE_NOW: + case REGW_CHARGE_FULL_DESIGN: + case REGW_CHARGE_FULL: + case REGW_VOLTAGE_MAX_DESIGN: + case REGW_VOLTAGE_NOW: + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) + return ret; + + *val = ret * 1000; + break; + + case REGW_CURRENT_NOW: + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) + return ret; + + *val = (s16)ret * 1000; + break; + + case REGW_CAPACITY: + case REGW_CYCLE_COUNT: + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) + return ret; + + *val = ret; + break; + + case REGB_STATUS: + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) + return ret; + + if (ret & BIT(0)) + *val = POWER_SUPPLY_STATUS_CHARGING; + else + *val = POWER_SUPPLY_STATUS_DISCHARGING; + break; + + case REGB_ONLINE: + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) + return ret; + + *val = (ret & BIT(1)) >> 1; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int srt_bat_power_supply_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct srt_ec_device *srt = power_supply_get_drvdata(psy); + struct i2c_client *client = srt->client; + int ret = 0; + + switch (psp) { + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = srt->manufacturer; + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = srt->model_name; + break; + case POWER_SUPPLY_PROP_SERIAL_NUMBER: + val->strval = srt->serial; + break; + case POWER_SUPPLY_PROP_CAPACITY: + ret = srt_bat_get_value(client, REGW_CAPACITY, &val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = srt_bat_get_value(client, REGW_CHARGE_NOW, &val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + ret = srt_bat_get_value(client, REGW_CHARGE_FULL, &val->intval); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + ret = srt_bat_get_value(client, REGW_CHARGE_FULL_DESIGN, + &val->intval); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = srt_bat_get_value(client, REGW_CURRENT_NOW, &val->intval); + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + ret = srt_bat_get_value(client, REGW_CYCLE_COUNT, &val->intval); + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + case POWER_SUPPLY_PROP_ONLINE: + ret = srt_bat_get_value(client, REGB_ONLINE, &val->intval); + break; + case POWER_SUPPLY_PROP_STATUS: + if (srt->capacity < 100) + ret = srt_bat_get_value(client, REGB_STATUS, &val->intval); + else + val->intval = POWER_SUPPLY_STATUS_FULL; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = srt->technology; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + ret = srt_bat_get_value(client, REGW_VOLTAGE_MAX_DESIGN, + &val->intval); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = srt_bat_get_value(client, REGW_VOLTAGE_NOW, &val->intval); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int srt_psy_power_supply_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct srt_ec_device *srt = power_supply_get_drvdata(psy); + struct i2c_client *client = srt->client; + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + case POWER_SUPPLY_PROP_PRESENT: + ret = i2c_smbus_read_byte_data(client, REGB_ONLINE); + if (ret < 0) + return ret; + + val->intval = ret & BIT(0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void srt_bat_poll_work(struct work_struct *work) +{ + struct srt_ec_device *srt = + container_of(work, struct srt_ec_device, poll_work.work); + int ret, capacity; + + ret = srt_bat_get_value(srt->client, REGW_CAPACITY, &capacity); + if (!ret && capacity != srt->capacity) { + srt->capacity = capacity; + power_supply_changed(srt->bat); + } + + /* continuously send uevent notification */ + schedule_delayed_work(&srt->poll_work, 30 * HZ); +} + +static irqreturn_t srt_psy_detect_irq(int irq, void *dev_id) +{ + struct srt_ec_device *srt = dev_id; + + power_supply_changed(srt->psy); + + return IRQ_HANDLED; +} + +static const struct power_supply_desc srt_bat_power_supply_desc = { + .name = "surface-rt-battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = srt_bat_power_supply_props, + .num_properties = ARRAY_SIZE(srt_bat_power_supply_props), + .get_property = srt_bat_power_supply_get_property, + .external_power_changed = power_supply_changed, +}; + +static const struct power_supply_desc srt_psy_power_supply_desc = { + .name = "surface-rt-ac-adapter", + .type = POWER_SUPPLY_TYPE_MAINS, + .properties = srt_psy_power_supply_props, + .num_properties = ARRAY_SIZE(srt_psy_power_supply_props), + .get_property = srt_psy_power_supply_get_property, +}; + +static char *battery_supplied_to[] = { "surface-rt-battery" }; + +static int srt_ec_probe(struct i2c_client *client) +{ + struct power_supply_config bat_cfg = {}; + struct power_supply_config psy_cfg = {}; + struct device *dev = &client->dev; + struct srt_ec_device *srt; + char str_buf[4]; + int ret; + + srt = devm_kzalloc(dev, sizeof(*srt), GFP_KERNEL); + if (!srt) + return -ENOMEM; + + i2c_set_clientdata(client, srt); + srt->client = client; + + srt->enable_gpiod = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(srt->enable_gpiod)) + return dev_err_probe(dev, PTR_ERR(srt->enable_gpiod), + "failed to get enable gpio\n"); + + /* wait till EC is ready */ + usleep_range(1000, 1500); + + ret = i2c_smbus_read_word_data(client, REGW_SERIAL_NUMBER); + if (ret < 0) + return ret; + + srt->serial = devm_kasprintf(dev, GFP_KERNEL, "%04x", ret); + if (!srt->serial) + return -ENOMEM; + + ret = i2c_smbus_read_i2c_block_data(client, REGS_MANUFACTURER, + sizeof(srt->manufacturer) - 1, + srt->manufacturer); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_i2c_block_data(client, REGS_MODEL_NAME, + sizeof(srt->model_name) - 1, + srt->model_name); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_i2c_block_data(client, REGS_TECHNOLOGY, + sizeof(str_buf), str_buf); + if (ret < 0) + return ret; + + if (!strncmp(str_buf, "LION", 4)) + srt->technology = POWER_SUPPLY_TECHNOLOGY_LION; + else + srt->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + + bat_cfg.drv_data = srt; + bat_cfg.fwnode = dev_fwnode(dev); + + srt->bat = devm_power_supply_register(dev, &srt_bat_power_supply_desc, + &bat_cfg); + if (IS_ERR(srt->bat)) + return dev_err_probe(dev, PTR_ERR(srt->bat), + "failed to register battery power supply\n"); + + psy_cfg.drv_data = srt; + psy_cfg.fwnode = dev_fwnode(dev); + psy_cfg.supplied_to = battery_supplied_to; + psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to); + + srt->psy = devm_power_supply_register(dev, &srt_psy_power_supply_desc, + &psy_cfg); + if (IS_ERR(srt->psy)) + return dev_err_probe(dev, PTR_ERR(srt->psy), + "failed to register AC power supply\n"); + + ret = devm_request_threaded_irq(dev, client->irq, NULL, srt_psy_detect_irq, + IRQF_ONESHOT, client->name, srt); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to request interrupt\n"); + + ret = devm_delayed_work_autocancel(dev, &srt->poll_work, srt_bat_poll_work); + if (ret < 0) + return ret; + + schedule_delayed_work(&srt->poll_work, HZ); + + return 0; +} + +static int srt_ec_suspend(struct device *dev) +{ + struct srt_ec_device *srt = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&srt->poll_work); + + return 0; +} + +static int srt_ec_resume(struct device *dev) +{ + struct srt_ec_device *srt = dev_get_drvdata(dev); + + schedule_delayed_work(&srt->poll_work, HZ); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(srt_ec_pm_ops, srt_ec_suspend, srt_ec_resume); + +static const struct of_device_id srt_ec_of_match[] = { + { .compatible = "microsoft,surface-rt-ec" }, + { } +}; +MODULE_DEVICE_TABLE(of, srt_ec_of_match); + +static struct i2c_driver srt_ec_driver = { + .driver = { + .name = "surface-rt-ec", + .of_match_table = srt_ec_of_match, + .pm = &srt_ec_pm_ops, + }, + .probe = srt_ec_probe, +}; +module_i2c_driver(srt_ec_driver); + +MODULE_AUTHOR("Jonas Schwöbel "); +MODULE_DESCRIPTION("Surface RT Embedded Controller driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7e541f6dbd05921d0bbb99646028cb9982535707 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Sat, 16 May 2026 03:08:42 +0530 Subject: power: supply: add support for Samsung S2M series PMIC charger device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a driver for charger controllers found in certain Samsung S2M series PMICs. The driver has very basic support for the device, with only charger online reporting working, and USB 2.0 device negotiations working. The driver includes initial support for the S2MU005 PMIC charger. Co-developed-by: Łukasz Lebiedziński Signed-off-by: Łukasz Lebiedziński Signed-off-by: Kaustabh Chakraborty Link: https://patch.msgid.link/20260516-s2mu005-pmic-v7-10-73f9702fb461@disroot.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 10 ++ drivers/power/supply/Makefile | 1 + drivers/power/supply/s2m-charger.c | 313 +++++++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 drivers/power/supply/s2m-charger.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index c56d7ace7d55..f0ede1cecb6a 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -856,6 +856,16 @@ config CHARGER_RK817 help Say Y to include support for Rockchip RK817 Battery Charger. +config CHARGER_S2M + tristate "Samsung S2M series PMIC battery charger support" + depends on EXTCON_S2M + depends on MFD_SEC_CORE + help + This option enables support for charger devices found in + certain Samsung S2M series PMICs, such as the S2MU005. These + devices provide USB power supply information and also required + for USB OTG role switching. + config CHARGER_SMB347 tristate "Summit Microelectronics SMB3XX Battery Charger" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index b55612d626c8..31fe4a145929 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -107,6 +107,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o obj-$(CONFIG_CHARGER_BQ25980) += bq25980_charger.o obj-$(CONFIG_CHARGER_BQ256XX) += bq256xx_charger.o obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o +obj-$(CONFIG_CHARGER_S2M) += s2m-charger.o obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o diff --git a/drivers/power/supply/s2m-charger.c b/drivers/power/supply/s2m-charger.c new file mode 100644 index 000000000000..4d1f2c2c7144 --- /dev/null +++ b/drivers/power/supply/s2m-charger.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Battery Charger Driver for Samsung S2M series PMICs. + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd + * Copyright (c) 2026 Kaustabh Chakraborty + * Copyright (c) 2026 Łukasz Lebiedziński + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct s2m_chgr { + struct device *dev; + struct regmap *regmap; + struct power_supply *psy; + struct extcon_dev *extcon; + struct work_struct extcon_work; + struct notifier_block extcon_nb; +}; + +static int s2mu005_chgr_get_online(struct s2m_chgr *priv, int *value) +{ + u32 val; + int ret; + + ret = regmap_read(priv->regmap, S2MU005_REG_CHGR_STATUS0, &val); + if (ret) { + dev_err(priv->dev, "failed to read register (%d)\n", ret); + return ret; + } + + *value = !!(val & S2MU005_CHGR_CHG); + + return 0; +} + +static void s2mu005_chgr_get_usb_type(struct s2m_chgr *priv, int *value) +{ + if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_CDP) > 0) + *value = POWER_SUPPLY_USB_TYPE_CDP; + else if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_SDP) > 0) + *value = POWER_SUPPLY_USB_TYPE_SDP; + else if (extcon_get_state(priv->extcon, EXTCON_CHG_USB_DCP) > 0) + *value = POWER_SUPPLY_USB_TYPE_DCP; + else + *value = POWER_SUPPLY_USB_TYPE_UNKNOWN; +} + +static int s2mu005_chgr_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct s2m_chgr *priv = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ret = s2mu005_chgr_get_online(priv, &val->intval); + if (ret) + return ret; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + s2mu005_chgr_get_usb_type(priv, &val->intval); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int s2mu005_chgr_mode_set_host(struct s2m_chgr *priv) +{ + int ret; + + /* set mode to OTG */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0, + S2MU005_CHGR_OP_MODE, + FIELD_PREP(S2MU005_CHGR_OP_MODE, + S2MU005_CHGR_OP_MODE_OTG)); + if (ret) { + dev_err(priv->dev, "failed to set OTG mode (%d)\n", ret); + return ret; + } + + /* set boost frequency to 2MHz */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL11, + S2MU005_CHGR_OSC_BOOST, + FIELD_PREP(S2MU005_CHGR_OSC_BOOST, + S2MU005_CHGR_OSC_BOOST_2MHZ)); + if (ret) { + dev_err(priv->dev, "failed to set boost frequency (%d)\n", ret); + return ret; + } + + /* set OTG current limit to 1.5 A */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL4, + S2MU005_CHGR_OTG_OCP, + FIELD_PREP(S2MU005_CHGR_OTG_OCP, + S2MU005_CHGR_OTG_OCP_1P5A)); + if (ret) { + dev_err(priv->dev, "failed to set OTG current limit (%d)\n", ret); + return ret; + } + + /* VBUS switches are OFF when OTG over-current happens */ + ret = regmap_set_bits(priv->regmap, S2MU005_REG_CHGR_CTRL4, + S2MU005_CHGR_OTG_OCP_OFF); + if (ret) { + dev_err(priv->dev, "failed to set OTG OCP switch (%d)\n", ret); + return ret; + } + + /* set OTG voltage to 5.1 V */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL5, + S2MU005_CHGR_VMID_BOOST, + FIELD_PREP(S2MU005_CHGR_VMID_BOOST, + S2MU005_CHGR_VMID_BOOST_5P1V)); + if (ret) { + dev_err(priv->dev, "failed to set OTG voltage (%d)\n", ret); + return ret; + } + + /* turn on OTG */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL15, + S2MU005_CHGR_OTG_EN, + FIELD_PREP(S2MU005_CHGR_OTG_EN, + S2MU005_CHGR_OTG_EN_ON)); + if (ret) { + dev_err(priv->dev, "failed to turn on OTG (%d)\n", ret); + return ret; + } + + return 0; +} + +static int s2mu005_chgr_mode_set_charger(struct s2m_chgr *priv) +{ + int ret; + + /* first reset to mode 0 */ + ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0, + S2MU005_CHGR_OP_MODE); + if (ret) { + dev_err(priv->dev, "failed to reset opmode (%d)\n", ret); + return ret; + } + + /* wait for the charger to settle before switching to charging mode */ + msleep(50); + /* then set to charging mode */ + ret = regmap_update_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0, + S2MU005_CHGR_OP_MODE, + FIELD_PREP(S2MU005_CHGR_OP_MODE, + S2MU005_CHGR_OP_MODE_CHG)); + if (ret) { + dev_err(priv->dev, "failed to set opmode to charging (%d)\n", ret); + return ret; + } + + return 0; +} + +static int s2mu005_chgr_mode_unset(struct s2m_chgr *priv) +{ + int ret; + + /* turn off OTG */ + ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL15, + S2MU005_CHGR_OTG_EN); + if (ret) { + dev_err(priv->dev, "failed to turn off OTG (%d)\n", ret); + return ret; + } + + /* reset operation mode */ + ret = regmap_clear_bits(priv->regmap, S2MU005_REG_CHGR_CTRL0, + S2MU005_CHGR_OP_MODE); + if (ret) { + dev_err(priv->dev, "failed to reset opmode (%d)\n", ret); + return ret; + } + + return 0; +} + +static void s2mu005_chgr_extcon_work(struct work_struct *work) +{ + struct s2m_chgr *priv = container_of(work, struct s2m_chgr, extcon_work); + + if (extcon_get_state(priv->extcon, EXTCON_USB_HOST) > 0) + s2mu005_chgr_mode_set_host(priv); + else if (extcon_get_state(priv->extcon, EXTCON_USB) > 0) + s2mu005_chgr_mode_set_charger(priv); + else + s2mu005_chgr_mode_unset(priv); + + power_supply_changed(priv->psy); +} + +static const enum power_supply_property s2mu005_chgr_properties[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_USB_TYPE, +}; + +static const struct power_supply_desc s2mu005_chgr_psy_desc = { + .name = "s2mu005-charger", + .type = POWER_SUPPLY_TYPE_USB, + .properties = s2mu005_chgr_properties, + .num_properties = ARRAY_SIZE(s2mu005_chgr_properties), + .get_property = s2mu005_chgr_get_property, + .usb_types = BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN), +}; + +static int s2m_chgr_extcon_notifier(struct notifier_block *nb, + unsigned long event, void *param) +{ + struct s2m_chgr *priv = container_of(nb, struct s2m_chgr, extcon_nb); + + schedule_work(&priv->extcon_work); + + return NOTIFY_OK; +} + +static int s2m_chgr_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sec_pmic_dev *pmic_drvdata = dev_get_drvdata(dev->parent); + struct s2m_chgr *priv; + struct device_node *extcon_node __free(device_node) = NULL; + struct power_supply_config psy_cfg = {}; + const struct power_supply_desc *psy_desc; + work_func_t extcon_work_func; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + priv->dev = dev; + priv->regmap = pmic_drvdata->regmap_pmic; + + switch (platform_get_device_id(pdev)->driver_data) { + case S2MU005: + psy_desc = &s2mu005_chgr_psy_desc; + extcon_work_func = s2mu005_chgr_extcon_work; + break; + default: + return dev_err_probe(dev, -ENODEV, + "device type %d is not supported by driver\n", + pmic_drvdata->device_type); + } + + /* MUIC is mandatory. If unavailable, request probe deferral */ + extcon_node = of_get_child_by_name(dev->parent->of_node, "muic"); + if (!extcon_node) + return dev_err_probe(dev, -ENODEV, "MUIC node required but not found\n"); + + priv->extcon = extcon_find_edev_by_node(extcon_node); + if (IS_ERR(priv->extcon)) + return -EPROBE_DEFER; + + psy_cfg.drv_data = priv; + psy_cfg.fwnode = dev_fwnode(dev->parent); + priv->psy = devm_power_supply_register(dev, psy_desc, &psy_cfg); + if (IS_ERR(priv->psy)) + return dev_err_probe(dev, PTR_ERR(priv->psy), + "failed to register power supply subsystem\n"); + + ret = devm_work_autocancel(dev, &priv->extcon_work, extcon_work_func); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize extcon work\n"); + + priv->extcon_nb.notifier_call = s2m_chgr_extcon_notifier; + ret = devm_extcon_register_notifier_all(dev, priv->extcon, &priv->extcon_nb); + if (ret) + return dev_err_probe(dev, ret, "failed to register extcon notifier\n"); + + return 0; +} + +static const struct platform_device_id s2m_chgr_id_table[] = { + { "s2mu005-charger", S2MU005 }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, s2m_chgr_id_table); + +static struct platform_driver s2m_chgr_driver = { + .driver = { + .name = "s2m-charger", + }, + .probe = s2m_chgr_probe, + .id_table = s2m_chgr_id_table, +}; +module_platform_driver(s2m_chgr_driver); + +MODULE_DESCRIPTION("Battery Charger Driver For Samsung S2M Series PMICs"); +MODULE_AUTHOR("Kaustabh Chakraborty "); +MODULE_AUTHOR("Łukasz Lebiedziński "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4acc0138c4f2fba453da5a5076ad2bba08a7463b Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 4 Jun 2026 22:52:28 -0700 Subject: power: supply: max17042_battery: Use modern PM ops to clear up warning When building for a platform that does not have power management, such as s390, there is an unused function warning, as max17042_suspend_soc_alerts() is only used in max17042_suspend(), which is under a CONFIG_PM_SLEEP #ifdef. drivers/power/supply/max17042_battery.c:957:13: error: 'max17042_suspend_soc_alerts' defined but not used [-Werror=unused-function] 957 | static void max17042_suspend_soc_alerts(struct max17042_chip *chip) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the modern DEFINE_SIMPLE_DEV_PM_OPS(), which allows the compiler to see the functions as used while allowing it to eliminate them as unused during the optimization phase. Use pm_ptr() to allow the compiler to drop max17042_pm_ops when there is no PM support. Fixes: 601885ffb5e9 ("power: supply: max17042_battery: Keep only critical alerts during suspend") Signed-off-by: Nathan Chancellor Link: https://patch.msgid.link/20260604-max17042_battery-fix-unused-suspend_soc_alerts-v1-1-3562a68e6f36@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 0fb46c1c203f..639dacdb9b31 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1296,7 +1296,6 @@ static int max17042_platform_probe(struct platform_device *pdev) return max17042_probe(i2c, dev, irq, id->driver_data); } -#ifdef CONFIG_PM_SLEEP static int max17042_suspend(struct device *dev) { struct max17042_chip *chip = dev_get_drvdata(dev); @@ -1327,10 +1326,9 @@ static int max17042_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend, - max17042_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend, + max17042_resume); #ifdef CONFIG_ACPI static const struct acpi_device_id max17042_acpi_match[] = { @@ -1397,7 +1395,7 @@ static struct i2c_driver max17042_i2c_driver = { .name = "max17042", .acpi_match_table = ACPI_PTR(max17042_acpi_match), .of_match_table = of_match_ptr(max17042_dt_match), - .pm = &max17042_pm_ops, + .pm = pm_ptr(&max17042_pm_ops), }, .probe = max17042_i2c_probe, .id_table = max17042_id, @@ -1407,7 +1405,7 @@ static struct platform_driver max17042_platform_driver = { .driver = { .name = "max17042", .acpi_match_table = ACPI_PTR(max17042_acpi_match), - .pm = &max17042_pm_ops, + .pm = pm_ptr(&max17042_pm_ops), }, .probe = max17042_platform_probe, .id_table = max17042_platform_id, -- cgit v1.2.3 From ba61aed9a34671222d1149acfc2f0179a9ce7e80 Mon Sep 17 00:00:00 2001 From: Lucas Tsai Date: Tue, 9 Jun 2026 19:44:03 +0800 Subject: power: supply: core: fix supplied_from allocations If dts property power-supplies has multiple values, then accessing to psy->supplied_from[i-1] in __power_supply_populate_supplied_from will overrun supplied_from array. Fixes: f6e0b081fb30 ("power_supply: Populate supplied_from hierarchy from the device tree") Signed-off-by: Lucas Tsai Link: https://patch.msgid.link/20260609114403.3896073-1-lucas_tsai@richtek.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index a446d3d086fc..2532e221b2e1 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -292,18 +292,13 @@ static int power_supply_check_supplies(struct power_supply *psy) if (cnt == 1) return 0; - /* All supplies found, allocate char ** array for filling */ - psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(*psy->supplied_from), + /* All supplies found, allocate char * array for filling */ + psy->supplied_from = devm_kcalloc(&psy->dev, + cnt - 1, sizeof(*psy->supplied_from), GFP_KERNEL); if (!psy->supplied_from) return -ENOMEM; - *psy->supplied_from = devm_kcalloc(&psy->dev, - cnt - 1, sizeof(**psy->supplied_from), - GFP_KERNEL); - if (!*psy->supplied_from) - return -ENOMEM; - return power_supply_populate_supplied_from(psy); } #else -- cgit v1.2.3 From 4373cfa38ead58f980362c841b0d0bdf8c4d956c Mon Sep 17 00:00:00 2001 From: WenTao Liang Date: Thu, 11 Jun 2026 08:53:21 +0800 Subject: power: supply: charger-manager: fix refcount leak in is_full_charged() In is_full_charged(), power_supply_get_by_name() is called to obtain a reference to the fuel_gauge power supply. If the voltage check (uV >= desc->fullbatt_uV) succeeds, the function returns true directly without releasing the reference, leaking the refcount. Fix this by setting a flag and jumping to the out label where power_supply_put() properly drops the reference. Cc: stable@vger.kernel.org Fixes: e132fc6bb89b ("power: supply: charger-manager: Make decisions focussed on battery status") Signed-off-by: WenTao Liang Link: https://patch.msgid.link/20260611005322.53096-1-vulab@iscas.ac.cn Signed-off-by: Sebastian Reichel --- drivers/power/supply/charger-manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index 5dc9cd37d697..10158b1bf8e2 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -303,8 +303,10 @@ static bool is_full_charged(struct charger_manager *cm) if (cm->battery_status == POWER_SUPPLY_STATUS_FULL && desc->fullbatt_vchkdrop_uV) uV += desc->fullbatt_vchkdrop_uV; - if (uV >= desc->fullbatt_uV) - return true; + if (uV >= desc->fullbatt_uV) { + is_full = true; + goto out; + } } } -- cgit v1.2.3 From a888754e51e915731c8974c4d6d62709facb35d3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 26 Apr 2026 16:27:05 -0700 Subject: Documentation: ABI: sysfs-class-reboot-mode-reboot_modes: fix doc warnings Repair the docs build warnings in this file by unindenting the description, adding blank lines, and using `` to quote *arg. WARNING: Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:36: abi_sys_class_reboot_mode_driver_reboot_modes doesn't have a description Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils] Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils] Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: WARNING: Inline emphasis start-string without end-string. [docutils] Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils] Fixes: d3da03025e6d ("Documentation: ABI: Add sysfs-class-reboot-mode-reboot_modes") Signed-off-by: Randy Dunlap Reviewed-by: Bartosz Golaszewski Link: https://patch.msgid.link/20260426232705.422938-1-rdunlap@infradead.org Signed-off-by: Sebastian Reichel --- .../ABI/testing/sysfs-class-reboot-mode-reboot_modes | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes b/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes index a16c54ab841b..4306966b7fcc 100644 --- a/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes +++ b/Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes @@ -2,33 +2,36 @@ What: /sys/class/reboot-mode//reboot_modes Date: March 2026(TBD) KernelVersion: TBD Contact: linux-pm@vger.kernel.org - Description: +Description: This interface exposes the reboot-mode arguments registered with the reboot-mode framework. It is a read-only interface and provides a space separated list of reboot-mode arguments supported on the current platform. Example: + recovery fastboot bootloader The exact sysfs path may vary depending on the name of the driver that registers the arguments. - Example: + Example:: + /sys/class/reboot-mode/nvmem-reboot-mode/reboot_modes /sys/class/reboot-mode/syscon-reboot-mode/reboot_modes /sys/class/reboot-mode/qcom-pon/reboot_modes The supported arguments can be used by userspace to invoke device reset using the standard reboot() system - call interface, with the "argument" as string to "*arg" - parameter along with LINUX_REBOOT_CMD_RESTART2. + call interface, with the "argument" as string to ``*arg`` + parameter along with ``LINUX_REBOOT_CMD_RESTART2``. A driver can expose the supported arguments by registering them with the reboot-mode framework using the property names that follow the mode- format. Example: - mode-bootloader, mode-recovery. + + mode-bootloader, mode-recovery This attribute is useful for scripts or initramfs logic that need to programmatically determine -- cgit v1.2.3