From 82ab575eb89e4d8c07ab8e693e0b31603a0d202d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 14:24:07 +0200 Subject: [PATCH 01/30] power: supply: max17040: extend help/description Reorganize the Kconfig driver description and mention all supported models. This helps when choosing drivers for given system. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index fcc7534edcb2..6e4201922f59 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -366,18 +366,20 @@ config AXP288_FUEL_GAUGE over/under temperature. config BATTERY_MAX17040 - tristate "Maxim MAX17040 Fuel Gauge" + tristate "Maxim MAX17040/17041/17043 family Fuel Gauge" depends on I2C select REGMAP_I2C help - Maxim models with ModelGauge are fuel-gauge systems for lithium-ion - (Li+) batteries in handheld and portable equipment, including - max17040, max17041, max17043, max17044, max17048, max17049, max17058, - max17059. It is also included in some batteries like max77836. + Driver supports Maxim fuel-gauge systems for lithium-ion (Li+) + batteries used mainly in handheld and portable equipment. + Supported devices: max17040, max17041, max17043, max17044, max17048, + max17049, max17058, max17059, max77836. Driver supports reporting SOC (State of Charge, i.e capacity), voltage and configurable low-SOC wakeup interrupt. + Driver can be build as a module (max17040_battery). + config BATTERY_MAX17042 tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" depends on I2C From 40a2d98c9763dbd05fa0eb7be96e161bb7e9d45c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 14:24:08 +0200 Subject: [PATCH 02/30] power: supply: max17042: extend help/description Reorganize the Kconfig driver description and mention all supported models. This helps when choosing drivers for given system. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 6e4201922f59..ad93b3550d6d 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -381,7 +381,7 @@ config BATTERY_MAX17040 Driver can be build as a module (max17040_battery). config BATTERY_MAX17042 - tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" + tristate "Maxim MAX17042/17047/17050/8997/8966 family Fuel Gauge" depends on I2C select REGMAP_I2C help @@ -389,8 +389,11 @@ config BATTERY_MAX17042 in handheld and portable equipment. The MAX17042 is configured to operate with a single lithium cell. MAX8997 and MAX8966 are multi-function devices that include fuel gauages that are compatible - with MAX17042. This driver also supports max17047/50 chips which are - improved version of max17042. + with MAX17042. + Supported devices: max8966, max8997, max17042, max17047, max17050, + max17055, max77693, max77849. + + Driver can be build as a module (max17042_battery). config BATTERY_MAX1721X tristate "MAX17211/MAX17215 standalone gas-gauge" From 067930724ecdca0e3a31b6d9e8c1b252b0976e68 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 23 Sep 2021 18:04:28 +0200 Subject: [PATCH 03/30] power: reset: ltc2952: Use hrtimer_forward_now() hrtimer_forward_now() provides the same functionality as the open coded hrtimer_forward() invocation. Prepares for removal of hrtimer_forward() from the public interfaces. Signed-off-by: Thomas Gleixner Cc: linux-pm@vger.kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/reset/ltc2952-poweroff.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/power/reset/ltc2952-poweroff.c b/drivers/power/reset/ltc2952-poweroff.c index 8688c8ba8894..fbb344353fe4 100644 --- a/drivers/power/reset/ltc2952-poweroff.c +++ b/drivers/power/reset/ltc2952-poweroff.c @@ -94,7 +94,6 @@ static struct ltc2952_poweroff *ltc2952_data; */ static enum hrtimer_restart ltc2952_poweroff_timer_wde(struct hrtimer *timer) { - ktime_t now; int state; struct ltc2952_poweroff *data = to_ltc2952(timer, timer_wde); @@ -104,8 +103,7 @@ static enum hrtimer_restart ltc2952_poweroff_timer_wde(struct hrtimer *timer) state = gpiod_get_value(data->gpio_watchdog); gpiod_set_value(data->gpio_watchdog, !state); - now = hrtimer_cb_get_time(timer); - hrtimer_forward(timer, now, data->wde_interval); + hrtimer_forward_now(timer, data->wde_interval); return HRTIMER_RESTART; } From 5d1f642aad69c76f6a260528a22701ec4a8f12f5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 16 Sep 2021 14:53:21 +0200 Subject: [PATCH 04/30] docs: ABI: sysfs-class-power: Documented cycle_count property Commit c955fe8e0bdd ("POWER: Add support for cycle_count") added a POWER_SUPPLY_PROP_CYCLE_COUNT "cycle_count" property to the set of standard power-supply properties, but this was never documented, document it now. Link: https://gitlab.freedesktop.org/upower/upower/-/issues/152 Reported-by: Bastien Nocera Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- Documentation/ABI/testing/sysfs-class-power | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index ca830c6cd809..f7904efc4cfa 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -480,6 +480,19 @@ Description: Valid values: Represented in microvolts +What: /sys/class/power_supply//cycle_count +Date: January 2010 +Contact: linux-pm@vger.kernel.org +Description: + Reports the number of full charge + discharge cycles the + battery has undergone. + + Access: Read + + Valid values: + Integer > 0: representing full cycles + Integer = 0: cycle_count info is not available + **USB Properties** What: /sys/class/power_supply//input_current_limit From 9ba533eb99bb2acf8b2268c6f48dcf73e1e47753 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 1 Sep 2021 16:59:36 -0700 Subject: [PATCH 05/30] power: supply: core: Add psy_has_property() Add the helper psy_has_property() to check whether a power supply has a given property and use it instead of ad hoc iterations over the property list in multiple locations. Signed-off-by: Matthias Kaehlcke Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 65 ++++++++++++++---------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 0c2132c7f5d4..75575ea45f21 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -975,26 +975,41 @@ static struct thermal_zone_device_ops psy_tzd_ops = { .get_temp = power_supply_read_temp, }; +static bool psy_has_property(const struct power_supply_desc *psy_desc, + enum power_supply_property psp) +{ + bool found = false; + int i; + + for (i = 0; i < psy_desc->num_properties; i++) { + if (psy_desc->properties[i] == psp) { + found = true; + break; + } + } + + return found; +} + static int psy_register_thermal(struct power_supply *psy) { - int i, ret; + int ret; if (psy->desc->no_thermal) return 0; /* Register battery zone device psy reports temperature */ - for (i = 0; i < psy->desc->num_properties; i++) { - if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) { - psy->tzd = thermal_zone_device_register(psy->desc->name, - 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); - if (IS_ERR(psy->tzd)) - return PTR_ERR(psy->tzd); - ret = thermal_zone_device_enable(psy->tzd); - if (ret) - thermal_zone_device_unregister(psy->tzd); - return ret; - } + if (psy_has_property(psy->desc, POWER_SUPPLY_PROP_TEMP)) { + psy->tzd = thermal_zone_device_register(psy->desc->name, + 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); + if (IS_ERR(psy->tzd)) + return PTR_ERR(psy->tzd); + ret = thermal_zone_device_enable(psy->tzd); + if (ret) + thermal_zone_device_unregister(psy->tzd); + return ret; } + return 0; } @@ -1065,18 +1080,14 @@ static const struct thermal_cooling_device_ops psy_tcd_ops = { static int psy_register_cooler(struct power_supply *psy) { - int i; - /* Register for cooling device if psy can control charging */ - for (i = 0; i < psy->desc->num_properties; i++) { - if (psy->desc->properties[i] == - POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) { - psy->tcd = thermal_cooling_device_register( - (char *)psy->desc->name, - psy, &psy_tcd_ops); - return PTR_ERR_OR_ZERO(psy->tcd); - } + if (psy_has_property(psy->desc, POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT)) { + psy->tcd = thermal_cooling_device_register( + (char *)psy->desc->name, + psy, &psy_tcd_ops); + return PTR_ERR_OR_ZERO(psy->tcd); } + return 0; } @@ -1114,7 +1125,7 @@ __power_supply_register(struct device *parent, { struct device *dev; struct power_supply *psy; - int i, rc; + int rc; if (!parent) pr_warn("%s: Expected proper parent device for '%s'\n", @@ -1123,11 +1134,9 @@ __power_supply_register(struct device *parent, if (!desc || !desc->name || !desc->properties || !desc->num_properties) return ERR_PTR(-EINVAL); - for (i = 0; i < desc->num_properties; ++i) { - if ((desc->properties[i] == POWER_SUPPLY_PROP_USB_TYPE) && - (!desc->usb_types || !desc->num_usb_types)) - return ERR_PTR(-EINVAL); - } + if (psy_has_property(desc, POWER_SUPPLY_PROP_USB_TYPE) && + (!desc->usb_types || !desc->num_usb_types)) + return ERR_PTR(-EINVAL); psy = kzalloc(sizeof(*psy), GFP_KERNEL); if (!psy) From 5ce39985c60418579fab1d4ee81427d12bf9e64f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 28 Sep 2021 14:00:19 +0200 Subject: [PATCH 06/30] power: supply: core: Move psy_has_property() to fix build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_THERMAL=n: drivers/power/supply/power_supply_core.c: In function ‘__power_supply_register’: drivers/power/supply/power_supply_core.c:1137:6: error: implicit declaration of function ‘psy_has_property’ [-Werror=implicit-function-declaration] 1137 | if (psy_has_property(desc, POWER_SUPPLY_PROP_USB_TYPE) && | ^~~~~~~~~~~~~~~~ Fix this by moving psy_has_property() outside the section protected by CONFIG_THERMAL. Fixes: 9ba533eb99bb2acf ("power: supply: core: Add psy_has_property()") Signed-off-by: Geert Uytterhoeven Reviewed-by: Matthias Kaehlcke Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 75575ea45f21..fc12a4f407f4 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -951,6 +951,22 @@ void power_supply_unreg_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); +static bool psy_has_property(const struct power_supply_desc *psy_desc, + enum power_supply_property psp) +{ + bool found = false; + int i; + + for (i = 0; i < psy_desc->num_properties; i++) { + if (psy_desc->properties[i] == psp) { + found = true; + break; + } + } + + return found; +} + #ifdef CONFIG_THERMAL static int power_supply_read_temp(struct thermal_zone_device *tzd, int *temp) @@ -975,22 +991,6 @@ static struct thermal_zone_device_ops psy_tzd_ops = { .get_temp = power_supply_read_temp, }; -static bool psy_has_property(const struct power_supply_desc *psy_desc, - enum power_supply_property psp) -{ - bool found = false; - int i; - - for (i = 0; i < psy_desc->num_properties; i++) { - if (psy_desc->properties[i] == psp) { - found = true; - break; - } - } - - return found; -} - static int psy_register_thermal(struct power_supply *psy) { int ret; From 73d59c9263a0fbcf8f769daea9c1fe33ae38c9e8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 1 Oct 2021 13:04:49 +0100 Subject: [PATCH 07/30] power: supply: wm831x_power: fix spelling mistake on function name There is a spelling mistake in the name wm831x_battey_apply_config, fix it. Signed-off-by: Colin Ian King Acked-by: Charles Keepax Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm831x_power.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c index 4cd2dd870039..82e31066c746 100644 --- a/drivers/power/supply/wm831x_power.c +++ b/drivers/power/supply/wm831x_power.c @@ -234,7 +234,7 @@ static struct chg_map chg_times[] = { { 510, 15 << WM831X_CHG_TIME_SHIFT }, }; -static void wm831x_battey_apply_config(struct wm831x *wm831x, +static void wm831x_battery_apply_config(struct wm831x *wm831x, struct chg_map *map, int count, int val, int *reg, const char *name, const char *units) @@ -281,24 +281,24 @@ static void wm831x_config_battery(struct wm831x *wm831x) if (pdata->fast_enable) reg1 |= WM831X_CHG_FAST; - wm831x_battey_apply_config(wm831x, trickle_ilims, + wm831x_battery_apply_config(wm831x, trickle_ilims, ARRAY_SIZE(trickle_ilims), pdata->trickle_ilim, ®2, "trickle charge current limit", "mA"); - wm831x_battey_apply_config(wm831x, vsels, ARRAY_SIZE(vsels), + wm831x_battery_apply_config(wm831x, vsels, ARRAY_SIZE(vsels), pdata->vsel, ®2, "target voltage", "mV"); - wm831x_battey_apply_config(wm831x, fast_ilims, ARRAY_SIZE(fast_ilims), + wm831x_battery_apply_config(wm831x, fast_ilims, ARRAY_SIZE(fast_ilims), pdata->fast_ilim, ®2, "fast charge current limit", "mA"); - wm831x_battey_apply_config(wm831x, eoc_iterms, ARRAY_SIZE(eoc_iterms), + wm831x_battery_apply_config(wm831x, eoc_iterms, ARRAY_SIZE(eoc_iterms), pdata->eoc_iterm, ®1, "end of charge current threshold", "mA"); - wm831x_battey_apply_config(wm831x, chg_times, ARRAY_SIZE(chg_times), + wm831x_battery_apply_config(wm831x, chg_times, ARRAY_SIZE(chg_times), pdata->timeout, ®2, "charger timeout", "min"); From f558c8072c3461b65c12c0068b108f78cebc8246 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 30 Sep 2021 13:09:28 +0300 Subject: [PATCH 08/30] power: reset: at91-reset: check properly the return value of devm_of_iomap devm_of_iomap() returns error code or valid pointer. Check its return value with IS_ERR(). Fixes: bd3127733f2c ("power: reset: at91-reset: use devm_of_iomap") Reported-by: Cristian Birsan Signed-off-by: Claudiu Beznea Signed-off-by: Sebastian Reichel --- drivers/power/reset/at91-reset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index 026649409135..64def79d557a 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -193,7 +193,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) return -ENOMEM; reset->rstc_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); - if (!reset->rstc_base) { + if (IS_ERR(reset->rstc_base)) { dev_err(&pdev->dev, "Could not map reset controller address\n"); return -ENODEV; } @@ -203,7 +203,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) for_each_matching_node_and_match(np, at91_ramc_of_match, &match) { reset->ramc_lpr = (u32)match->data; reset->ramc_base[idx] = devm_of_iomap(&pdev->dev, np, 0, NULL); - if (!reset->ramc_base[idx]) { + if (IS_ERR(reset->ramc_base[idx])) { dev_err(&pdev->dev, "Could not map ram controller address\n"); of_node_put(np); return -ENODEV; From 0fd1cdf222a092ec0a08968913aeaefd6ce2d298 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 29 Sep 2021 18:06:05 +0200 Subject: [PATCH 09/30] dt-bindings: power: supply: max17040: switch to unevaluatedProperties Required for validation of power-supplies from power-supply.yaml. Signed-off-by: David Heidelberg Signed-off-by: Sebastian Reichel --- .../devicetree/bindings/power/supply/maxim,max17040.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml index f792d06db413..ffb344987a7b 100644 --- a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml +++ b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml @@ -62,7 +62,7 @@ required: - compatible - reg -additionalProperties: false +unevaluatedProperties: false examples: - | From 223a3b82834f036a62aa831f67cbf1f1d644c6e2 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 29 Sep 2021 20:14:17 +0200 Subject: [PATCH 10/30] power: supply: max17042_battery: use VFSOC for capacity when no rsns On Galaxy S3 (i9300/i9305), which has the max17047 fuel gauge and no current sense resistor (rsns), the RepSOC register does not provide an accurate state of charge value. The reported value is wrong, and does not change over time. VFSOC however, which uses the voltage fuel gauge to determine the state of charge, always shows an accurate value. For devices without current sense, VFSOC is already used for the soc-alert (0x0003 is written to MiscCFG register), so with this change the source of the alert and the PROP_CAPACITY value match. Fixes: 359ab9f5b154 ("power_supply: Add MAX17042 Fuel Gauge Driver") Cc: Reviewed-by: Krzysztof Kozlowski Suggested-by: Wolfgang Wiedmeyer Signed-off-by: Henrik Grimler Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 8dffae76b6a3..5809ba997093 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -313,7 +313,10 @@ static int max17042_get_property(struct power_supply *psy, val->intval = data * 625 / 8; break; case POWER_SUPPLY_PROP_CAPACITY: - ret = regmap_read(map, MAX17042_RepSOC, &data); + if (chip->pdata->enable_current_sense) + ret = regmap_read(map, MAX17042_RepSOC, &data); + else + ret = regmap_read(map, MAX17042_VFSOC, &data); if (ret < 0) return ret; From d0c27c9211fef3ce8083cc3ad2ca3067d211edc9 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 29 Sep 2021 20:14:18 +0200 Subject: [PATCH 11/30] power: supply: max17042_battery: fix typo in MAX17042_IAvg_empty Datasheet gives the name IAvg_empty, not LAvg_empty. Signed-off-by: Henrik Grimler Reviewed-by: Hans de Goede Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 2 +- include/linux/power/max17042_battery.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 5809ba997093..32f331480487 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -786,7 +786,7 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) if ((chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042) || (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17047) || (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17050)) { - max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty); + max17042_override_por(map, MAX17042_IAvg_empty, config->iavg_empty); max17042_override_por(map, MAX17042_TempNom, config->temp_nom); max17042_override_por(map, MAX17042_TempLim, config->temp_lim); max17042_override_por(map, MAX17042_FCTC, config->fctc); diff --git a/include/linux/power/max17042_battery.h b/include/linux/power/max17042_battery.h index dd24756a8af7..c417abd2ab70 100644 --- a/include/linux/power/max17042_battery.h +++ b/include/linux/power/max17042_battery.h @@ -78,7 +78,7 @@ enum max17042_register { MAX17042_T_empty = 0x34, MAX17042_FullCAP0 = 0x35, - MAX17042_LAvg_empty = 0x36, + MAX17042_IAvg_empty = 0x36, MAX17042_FCTC = 0x37, MAX17042_RCOMP0 = 0x38, MAX17042_TempCo = 0x39, @@ -221,7 +221,7 @@ struct max17042_config_data { u16 fullcap; /* 0x10 */ u16 fullcapnom; /* 0x23 */ u16 socempty; /* 0x33 */ - u16 lavg_empty; /* 0x36 */ + u16 iavg_empty; /* 0x36 */ u16 dqacc; /* 0x45 */ u16 dpacc; /* 0x46 */ u16 qrtbl00; /* 0x12 */ From 0668281d329db2c21ba6494a7bfcb8331dd0f5fa Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Tue, 28 Sep 2021 10:06:23 +0800 Subject: [PATCH 12/30] power: supply: cpcap-battery: use device_get_match_data() to simplify code In the function cpcap_battery_probe(), the driver only needs the data object, so use device_get_match_data() instead, to make the code cleaner. Signed-off-by: Tang Bin Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-battery.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index 8d62d4241da3..18e3ff0e15d5 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -1026,20 +1026,13 @@ static const struct power_supply_desc cpcap_charger_battery_desc = { static int cpcap_battery_probe(struct platform_device *pdev) { struct cpcap_battery_ddata *ddata; - const struct of_device_id *match; struct power_supply_config psy_cfg = {}; int error; + const struct cpcap_battery_config *cfg; - match = of_match_device(of_match_ptr(cpcap_battery_id_table), - &pdev->dev); - if (!match) - return -EINVAL; - - if (!match->data) { - dev_err(&pdev->dev, "no configuration data found\n"); - + cfg = device_get_match_data(&pdev->dev); + if (!cfg) return -ENODEV; - } ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); if (!ddata) @@ -1047,7 +1040,7 @@ static int cpcap_battery_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ddata->irq_list); ddata->dev = &pdev->dev; - memcpy(&ddata->config, match->data, sizeof(ddata->config)); + memcpy(&ddata->config, cfg, sizeof(ddata->config)); ddata->reg = dev_get_regmap(ddata->dev->parent, NULL); if (!ddata->reg) From a3d5c47c328a8002cb748d293fdcaef0c752bcdf Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 6 Aug 2021 11:00:50 +0200 Subject: [PATCH 13/30] dt-bindings: power: Bindings for Samsung batteries This adds device tree bindings for Samsung SDI batteries. Everything can be determined from the product number so the entire battery is just a specific compatible string. Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Sebastian Reichel --- .../power/supply/samsung,battery.yaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/samsung,battery.yaml diff --git a/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml b/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml new file mode 100644 index 000000000000..40292d581b10 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/samsung,battery.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung SDI Batteries + +maintainers: + - Linus Walleij + +description: | + Samsung SDI (Samsung Digital Interface) batteries are all different versions + of lithium ion chemistry devices used for mobile phones, laptops and other + portable electronics. The batteries are adapted to a specific product and + the physical restrictions make it impossible to use another battery with the + product, so product device trees can specify these batteries. Operating + systems should determine hardware characteristics of the batteries from the + compatible string. + +properties: + compatible: + oneOf: + - const: samsung,eb-l1m7flu + description: 3.8V 1500 mAh battery used in Samsung GT-I8190 + - const: samsung,eb425161la + description: 3.8V 1500 mAh battery used in Samsung SGH-T599 and SGH-I407 + - const: samsung,eb425161lu + description: 3.8V 1500 mAh battery used in Samsung GT-I8160 + - const: samsung,eb485159lu + description: 3.8V 1700 mAh battery used in Samsung GT-S7710 + - const: samsung,eb535151vu + description: 3.8V 1500 mAh battery used in Samsung GT-I9070 + - const: samsung,eb585157lu + description: 3.8V 2000 mAh battery used in Samsung GT-I8530 + +required: + - compatible + +additionalProperties: false + +examples: + - | + power { + #address-cells = <1>; + #size-cells = <0>; + + battery: battery { + compatible = "samsung,eb425161la"; + }; + + charger@11 { + reg = <0x11>; + monitored-battery = <&battery>; + }; + }; From ed229454856e565c5a7d3287cbc63f2cf077b34f Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Tue, 12 Oct 2021 13:45:45 +0800 Subject: [PATCH 14/30] power: supply: axp288-charger: Optimize register reading method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original implementation access the charger the same register value several times to get the charger status, such as online, enabled, and bus limits. It takes a long time and bandwidth for every "status get" operation.  To reduce the access of the register and save bandwidth, this commit integrated every read operation into only one "register value get"  operation and cache them in the variables. Once the "get properties" is requested from the user space, the cached information can be returned immediately. I2C access between Linux kernel and P-Unit is improved by explicitly taking semaphore once for the entire set of register accesses in the new axp288_charger_usb_update_property() function. The I2C-Bus to the XPower AXP288 is shared between the Linux kernel and SoCs P-Unit. The P-Unit has a semaphore which the kernel must "lock" before it may use the bus. If not explicitly taken by the I2C-Driver, then this semaphore is automatically taken by the I2C-bus-driver for each I2C-transfer. In other words, the semaphore will be locked and released several times for entire set of register accesses. Signed-off-by: Kate Hsuan Reviewed-by: Hans de Goede Tested-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 150 +++++++++++++++++--------- 1 file changed, 99 insertions(+), 51 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index b9553be9bed5..fd4983c98fd9 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -22,6 +22,7 @@ #include #include #include +#include #define PS_STAT_VBUS_TRIGGER BIT(0) #define PS_STAT_BAT_CHRG_DIR BIT(2) @@ -95,6 +96,8 @@ #define CV_4200MV 4200 /* 4200mV */ #define CV_4350MV 4350 /* 4350mV */ +#define AXP288_REG_UPDATE_INTERVAL (60 * HZ) + #define AXP288_EXTCON_DEV_NAME "axp288_extcon" #define USB_HOST_EXTCON_HID "INT3496" #define USB_HOST_EXTCON_NAME "INT3496:00" @@ -118,6 +121,7 @@ struct axp288_chrg_info { struct regmap_irq_chip_data *regmap_irqc; int irq[CHRG_INTR_END]; struct power_supply *psy_usb; + struct mutex lock; /* OTG/Host mode */ struct { @@ -138,6 +142,12 @@ struct axp288_chrg_info { int cv; int max_cc; int max_cv; + + unsigned long last_updated; + unsigned int input_status; + unsigned int op_mode; + unsigned int backend_control; + bool valid; }; static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc) @@ -197,11 +207,8 @@ static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv) static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info) { unsigned int val; - int ret; - ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val); - if (ret < 0) - return ret; + val = info->backend_control; val >>= CHRG_VBUS_ILIM_BIT_POS; switch (val) { @@ -297,55 +304,34 @@ static int axp288_charger_enable_charger(struct axp288_chrg_info *info, static int axp288_charger_is_present(struct axp288_chrg_info *info) { - int ret, present = 0; - unsigned int val; + int present = 0; - ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); - if (ret < 0) - return ret; - - if (val & PS_STAT_VBUS_PRESENT) + if (info->input_status & PS_STAT_VBUS_PRESENT) present = 1; return present; } static int axp288_charger_is_online(struct axp288_chrg_info *info) { - int ret, online = 0; - unsigned int val; + int online = 0; - ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); - if (ret < 0) - return ret; - - if (val & PS_STAT_VBUS_VALID) + if (info->input_status & PS_STAT_VBUS_VALID) online = 1; return online; } static int axp288_get_charger_health(struct axp288_chrg_info *info) { - int ret, pwr_stat, chrg_stat; int health = POWER_SUPPLY_HEALTH_UNKNOWN; - unsigned int val; - ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); - if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT)) + if (!(info->input_status & PS_STAT_VBUS_PRESENT)) goto health_read_fail; - else - pwr_stat = val; - ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val); - if (ret < 0) - goto health_read_fail; - else - chrg_stat = val; - - if (!(pwr_stat & PS_STAT_VBUS_VALID)) + if (!(info->input_status & PS_STAT_VBUS_VALID)) health = POWER_SUPPLY_HEALTH_DEAD; - else if (chrg_stat & CHRG_STAT_PMIC_OTP) + else if (info->op_mode & CHRG_STAT_PMIC_OTP) health = POWER_SUPPLY_HEALTH_OVERHEAT; - else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE) + else if (info->op_mode & CHRG_STAT_BAT_SAFE_MODE) health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; else health = POWER_SUPPLY_HEALTH_GOOD; @@ -362,30 +348,86 @@ static int axp288_charger_usb_set_property(struct power_supply *psy, int ret = 0; int scaled_val; + mutex_lock(&info->lock); switch (psp) { case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: scaled_val = min(val->intval, info->max_cc); scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); ret = axp288_charger_set_cc(info, scaled_val); - if (ret < 0) + if (ret < 0) { dev_warn(&info->pdev->dev, "set charge current failed\n"); + goto out; + } break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: scaled_val = min(val->intval, info->max_cv); scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); ret = axp288_charger_set_cv(info, scaled_val); - if (ret < 0) + if (ret < 0) { dev_warn(&info->pdev->dev, "set charge voltage failed\n"); + goto out; + } break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: ret = axp288_charger_set_vbus_inlmt(info, val->intval); - if (ret < 0) + if (ret < 0) { dev_warn(&info->pdev->dev, "set input current limit failed\n"); + goto out; + } + info->valid = false; break; default: ret = -EINVAL; } +out: + mutex_unlock(&info->lock); + return ret; +} + +static int axp288_charger_reg_readb(struct axp288_chrg_info *info, int reg, unsigned int *ret_val) +{ + int ret; + + ret = regmap_read(info->regmap, reg, ret_val); + if (ret < 0) { + dev_err(&info->pdev->dev, "Error %d on reading value from register 0x%04x\n", + ret, + reg); + return ret; + } + return 0; +} + +static int axp288_charger_usb_update_property(struct axp288_chrg_info *info) +{ + int ret = 0; + + if (info->valid && time_before(jiffies, info->last_updated + AXP288_REG_UPDATE_INTERVAL)) + return 0; + + dev_dbg(&info->pdev->dev, "Charger updating register values...\n"); + + ret = iosf_mbi_block_punit_i2c_access(); + if (ret < 0) + return ret; + + ret = axp288_charger_reg_readb(info, AXP20X_PWR_INPUT_STATUS, &info->input_status); + if (ret < 0) + goto out; + + ret = axp288_charger_reg_readb(info, AXP20X_PWR_OP_MODE, &info->op_mode); + if (ret < 0) + goto out; + + ret = axp288_charger_reg_readb(info, AXP20X_CHRG_BAK_CTRL, &info->backend_control); + if (ret < 0) + goto out; + + info->last_updated = jiffies; + info->valid = true; +out: + iosf_mbi_unblock_punit_i2c_access(); return ret; } @@ -396,6 +438,11 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, struct axp288_chrg_info *info = power_supply_get_drvdata(psy); int ret; + mutex_lock(&info->lock); + ret = axp288_charger_usb_update_property(info); + if (ret < 0) + goto out; + switch (psp) { case POWER_SUPPLY_PROP_PRESENT: /* Check for OTG case first */ @@ -403,10 +450,7 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, val->intval = 0; break; } - ret = axp288_charger_is_present(info); - if (ret < 0) - return ret; - val->intval = ret; + val->intval = axp288_charger_is_present(info); break; case POWER_SUPPLY_PROP_ONLINE: /* Check for OTG case first */ @@ -414,10 +458,7 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, val->intval = 0; break; } - ret = axp288_charger_is_online(info); - if (ret < 0) - return ret; - val->intval = ret; + val->intval = axp288_charger_is_online(info); break; case POWER_SUPPLY_PROP_HEALTH: val->intval = axp288_get_charger_health(info); @@ -435,16 +476,15 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, val->intval = info->max_cv * 1000; break; case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: - ret = axp288_charger_get_vbus_inlmt(info); - if (ret < 0) - return ret; - val->intval = ret; + val->intval = axp288_charger_get_vbus_inlmt(info); break; default: - return -EINVAL; + ret = -EINVAL; } - return 0; +out: + mutex_unlock(&info->lock); + return ret; } static int axp288_charger_property_is_writeable(struct power_supply *psy, @@ -540,7 +580,9 @@ static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev) dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n"); goto out; } - + mutex_lock(&info->lock); + info->valid = false; + mutex_unlock(&info->lock); power_supply_changed(info->psy_usb); out: return IRQ_HANDLED; @@ -613,6 +655,9 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work) if (!(val & PS_STAT_VBUS_VALID)) { dev_dbg(&info->pdev->dev, "USB charger disconnected\n"); axp288_charger_enable_charger(info, false); + mutex_lock(&info->lock); + info->valid = false; + mutex_unlock(&info->lock); power_supply_changed(info->psy_usb); return; } @@ -644,6 +689,9 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work) dev_err(&info->pdev->dev, "error setting current limit (%d)\n", ret); + mutex_lock(&info->lock); + info->valid = false; + mutex_unlock(&info->lock); power_supply_changed(info->psy_usb); } From bf895295e9a73411889816f1a0c1f4f1a2d9c678 Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Fri, 8 Oct 2021 10:32:45 +0200 Subject: [PATCH 15/30] =?UTF-8?q?power:=20supply:=20rt5033=5Fbattery:=20Ch?= =?UTF-8?q?ange=20voltage=20values=20to=20=C2=B5V?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the rt5033_battery driver provides voltage values in mV. It should be µV as stated in Documentation/power/power_supply_class.rst. Fixes: b847dd96e659 ("power: rt5033_battery: Add RT5033 Fuel gauge device driver") Cc: Beomho Seo Cc: Chanwoo Choi Signed-off-by: Jakob Hauser Signed-off-by: Sebastian Reichel --- drivers/power/supply/rt5033_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index 9ad0afe83d1b..7a23c70f4879 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -60,7 +60,7 @@ static int rt5033_battery_get_watt_prop(struct i2c_client *client, regmap_read(battery->regmap, regh, &msb); regmap_read(battery->regmap, regl, &lsb); - ret = ((msb << 4) + (lsb >> 4)) * 1250 / 1000; + ret = ((msb << 4) + (lsb >> 4)) * 1250; return ret; } From 1d422ecfc48ee683ae1ccc9217764f6310c0ffce Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 8 Oct 2021 14:31:50 +0800 Subject: [PATCH 16/30] power: supply: max17040: fix null-ptr-deref in max17040_probe() Add check the return value of devm_regmap_init_i2c(), otherwise later access may cause null-ptr-deref as follows: KASAN: null-ptr-deref in range [0x0000000000000360-0x0000000000000367] RIP: 0010:regmap_read+0x33/0x170 Call Trace: max17040_probe+0x61b/0xff0 [max17040_battery] ? write_comp_data+0x2a/0x90 ? max17040_set_property+0x1d0/0x1d0 [max17040_battery] ? tracer_hardirqs_on+0x33/0x520 ? __sanitizer_cov_trace_pc+0x1d/0x50 ? _raw_spin_unlock_irqrestore+0x4b/0x60 ? trace_hardirqs_on+0x63/0x2d0 ? write_comp_data+0x2a/0x90 ? __sanitizer_cov_trace_pc+0x1d/0x50 ? max17040_set_property+0x1d0/0x1d0 [max17040_battery] i2c_device_probe+0xa31/0xbe0 Fixes: 6455a8a84bdf ("power: supply: max17040: Use regmap i2c") Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17040_battery.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 3cea92e28dc3..a9aef1e8b186 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -449,6 +449,8 @@ static int max17040_probe(struct i2c_client *client, chip->client = client; chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap); + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); chip_id = (enum chip_id) id->driver_data; if (client->dev.of_node) { ret = max17040_get_of_data(chip); From 744bbdb7958d424f469863f2b402040fcbf0e76d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 13:56:18 +0200 Subject: [PATCH 17/30] MAINTAINERS: power: supply: max17042: add entry with reviewers The Maxim max17042 fuel gauge driver supports several devices used on multiple different boards - both devicetree and ACPI based. The driver is incomplete and has few known issues. Fixing these might break other platforms so mention recent contributors who can provide feedback. This way most of interested parties might help reviewing the patches. Cc: Hans de Goede Cc: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski Reviewed-by: Sebastian Krzyszkowiak Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- MAINTAINERS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index eeb4c70b3d5b..51a9f6e50812 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11366,6 +11366,17 @@ S: Maintained F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml F: drivers/iio/proximity/mb1232.c +MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS +R: Hans de Goede +R: Krzysztof Kozlowski +R: Marek Szyprowski +R: Sebastian Krzyszkowiak +R: Purism Kernel Team +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/supply/maxim,max17042.yaml +F: drivers/power/supply/max17042_battery.c + MAXIM MAX77650 PMIC MFD DRIVER M: Bartosz Golaszewski L: linux-kernel@vger.kernel.org From 7462a894bd53b3d149c01518c82562d20368f960 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 24 Sep 2021 13:56:19 +0200 Subject: [PATCH 18/30] MAINTAINERS: power: supply: max17040: add entry with reviewers The Maxim max17040 fuel gauge driver supports several devices used on multiple different boards. The driver is incomplete and has few known issues. Fixing these might break other platforms so mention recent contributors who can provide feedback. This way most of interested parties might help reviewing the patches. Cc: Iskren Chernev Cc: Marek Szyprowski Cc: Matheus Castello Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sebastian Reichel --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51a9f6e50812..a6d670c58f3e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11366,6 +11366,16 @@ S: Maintained F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml F: drivers/iio/proximity/mb1232.c +MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS +R: Iskren Chernev +R: Krzysztof Kozlowski +R: Marek Szyprowski +R: Matheus Castello +L: linux-pm@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml +F: drivers/power/supply/max17040_battery.c + MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS R: Hans de Goede R: Krzysztof Kozlowski From 0cf48167b87e388fa1268c9fe6d2443ae7f43d8a Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Tue, 14 Sep 2021 14:18:05 +0200 Subject: [PATCH 19/30] power: supply: max17042_battery: Clear status bits in interrupt handler The gauge requires us to clear the status bits manually for some alerts to be properly dismissed. Previously the IRQ was configured to react only on falling edge, which wasn't technically correct (the ALRT line is active low), but it had a happy side-effect of preventing interrupt storms on uncleared alerts from happening. Fixes: 7fbf6b731bca ("power: supply: max17042: Do not enforce (incorrect) interrupt trigger type") Cc: Signed-off-by: Sebastian Krzyszkowiak Reviewed-by: Krzysztof Kozlowski Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 32f331480487..2eb61856f3e4 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -879,6 +879,10 @@ static irqreturn_t max17042_thread_handler(int id, void *dev) max17042_set_soc_threshold(chip, 1); } + /* we implicitly handle all alerts via power_supply_changed */ + regmap_clear_bits(chip->regmap, MAX17042_STATUS, + 0xFFFF & ~(STATUS_POR_BIT | STATUS_BST_BIT)); + power_supply_changed(chip->battery); return IRQ_HANDLED; } From e660dbb68c6b3f7b9eb8b9775846a44f9798b719 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Tue, 14 Sep 2021 14:18:06 +0200 Subject: [PATCH 20/30] power: supply: max17042_battery: Prevent int underflow in set_soc_threshold max17042_set_soc_threshold gets called with offset set to 1, which means that minimum threshold value would underflow once SOC got down to 0, causing invalid alerts from the gauge. Fixes: e5f3872d2044 ("max17042: Add support for signalling change in SOC") Cc: Signed-off-by: Sebastian Krzyszkowiak Reviewed-by: Krzysztof Kozlowski 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 2eb61856f3e4..87128cf0d577 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -860,7 +860,8 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) regmap_read(map, MAX17042_RepSOC, &soc); soc >>= 8; soc_tr = (soc + off) << 8; - soc_tr |= (soc - off); + if (off < soc) + soc_tr |= soc - off; regmap_write(map, MAX17042_SALRT_Th, soc_tr); } From db6e436264dae9fbfc92d93bf61772e8a129940c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 13 Oct 2021 09:31:15 +0000 Subject: [PATCH 21/30] power: supply: axp288_charger: Fix missing mutex_init() The driver allocates the mutex but not initialize it. Use mutex_init() on it to initialize it correctly. Fixes: ed229454856e ("power: supply: axp288-charger: Optimize register reading method") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Reviewed-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index fd4983c98fd9..9987b1731e38 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -865,6 +865,7 @@ static int axp288_charger_probe(struct platform_device *pdev) if (!info) return -ENOMEM; + mutex_init(&info->lock); info->pdev = pdev; info->regmap = axp20x->regmap; info->regmap_irqc = axp20x->regmap_irqc; From eb415571c78267162e4adc91f259a9f6ee5b344b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 7 Oct 2021 00:40:06 +0200 Subject: [PATCH 22/30] dt-bindings: power: supply: ab8500: Standard monitored-battery Make monitored-battery the standard phandle to the battery we monitor for the AB8500 charger components. We make the old "battery" phandle deprecated, and the new one required so we detect and fix all users to use the standard phandle name. Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- .../bindings/power/supply/stericsson,ab8500-btemp.yaml | 10 +++++++--- .../power/supply/stericsson,ab8500-chargalg.yaml | 10 +++++++--- .../power/supply/stericsson,ab8500-charger.yaml | 10 +++++++--- .../bindings/power/supply/stericsson,ab8500-fg.yaml | 10 +++++++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-btemp.yaml b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-btemp.yaml index 2f57aa5a5f4e..4b8a00cec39c 100644 --- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-btemp.yaml +++ b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-btemp.yaml @@ -17,10 +17,14 @@ properties: compatible: const: stericsson,ab8500-btemp - battery: + monitored-battery: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to battery node + battery: + $ref: /schemas/types.yaml#/definitions/phandle + deprecated: true + interrupts: maxItems: 5 @@ -42,7 +46,7 @@ properties: required: - compatible - - battery + - monitored-battery - interrupts - interrupt-names - io-channels @@ -56,7 +60,7 @@ examples: pmic { battery-temperature { compatible = "stericsson,ab8500-btemp"; - battery = <&ab8500_battery>; + monitored-battery = <&battery>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH>, <80 IRQ_TYPE_LEVEL_HIGH>, <83 IRQ_TYPE_LEVEL_HIGH>, diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-chargalg.yaml b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-chargalg.yaml index 0897231c2f6e..6799224f7fb4 100644 --- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-chargalg.yaml +++ b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-chargalg.yaml @@ -17,13 +17,17 @@ properties: compatible: const: stericsson,ab8500-chargalg - battery: + monitored-battery: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to battery node + battery: + $ref: /schemas/types.yaml#/definitions/phandle + deprecated: true + required: - compatible - - battery + - monitored-battery additionalProperties: false @@ -32,6 +36,6 @@ examples: pmic { charging-algorithm { compatible = "stericsson,ab8500-chargalg"; - battery = <&ab8500_battery>; + monitored-battery = <&ab8500_battery>; }; }; diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-charger.yaml b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-charger.yaml index e13305afea69..9518eb7289d0 100644 --- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-charger.yaml @@ -17,10 +17,14 @@ properties: compatible: const: stericsson,ab8500-charger - battery: + monitored-battery: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to battery node + battery: + $ref: /schemas/types.yaml#/definitions/phandle + deprecated: true + vddadc-supply: description: Supply for USB and Main charger @@ -66,7 +70,7 @@ properties: required: - compatible - - battery + - monitored-battery - vddadc-supply - interrupts - interrupt-names @@ -81,7 +85,7 @@ examples: pmic { charger { compatible = "stericsson,ab8500-charger"; - battery = <&ab8500_battery>; + monitored-battery = <&battery>; vddadc-supply = <&ab8500_ldo_tvout_reg>; interrupts = <10 IRQ_TYPE_LEVEL_HIGH>, <11 IRQ_TYPE_LEVEL_HIGH>, diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-fg.yaml b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-fg.yaml index db342e5ac0d1..54ac42a9d354 100644 --- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-fg.yaml +++ b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-fg.yaml @@ -17,10 +17,14 @@ properties: compatible: const: stericsson,ab8500-fg - battery: + monitored-battery: $ref: /schemas/types.yaml#/definitions/phandle description: phandle to battery node + battery: + $ref: /schemas/types.yaml#/definitions/phandle + deprecated: true + interrupts: maxItems: 5 @@ -41,7 +45,7 @@ properties: required: - compatible - - battery + - monitored-battery - interrupts - interrupt-names - io-channels @@ -55,7 +59,7 @@ examples: pmic { fuel-gauge { compatible = "stericsson,ab8500-fg"; - battery = <&ab8500_battery>; + monitored-battery = <&battery>; interrupts = <24 IRQ_TYPE_LEVEL_HIGH>, <8 IRQ_TYPE_LEVEL_HIGH>, <28 IRQ_TYPE_LEVEL_HIGH>, From 1a6784359540dcfbf4fa73c07868b80c8405cc14 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 7 Oct 2021 00:40:07 +0200 Subject: [PATCH 23/30] power: supply: ab8500_bmdata: Use standard phandle Look up the battery using the "monitored-battery" phandle as is nowadays a standard DT binding. The actual bindings for these charger elements are not upstream so let's sort out this mess by conforming to the standard. Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_bmdata.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/power/supply/ab8500_bmdata.c b/drivers/power/supply/ab8500_bmdata.c index 6f5fb794042c..bfc1245d7912 100644 --- a/drivers/power/supply/ab8500_bmdata.c +++ b/drivers/power/supply/ab8500_bmdata.c @@ -497,8 +497,7 @@ int ab8500_bm_of_probe(struct device *dev, const char *btech; int i; - /* get phandle to 'battery-info' node */ - battery_node = of_parse_phandle(np, "battery", 0); + battery_node = of_parse_phandle(np, "monitored-battery", 0); if (!battery_node) { dev_err(dev, "battery node or reference missing\n"); return -EINVAL; From 0b5a9135d5f12dce8dedaa18de6336364e04e873 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Oct 2021 15:50:51 +0200 Subject: [PATCH 24/30] power: supply: axp288-charger: Add depends on IOSF_MBIO to Kconfig Add "depends on IOSF_MBI" to CONFIG_AXP288_CHARGER as the changes from commit ed229454856e ("power: supply: axp288-charger: Optimize register reading method") use symbols which are only defined when IOSF_MBI support is enabled. Depending on this is ok since IOSF_MBI support should always be enabled on devices which use the AXP288 PMIC. Fixes: ed229454856e ("power: supply: axp288-charger: Optimize register reading method") Reported-by: kernel test robot Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index ad93b3550d6d..5cf5bb56d2e3 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -351,7 +351,7 @@ config AXP20X_POWER config AXP288_CHARGER tristate "X-Powers AXP288 Charger" - depends on MFD_AXP20X && EXTCON_AXP288 + depends on MFD_AXP20X && EXTCON_AXP288 && IOSF_MBI help Say yes here to have support X-Power AXP288 power management IC (PMIC) integrated charger. From 9052ff9b0387a6931d40f6999186099d038d2d33 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Oct 2021 15:50:52 +0200 Subject: [PATCH 25/30] power: supply: axp288-charger: Remove unnecessary is_present and is_online helpers Now that axp288_charger_usb_update_property() reads and caches all relevant registers, the axp288_charger_is_present() and axp288_charger_is_online() helpers are not necessary anymore. Directly check the cached input_status instead, allowing the removal of these 2 helpers. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 9987b1731e38..6dfecf7c9250 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -302,24 +302,6 @@ static int axp288_charger_enable_charger(struct axp288_chrg_info *info, return ret; } -static int axp288_charger_is_present(struct axp288_chrg_info *info) -{ - int present = 0; - - if (info->input_status & PS_STAT_VBUS_PRESENT) - present = 1; - return present; -} - -static int axp288_charger_is_online(struct axp288_chrg_info *info) -{ - int online = 0; - - if (info->input_status & PS_STAT_VBUS_VALID) - online = 1; - return online; -} - static int axp288_get_charger_health(struct axp288_chrg_info *info) { int health = POWER_SUPPLY_HEALTH_UNKNOWN; @@ -450,7 +432,7 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, val->intval = 0; break; } - val->intval = axp288_charger_is_present(info); + val->intval = (info->input_status & PS_STAT_VBUS_PRESENT) ? 1 : 0; break; case POWER_SUPPLY_PROP_ONLINE: /* Check for OTG case first */ @@ -458,7 +440,7 @@ static int axp288_charger_usb_get_property(struct power_supply *psy, val->intval = 0; break; } - val->intval = axp288_charger_is_online(info); + val->intval = (info->input_status & PS_STAT_VBUS_VALID) ? 1 : 0; break; case POWER_SUPPLY_PROP_HEALTH: val->intval = axp288_get_charger_health(info); From 5b5100c569b533195d9535fd2155d9f1cf389d0c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Oct 2021 15:50:53 +0200 Subject: [PATCH 26/30] power: supply: axp288-charger: Simplify axp288_get_charger_health() Now that axp288_charger_usb_update_property() reads and caches all relevant registers, axp288_get_charger_health() can be simplified by directly returning the health. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 6dfecf7c9250..ec41f6cd3f93 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -304,22 +304,17 @@ static int axp288_charger_enable_charger(struct axp288_chrg_info *info, static int axp288_get_charger_health(struct axp288_chrg_info *info) { - int health = POWER_SUPPLY_HEALTH_UNKNOWN; - if (!(info->input_status & PS_STAT_VBUS_PRESENT)) - goto health_read_fail; + return POWER_SUPPLY_HEALTH_UNKNOWN; if (!(info->input_status & PS_STAT_VBUS_VALID)) - health = POWER_SUPPLY_HEALTH_DEAD; + return POWER_SUPPLY_HEALTH_DEAD; else if (info->op_mode & CHRG_STAT_PMIC_OTP) - health = POWER_SUPPLY_HEALTH_OVERHEAT; + return POWER_SUPPLY_HEALTH_OVERHEAT; else if (info->op_mode & CHRG_STAT_BAT_SAFE_MODE) - health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; + return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; else - health = POWER_SUPPLY_HEALTH_GOOD; - -health_read_fail: - return health; + return POWER_SUPPLY_HEALTH_GOOD; } static int axp288_charger_usb_set_property(struct power_supply *psy, From 172d0ccea55ce69718bac693d2ea9341fb61b6c7 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 14 Oct 2021 11:45:33 +0200 Subject: [PATCH 27/30] power: bq25890: add return values to error messages Add more details to the error messages that indicate what went wrong and use dev_err_probe() at a few places in the probe() path in order to avoid error messages for deferred probe after which the driver probes correctly. Signed-off-by: Martin Kepplinger Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq25890_charger.c | 34 ++++++++++++-------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 945c3257ca93..56815e6d5a9d 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -788,13 +788,13 @@ static int bq25890_get_chip_version(struct bq25890_device *bq) id = bq25890_field_read(bq, F_PN); if (id < 0) { - dev_err(bq->dev, "Cannot read chip ID.\n"); + dev_err(bq->dev, "Cannot read chip ID: %d\n", id); return id; } rev = bq25890_field_read(bq, F_DEV_REV); if (rev < 0) { - dev_err(bq->dev, "Cannot read chip revision.\n"); + dev_err(bq->dev, "Cannot read chip revision: %d\n", rev); return rev; } @@ -837,10 +837,9 @@ static int bq25890_irq_probe(struct bq25890_device *bq) struct gpio_desc *irq; irq = devm_gpiod_get(bq->dev, BQ25890_IRQ_PIN, GPIOD_IN); - if (IS_ERR(irq)) { - dev_err(bq->dev, "Could not probe irq pin.\n"); - return PTR_ERR(irq); - } + if (IS_ERR(irq)) + return dev_err_probe(bq->dev, PTR_ERR(irq), + "Could not probe irq pin.\n"); return gpiod_to_irq(irq); } @@ -929,34 +928,33 @@ static int bq25890_probe(struct i2c_client *client, mutex_init(&bq->lock); bq->rmap = devm_regmap_init_i2c(client, &bq25890_regmap_config); - if (IS_ERR(bq->rmap)) { - dev_err(dev, "failed to allocate register map\n"); - return PTR_ERR(bq->rmap); - } + if (IS_ERR(bq->rmap)) + return dev_err_probe(dev, PTR_ERR(bq->rmap), + "failed to allocate register map\n"); for (i = 0; i < ARRAY_SIZE(bq25890_reg_fields); i++) { const struct reg_field *reg_fields = bq25890_reg_fields; bq->rmap_fields[i] = devm_regmap_field_alloc(dev, bq->rmap, reg_fields[i]); - if (IS_ERR(bq->rmap_fields[i])) { - dev_err(dev, "cannot allocate regmap field\n"); - return PTR_ERR(bq->rmap_fields[i]); - } + if (IS_ERR(bq->rmap_fields[i])) + return dev_err_probe(dev, PTR_ERR(bq->rmap_fields[i]), + "cannot allocate regmap field\n"); } i2c_set_clientdata(client, bq); ret = bq25890_get_chip_version(bq); if (ret) { - dev_err(dev, "Cannot read chip ID or unknown chip.\n"); + dev_err(dev, "Cannot read chip ID or unknown chip: %d\n", ret); return ret; } if (!dev->platform_data) { ret = bq25890_fw_probe(bq); if (ret < 0) { - dev_err(dev, "Cannot read device properties.\n"); + dev_err(dev, "Cannot read device properties: %d\n", + ret); return ret; } } else { @@ -965,7 +963,7 @@ static int bq25890_probe(struct i2c_client *client, ret = bq25890_hw_init(bq); if (ret < 0) { - dev_err(dev, "Cannot initialize the chip.\n"); + dev_err(dev, "Cannot initialize the chip: %d\n", ret); return ret; } @@ -994,7 +992,7 @@ static int bq25890_probe(struct i2c_client *client, ret = bq25890_power_supply_init(bq); if (ret < 0) { - dev_err(dev, "Failed to register power supply\n"); + dev_err_probe(dev, ret, "Failed to register power supply.\n"); goto irq_fail; } From cdf10ffe8f626d8a2edc354abf063df0078b2d71 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 31 Oct 2021 16:25:22 +0100 Subject: [PATCH 28/30] power: supply: bq27xxx: Fix kernel crash on IRQ handler register error When registering the IRQ handler fails, do not just return the error code, this will free the devm_kzalloc()-ed data struct while leaving the queued work queued and the registered power_supply registered with both of them now pointing to free-ed memory, resulting in various kernel crashes soon afterwards. Instead properly tear-down things on IRQ handler register errors. Fixes: 703df6c09795 ("power: bq27xxx_battery: Reorganize I2C into a module") Cc: Andrew F. Davis Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq27xxx_battery_i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index 46f078350fd3..cf38cbfe13e9 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c @@ -187,7 +187,8 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, dev_err(&client->dev, "Unable to register IRQ %d error %d\n", client->irq, ret); - return ret; + bq27xxx_battery_teardown(di); + goto err_failed; } } From d01363da53ebd1920a9676ea12e5c1168e292346 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 30 Oct 2021 20:28:03 +0200 Subject: [PATCH 29/30] power: supply: bq25890: Fix race causing oops at boot Before this commit the driver was registering its interrupt handler before it registered the power_supply, causing bq->charger to potentially be NULL when the interrupt handler runs, triggering a NULL pointer exception in the interrupt handler: [ 21.213531] BUG: kernel NULL pointer dereference, address: 0000000000000680 ... [ 21.213573] Hardware name: Xiaomi Inc Mipad2/Mipad, BIOS MIPad-P4.X64.0043.R03.1603071414 03/07/2016 [ 21.213576] RIP: 0010:__lock_acquire+0x5c5/0x1de0 ... [ 21.213629] Call Trace: [ 21.213636] ? disable_irq_nosync+0x10/0x10 [ 21.213644] ? __mutex_unlock_slowpath+0x35/0x260 [ 21.213655] lock_acquire+0xb5/0x2b0 [ 21.213661] ? power_supply_changed+0x23/0x90 [ 21.213670] ? disable_irq_nosync+0x10/0x10 [ 21.213676] _raw_spin_lock_irqsave+0x48/0x60 [ 21.213682] ? power_supply_changed+0x23/0x90 [ 21.213687] power_supply_changed+0x23/0x90 [ 21.213697] __bq25890_handle_irq+0x5e/0xe0 [bq25890_charger] [ 21.213709] bq25890_irq_handler_thread+0x26/0x40 [bq25890_charger] [ 21.213718] irq_thread_fn+0x20/0x60 ... Fix this by moving the power_supply_register() call to above the request_threaded_irq() call. Note this fix includes making the following 2 (necessary) changes: 1. Switch to the devm version of power_supply_register() to avoid the need to make the error-handling in probe() more complicated. 2. Rename the "irq_fail" label to "err_unregister_usb_notifier" since the old name no longer makes sense after this fix. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq25890_charger.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 56815e6d5a9d..42d82bee9727 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -734,8 +734,9 @@ static int bq25890_power_supply_init(struct bq25890_device *bq) psy_cfg.supplied_to = bq25890_charger_supplied_to; psy_cfg.num_supplicants = ARRAY_SIZE(bq25890_charger_supplied_to); - bq->charger = power_supply_register(bq->dev, &bq25890_power_supply_desc, - &psy_cfg); + bq->charger = devm_power_supply_register(bq->dev, + &bq25890_power_supply_desc, + &psy_cfg); return PTR_ERR_OR_ZERO(bq->charger); } @@ -983,22 +984,22 @@ static int bq25890_probe(struct i2c_client *client, usb_register_notifier(bq->usb_phy, &bq->usb_nb); } + ret = bq25890_power_supply_init(bq); + if (ret < 0) { + dev_err(dev, "Failed to register power supply\n"); + goto err_unregister_usb_notifier; + } + ret = devm_request_threaded_irq(dev, client->irq, NULL, bq25890_irq_handler_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, BQ25890_IRQ_PIN, bq); if (ret) - goto irq_fail; - - ret = bq25890_power_supply_init(bq); - if (ret < 0) { - dev_err_probe(dev, ret, "Failed to register power supply.\n"); - goto irq_fail; - } + goto err_unregister_usb_notifier; return 0; -irq_fail: +err_unregister_usb_notifier: if (!IS_ERR_OR_NULL(bq->usb_phy)) usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); @@ -1009,8 +1010,6 @@ static int bq25890_remove(struct i2c_client *client) { struct bq25890_device *bq = i2c_get_clientdata(client); - power_supply_unregister(bq->charger); - if (!IS_ERR_OR_NULL(bq->usb_phy)) usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); From 22ad4f99f63fc892412cde5a45d43b2288a60b88 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 30 Oct 2021 20:28:04 +0200 Subject: [PATCH 30/30] power: supply: bq25890: Fix initial setting of the F_CONV_RATE field The code doing the initial setting of the F_CONV_RATE field based on the bq->state.online flag. In order for this to work properly, this must be done after the initial bq25890_get_chip_state() call. Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq25890_charger.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 42d82bee9727..34ec186a2e9a 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -682,6 +682,12 @@ static int bq25890_hw_init(struct bq25890_device *bq) } } + ret = bq25890_get_chip_state(bq, &bq->state); + if (ret < 0) { + dev_dbg(bq->dev, "Get state failed %d\n", ret); + return ret; + } + /* Configure ADC for continuous conversions when charging */ ret = bq25890_field_write(bq, F_CONV_RATE, !!bq->state.online); if (ret < 0) { @@ -689,12 +695,6 @@ static int bq25890_hw_init(struct bq25890_device *bq) return ret; } - ret = bq25890_get_chip_state(bq, &bq->state); - if (ret < 0) { - dev_dbg(bq->dev, "Get state failed %d\n", ret); - return ret; - } - return 0; }