From f28992902b17245af042913d6cfd6a1cc100bcaf Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 21:25:04 +0100 Subject: [PATCH 01/91] power: supply: bq256xx: Use i2c_get_match_data() Use i2c_get_match_data() for OF/ID/ACPI match instead of ID lookup by replacing OF/ACPI/ID match data from enum bq256xx_id to struct bq256xx_chip_info. Signed-off-by: Biju Das Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230902202505.97609-2-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq256xx_charger.c | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index 82d3cd5ee2f9..fda4286323ee 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -1702,7 +1702,7 @@ static int bq256xx_probe(struct i2c_client *client) bq->client = client; bq->dev = dev; - bq->chip_info = &bq256xx_chip_info_tbl[id->driver_data]; + bq->chip_info = i2c_get_match_data(client); mutex_init(&bq->lock); @@ -1771,37 +1771,37 @@ static int bq256xx_probe(struct i2c_client *client) } static const struct i2c_device_id bq256xx_i2c_ids[] = { - { "bq25600", BQ25600 }, - { "bq25600d", BQ25600D }, - { "bq25601", BQ25601 }, - { "bq25601d", BQ25601D }, - { "bq25611d", BQ25611D }, - { "bq25618", BQ25618 }, - { "bq25619", BQ25619 }, + { "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] }, {}, }; MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids); static const struct of_device_id bq256xx_of_match[] = { - { .compatible = "ti,bq25600", .data = (void *)BQ25600 }, - { .compatible = "ti,bq25600d", .data = (void *)BQ25600D }, - { .compatible = "ti,bq25601", .data = (void *)BQ25601 }, - { .compatible = "ti,bq25601d", .data = (void *)BQ25601D }, - { .compatible = "ti,bq25611d", .data = (void *)BQ25611D }, - { .compatible = "ti,bq25618", .data = (void *)BQ25618 }, - { .compatible = "ti,bq25619", .data = (void *)BQ25619 }, + { .compatible = "ti,bq25600", .data = &bq256xx_chip_info_tbl[BQ25600] }, + { .compatible = "ti,bq25600d", .data = &bq256xx_chip_info_tbl[BQ25600D] }, + { .compatible = "ti,bq25601", .data = &bq256xx_chip_info_tbl[BQ25601] }, + { .compatible = "ti,bq25601d", .data = &bq256xx_chip_info_tbl[BQ25601D] }, + { .compatible = "ti,bq25611d", .data = &bq256xx_chip_info_tbl[BQ25611D] }, + { .compatible = "ti,bq25618", .data = &bq256xx_chip_info_tbl[BQ25618] }, + { .compatible = "ti,bq25619", .data = &bq256xx_chip_info_tbl[BQ25619] }, { }, }; MODULE_DEVICE_TABLE(of, bq256xx_of_match); static const struct acpi_device_id bq256xx_acpi_match[] = { - { "bq25600", BQ25600 }, - { "bq25600d", BQ25600D }, - { "bq25601", BQ25601 }, - { "bq25601d", BQ25601D }, - { "bq25611d", BQ25611D }, - { "bq25618", BQ25618 }, - { "bq25619", BQ25619 }, + { "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] }, {}, }; MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match); From 02e673e59c3d374924422f74fb229ae4ee6715fc Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 21:25:05 +0100 Subject: [PATCH 02/91] power: supply: bq256xx: Some cleanups Some cleanups: * Remove trailing comma in the terminator entry for OF/ID/ACPI table. * Drop a space from terminator entry for OF table. Signed-off-by: Biju Das Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230902202505.97609-3-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq256xx_charger.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index fda4286323ee..474201815a27 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -1778,7 +1778,7 @@ static const struct i2c_device_id bq256xx_i2c_ids[] = { { "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] }, - {}, + {} }; MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids); @@ -1790,7 +1790,7 @@ static const struct of_device_id bq256xx_of_match[] = { { .compatible = "ti,bq25611d", .data = &bq256xx_chip_info_tbl[BQ25611D] }, { .compatible = "ti,bq25618", .data = &bq256xx_chip_info_tbl[BQ25618] }, { .compatible = "ti,bq25619", .data = &bq256xx_chip_info_tbl[BQ25619] }, - { }, + {} }; MODULE_DEVICE_TABLE(of, bq256xx_of_match); @@ -1802,7 +1802,7 @@ static const struct acpi_device_id bq256xx_acpi_match[] = { { "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] }, - {}, + {} }; MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match); From a7d79bcc8364483b0d39c944d72b425cf06eccc5 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 31 Aug 2023 18:12:35 +0100 Subject: [PATCH 03/91] power: supply: sbs-battery: Make similar OF and ID table Make similar OF and ID table to extend support for ID match using i2c_match_data(). Currently it works only for OF match tables as the field is wrong for ID match. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230831171235.58477-1-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/sbs-battery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index cdfc8466d129..a6c204c08232 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -1135,7 +1135,7 @@ static int sbs_probe(struct i2c_client *client) if (!chip) return -ENOMEM; - chip->flags = (u32)(uintptr_t)device_get_match_data(&client->dev); + chip->flags = (uintptr_t)i2c_get_match_data(client); chip->client = client; psy_cfg.of_node = client->dev.of_node; psy_cfg.drv_data = chip; @@ -1253,9 +1253,9 @@ static SIMPLE_DEV_PM_OPS(sbs_pm_ops, sbs_suspend, NULL); #endif static const struct i2c_device_id sbs_id[] = { - { "bq20z65", 0 }, - { "bq20z75", 0 }, - { "sbs-battery", 1 }, + { "bq20z65", SBS_FLAGS_TI_BQ20ZX5 }, + { "bq20z75", SBS_FLAGS_TI_BQ20ZX5 }, + { "sbs-battery", 0 }, {} }; MODULE_DEVICE_TABLE(i2c, sbs_id); From 8e511f42ac9cdab84c692bcd0f9e0c55c75b1856 Mon Sep 17 00:00:00 2001 From: Andrew Halaney Date: Thu, 17 Aug 2023 16:41:57 -0500 Subject: [PATCH 04/91] power: reset: nvmem-reboot-mode: quiet some device deferrals Some errors are being logged that are really due to deferrals, which is confusing to users. Use dev_err_probe() to handle when to log at error level versus debug. This also has the added bonuses of logging to devices_deferred and printing the error value. Signed-off-by: Andrew Halaney Reviewed-by: Brian Masney Tested-by: Brian Masney Link: https://lore.kernel.org/r/20230817214218.638846-1-ahalaney@redhat.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/nvmem-reboot-mode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index e229308d43e2..41530b70cfc4 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c @@ -45,8 +45,8 @@ static int nvmem_reboot_mode_probe(struct platform_device *pdev) nvmem_rbm->cell = devm_nvmem_cell_get(&pdev->dev, "reboot-mode"); if (IS_ERR(nvmem_rbm->cell)) { - dev_err(&pdev->dev, "failed to get the nvmem cell reboot-mode\n"); - return PTR_ERR(nvmem_rbm->cell); + return dev_err_probe(&pdev->dev, PTR_ERR(nvmem_rbm->cell), + "failed to get the nvmem cell reboot-mode\n"); } ret = devm_reboot_mode_register(&pdev->dev, &nvmem_rbm->reboot); From 70c81c37cf252798bef5fe047a57129ff6a2b31b Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Aug 2023 21:19:47 +0800 Subject: [PATCH 05/91] power: reset: st-poweroff: use builtin_platform_driver() to simplify code The st_reset_init() doesn't do anything special, so it can use the builtin_platform_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230807131951.3443880-2-yangyingliang@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/st-poweroff.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/power/reset/st-poweroff.c b/drivers/power/reset/st-poweroff.c index 56ba21873882..85175066beea 100644 --- a/drivers/power/reset/st-poweroff.c +++ b/drivers/power/reset/st-poweroff.c @@ -100,12 +100,7 @@ static struct platform_driver st_reset_driver = { }, }; -static int __init st_reset_init(void) -{ - return platform_driver_register(&st_reset_driver); -} - -device_initcall(st_reset_init); +builtin_platform_driver(st_reset_driver); MODULE_AUTHOR("Christophe Kerello "); MODULE_DESCRIPTION("STMicroelectronics Power off Restart driver"); From 4e579a5c68d88b340776c2270659de111f8923f6 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Aug 2023 21:19:48 +0800 Subject: [PATCH 06/91] power: reset: msm: use builtin_platform_driver() to simplify code The msm_restart_init() doesn't do anything special, so it can use the builtin_platform_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230807131951.3443880-3-yangyingliang@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/msm-poweroff.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index b9a401bd280b..d96d248a6e25 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -59,9 +59,4 @@ static struct platform_driver msm_restart_driver = { .of_match_table = of_match_ptr(of_msm_restart_match), }, }; - -static int __init msm_restart_init(void) -{ - return platform_driver_register(&msm_restart_driver); -} -device_initcall(msm_restart_init); +builtin_platform_driver(msm_restart_driver); From 764db16149ec6128da548aac54a16b651461fbc8 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Aug 2023 21:19:49 +0800 Subject: [PATCH 07/91] power: reset: xgene-reboot: use builtin_platform_driver() to simplify code The xgene_reboot_init() doesn't do anything special, so it can use the builtin_platform_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230807131951.3443880-4-yangyingliang@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/xgene-reboot.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 3260bd93158e..c2e5a99940d3 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -87,9 +87,4 @@ static struct platform_driver xgene_reboot_driver = { .of_match_table = xgene_reboot_of_match, }, }; - -static int __init xgene_reboot_init(void) -{ - return platform_driver_register(&xgene_reboot_driver); -} -device_initcall(xgene_reboot_init); +builtin_platform_driver(xgene_reboot_driver); From 6a7f7f27e2c766f36c6bd948a5de91ca2703c2a4 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Aug 2023 21:19:50 +0800 Subject: [PATCH 08/91] power: reset: axxia-reset: use builtin_platform_driver() to simplify code The axxia_reset_init() doesn't do anything special, so it can use the builtin_platform_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230807131951.3443880-5-yangyingliang@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/axxia-reset.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c index f7b40be5d6b6..24946766760c 100644 --- a/drivers/power/reset/axxia-reset.c +++ b/drivers/power/reset/axxia-reset.c @@ -80,9 +80,4 @@ static struct platform_driver axxia_reset_driver = { .of_match_table = of_match_ptr(of_axxia_reset_match), }, }; - -static int __init axxia_reset_init(void) -{ - return platform_driver_register(&axxia_reset_driver); -} -device_initcall(axxia_reset_init); +builtin_platform_driver(axxia_reset_driver); From 5b69b5f209b7a6d21329b14b533b390fff6895d5 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 7 Aug 2023 21:19:51 +0800 Subject: [PATCH 09/91] power: reset: syscon-poweroff: use builtin_platform_driver() to simplify code The syscon_poweroff_register() doesn't do anything special, so it can use the builtin_platform_driver() macro to eliminate boilerplate code. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230807131951.3443880-6-yangyingliang@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/syscon-poweroff.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index 430d440d55c6..270f289239a5 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -93,9 +93,4 @@ static struct platform_driver syscon_poweroff_driver = { .of_match_table = syscon_poweroff_of_match, }, }; - -static int __init syscon_poweroff_register(void) -{ - return platform_driver_register(&syscon_poweroff_driver); -} -device_initcall(syscon_poweroff_register); +builtin_platform_driver(syscon_poweroff_driver); From 6eca10a1c2e5c5edaf92d5a9d1bcf415456369b7 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Mon, 31 Jul 2023 19:39:59 +0800 Subject: [PATCH 10/91] power: supply: 88pm860x_battery: fix the return value handle for platform_get_irq() There is no possible for platform_get_irq() to return 0, and the return value of platform_get_irq() is more sensible to show the error reason. Signed-off-by: Ruan Jinjie Link: https://lore.kernel.org/r/20230731113959.1957820-1-ruanjinjie@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/88pm860x_battery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/88pm860x_battery.c b/drivers/power/supply/88pm860x_battery.c index f3f3f8cd1a7f..34619c4d4ece 100644 --- a/drivers/power/supply/88pm860x_battery.c +++ b/drivers/power/supply/88pm860x_battery.c @@ -921,12 +921,12 @@ static int pm860x_battery_probe(struct platform_device *pdev) return -ENOMEM; info->irq_cc = platform_get_irq(pdev, 0); - if (info->irq_cc <= 0) - return -EINVAL; + if (info->irq_cc < 0) + return info->irq_cc; info->irq_batt = platform_get_irq(pdev, 1); - if (info->irq_batt <= 0) - return -EINVAL; + if (info->irq_batt < 0) + return info->irq_batt; info->chip = chip; info->i2c = From 389405146ca11d24f85b3277121a58f98a926a28 Mon Sep 17 00:00:00 2001 From: Ruan Jinjie Date: Thu, 27 Jul 2023 19:35:50 +0800 Subject: [PATCH 11/91] power: supply: Remove redundant dev_err_probe() for platform_get_irq_byname() There is no need to call the dev_err_probe() function directly to print a custom message when handling an error from platform_get_irq_byname() function as it is going to display an appropriate error message in case of a failure. Signed-off-by: Ruan Jinjie Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Dhruva Gole Link: https://lore.kernel.org/r/20230727113550.2599335-1-ruanjinjie@huawei.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/mt6370-charger.c | 4 +--- drivers/power/supply/qcom_pmi8998_charger.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/mt6370-charger.c b/drivers/power/supply/mt6370-charger.c index f27dae5043f5..571cf00dde07 100644 --- a/drivers/power/supply/mt6370-charger.c +++ b/drivers/power/supply/mt6370-charger.c @@ -849,9 +849,7 @@ static int mt6370_chg_init_irq(struct mt6370_priv *priv) ret = platform_get_irq_byname(to_platform_device(priv->dev), mt6370_chg_irqs[i].name); if (ret < 0) - return dev_err_probe(priv->dev, ret, - "Failed to get irq %s\n", - mt6370_chg_irqs[i].name); + return ret; priv->irq_nums[i] = ret; ret = devm_request_threaded_irq(priv->dev, ret, NULL, diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c index 10f4dd0caca1..8acf63ee6897 100644 --- a/drivers/power/supply/qcom_pmi8998_charger.c +++ b/drivers/power/supply/qcom_pmi8998_charger.c @@ -915,8 +915,7 @@ static int smb2_init_irq(struct smb2_chip *chip, int *irq, const char *name, irqnum = platform_get_irq_byname(to_platform_device(chip->dev), name); if (irqnum < 0) - return dev_err_probe(chip->dev, irqnum, - "Couldn't get irq %s byname\n", name); + return irqnum; rc = devm_request_threaded_irq(chip->dev, irqnum, NULL, handler, IRQF_ONESHOT, name, chip); From c06a65ac4e4945478f46654920f5af1be1cf384e Mon Sep 17 00:00:00 2001 From: Przemyslaw Chwiala Date: Thu, 20 Jul 2023 14:31:02 +0200 Subject: [PATCH 12/91] power: supply: max17042_battery: Do not use CONFIG_ prefix in regular C code Using CONFIG_ prefix for macros is not a good practice. Use CONFIG_ prefix in Kconfig only. Signed-off-by: Przemyslaw Chwiala Reviewed-by: Krzysztof Kozlowski Reviewed-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20230720123102.154699-1-przemekchwiala@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 17ac2ab78c4e..e7d37e422c3f 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -36,7 +36,7 @@ #define STATUS_BR_BIT (1 << 15) /* Interrupt mask bits */ -#define CONFIG_ALRT_BIT_ENBL (1 << 2) +#define CFG_ALRT_BIT_ENBL (1 << 2) #define VFSOC0_LOCK 0x0000 #define VFSOC0_UNLOCK 0x0080 @@ -1116,8 +1116,8 @@ static int max17042_probe(struct i2c_client *client) chip); if (!ret) { regmap_update_bits(chip->regmap, MAX17042_CONFIG, - CONFIG_ALRT_BIT_ENBL, - CONFIG_ALRT_BIT_ENBL); + CFG_ALRT_BIT_ENBL, + CFG_ALRT_BIT_ENBL); max17042_set_soc_threshold(chip, 1); } else { client->irq = 0; From 716293381a0f9a400d0010628a9ba4354c2bea40 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 Sep 2023 14:00:55 +0200 Subject: [PATCH 13/91] dt-bindings: power: syscon-poweroff: get regmap from parent node Just like syscon-reboot device, the syscon-poweroff is supposed to be a child of syscon node, thus we can take the same approach as syscon-poweroff: deprecate the 'regmap' field in favor of taking it from the parent's node. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Conor Dooley Link: https://lore.kernel.org/r/20230901120057.47018-1-krzysztof.kozlowski@linaro.org Signed-off-by: Sebastian Reichel --- .../bindings/power/reset/syscon-poweroff.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml b/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml index 3412fe7e1e80..d342b113fca2 100644 --- a/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml +++ b/Documentation/devicetree/bindings/power/reset/syscon-poweroff.yaml @@ -15,6 +15,9 @@ description: |+ defined by the register map pointed by syscon reference plus the offset with the value and mask defined in the poweroff node. Default will be little endian mode, 32 bit access only. + The SYSCON register map is normally retrieved from the parental dt-node. So + the SYSCON poweroff node should be represented as a sub-node of a "syscon", + "simple-mfd" node. properties: compatible: @@ -30,7 +33,10 @@ properties: regmap: $ref: /schemas/types.yaml#/definitions/phandle - description: Phandle to the register map node. + deprecated: true + description: + Phandle to the register map node. This property is deprecated in favor of + the syscon-poweroff node being a child of a system controller node. value: $ref: /schemas/types.yaml#/definitions/uint32 @@ -38,7 +44,6 @@ properties: required: - compatible - - regmap - offset additionalProperties: false @@ -56,7 +61,6 @@ examples: - | poweroff { compatible = "syscon-poweroff"; - regmap = <®mapnode>; offset = <0x0>; mask = <0x7a>; }; From 6f9c8a1338d90d150767331d4fab051fb8abdba5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 Sep 2023 14:00:56 +0200 Subject: [PATCH 14/91] power: reset: syscon-poweroff: simplify pdev->dev usage Make the probe() code a bit simpler and shorter by storing all the '&pdev->dev' as 'dev'. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230901120057.47018-2-krzysztof.kozlowski@linaro.org Signed-off-by: Sebastian Reichel --- drivers/power/reset/syscon-poweroff.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index 270f289239a5..9ef7eef4c979 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -32,23 +32,24 @@ static void syscon_poweroff(void) static int syscon_poweroff_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; int mask_err, value_err; - map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap"); + map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap"); if (IS_ERR(map)) { - dev_err(&pdev->dev, "unable to get syscon"); + dev_err(dev, "unable to get syscon"); return PTR_ERR(map); } - if (of_property_read_u32(pdev->dev.of_node, "offset", &offset)) { - dev_err(&pdev->dev, "unable to read 'offset'"); + if (of_property_read_u32(dev->of_node, "offset", &offset)) { + dev_err(dev, "unable to read 'offset'"); return -EINVAL; } - value_err = of_property_read_u32(pdev->dev.of_node, "value", &value); - mask_err = of_property_read_u32(pdev->dev.of_node, "mask", &mask); + value_err = of_property_read_u32(dev->of_node, "value", &value); + mask_err = of_property_read_u32(dev->of_node, "mask", &mask); if (value_err && mask_err) { - dev_err(&pdev->dev, "unable to read 'value' and 'mask'"); + dev_err(dev, "unable to read 'value' and 'mask'"); return -EINVAL; } @@ -62,7 +63,7 @@ static int syscon_poweroff_probe(struct platform_device *pdev) } if (pm_power_off) { - dev_err(&pdev->dev, "pm_power_off already claimed for %ps", + dev_err(dev, "pm_power_off already claimed for %ps", pm_power_off); return -EBUSY; } From 92bbb93aaaefe14c01eac18df46f8260ee4c2825 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 1 Sep 2023 14:00:57 +0200 Subject: [PATCH 15/91] power: reset: syscon-poweroff: get regmap from parent node Just like syscon-reboot device, the syscon-poweroff is supposed to be a child of syscon node, thus we can take the same approach as syscon-poweroff: deprecate the 'regmap' field in favor of taking it from the parent's node. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230901120057.47018-3-krzysztof.kozlowski@linaro.org Signed-off-by: Sebastian Reichel --- drivers/power/reset/syscon-poweroff.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index 9ef7eef4c979..c3aab7f59345 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -37,8 +37,11 @@ static int syscon_poweroff_probe(struct platform_device *pdev) map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap"); if (IS_ERR(map)) { - dev_err(dev, "unable to get syscon"); - return PTR_ERR(map); + map = syscon_node_to_regmap(dev->parent->of_node); + if (IS_ERR(map)) { + dev_err(dev, "unable to get syscon"); + return PTR_ERR(map); + } } if (of_property_read_u32(dev->of_node, "offset", &offset)) { From ef2730fb8122ff90747ee79261c2a9fd35032e17 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 21:05:17 +0100 Subject: [PATCH 16/91] power: supply: bq2515x: Simpilfy bq2515x_read_properties() and probe() Add struct bq2515x_info and replace device_id->info in struct bq2515x_device. Simpilfy bq2515x_read_properties() and probe() by adding struct bq2425x_chip_info as match data for OF/ID tables and use i2c_get_match_data for retrieving match data instead of ID lookup. Drop enum bq2515x_id as there is no user. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230902200518.91585-2-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq2515x_charger.c | 61 ++++++++++++-------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index 1dbacc9b015d..ada4532fda45 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -147,9 +147,14 @@ struct bq2515x_init_data { int iprechg; }; -enum bq2515x_id { - BQ25150, - BQ25155, +/** + * struct bq2515x_info - + * @regmap_config: register map config + * @ilim: input current limit + */ +struct bq2515x_info { + const struct regmap_config *regmap_config; + int ilim; }; /** @@ -164,8 +169,8 @@ enum bq2515x_id { * @ac_detect_gpio: power good (PG) pin * @ce_gpio: charge enable (CE) pin * + * @info: device info * @model_name: string value describing device model - * @device_id: value of device_id * @mains_online: boolean value indicating power supply online * * @init_data: charger initialization data structure @@ -181,8 +186,8 @@ struct bq2515x_device { struct gpio_desc *ac_detect_gpio; struct gpio_desc *ce_gpio; + const struct bq2515x_info *info; char model_name[I2C_NAME_SIZE]; - int device_id; bool mains_online; struct bq2515x_init_data init_data; @@ -998,16 +1003,8 @@ static int bq2515x_read_properties(struct bq2515x_device *bq2515x) ret = device_property_read_u32(bq2515x->dev, "input-current-limit-microamp", &bq2515x->init_data.ilim); - if (ret) { - switch (bq2515x->device_id) { - case BQ25150: - bq2515x->init_data.ilim = BQ25150_DEFAULT_ILIM_UA; - break; - case BQ25155: - bq2515x->init_data.ilim = BQ25155_DEFAULT_ILIM_UA; - break; - } - } + if (ret) + bq2515x->init_data.ilim = bq2515x->info->ilim; bq2515x->ac_detect_gpio = devm_gpiod_get_optional(bq2515x->dev, "ac-detect", GPIOD_IN); @@ -1094,19 +1091,9 @@ static int bq2515x_probe(struct i2c_client *client) strncpy(bq2515x->model_name, id->name, I2C_NAME_SIZE); - bq2515x->device_id = id->driver_data; - - switch (bq2515x->device_id) { - case BQ25150: - bq2515x->regmap = devm_regmap_init_i2c(client, - &bq25150_regmap_config); - break; - case BQ25155: - bq2515x->regmap = devm_regmap_init_i2c(client, - &bq25155_regmap_config); - break; - } - + bq2515x->info = i2c_get_match_data(client); + bq2515x->regmap = devm_regmap_init_i2c(client, + bq2515x->info->regmap_config); if (IS_ERR(bq2515x->regmap)) { dev_err(dev, "failed to allocate register map\n"); return PTR_ERR(bq2515x->regmap); @@ -1139,16 +1126,26 @@ static int bq2515x_probe(struct i2c_client *client) return 0; } +static const struct bq2515x_info bq25150 = { + .regmap_config = &bq25150_regmap_config, + .ilim = BQ25150_DEFAULT_ILIM_UA, +}; + +static const struct bq2515x_info bq25155 = { + .regmap_config = &bq25155_regmap_config, + .ilim = BQ25155_DEFAULT_ILIM_UA, +}; + static const struct i2c_device_id bq2515x_i2c_ids[] = { - { "bq25150", BQ25150, }, - { "bq25155", BQ25155, }, + { "bq25150", (kernel_ulong_t)&bq25150 }, + { "bq25155", (kernel_ulong_t)&bq25155 }, {}, }; MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids); static const struct of_device_id bq2515x_of_match[] = { - { .compatible = "ti,bq25150", }, - { .compatible = "ti,bq25155", }, + { .compatible = "ti,bq25150", .data = &bq25150 }, + { .compatible = "ti,bq25155", .data = &bq25155 }, { }, }; MODULE_DEVICE_TABLE(of, bq2515x_of_match); From ab907d99d5d4e40ba638b6a27940d59fcb2ad24d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 21:05:18 +0100 Subject: [PATCH 17/91] power: supply: bq2515x: Cleanup OF/ID table terminators Some cleanups: * Remove trailing comma in the terminator entry for OF/ID table. * Drop a space from terminator entry for OF table. Signed-off-by: Biju Das Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230902200518.91585-3-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq2515x_charger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index ada4532fda45..49fa6386a509 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -1139,14 +1139,14 @@ 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 }, - {}, + {} }; MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids); static const struct of_device_id bq2515x_of_match[] = { { .compatible = "ti,bq25150", .data = &bq25150 }, { .compatible = "ti,bq25155", .data = &bq25155 }, - { }, + {} }; MODULE_DEVICE_TABLE(of, bq2515x_of_match); From 3dc4a291a1b156d3ee9a78672ec950601bd68c1c Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 20:33:30 +0100 Subject: [PATCH 18/91] power: supply: bq24257_charger: Make chip type and name in sync Add struct bq2425x_chip_info to make enum bq2425x_chip and it's name in sync and replace chip->info in struct bq24257_device and add struct bq2425x_chip_info as match data for OF/ACPI/ID tables. Simpilfy probe() by replacing acpi_match_device() and id lookup for retrieving match data by using i2c_get_match_data(). Drop bq2425x_chip_name as there is no user and also drop the comment related to syncing chip and name as it is taken care by struct bq2425x_chip_info. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230902193331.83672-2-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24257_charger.c | 70 +++++++++++++------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c index 2852860abf86..188812f4a79b 100644 --- a/drivers/power/supply/bq24257_charger.c +++ b/drivers/power/supply/bq24257_charger.c @@ -35,20 +35,15 @@ #define BQ24257_ILIM_SET_DELAY 1000 /* msec */ -/* - * When adding support for new devices make sure that enum bq2425x_chip and - * bq2425x_chip_name[] always stay in sync! - */ enum bq2425x_chip { BQ24250, BQ24251, BQ24257, }; -static const char *const bq2425x_chip_name[] = { - "bq24250", - "bq24251", - "bq24257", +struct bq2425x_chip_info { + const char *const name; + enum bq2425x_chip chip; }; enum bq24257_fields { @@ -84,7 +79,7 @@ struct bq24257_device { struct device *dev; struct power_supply *charger; - enum bq2425x_chip chip; + const struct bq2425x_chip_info *info; struct regmap *rmap; struct regmap_field *rmap_fields[F_MAX_FIELDS]; @@ -329,7 +324,7 @@ static int bq24257_power_supply_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_MODEL_NAME: - val->strval = bq2425x_chip_name[bq->chip]; + val->strval = bq->info->name; break; case POWER_SUPPLY_PROP_ONLINE: @@ -947,10 +942,8 @@ static int bq24257_fw_probe(struct bq24257_device *bq) static int bq24257_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct i2c_adapter *adapter = client->adapter; struct device *dev = &client->dev; - const struct acpi_device_id *acpi_id; struct bq24257_device *bq; int ret; int i; @@ -967,17 +960,9 @@ static int bq24257_probe(struct i2c_client *client) bq->client = client; bq->dev = dev; - if (ACPI_HANDLE(dev)) { - acpi_id = acpi_match_device(dev->driver->acpi_match_table, - &client->dev); - if (!acpi_id) { - dev_err(dev, "Failed to match ACPI device\n"); - return -ENODEV; - } - bq->chip = (enum bq2425x_chip)acpi_id->driver_data; - } else { - bq->chip = (enum bq2425x_chip)id->driver_data; - } + bq->info = i2c_get_match_data(client); + if (!bq->info) + return dev_err_probe(dev, -ENODEV, "Failed to match device\n"); mutex_init(&bq->lock); @@ -1015,7 +1000,7 @@ static int bq24257_probe(struct i2c_client *client) * used for the automatic setting of the input current limit setting so * explicitly disable that feature. */ - if (bq->chip == BQ24250) + if (bq->info->chip == BQ24250) bq->iilimit_autoset_enable = false; if (bq->iilimit_autoset_enable) @@ -1028,7 +1013,7 @@ static int bq24257_probe(struct i2c_client *client) * the PG state. We also use a SW-based approach for all other devices * if the PG pin is either not defined or can't be probed. */ - if (bq->chip != BQ24250) + if (bq->info->chip != BQ24250) bq24257_pg_gpio_probe(bq); if (PTR_ERR(bq->pg) == -EPROBE_DEFER) @@ -1066,7 +1051,7 @@ static int bq24257_probe(struct i2c_client *client) bq24257_irq_handler_thread, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, - bq2425x_chip_name[bq->chip], bq); + bq->info->name, bq); if (ret) { dev_err(dev, "Failed to request IRQ #%d\n", client->irq); return ret; @@ -1132,27 +1117,42 @@ static const struct dev_pm_ops bq24257_pm = { SET_SYSTEM_SLEEP_PM_OPS(bq24257_suspend, bq24257_resume) }; +static const struct bq2425x_chip_info bq24250_info = { + .name = "bq24250", + .chip = BQ24250, +}; + +static const struct bq2425x_chip_info bq24251_info = { + .name = "bq24251", + .chip = BQ24251, +}; + +static const struct bq2425x_chip_info bq24257_info = { + .name = "bq24257", + .chip = BQ24257, +}; + static const struct i2c_device_id bq24257_i2c_ids[] = { - { "bq24250", BQ24250 }, - { "bq24251", BQ24251 }, - { "bq24257", BQ24257 }, + { "bq24250", (kernel_ulong_t)&bq24250_info }, + { "bq24251", (kernel_ulong_t)&bq24251_info }, + { "bq24257", (kernel_ulong_t)&bq24257_info }, {}, }; MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); static const struct of_device_id bq24257_of_match[] __maybe_unused = { - { .compatible = "ti,bq24250", }, - { .compatible = "ti,bq24251", }, - { .compatible = "ti,bq24257", }, + { .compatible = "ti,bq24250", &bq24250_info }, + { .compatible = "ti,bq24251", &bq24251_info }, + { .compatible = "ti,bq24257", &bq24257_info }, { }, }; MODULE_DEVICE_TABLE(of, bq24257_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id bq24257_acpi_match[] = { - { "BQ242500", BQ24250 }, - { "BQ242510", BQ24251 }, - { "BQ242570", BQ24257 }, + { "BQ242500", (kernel_ulong_t)&bq24250_info }, + { "BQ242510", (kernel_ulong_t)&bq24251_info }, + { "BQ242570", (kernel_ulong_t)&bq24257_info }, {}, }; MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match); From b92f5e4fccc2ca96241904bb1a4e96547b69163d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 2 Sep 2023 20:33:31 +0100 Subject: [PATCH 19/91] power: supply: bq24257_charger: Cleanup OF/ID table terminators Some cleanups: * Remove trailing comma in the terminator entry for OF/ID/ACPI table. * Drop a space from terminator entry for OF table. Signed-off-by: Biju Das Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230902193331.83672-3-biju.das.jz@bp.renesas.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24257_charger.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/bq24257_charger.c b/drivers/power/supply/bq24257_charger.c index 188812f4a79b..801d0d2c5f2e 100644 --- a/drivers/power/supply/bq24257_charger.c +++ b/drivers/power/supply/bq24257_charger.c @@ -1136,7 +1136,7 @@ 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 }, - {}, + {} }; MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); @@ -1144,7 +1144,7 @@ static const struct of_device_id bq24257_of_match[] __maybe_unused = { { .compatible = "ti,bq24250", &bq24250_info }, { .compatible = "ti,bq24251", &bq24251_info }, { .compatible = "ti,bq24257", &bq24257_info }, - { }, + {} }; MODULE_DEVICE_TABLE(of, bq24257_of_match); @@ -1153,7 +1153,7 @@ static const struct acpi_device_id bq24257_acpi_match[] = { { "BQ242500", (kernel_ulong_t)&bq24250_info }, { "BQ242510", (kernel_ulong_t)&bq24251_info }, { "BQ242570", (kernel_ulong_t)&bq24257_info }, - {}, + {} }; MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match); #endif From bbaa6ffa5b6c9609d3b3c431c389b407eea5441f Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 13 Sep 2023 11:32:33 +0800 Subject: [PATCH 20/91] power: supply: core: Use blocking_notifier_call_chain to avoid RCU complaint AMD PMF driver can cause the following warning: [ 196.159546] ------------[ cut here ]------------ [ 196.159556] Voluntary context switch within RCU read-side critical section! [ 196.159571] WARNING: CPU: 0 PID: 9 at kernel/rcu/tree_plugin.h:320 rcu_note_context_switch+0x43d/0x560 [ 196.159604] Modules linked in: nvme_fabrics ccm rfcomm snd_hda_scodec_cs35l41_spi cmac algif_hash algif_skcipher af_alg bnep joydev btusb btrtl uvcvideo btintel btbcm videobuf2_vmalloc intel_rapl_msr btmtk videobuf2_memops uvc videobuf2_v4l2 intel_rapl_common binfmt_misc hid_sensor_als snd_sof_amd_vangogh hid_sensor_trigger bluetooth industrialio_triggered_buffer videodev snd_sof_amd_rembrandt hid_sensor_iio_common amdgpu ecdh_generic kfifo_buf videobuf2_common hp_wmi kvm_amd sparse_keymap snd_sof_amd_renoir wmi_bmof industrialio ecc mc nls_iso8859_1 kvm snd_sof_amd_acp irqbypass snd_sof_xtensa_dsp crct10dif_pclmul crc32_pclmul mt7921e snd_sof_pci snd_ctl_led polyval_clmulni mt7921_common polyval_generic snd_sof ghash_clmulni_intel mt792x_lib mt76_connac_lib sha512_ssse3 snd_sof_utils aesni_intel snd_hda_codec_realtek crypto_simd mt76 snd_hda_codec_generic cryptd snd_soc_core snd_hda_codec_hdmi rapl ledtrig_audio input_leds snd_compress i2c_algo_bit drm_ttm_helper mac80211 snd_pci_ps hid_multitouch ttm drm_exec [ 196.159970] drm_suballoc_helper snd_rpl_pci_acp6x amdxcp drm_buddy snd_hda_intel snd_acp_pci snd_hda_scodec_cs35l41_i2c serio_raw gpu_sched snd_hda_scodec_cs35l41 snd_acp_legacy_common snd_intel_dspcfg snd_hda_cs_dsp_ctls snd_hda_codec libarc4 drm_display_helper snd_pci_acp6x cs_dsp snd_hwdep snd_soc_cs35l41_lib video k10temp snd_pci_acp5x thunderbolt snd_hda_core drm_kms_helper cfg80211 snd_seq snd_rn_pci_acp3x snd_pcm snd_acp_config cec snd_soc_acpi snd_seq_device rc_core ccp snd_pci_acp3x snd_timer snd soundcore wmi amd_pmf platform_profile amd_pmc mac_hid serial_multi_instantiate wireless_hotkey hid_sensor_hub sch_fq_codel msr parport_pc ppdev lp parport efi_pstore ip_tables x_tables autofs4 btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx libcrc32c xor raid6_pq raid1 raid0 multipath linear dm_mirror dm_region_hash dm_log cdc_ether usbnet r8152 mii hid_generic nvme i2c_hid_acpi i2c_hid nvme_core i2c_piix4 xhci_pci amd_sfh drm xhci_pci_renesas nvme_common hid [ 196.160382] CPU: 0 PID: 9 Comm: kworker/0:1 Not tainted 6.6.0-rc1 #4 [ 196.160397] Hardware name: HP HP EliteBook 845 14 inch G10 Notebook PC/8B6E, BIOS V82 Ver. 01.02.00 08/24/2023 [ 196.160405] Workqueue: events power_supply_changed_work [ 196.160426] RIP: 0010:rcu_note_context_switch+0x43d/0x560 [ 196.160440] Code: 00 48 89 be 40 08 00 00 48 89 86 48 08 00 00 48 89 10 e9 63 fe ff ff 48 c7 c7 10 e7 b0 9e c6 05 e8 d8 20 02 01 e8 13 0f f3 ff <0f> 0b e9 27 fc ff ff a9 ff ff ff 7f 0f 84 cf fc ff ff 65 48 8b 3c [ 196.160450] RSP: 0018:ffffc900001878f0 EFLAGS: 00010046 [ 196.160462] RAX: 0000000000000000 RBX: ffff88885e834040 RCX: 0000000000000000 [ 196.160470] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 [ 196.160476] RBP: ffffc90000187910 R08: 0000000000000000 R09: 0000000000000000 [ 196.160482] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 196.160488] R13: 0000000000000000 R14: ffff888100990000 R15: ffff888100990000 [ 196.160495] FS: 0000000000000000(0000) GS:ffff88885e800000(0000) knlGS:0000000000000000 [ 196.160504] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 196.160512] CR2: 000055cb053c8246 CR3: 000000013443a000 CR4: 0000000000750ef0 [ 196.160520] PKRU: 55555554 [ 196.160526] Call Trace: [ 196.160532] [ 196.160548] ? show_regs+0x72/0x90 [ 196.160570] ? rcu_note_context_switch+0x43d/0x560 [ 196.160580] ? __warn+0x8d/0x160 [ 196.160600] ? rcu_note_context_switch+0x43d/0x560 [ 196.160613] ? report_bug+0x1bb/0x1d0 [ 196.160637] ? handle_bug+0x46/0x90 [ 196.160658] ? exc_invalid_op+0x19/0x80 [ 196.160675] ? asm_exc_invalid_op+0x1b/0x20 [ 196.160709] ? rcu_note_context_switch+0x43d/0x560 [ 196.160727] __schedule+0xb9/0x15f0 [ 196.160746] ? srso_alias_return_thunk+0x5/0x7f [ 196.160765] ? srso_alias_return_thunk+0x5/0x7f [ 196.160778] ? acpi_ns_search_one_scope+0xbe/0x270 [ 196.160806] schedule+0x68/0x110 [ 196.160820] schedule_timeout+0x151/0x160 [ 196.160829] ? srso_alias_return_thunk+0x5/0x7f [ 196.160842] ? srso_alias_return_thunk+0x5/0x7f [ 196.160855] ? acpi_ns_lookup+0x3c5/0xa90 [ 196.160878] __down_common+0xff/0x220 [ 196.160905] __down_timeout+0x16/0x30 [ 196.160920] down_timeout+0x64/0x70 [ 196.160938] acpi_os_wait_semaphore+0x85/0x200 [ 196.160959] acpi_ut_acquire_mutex+0x9e/0x280 [ 196.160979] acpi_ex_enter_interpreter+0x2d/0xb0 [ 196.160992] acpi_ns_evaluate+0x2f0/0x5f0 [ 196.161005] acpi_evaluate_object+0x172/0x490 [ 196.161018] ? acpi_os_signal_semaphore+0x8a/0xd0 [ 196.161038] acpi_evaluate_integer+0x52/0xe0 [ 196.161055] ? kfree+0x79/0x120 [ 196.161071] ? srso_alias_return_thunk+0x5/0x7f [ 196.161089] acpi_ac_get_state.part.0+0x27/0x80 [ 196.161110] get_ac_property+0x5c/0x70 [ 196.161127] ? __pfx___power_supply_is_system_supplied+0x10/0x10 [ 196.161146] __power_supply_is_system_supplied+0x44/0xb0 [ 196.161166] class_for_each_device+0x124/0x160 [ 196.161184] ? acpi_ac_get_state.part.0+0x27/0x80 [ 196.161203] ? srso_alias_return_thunk+0x5/0x7f [ 196.161223] power_supply_is_system_supplied+0x3c/0x70 [ 196.161243] amd_pmf_get_power_source+0xe/0x20 [amd_pmf] [ 196.161276] amd_pmf_power_slider_update_event+0x49/0x90 [amd_pmf] [ 196.161310] amd_pmf_pwr_src_notify_call+0xe7/0x100 [amd_pmf] [ 196.161340] notifier_call_chain+0x5f/0xe0 [ 196.161362] atomic_notifier_call_chain+0x33/0x60 [ 196.161378] power_supply_changed_work+0x84/0x110 [ 196.161394] process_one_work+0x178/0x360 [ 196.161412] ? __pfx_worker_thread+0x10/0x10 [ 196.161424] worker_thread+0x307/0x430 [ 196.161440] ? __pfx_worker_thread+0x10/0x10 [ 196.161451] kthread+0xf4/0x130 [ 196.161467] ? __pfx_kthread+0x10/0x10 [ 196.161486] ret_from_fork+0x43/0x70 [ 196.161502] ? __pfx_kthread+0x10/0x10 [ 196.161518] ret_from_fork_asm+0x1b/0x30 [ 196.161558] [ 196.161562] ---[ end trace 0000000000000000 ]--- Since there's no guarantee that all the callbacks can work in atomic context, switch to use blocking_notifier_call_chain to relax the constraint. Signed-off-by: Kai-Heng Feng Reported-by: Allen Zhong Fixes: 4c71ae414474 ("platform/x86/amd/pmf: Add support SPS PMF feature") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217571 Reviewed-by: Mario Limonciello Link: https://lore.kernel.org/r/20230913033233.602986-1-kai.heng.feng@canonical.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 8 ++++---- include/linux/power_supply.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 0b69fb7bafd8..416409e2fd6d 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -29,7 +29,7 @@ struct class *power_supply_class; EXPORT_SYMBOL_GPL(power_supply_class); -ATOMIC_NOTIFIER_HEAD(power_supply_notifier); +BLOCKING_NOTIFIER_HEAD(power_supply_notifier); EXPORT_SYMBOL_GPL(power_supply_notifier); static struct device_type power_supply_dev_type; @@ -97,7 +97,7 @@ static void power_supply_changed_work(struct work_struct *work) class_for_each_device(power_supply_class, NULL, psy, __power_supply_changed_work); power_supply_update_leds(psy); - atomic_notifier_call_chain(&power_supply_notifier, + blocking_notifier_call_chain(&power_supply_notifier, PSY_EVENT_PROP_CHANGED, psy); kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE); spin_lock_irqsave(&psy->changed_lock, flags); @@ -1262,13 +1262,13 @@ static void power_supply_dev_release(struct device *dev) int power_supply_reg_notifier(struct notifier_block *nb) { - return atomic_notifier_chain_register(&power_supply_notifier, nb); + return blocking_notifier_chain_register(&power_supply_notifier, nb); } EXPORT_SYMBOL_GPL(power_supply_reg_notifier); void power_supply_unreg_notifier(struct notifier_block *nb) { - atomic_notifier_chain_unregister(&power_supply_notifier, nb); + blocking_notifier_chain_unregister(&power_supply_notifier, nb); } EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index a427f13c757f..85b86768c0b9 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -767,7 +767,7 @@ struct power_supply_battery_info { int bti_resistance_tolerance; }; -extern struct atomic_notifier_head power_supply_notifier; +extern struct blocking_notifier_head power_supply_notifier; extern int power_supply_reg_notifier(struct notifier_block *nb); extern void power_supply_unreg_notifier(struct notifier_block *nb); #if IS_ENABLED(CONFIG_POWER_SUPPLY) From ddf5bbee5fa6cb157ecef4fe5263f3f36635e1c3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 31 Jul 2023 10:36:10 +0300 Subject: [PATCH 21/91] dt-bindings: power: supply: maxim,max17040: add temperature support Add temperature monitoring support. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Krzysztof Kozlowski Reviewed-by: Iskren Chernev Link: https://lore.kernel.org/r/20230731073613.10394-2-clamor95@gmail.com Signed-off-by: Sebastian Reichel --- .../bindings/power/supply/maxim,max17040.yaml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml index 2627cd3eed83..377cbb2c2c1f 100644 --- a/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml +++ b/Documentation/devicetree/bindings/power/supply/maxim,max17040.yaml @@ -55,6 +55,14 @@ properties: interrupts: maxItems: 1 + io-channels: + items: + - description: battery temperature + + io-channel-names: + items: + - const: temp + wakeup-source: type: boolean description: | @@ -95,3 +103,26 @@ examples: wakeup-source; }; }; + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + fuel-gauge@36 { + compatible = "maxim,max17043"; + reg = <0x36>; + + interrupt-parent = <&gpio>; + interrupts = <144 IRQ_TYPE_EDGE_FALLING>; + + monitored-battery = <&battery>; + power-supplies = <&charger>; + + io-channels = <&adc 8>; + io-channel-names = "temp"; + + maxim,alert-low-soc-level = <10>; + wakeup-source; + }; + }; From f4b782af61ae7bbf93008d5809b0e3a8ac2bb88e Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 31 Jul 2023 10:36:11 +0300 Subject: [PATCH 22/91] power: max17040: pass status property from supplier Optionally pass status property from supplier if has support for it. If cell is online assume it is present as well. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Iskren Chernev Link: https://lore.kernel.org/r/20230731073613.10394-3-clamor95@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17040_battery.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index ff42db672899..92caf6c7a48c 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -389,6 +389,7 @@ static int max17040_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: + case POWER_SUPPLY_PROP_PRESENT: val->intval = max17040_get_online(chip); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: @@ -400,6 +401,9 @@ static int max17040_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN: val->intval = chip->low_soc_alert; break; + case POWER_SUPPLY_PROP_STATUS: + power_supply_get_property_from_supplier(psy, psp, val); + break; default: return -EINVAL; } @@ -415,9 +419,11 @@ static const struct regmap_config max17040_regmap = { static enum power_supply_property max17040_battery_props[] = { POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, + POWER_SUPPLY_PROP_STATUS, }; static const struct power_supply_desc max17040_battery_desc = { From 814755c48f8b2c3e83b3c11535c48ab416128978 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Mon, 31 Jul 2023 10:36:12 +0300 Subject: [PATCH 23/91] power: max17040: get thermal data from adc if available Since fuel gauge does not support thermal monitoring, some vendors may couple this fuel gauge with thermal/adc sensor to monitor battery cell exact temperature. Add this feature by adding optional iio thermal channel. Signed-off-by: Svyatoslav Ryhel Reviewed-by: Iskren Chernev Link: https://lore.kernel.org/r/20230731073613.10394-4-clamor95@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 2 +- drivers/power/supply/max17040_battery.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 663a1c423806..d99db3a049f2 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -374,7 +374,7 @@ config AXP288_FUEL_GAUGE config BATTERY_MAX17040 tristate "Maxim MAX17040/17041/17043 family Fuel Gauge" - depends on I2C + depends on I2C && IIO select REGMAP_I2C help Driver supports Maxim fuel-gauge systems for lithium-ion (Li+) diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 92caf6c7a48c..51310f6e4803 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -18,6 +18,7 @@ #include #include #include +#include #define MAX17040_VCELL 0x02 #define MAX17040_SOC 0x04 @@ -142,6 +143,7 @@ struct max17040_chip { struct delayed_work work; struct power_supply *battery; struct chip_data data; + struct iio_channel *channel_temp; /* battery capacity */ int soc; @@ -404,6 +406,13 @@ static int max17040_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_STATUS: power_supply_get_property_from_supplier(psy, psp, val); break; + case POWER_SUPPLY_PROP_TEMP: + if (!chip->channel_temp) + return -ENODATA; + + iio_read_channel_processed_scale(chip->channel_temp, + &val->intval, 10); + break; default: return -EINVAL; } @@ -424,6 +433,7 @@ static enum power_supply_property max17040_battery_props[] = { POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TEMP, }; static const struct power_supply_desc max17040_battery_desc = { @@ -469,6 +479,17 @@ static int max17040_probe(struct i2c_client *client) i2c_set_clientdata(client, chip); psy_cfg.drv_data = chip; + /* Switch to devm_iio_channel_get_optional when available */ + chip->channel_temp = devm_iio_channel_get(&client->dev, "temp"); + if (IS_ERR(chip->channel_temp)) { + ret = PTR_ERR(chip->channel_temp); + if (ret != -ENODEV) + return dev_err_probe(&client->dev, PTR_ERR(chip->channel_temp), + "failed to get temp\n"); + else + chip->channel_temp = NULL; + } + chip->battery = devm_power_supply_register(&client->dev, &max17040_battery_desc, &psy_cfg); if (IS_ERR(chip->battery)) { From 1769142a14c34a8acd67657bc3e637f22f75e026 Mon Sep 17 00:00:00 2001 From: Maximilian Weigand Date: Wed, 14 Jun 2023 20:10:43 +0200 Subject: [PATCH 24/91] power: supply: rk817: query battery properties right after resume The driver reads battery properties every 8 seconds. In order to prevent problems with wrong property values right after resume, trigger an update of those properties on resuming the system and restart the 8-second interval from there. Signed-off-by: Maximilian Weigand Link: https://lore.kernel.org/r/20230601-rk817_query_at_resume-v1-1-630b0adefbd9@mweigand.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/rk817_charger.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c index 8328bcea1a29..393de49b010b 100644 --- a/drivers/power/supply/rk817_charger.c +++ b/drivers/power/supply/rk817_charger.c @@ -1198,11 +1198,24 @@ static int rk817_charger_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused rk817_resume(struct device *dev) +{ + + struct rk817_charger *charger = dev_get_drvdata(dev); + + /* force an immediate update */ + mod_delayed_work(system_wq, &charger->work, 0); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(rk817_charger_pm, NULL, rk817_resume); static struct platform_driver rk817_charger_driver = { .probe = rk817_charger_probe, .driver = { .name = "rk817-charger", + .pm = &rk817_charger_pm, }, }; module_platform_driver(rk817_charger_driver); From dc2dc941730438250a5c6567b8685f065ce1dd0f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 15 Sep 2023 14:45:15 +0200 Subject: [PATCH 25/91] dt-bindings: vendor-prefixes: Add Mitsumi Electric Co., Ltd. Mitsumi was [1] a Japanese company making various electronics devices and components. They've merged into a new entity, MinebeaMitsumi in 2017. Their current main page is available at [2] [1] https://en.wikipedia.org/wiki/Mitsumi_Electric [2] https://product.minebeamitsumi.com/en/ Acked-by: Krzysztof Kozlowski Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230621-topic-mm8013-v4-1-975aecd173ed@linaro.org Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 573578db9509..565b13fb429d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -871,6 +871,8 @@ patternProperties: description: MiraMEMS Sensing Technology Co., Ltd. "^mitsubishi,.*": description: Mitsubishi Electric Corporation + "^mitsumi,.*": + description: Mitsumi Electric Co., Ltd. "^mixel,.*": description: Mixel, Inc. "^miyoo,.*": From 9d15ff53398b4b21198ee6dec4f65a251de881dc Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 15 Sep 2023 14:45:16 +0200 Subject: [PATCH 26/91] dt-bindings: power: supply: Document Mitsumi MM8013 fuel gauge The Mitsumi MM8013 is an I2C fuel gauge for Li-Ion cells. The partial datasheet is available at [1]. Add bindings for this chip. [1] https://www.mitsumi.co.jp/latest-M/Catalog/pdf/battery_mm_8013_e.pdf Reviewed-by: Krzysztof Kozlowski Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230621-topic-mm8013-v4-2-975aecd173ed@linaro.org Signed-off-by: Sebastian Reichel --- .../bindings/power/supply/mitsumi,mm8013.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml diff --git a/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml b/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml new file mode 100644 index 000000000000..6865640cbdfa --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/mitsumi,mm8013.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mitsumi MM8013 fuel gauge + +maintainers: + - Konrad Dybcio + +allOf: + - $ref: power-supply.yaml# + +properties: + compatible: + const: mitsumi,mm8013 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + fuel-gauge@55 { + compatible = "mitsumi,mm8013"; + reg = <0x55>; + }; + }; From c75f4bf6800bde67df22ac95139279ec8764118a Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 15 Sep 2023 14:45:17 +0200 Subject: [PATCH 27/91] power: supply: Introduce MM8013 fuel gauge driver Add a driver for the Mitsumi MM8013 fuel gauge. The driver is a vastly cleaned up and improved version of the one that shipped in some obscure Lenovo downstream kernel [1], with some register definitions borrowed from ChromeOS EC platform code [2]. [1] https://github.com/adazem009/kernel_lenovo_bengal/commit/b6b346427a871715709bd22aae449b9383f3b66b [2] https://chromium.googlesource.com/chromiumos/platform/ec/+/master/driver/battery/mm8013.h Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230621-topic-mm8013-v4-3-975aecd173ed@linaro.org Signed-off-by: Sebastian Reichel --- MAINTAINERS | 5 + drivers/power/supply/Kconfig | 9 ++ drivers/power/supply/Makefile | 1 + drivers/power/supply/mm8013.c | 274 ++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 drivers/power/supply/mm8013.c diff --git a/MAINTAINERS b/MAINTAINERS index 90f13281d297..fb458f7e397c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14376,6 +14376,11 @@ W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git F: drivers/media/radio/radio-miropcm20* +MITSUMI MM8013 FG DRIVER +M: Konrad Dybcio +F: Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml +F: drivers/power/supply/mm8013.c + MMP SUPPORT R: Lubomir Rintel L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index d99db3a049f2..c816dc4265df 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -951,4 +951,13 @@ config CHARGER_QCOM_SMB2 adds support for the SMB2 switch mode battery charger found in PMI8998 and related PMICs. +config FUEL_GAUGE_MM8013 + tristate "Mitsumi MM8013 fuel gauge driver" + depends on I2C + help + Say Y here to enable the Mitsumi MM8013 fuel gauge driver. + It enables the monitoring of many battery parameters, including + the state of charge, temperature, cycle count, actual and design + capacity, etc. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index a8a9fa6de1e9..ba2c41f060be 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -111,3 +111,4 @@ obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o +obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c new file mode 100644 index 000000000000..bd8d54d6597f --- /dev/null +++ b/drivers/power/supply/mm8013.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Limited + */ +#include +#include +#include +#include + +#define REG_BATID 0x00 /* This one is very unclear */ + #define BATID_101 0x0101 /* 107kOhm */ + #define BATID_102 0x0102 /* 10kOhm */ +#define REG_TEMPERATURE 0x06 +#define REG_VOLTAGE 0x08 +#define REG_FLAGS 0x0a + #define MM8013_FLAG_OTC BIT(15) + #define MM8013_FLAG_OTD BIT(14) + #define MM8013_FLAG_BATHI BIT(13) + #define MM8013_FLAG_FC BIT(9) + #define MM8013_FLAG_CHG BIT(8) + #define MM8013_FLAG_DSG BIT(0) +#define REG_FULL_CHARGE_CAPACITY 0x0e +#define REG_AVERAGE_CURRENT 0x14 +#define REG_AVERAGE_TIME_TO_EMPTY 0x16 +#define REG_AVERAGE_TIME_TO_FULL 0x18 +#define REG_CYCLE_COUNT 0x2a +#define REG_STATE_OF_CHARGE 0x2c +#define REG_DESIGN_CAPACITY 0x3c +/* TODO: 0x62-0x68 seem to contain 'MM8013C' in a length-prefixed, non-terminated string */ + +#define DECIKELVIN_TO_DECIDEGC(t) (t - 2731) + +struct mm8013_chip { + struct i2c_client *client; + struct regmap *regmap; +}; + +static int mm8013_checkdevice(struct mm8013_chip *chip) +{ + int battery_id, ret; + u32 val; + + ret = regmap_write(chip->regmap, REG_BATID, 0x0008); + if (ret < 0) + return ret; + + regmap_read(chip->regmap, REG_BATID, &val); + if (ret < 0) + return ret; + + if (val == BATID_102) + battery_id = 2; + else if (val == BATID_101) + battery_id = 1; + else + return -EINVAL; + + dev_dbg(&chip->client->dev, "battery_id: %d\n", battery_id); + + return 0; +} + +static enum power_supply_property mm8013_battery_props[] = { + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CYCLE_COUNT, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, + POWER_SUPPLY_PROP_VOLTAGE_NOW, +}; + +static int mm8013_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct mm8013_chip *chip = psy->drv_data; + int ret = 0; + u32 regval; + + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + ret = regmap_read(chip->regmap, REG_STATE_OF_CHARGE, ®val); + if (ret < 0) + return ret; + + val->intval = regval; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val); + if (ret < 0) + return ret; + + val->intval = 1000 * regval; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + ret = regmap_read(chip->regmap, REG_DESIGN_CAPACITY, ®val); + if (ret < 0) + return ret; + + val->intval = 1000 * regval; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + ret = regmap_read(chip->regmap, REG_AVERAGE_CURRENT, ®val); + if (ret < 0) + return ret; + + val->intval = -1000 * (s16)regval; + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + ret = regmap_read(chip->regmap, REG_CYCLE_COUNT, ®val); + if (ret < 0) + return ret; + + val->intval = regval; + break; + case POWER_SUPPLY_PROP_HEALTH: + ret = regmap_read(chip->regmap, REG_FLAGS, ®val); + if (ret < 0) + return ret; + + if (regval & MM8013_FLAG_BATHI) + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else if (regval & (MM8013_FLAG_OTD | MM8013_FLAG_OTC)) + val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_PRESENT: + ret = regmap_read(chip->regmap, REG_TEMPERATURE, ®val); + if (ret < 0) + return ret; + + val->intval = ((s16)regval > 0); + break; + case POWER_SUPPLY_PROP_STATUS: + ret = regmap_read(chip->regmap, REG_FLAGS, ®val); + if (ret < 0) + return ret; + + if (regval & MM8013_FLAG_DSG) + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + else if (regval & MM8013_FLAG_CHG) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (regval & MM8013_FLAG_FC) + val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + break; + case POWER_SUPPLY_PROP_TEMP: + ret = regmap_read(chip->regmap, REG_TEMPERATURE, ®val); + if (ret < 0) + return ret; + + val->intval = DECIKELVIN_TO_DECIDEGC(regval); + break; + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + ret = regmap_read(chip->regmap, REG_AVERAGE_TIME_TO_EMPTY, ®val); + if (ret < 0) + return ret; + + /* The estimation is not yet ready */ + if (regval == U16_MAX) + return -ENODATA; + + val->intval = regval; + break; + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + ret = regmap_read(chip->regmap, REG_AVERAGE_TIME_TO_FULL, ®val); + if (ret < 0) + return ret; + + /* The estimation is not yet ready */ + if (regval == U16_MAX) + return -ENODATA; + + val->intval = regval; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + ret = regmap_read(chip->regmap, REG_VOLTAGE, ®val); + if (ret < 0) + return ret; + + val->intval = 1000 * regval; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct power_supply_desc mm8013_desc = { + .name = "mm8013", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = mm8013_battery_props, + .num_properties = ARRAY_SIZE(mm8013_battery_props), + .get_property = mm8013_get_property, +}; + +static const struct regmap_config mm8013_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .max_register = 0x68, + .use_single_read = true, + .use_single_write = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int mm8013_probe(struct i2c_client *client) +{ + struct power_supply_config psy_cfg = {}; + struct device *dev = &client->dev; + struct power_supply *psy; + struct mm8013_chip *chip; + int ret = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return dev_err_probe(dev, -EIO, + "I2C_FUNC_SMBUS_WORD_DATA not supported\n"); + + chip = devm_kzalloc(dev, sizeof(struct mm8013_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->client = client; + + chip->regmap = devm_regmap_init_i2c(client, &mm8013_regmap_config); + if (IS_ERR(chip->regmap)) + return dev_err_probe(dev, ret, "Couldn't initialize regmap\n"); + + ret = mm8013_checkdevice(chip); + if (ret) + return dev_err_probe(dev, ret, "MM8013 not found\n"); + + psy_cfg.drv_data = chip; + psy_cfg.of_node = dev->of_node; + + psy = devm_power_supply_register(dev, &mm8013_desc, &psy_cfg); + if (IS_ERR(psy)) + return PTR_ERR(psy); + + return 0; +} + +static const struct i2c_device_id mm8013_id_table[] = { + { "mm8013", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, mm8013_id_table); + +static const struct of_device_id mm8013_match_table[] = { + { .compatible = "mitsumi,mm8013" }, + {} +}; + +static struct i2c_driver mm8013_i2c_driver = { + .probe = mm8013_probe, + .id_table = mm8013_id_table, + .driver = { + .name = "mm8013", + .of_match_table = mm8013_match_table, + }, +}; +module_i2c_driver(mm8013_i2c_driver); + +MODULE_DESCRIPTION("MM8013 fuel gauge driver"); +MODULE_LICENSE("GPL"); From 58e4aacb746321d8692996f40a1dcfb9e8b34c23 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Fri, 15 Sep 2023 09:02:14 +0200 Subject: [PATCH 28/91] power: supply: Propagate of_node to child device Ensure that the dynamically created power supply device sets its ->of_node if the driver supplies one. This brings it in line with several other subsystems (see git grep 'of_node =.*parent.*of_node') and allows easier identification of the device from udev rules and similar. Before this patch: /sys/class/power_supply# ls -l bq256xx-battery/of_node ls: cannot access 'bq256xx-battery/of_node': No such file or directory # ls -l bq256xx-battery/hwmon1/of_node ls: cannot access 'bq256xx-battery/hwmon1/of_node': No such file or directory After: /sys/class/power_supply# ls -l bq256xx-battery/of_node lrwxrwxrwx 1 root root 0 May 17 09:14 bq256xx-battery/of_node -> ../../../../../../../../firmware/devicetree/base/virtio@1/i2c/bq25619@09 # ls -l bq256xx-battery/hwmon1/of_node lrwxrwxrwx 1 root root 0 May 17 09:14 bq256xx-battery/hwmon1/of_node -> ../../../../../../../../../firmware/devicetree/base/virtio@1/i2c/bq25619@09 Signed-off-by: Vincent Whitchurch Link: https://lore.kernel.org/r/20230915-power-of-v2-1-ca54c441867e@axis.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 416409e2fd6d..6e30674be366 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -1380,6 +1380,7 @@ __power_supply_register(struct device *parent, psy->drv_data = cfg->drv_data; psy->of_node = cfg->fwnode ? to_of_node(cfg->fwnode) : cfg->of_node; + dev->of_node = psy->of_node; psy->supplied_to = cfg->supplied_to; psy->num_supplicants = cfg->num_supplicants; } From 7f590e38317657123fed828d267372a3d6f93260 Mon Sep 17 00:00:00 2001 From: Nikita Travkin Date: Fri, 15 Sep 2023 10:01:18 +0500 Subject: [PATCH 29/91] dt-bindings: power: supply: Add pm8916 VM-BMS Qualcomm Voltage Mode BMS is a battery monitoring block in PM8916 PMIC. Document it's DT binding. Signed-off-by: Nikita Travkin Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230915-pm8916-bms-lbc-v3-1-f30881e951a0@trvn.ru Signed-off-by: Sebastian Reichel --- .../power/supply/qcom,pm8916-bms-vm.yaml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml new file mode 100644 index 000000000000..ad764e69ab57 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-bms-vm.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-bms-vm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Voltage Mode BMS + +maintainers: + - Nikita Travkin + +description: + Voltage Mode BMS is a hardware block found in some Qualcomm PMICs + such as pm8916. This block performs battery voltage monitoring. + +allOf: + - $ref: power-supply.yaml# + +properties: + compatible: + const: qcom,pm8916-bms-vm + + reg: + maxItems: 1 + + interrupts: + items: + - description: BMS FSM left S3 mode + - description: BMS FSM entered S2 mode + - description: OCV measured in S3 mode + - description: OCV below threshold + - description: FIFO update done + - description: BMS FSM switched state + + interrupt-names: + items: + - const: cv_leave + - const: cv_enter + - const: ocv_good + - const: ocv_thr + - const: fifo + - const: state_chg + + monitored-battery: true + + power-supplies: true + +required: + - compatible + - reg + - interrupts + - interrupt-names + - monitored-battery + +additionalProperties: false + +examples: + - | + #include + pmic { + #address-cells = <1>; + #size-cells = <0>; + + battery@4000 { + compatible = "qcom,pm8916-bms-vm"; + reg = <0x4000>; + interrupts = <0x0 0x40 0 IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 2 IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 3 IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 4 IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 5 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "cv_leave", + "cv_enter", + "ocv_good", + "ocv_thr", + "fifo", + "state_chg"; + + monitored-battery = <&battery>; + power-supplies = <&pm8916_charger>; + }; + }; From 5cee843d56072135c0d4be4a2d8a20df05155009 Mon Sep 17 00:00:00 2001 From: Nikita Travkin Date: Fri, 15 Sep 2023 10:01:19 +0500 Subject: [PATCH 30/91] dt-bindings: power: supply: Add pm8916 LBC Qualcomm Linear Battery Charger is a CC/CV charger block in PM8916 PMIC. Document it's DT binding. Signed-off-by: Nikita Travkin Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230915-pm8916-bms-lbc-v3-2-f30881e951a0@trvn.ru Signed-off-by: Sebastian Reichel --- .../power/supply/qcom,pm8916-lbc.yaml | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml diff --git a/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml new file mode 100644 index 000000000000..cdf14e5ed119 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/qcom,pm8916-lbc.yaml @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-lbc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Linear Battery Charger + +maintainers: + - Nikita Travkin + +description: + Linear Battery Charger hardware block, found in some Qualcomm PMICs + such as pm8916. Implements a simple, autonomous CC/CV charger. + +allOf: + - $ref: power-supply.yaml# + +properties: + compatible: + const: qcom,pm8916-lbc + + reg: + items: + - description: Charger + - description: Battery + - description: USB + - description: MISC + + reg-names: + items: + - const: chgr + - const: bat_if + - const: usb + - const: misc + + interrupts: + items: + - description: Battery detection + - description: Fast charging + - description: Charging failed + - description: Charging done + - description: Battery present + - description: Battery temperature OK + - description: USB coarse detection + - description: USB IN valid + - description: Charger gone + - description: Overtemperature + + interrupt-names: + items: + - const: vbat_det + - const: fast_chg + - const: chg_fail + - const: chg_done + - const: bat_pres + - const: temp_ok + - const: coarse_det + - const: usb_vbus + - const: chg_gone + - const: overtemp + + qcom,fast-charge-safe-voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 4000000 + maximum: 4775000 + description: + Maximum safe battery voltage in uV; May be pre-set by bootloader, + in which case, setting this will harmlessly fail. + + qcom,fast-charge-safe-current: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 90000 + maximum: 1440000 + description: + Maximum safe battery charge current in uA; May be pre-set by + bootloader, in which case setting this will harmlessly fail. + + monitored-battery: true + +required: + - compatible + - reg + - interrupts + - interrupt-names + - qcom,fast-charge-safe-voltage + - qcom,fast-charge-safe-current + +additionalProperties: false + +examples: + - | + #include + pmic { + #address-cells = <1>; + #size-cells = <0>; + + charger@1000 { + compatible = "qcom,pm8916-lbc"; + reg = <0x1000>, <0x1200>, <0x1300>, <0x1600>; + reg-names = "chgr", "bat_if", "usb", "misc"; + + interrupts = <0x0 0x10 0 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x10 5 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x10 6 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x10 7 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 0 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x12 1 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 0 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 1 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 2 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x13 4 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "vbat_det", + "fast_chg", + "chg_fail", + "chg_done", + "bat_pres", + "temp_ok", + "coarse_det", + "usb_vbus", + "chg_gone", + "overtemp"; + monitored-battery = <&battery>; + + qcom,fast-charge-safe-current = <900000>; + qcom,fast-charge-safe-voltage = <4300000>; + }; + }; From 098bce1838e0549228c8d426e5de72ec5594b5c4 Mon Sep 17 00:00:00 2001 From: Nikita Travkin Date: Fri, 15 Sep 2023 10:01:20 +0500 Subject: [PATCH 31/91] power: supply: Add pm8916 VM-BMS support This driver adds basic support for VM-BMS found in pm8916. VM-BMS is a very basic fuel-gauge hardware block that is, sadly, incapable of any gauging. The hardware supports measuring OCV in sleep mode, where the battery is not in use, or measuring average voltage over time when the device is active. This driver implements basic value readout from this block. Signed-off-by: Nikita Travkin Link: https://lore.kernel.org/r/20230915-pm8916-bms-lbc-v3-3-f30881e951a0@trvn.ru Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 11 + drivers/power/supply/Makefile | 1 + drivers/power/supply/pm8916_bms_vm.c | 305 +++++++++++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 drivers/power/supply/pm8916_bms_vm.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index c816dc4265df..ed5b72b06dfa 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -629,6 +629,17 @@ config CHARGER_QCOM_SMBB documentation for more detail. The base name for this driver is 'pm8941_charger'. +config BATTERY_PM8916_BMS_VM + tristate "Qualcomm PM8916 BMS-VM support" + depends on MFD_SPMI_PMIC || COMPILE_TEST + help + Say Y to add support for Voltage Mode BMS block found in some + Qualcomm PMICs such as PM8916. This hardware block provides + battery voltage monitoring for the system. + + To compile this driver as module, choose M here: the + module will be called pm8916_bms_vm. + config CHARGER_BQ2415X tristate "TI BQ2415x battery charger driver" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index ba2c41f060be..fc82f0401a69 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o obj-$(CONFIG_CHARGER_MT6360) += mt6360_charger.o obj-$(CONFIG_CHARGER_MT6370) += mt6370-charger.o obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o +obj-$(CONFIG_BATTERY_PM8916_BMS_VM) += pm8916_bms_vm.o obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o diff --git a/drivers/power/supply/pm8916_bms_vm.c b/drivers/power/supply/pm8916_bms_vm.c new file mode 100644 index 000000000000..5d0dd842509c --- /dev/null +++ b/drivers/power/supply/pm8916_bms_vm.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Nikita Travkin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PM8916_PERPH_TYPE 0x04 +#define PM8916_BMS_VM_TYPE 0x020D + +#define PM8916_SEC_ACCESS 0xD0 +#define PM8916_SEC_MAGIC 0xA5 + +#define PM8916_BMS_VM_STATUS1 0x08 +#define PM8916_BMS_VM_FSM_STATE(x) (((x) & 0b00111000) >> 3) +#define PM8916_BMS_VM_FSM_STATE_S2 0x2 + +#define PM8916_BMS_VM_MODE_CTL 0x40 +#define PM8916_BMS_VM_MODE_FORCE_S3 (BIT(0) | BIT(1)) +#define PM8916_BMS_VM_MODE_NORMAL (BIT(1) | BIT(3)) + +#define PM8916_BMS_VM_EN_CTL 0x46 +#define PM8916_BMS_ENABLED BIT(7) + +#define PM8916_BMS_VM_FIFO_LENGTH_CTL 0x47 +#define PM8916_BMS_VM_S1_SAMPLE_INTERVAL_CTL 0x55 +#define PM8916_BMS_VM_S2_SAMPLE_INTERVAL_CTL 0x56 +#define PM8916_BMS_VM_S3_S7_OCV_DATA0 0x6A +#define PM8916_BMS_VM_BMS_FIFO_REG_0_LSB 0xC0 + +/* Using only 1 fifo is broken in hardware */ +#define PM8916_BMS_VM_FIFO_COUNT 2 /* 2 .. 8 */ + +#define PM8916_BMS_VM_S1_SAMPLE_INTERVAL 10 +#define PM8916_BMS_VM_S2_SAMPLE_INTERVAL 10 + +struct pm8916_bms_vm_battery { + struct device *dev; + struct power_supply *battery; + struct power_supply_battery_info *info; + struct regmap *regmap; + unsigned int reg; + unsigned int last_ocv; + time64_t last_ocv_time; + unsigned int vbat_now; +}; + +static int pm8916_bms_vm_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct pm8916_bms_vm_battery *bat = power_supply_get_drvdata(psy); + struct power_supply_battery_info *info = bat->info; + int supplied; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + supplied = power_supply_am_i_supplied(psy); + + if (supplied < 0 && supplied != -ENODEV) + return supplied; + else if (supplied && supplied != -ENODEV) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + return 0; + + case POWER_SUPPLY_PROP_HEALTH: + if (bat->vbat_now < info->voltage_min_design_uv) + val->intval = POWER_SUPPLY_HEALTH_DEAD; + else if (bat->vbat_now > info->voltage_max_design_uv) + val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + return 0; + + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = bat->vbat_now; + return 0; + + case POWER_SUPPLY_PROP_VOLTAGE_OCV: + /* + * Hardware only reliably measures OCV when the system is off or suspended. + * We expose the last known OCV value on boot, invalidating it after 180 seconds. + */ + if (ktime_get_seconds() - bat->last_ocv_time > 180) + return -ENODATA; + + val->intval = bat->last_ocv; + return 0; + + default: + return -EINVAL; + } +} + +static enum power_supply_property pm8916_bms_vm_battery_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_OCV, + POWER_SUPPLY_PROP_HEALTH, +}; + +static irqreturn_t pm8916_bms_vm_fifo_update_done_irq(int irq, void *data) +{ + struct pm8916_bms_vm_battery *bat = data; + u16 vbat_data[PM8916_BMS_VM_FIFO_COUNT]; + int ret; + + ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_BMS_VM_BMS_FIFO_REG_0_LSB, + &vbat_data, PM8916_BMS_VM_FIFO_COUNT * 2); + if (ret) + return IRQ_HANDLED; + + /* + * The VM-BMS hardware only collects voltage data and the software + * has to process it to calculate the OCV and SoC. Hardware provides + * up to 8 averaged measurements for software to take in account. + * + * Just use the last measured value for now to report the current + * battery voltage. + */ + bat->vbat_now = vbat_data[PM8916_BMS_VM_FIFO_COUNT - 1] * 300; + + power_supply_changed(bat->battery); + + return IRQ_HANDLED; +} + +static const struct power_supply_desc pm8916_bms_vm_battery_psy_desc = { + .name = "pm8916-bms-vm", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = pm8916_bms_vm_battery_properties, + .num_properties = ARRAY_SIZE(pm8916_bms_vm_battery_properties), + .get_property = pm8916_bms_vm_battery_get_property, +}; + +static int pm8916_bms_vm_battery_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pm8916_bms_vm_battery *bat; + struct power_supply_config psy_cfg = {}; + int ret, irq; + unsigned int tmp; + + bat = devm_kzalloc(dev, sizeof(*bat), GFP_KERNEL); + if (!bat) + return -ENOMEM; + + bat->dev = dev; + + bat->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!bat->regmap) + return -ENODEV; + + ret = device_property_read_u32(dev, "reg", &bat->reg); + if (ret < 0) + return -EINVAL; + + irq = platform_get_irq_byname(pdev, "fifo"); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq, + IRQF_ONESHOT, "pm8916_vm_bms", bat); + if (ret) + return ret; + + ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_PERPH_TYPE, &tmp, 2); + if (ret) + goto comm_error; + + if (tmp != PM8916_BMS_VM_TYPE) + return dev_err_probe(dev, -ENODEV, "Device reported wrong type: 0x%X\n", tmp); + + ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_S1_SAMPLE_INTERVAL_CTL, + PM8916_BMS_VM_S1_SAMPLE_INTERVAL); + if (ret) + goto comm_error; + ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_S2_SAMPLE_INTERVAL_CTL, + PM8916_BMS_VM_S2_SAMPLE_INTERVAL); + if (ret) + goto comm_error; + ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_FIFO_LENGTH_CTL, + PM8916_BMS_VM_FIFO_COUNT << 4 | PM8916_BMS_VM_FIFO_COUNT); + if (ret) + goto comm_error; + ret = regmap_write(bat->regmap, + bat->reg + PM8916_BMS_VM_EN_CTL, PM8916_BMS_ENABLED); + if (ret) + goto comm_error; + + ret = regmap_bulk_read(bat->regmap, + bat->reg + PM8916_BMS_VM_S3_S7_OCV_DATA0, &tmp, 2); + if (ret) + goto comm_error; + + bat->last_ocv_time = ktime_get_seconds(); + bat->last_ocv = tmp * 300; + bat->vbat_now = bat->last_ocv; + + psy_cfg.drv_data = bat; + psy_cfg.of_node = dev->of_node; + + bat->battery = devm_power_supply_register(dev, &pm8916_bms_vm_battery_psy_desc, &psy_cfg); + if (IS_ERR(bat->battery)) + return dev_err_probe(dev, PTR_ERR(bat->battery), "Unable to register battery\n"); + + ret = power_supply_get_battery_info(bat->battery, &bat->info); + if (ret) + return dev_err_probe(dev, ret, "Unable to get battery info\n"); + + platform_set_drvdata(pdev, bat); + + return 0; + +comm_error: + return dev_err_probe(dev, ret, "Unable to communicate with device\n"); +} + +static int pm8916_bms_vm_battery_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pm8916_bms_vm_battery *bat = platform_get_drvdata(pdev); + int ret; + + /* + * Due to a hardware quirk the FSM doesn't switch states normally. + * Instead we unlock the debug registers and force S3 (Measure OCV/Sleep) + * mode every time we suspend. + */ + + ret = regmap_write(bat->regmap, + bat->reg + PM8916_SEC_ACCESS, PM8916_SEC_MAGIC); + if (ret) + goto error; + ret = regmap_write(bat->regmap, + bat->reg + PM8916_BMS_VM_MODE_CTL, PM8916_BMS_VM_MODE_FORCE_S3); + if (ret) + goto error; + + return 0; + +error: + dev_err(bat->dev, "Failed to force S3 mode: %pe\n", ERR_PTR(ret)); + return ret; +} + +static int pm8916_bms_vm_battery_resume(struct platform_device *pdev) +{ + struct pm8916_bms_vm_battery *bat = platform_get_drvdata(pdev); + int ret; + unsigned int tmp; + + ret = regmap_bulk_read(bat->regmap, + bat->reg + PM8916_BMS_VM_S3_S7_OCV_DATA0, &tmp, 2); + + bat->last_ocv_time = ktime_get_seconds(); + bat->last_ocv = tmp * 300; + + ret = regmap_write(bat->regmap, + bat->reg + PM8916_SEC_ACCESS, PM8916_SEC_MAGIC); + if (ret) + goto error; + ret = regmap_write(bat->regmap, + bat->reg + PM8916_BMS_VM_MODE_CTL, PM8916_BMS_VM_MODE_NORMAL); + if (ret) + goto error; + + return 0; + +error: + dev_err(bat->dev, "Failed to return normal mode: %pe\n", ERR_PTR(ret)); + return ret; +} + +static const struct of_device_id pm8916_bms_vm_battery_of_match[] = { + { .compatible = "qcom,pm8916-bms-vm", }, + {} +}; +MODULE_DEVICE_TABLE(of, pm8916_bms_vm_battery_of_match); + +static struct platform_driver pm8916_bms_vm_battery_driver = { + .driver = { + .name = "pm8916-bms-vm", + .of_match_table = pm8916_bms_vm_battery_of_match, + }, + .probe = pm8916_bms_vm_battery_probe, + .suspend = pm8916_bms_vm_battery_suspend, + .resume = pm8916_bms_vm_battery_resume, +}; +module_platform_driver(pm8916_bms_vm_battery_driver); + +MODULE_DESCRIPTION("pm8916 BMS-VM driver"); +MODULE_AUTHOR("Nikita Travkin "); +MODULE_LICENSE("GPL"); From f8d7a3d21160a0cab4d15b81231f2a76b0fcee13 Mon Sep 17 00:00:00 2001 From: Nikita Travkin Date: Fri, 15 Sep 2023 10:01:21 +0500 Subject: [PATCH 32/91] power: supply: Add driver for pm8916 lbc pm8916 LBC is a Linear Battery Charger hardware block in pm8916 PMIC. This block implements simple CC/CV charging for Li-Po batteries. The hardware has internal state machine to switch between modes and works mostly autonomously, only needing the limits and targets to be set to operate. This driver allows setting limits and enabling the LBC block, monitoring it's state. Signed-off-by: Nikita Travkin Link: https://lore.kernel.org/r/20230915-pm8916-bms-lbc-v3-4-f30881e951a0@trvn.ru Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 11 + drivers/power/supply/Makefile | 1 + drivers/power/supply/pm8916_lbc.c | 381 ++++++++++++++++++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 drivers/power/supply/pm8916_lbc.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index ed5b72b06dfa..4bfd5a336163 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -640,6 +640,17 @@ config BATTERY_PM8916_BMS_VM To compile this driver as module, choose M here: the module will be called pm8916_bms_vm. +config CHARGER_PM8916_LBC + tristate "Qualcomm PM8916 Linear Battery Charger support" + depends on MFD_SPMI_PMIC || COMPILE_TEST + help + Say Y here to add support for Linear Battery Charger block + found in some Qualcomm PMICs such as PM8916. This hardware + blokc provides simple CC/CV battery charger. + + To compile this driver as module, choose M here: the + module will be called pm8916_lbc. + config CHARGER_BQ2415X tristate "TI BQ2415x battery charger driver" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index fc82f0401a69..58b567278034 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_CHARGER_MT6360) += mt6360_charger.o obj-$(CONFIG_CHARGER_MT6370) += mt6370-charger.o obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o obj-$(CONFIG_BATTERY_PM8916_BMS_VM) += pm8916_bms_vm.o +obj-$(CONFIG_CHARGER_PM8916_LBC) += pm8916_lbc.o obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o diff --git a/drivers/power/supply/pm8916_lbc.c b/drivers/power/supply/pm8916_lbc.c new file mode 100644 index 000000000000..6d92e98cbecc --- /dev/null +++ b/drivers/power/supply/pm8916_lbc.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Nikita Travkin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Two bytes: type + subtype */ +#define PM8916_PERPH_TYPE 0x04 +#define PM8916_LBC_CHGR_TYPE 0x1502 +#define PM8916_LBC_BAT_IF_TYPE 0x1602 +#define PM8916_LBC_USB_TYPE 0x1702 +#define PM8916_LBC_MISC_TYPE 0x1802 + +#define PM8916_LBC_CHGR_CHG_OPTION 0x08 +#define PM8916_LBC_CHGR_PMIC_CHARGER BIT(7) + +#define PM8916_LBC_CHGR_CHG_STATUS 0x09 + +#define PM8916_INT_RT_STS 0x10 + +#define PM8916_LBC_USB_USBIN_VALID BIT(1) + +#define PM8916_LBC_CHGR_VDD_MAX 0x40 +#define PM8916_LBC_CHGR_VDD_SAFE 0x41 +#define PM8916_LBC_CHGR_IBAT_MAX 0x44 +#define PM8916_LBC_CHGR_IBAT_SAFE 0x45 + +#define PM8916_LBC_CHGR_TCHG_MAX_EN 0x60 +#define PM8916_LBC_CHGR_TCHG_MAX_ENABLED BIT(7) +#define PM8916_LBC_CHGR_TCHG_MAX 0x61 + +#define PM8916_LBC_CHGR_CHG_CTRL 0x49 +#define PM8916_LBC_CHGR_CHG_EN BIT(7) +#define PM8916_LBC_CHGR_PSTG_EN BIT(5) + +#define PM8916_LBC_CHGR_MIN_CURRENT 90000 +#define PM8916_LBC_CHGR_MAX_CURRENT 1440000 + +#define PM8916_LBC_CHGR_MIN_VOLTAGE 4000000 +#define PM8916_LBC_CHGR_MAX_VOLTAGE 4775000 +#define PM8916_LBC_CHGR_VOLTAGE_STEP 25000 + +#define PM8916_LBC_CHGR_MIN_TIME 4 +#define PM8916_LBC_CHGR_MAX_TIME 256 + +struct pm8916_lbc_charger { + struct device *dev; + struct extcon_dev *edev; + struct power_supply *charger; + struct power_supply_battery_info *info; + struct regmap *regmap; + unsigned int reg[4]; + bool online; + unsigned int charge_voltage_max; + unsigned int charge_voltage_safe; + unsigned int charge_current_max; + unsigned int charge_current_safe; +}; + +static const unsigned int pm8916_lbc_charger_cable[] = { + EXTCON_USB, + EXTCON_NONE, +}; + +enum { + LBC_CHGR = 0, + LBC_BAT_IF, + LBC_USB, + LBC_MISC, +}; + +static int pm8916_lbc_charger_configure(struct pm8916_lbc_charger *chg) +{ + int ret = 0; + unsigned int tmp; + + chg->charge_voltage_max = clamp_t(u32, chg->charge_voltage_max, + PM8916_LBC_CHGR_MIN_VOLTAGE, chg->charge_voltage_safe); + + tmp = chg->charge_voltage_max - PM8916_LBC_CHGR_MIN_VOLTAGE; + tmp /= PM8916_LBC_CHGR_VOLTAGE_STEP; + chg->charge_voltage_max = PM8916_LBC_CHGR_MIN_VOLTAGE + tmp * PM8916_LBC_CHGR_VOLTAGE_STEP; + + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, tmp); + if (ret) + goto error; + + chg->charge_current_max = min(chg->charge_current_max, chg->charge_current_safe); + + tmp = clamp_t(u32, chg->charge_current_max, + PM8916_LBC_CHGR_MIN_CURRENT, PM8916_LBC_CHGR_MAX_CURRENT); + + tmp = chg->charge_current_max / PM8916_LBC_CHGR_MIN_CURRENT - 1; + chg->charge_current_max = (tmp + 1) * PM8916_LBC_CHGR_MIN_CURRENT; + + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_MAX, tmp); + if (ret) + goto error; + + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_CTRL, + PM8916_LBC_CHGR_CHG_EN | PM8916_LBC_CHGR_PSTG_EN); + if (ret) + goto error; + + return ret; + +error: + dev_err(chg->dev, "Failed to configure charging: %pe\n", ERR_PTR(ret)); + return ret; +} + +static int pm8916_lbc_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct pm8916_lbc_charger *chg = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = chg->online; + return 0; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: + val->intval = chg->charge_voltage_max; + return 0; + + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + val->intval = chg->charge_current_max; + return 0; + + default: + return -EINVAL; + }; +} + +static int pm8916_lbc_charger_set_property(struct power_supply *psy, + enum power_supply_property prop, + const union power_supply_propval *val) +{ + struct pm8916_lbc_charger *chg = power_supply_get_drvdata(psy); + + switch (prop) { + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + chg->charge_current_max = val->intval; + return pm8916_lbc_charger_configure(chg); + default: + return -EINVAL; + } +} + +static int pm8916_lbc_charger_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + return true; + default: + return false; + } +} + +static enum power_supply_property pm8916_lbc_charger_properties[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, +}; + +static irqreturn_t pm8916_lbc_charger_state_changed_irq(int irq, void *data) +{ + struct pm8916_lbc_charger *chg = data; + unsigned int tmp; + int ret; + + ret = regmap_read(chg->regmap, chg->reg[LBC_USB] + PM8916_INT_RT_STS, &tmp); + if (ret) + return IRQ_HANDLED; + + chg->online = !!(tmp & PM8916_LBC_USB_USBIN_VALID); + extcon_set_state_sync(chg->edev, EXTCON_USB, chg->online); + + power_supply_changed(chg->charger); + + return IRQ_HANDLED; +} + +static int pm8916_lbc_charger_probe_dt(struct pm8916_lbc_charger *chg) +{ + struct device *dev = chg->dev; + int ret = 0; + unsigned int tmp; + + ret = device_property_read_u32(dev, "qcom,fast-charge-safe-voltage", &chg->charge_voltage_safe); + if (ret) + return ret; + if (chg->charge_voltage_safe < PM8916_LBC_CHGR_MIN_VOLTAGE) + return -EINVAL; + + chg->charge_voltage_safe = clamp_t(u32, chg->charge_voltage_safe, + PM8916_LBC_CHGR_MIN_VOLTAGE, PM8916_LBC_CHGR_MAX_VOLTAGE); + + tmp = chg->charge_voltage_safe - PM8916_LBC_CHGR_MIN_VOLTAGE; + tmp /= PM8916_LBC_CHGR_VOLTAGE_STEP; + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_SAFE, tmp); + if (ret) + return ret; + + ret = device_property_read_u32(dev, "qcom,fast-charge-safe-current", &chg->charge_current_safe); + if (ret) + return ret; + if (chg->charge_current_safe < PM8916_LBC_CHGR_MIN_CURRENT) + return -EINVAL; + + chg->charge_current_safe = clamp_t(u32, chg->charge_current_safe, + PM8916_LBC_CHGR_MIN_CURRENT, PM8916_LBC_CHGR_MAX_CURRENT); + + chg->charge_current_max = chg->charge_current_safe; + + tmp = chg->charge_current_safe / PM8916_LBC_CHGR_MIN_CURRENT - 1; + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_SAFE, tmp); + if (ret) + return ret; + + /* Disable charger timeout. */ + ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_TCHG_MAX_EN, 0x00); + if (ret) + return ret; + + return ret; +} + +static const struct power_supply_desc pm8916_lbc_charger_psy_desc = { + .name = "pm8916-lbc-chgr", + .type = POWER_SUPPLY_TYPE_USB, + .properties = pm8916_lbc_charger_properties, + .num_properties = ARRAY_SIZE(pm8916_lbc_charger_properties), + .get_property = pm8916_lbc_charger_get_property, + .set_property = pm8916_lbc_charger_set_property, + .property_is_writeable = pm8916_lbc_charger_property_is_writeable, +}; + +static int pm8916_lbc_charger_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pm8916_lbc_charger *chg; + struct power_supply_config psy_cfg = {}; + int ret, len, irq; + unsigned int tmp; + + chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); + if (!chg) + return -ENOMEM; + + chg->dev = dev; + + chg->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!chg->regmap) + return -ENODEV; + + len = device_property_count_u32(dev, "reg"); + if (len < 0) + return len; + if (len != 4) + return dev_err_probe(dev, -EINVAL, + "Wrong amount of reg values: %d (4 expected)\n", len); + + irq = platform_get_irq_byname(pdev, "usb_vbus"); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq, + IRQF_ONESHOT, "pm8916_lbc", chg); + if (ret) + return ret; + + ret = device_property_read_u32_array(dev, "reg", chg->reg, len); + if (ret) + return ret; + + ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_PERPH_TYPE, &tmp, 2); + if (ret) + goto comm_error; + if (tmp != PM8916_LBC_CHGR_TYPE) + goto type_error; + + ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_BAT_IF] + PM8916_PERPH_TYPE, &tmp, 2); + if (ret) + goto comm_error; + if (tmp != PM8916_LBC_BAT_IF_TYPE) + goto type_error; + + ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_USB] + PM8916_PERPH_TYPE, &tmp, 2); + if (ret) + goto comm_error; + if (tmp != PM8916_LBC_USB_TYPE) + goto type_error; + + ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_MISC] + PM8916_PERPH_TYPE, &tmp, 2); + if (ret) + goto comm_error; + if (tmp != PM8916_LBC_MISC_TYPE) + goto type_error; + + ret = regmap_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_OPTION, &tmp); + if (ret) + goto comm_error; + if (tmp != PM8916_LBC_CHGR_PMIC_CHARGER) + dev_err_probe(dev, -ENODEV, "The system is using an external charger\n"); + + ret = pm8916_lbc_charger_probe_dt(chg); + if (ret) + dev_err_probe(dev, ret, "Error while parsing device tree\n"); + + psy_cfg.drv_data = chg; + psy_cfg.of_node = dev->of_node; + + chg->charger = devm_power_supply_register(dev, &pm8916_lbc_charger_psy_desc, &psy_cfg); + if (IS_ERR(chg->charger)) + return dev_err_probe(dev, PTR_ERR(chg->charger), "Unable to register charger\n"); + + ret = power_supply_get_battery_info(chg->charger, &chg->info); + if (ret) + return dev_err_probe(dev, ret, "Unable to get battery info\n"); + + chg->edev = devm_extcon_dev_allocate(dev, pm8916_lbc_charger_cable); + if (IS_ERR(chg->edev)) + return PTR_ERR(chg->edev); + + ret = devm_extcon_dev_register(dev, chg->edev); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to register extcon device\n"); + + ret = regmap_read(chg->regmap, chg->reg[LBC_USB] + PM8916_INT_RT_STS, &tmp); + if (ret) + goto comm_error; + + chg->online = !!(tmp & PM8916_LBC_USB_USBIN_VALID); + extcon_set_state_sync(chg->edev, EXTCON_USB, chg->online); + + chg->charge_voltage_max = chg->info->voltage_max_design_uv; + ret = pm8916_lbc_charger_configure(chg); + if (ret) + return ret; + + return 0; + +comm_error: + return dev_err_probe(dev, ret, "Unable to communicate with device\n"); + +type_error: + return dev_err_probe(dev, -ENODEV, "Device reported wrong type: 0x%X\n", tmp); +} + +static const struct of_device_id pm8916_lbc_charger_of_match[] = { + { .compatible = "qcom,pm8916-lbc", }, + {} +}; +MODULE_DEVICE_TABLE(of, pm8916_lbc_charger_of_match); + +static struct platform_driver pm8916_lbc_charger_driver = { + .driver = { + .name = "pm8916-lbc", + .of_match_table = pm8916_lbc_charger_of_match, + }, + .probe = pm8916_lbc_charger_probe, +}; +module_platform_driver(pm8916_lbc_charger_driver); + +MODULE_DESCRIPTION("pm8916 LBC driver"); +MODULE_AUTHOR("Nikita Travkin "); +MODULE_LICENSE("GPL"); From e39257cde7e8ceec6165f54b6e20c72e2862a0b1 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 16 Sep 2023 02:31:59 +0200 Subject: [PATCH 33/91] power: supply: mm8013: Add more properties While scanning the internet for MM8013 PDFs, I found one for a different IC from Mitsumi, MM8118 at [1]. It turned out however, that when you search through the PDF, the MM8118 text has an invsible text layer containing "MM8013" underneath.. With some elbow grease, I was able to confirm that most of the registers match between the two ICs. Based on that finding, introduce live battery voltage readout, hw-decided charge behavior readout and max current readout. Also, expand the existing POWER_SUPPLY_HEALTH reporting. [1] https://product.minebeamitsumi.com/en/product/category/ics/battery/fuel_gauge/parts/download/__icsFiles/afieldfile/2023/07/12/1_download_01_12.pdf Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230916-topic-mm8013_2-v1-1-02495e07fca0@linaro.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/mm8013.c | 45 +++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c index bd8d54d6597f..ddac40ef9ae5 100644 --- a/drivers/power/supply/mm8013.c +++ b/drivers/power/supply/mm8013.c @@ -17,13 +17,21 @@ #define MM8013_FLAG_OTC BIT(15) #define MM8013_FLAG_OTD BIT(14) #define MM8013_FLAG_BATHI BIT(13) + #define MM8013_FLAG_BATLOW BIT(12) + #define MM8013_FLAG_CHG_INH BIT(11) #define MM8013_FLAG_FC BIT(9) #define MM8013_FLAG_CHG BIT(8) + #define MM8013_FLAG_OCC BIT(6) + #define MM8013_FLAG_ODC BIT(5) + #define MM8013_FLAG_OT BIT(4) + #define MM8013_FLAG_UT BIT(3) #define MM8013_FLAG_DSG BIT(0) #define REG_FULL_CHARGE_CAPACITY 0x0e +#define REG_NOMINAL_CHARGE_CAPACITY 0x0c #define REG_AVERAGE_CURRENT 0x14 #define REG_AVERAGE_TIME_TO_EMPTY 0x16 #define REG_AVERAGE_TIME_TO_FULL 0x18 +#define REG_MAX_LOAD_CURRENT 0x1e #define REG_CYCLE_COUNT 0x2a #define REG_STATE_OF_CHARGE 0x2c #define REG_DESIGN_CAPACITY 0x3c @@ -63,8 +71,11 @@ static int mm8013_checkdevice(struct mm8013_chip *chip) static enum power_supply_property mm8013_battery_props[] = { POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_HEALTH, @@ -92,6 +103,16 @@ static int mm8013_get_property(struct power_supply *psy, val->intval = regval; break; + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: + ret = regmap_read(chip->regmap, REG_FLAGS, ®val); + if (ret < 0) + return ret; + + if (regval & MM8013_FLAG_CHG_INH) + val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; + else + val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO; + break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val); if (ret < 0) @@ -106,6 +127,20 @@ static int mm8013_get_property(struct power_supply *psy, val->intval = 1000 * regval; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = regmap_read(chip->regmap, REG_NOMINAL_CHARGE_CAPACITY, ®val); + if (ret < 0) + return ret; + + val->intval = 1000 * regval; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + ret = regmap_read(chip->regmap, REG_MAX_LOAD_CURRENT, ®val); + if (ret < 0) + return ret; + + val->intval = -1000 * (s16)regval; + break; case POWER_SUPPLY_PROP_CURRENT_NOW: ret = regmap_read(chip->regmap, REG_AVERAGE_CURRENT, ®val); if (ret < 0) @@ -125,9 +160,15 @@ static int mm8013_get_property(struct power_supply *psy, if (ret < 0) return ret; - if (regval & MM8013_FLAG_BATHI) + if (regval & MM8013_FLAG_UT) + val->intval = POWER_SUPPLY_HEALTH_COLD; + else if (regval & (MM8013_FLAG_ODC | MM8013_FLAG_OCC)) + val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT; + else if (regval & (MM8013_FLAG_BATLOW)) + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + else if (regval & MM8013_FLAG_BATHI) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - else if (regval & (MM8013_FLAG_OTD | MM8013_FLAG_OTC)) + else if (regval & (MM8013_FLAG_OT | MM8013_FLAG_OTD | MM8013_FLAG_OTC)) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; else val->intval = POWER_SUPPLY_HEALTH_GOOD; From 12e94aee074ce1c5ffdb8f2246a8c4a095b6aa8a Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 13 Sep 2023 15:39:00 +0200 Subject: [PATCH 34/91] power: supply: core: Don't export power_supply_notifier power_supply_notifier can be internal, since all users are going through power_supply_reg_notifier()/power_supply_unreg_notifier(). Link: https://lore.kernel.org/r/20230913133900.591637-1-sebastian.reichel@collabora.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_core.c | 3 +-- include/linux/power_supply.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 6e30674be366..73265001dd4b 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -29,8 +29,7 @@ struct class *power_supply_class; EXPORT_SYMBOL_GPL(power_supply_class); -BLOCKING_NOTIFIER_HEAD(power_supply_notifier); -EXPORT_SYMBOL_GPL(power_supply_notifier); +static BLOCKING_NOTIFIER_HEAD(power_supply_notifier); static struct device_type power_supply_dev_type; diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 85b86768c0b9..c0992a77feea 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -767,7 +767,6 @@ struct power_supply_battery_info { int bti_resistance_tolerance; }; -extern struct blocking_notifier_head power_supply_notifier; extern int power_supply_reg_notifier(struct notifier_block *nb); extern void power_supply_unreg_notifier(struct notifier_block *nb); #if IS_ENABLED(CONFIG_POWER_SUPPLY) From f392f3796bba1a160b8ad706bfe1e1ec3581ad48 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Sep 2023 21:01:24 +0200 Subject: [PATCH 35/91] dt-bindings: power: supply: Drop deprecated ab8500-battery Linus Walleij modified AB8500 to use the generic simple-battery and samsung,battery bindings. This is an unused leftover that can be removed. Reviewed-by: Linus Walleij Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230917190124.1012316-1-sebastian.reichel@collabora.com Signed-off-by: Sebastian Reichel --- .../supply/stericsson,ab8500-battery.txt | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt diff --git a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt b/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt deleted file mode 100644 index ee125cb0e46d..000000000000 --- a/Documentation/devicetree/bindings/power/supply/stericsson,ab8500-battery.txt +++ /dev/null @@ -1,34 +0,0 @@ -AB85000 PMIC contains a node, which contains shared -information about the battery connected to the PMIC. -The node has no compatible property. - -Properties of this node are: - -thermistor-on-batctrl: - A boolean value indicating thermistor interface to battery - - Note: - 'btemp' and 'batctrl' are the pins interfaced for battery temperature - measurement, 'btemp' signal is used when NTC(negative temperature - coefficient) resister is interfaced external to battery whereas - 'batctrl' pin is used when NTC resister is internal to battery. - - Example: - ab8500_battery: ab8500_battery { - thermistor-on-batctrl; - }; - indicates: NTC resister is internal to battery, 'batctrl' is used - for thermal measurement. - - The absence of property 'thermal-on-batctrl' indicates - NTC resister is external to battery and 'btemp' signal is used - for thermal measurement. - -battery-type: - This shall be the battery manufacturing technology type, - allowed types are: - "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn" - Example: - ab8500_battery: ab8500_battery { - stericsson,battery-type = "LIPO"; - } From dab952c77e5a0bad3a391b8cbb6995f32c9a7b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:29 +0200 Subject: [PATCH 36/91] power: supply: ab8500_btemp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-2-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_btemp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 6f83e99d2eb7..274e86d0b59e 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -811,11 +811,9 @@ static int ab8500_btemp_probe(struct platform_device *pdev) return component_add(dev, &ab8500_btemp_component_ops); } -static int ab8500_btemp_remove(struct platform_device *pdev) +static void ab8500_btemp_remove(struct platform_device *pdev) { component_del(&pdev->dev, &ab8500_btemp_component_ops); - - return 0; } static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); @@ -828,7 +826,7 @@ MODULE_DEVICE_TABLE(of, ab8500_btemp_match); struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, - .remove = ab8500_btemp_remove, + .remove_new = ab8500_btemp_remove, .driver = { .name = "ab8500-btemp", .of_match_table = ab8500_btemp_match, From 465ec888880be0f3170b97a0e975bcb1e9b6961b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:30 +0200 Subject: [PATCH 37/91] power: supply: ab8500_chargalg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-3-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_chargalg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c index ea4ad61d4c7e..cc5d91444422 100644 --- a/drivers/power/supply/ab8500_chargalg.c +++ b/drivers/power/supply/ab8500_chargalg.c @@ -1824,11 +1824,9 @@ static int ab8500_chargalg_probe(struct platform_device *pdev) return component_add(dev, &ab8500_chargalg_component_ops); } -static int ab8500_chargalg_remove(struct platform_device *pdev) +static void ab8500_chargalg_remove(struct platform_device *pdev) { component_del(&pdev->dev, &ab8500_chargalg_component_ops); - - return 0; } static SIMPLE_DEV_PM_OPS(ab8500_chargalg_pm_ops, ab8500_chargalg_suspend, ab8500_chargalg_resume); @@ -1840,7 +1838,7 @@ static const struct of_device_id ab8500_chargalg_match[] = { struct platform_driver ab8500_chargalg_driver = { .probe = ab8500_chargalg_probe, - .remove = ab8500_chargalg_remove, + .remove_new = ab8500_chargalg_remove, .driver = { .name = "ab8500_chargalg", .of_match_table = ab8500_chargalg_match, From c5b08e1bfe087c42e43e64f308b16c6f79444dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:31 +0200 Subject: [PATCH 38/91] power: supply: ab8500_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-4-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index 308e68545d44..d72f32c663bc 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3679,7 +3679,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) return ret; } -static int ab8500_charger_remove(struct platform_device *pdev) +static void ab8500_charger_remove(struct platform_device *pdev) { struct ab8500_charger *di = platform_get_drvdata(pdev); @@ -3688,8 +3688,6 @@ static int ab8500_charger_remove(struct platform_device *pdev) usb_unregister_notifier(di->usb_phy, &di->nb); ab8500_bm_of_remove(di->usb_chg.psy, di->bm); usb_put_phy(di->usb_phy); - - return 0; } static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); @@ -3702,7 +3700,7 @@ MODULE_DEVICE_TABLE(of, ab8500_charger_match); static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, - .remove = ab8500_charger_remove, + .remove_new = ab8500_charger_remove, .driver = { .name = "ab8500-charger", .of_match_table = ab8500_charger_match, From 59016f4c0e106ec9ba3ac039bf7e96a474648ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:32 +0200 Subject: [PATCH 39/91] power: supply: ab8500_fg: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-5-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_fg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 53560fbb6dcd..8c593fbdd45a 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -3227,7 +3227,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) return component_add(dev, &ab8500_fg_component_ops); } -static int ab8500_fg_remove(struct platform_device *pdev) +static void ab8500_fg_remove(struct platform_device *pdev) { struct ab8500_fg *di = platform_get_drvdata(pdev); @@ -3236,8 +3236,6 @@ static int ab8500_fg_remove(struct platform_device *pdev) list_del(&di->node); ab8500_fg_sysfs_exit(di); ab8500_fg_sysfs_psy_remove_attrs(di); - - return 0; } static SIMPLE_DEV_PM_OPS(ab8500_fg_pm_ops, ab8500_fg_suspend, ab8500_fg_resume); @@ -3250,7 +3248,7 @@ MODULE_DEVICE_TABLE(of, ab8500_fg_match); struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, - .remove = ab8500_fg_remove, + .remove_new = ab8500_fg_remove, .driver = { .name = "ab8500-fg", .of_match_table = ab8500_fg_match, From 179297b95198526fbef8f6b92f1b486502144861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:33 +0200 Subject: [PATCH 40/91] power: supply: acer_a500_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-6-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/acer_a500_battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/acer_a500_battery.c b/drivers/power/supply/acer_a500_battery.c index 32a0bfcac08f..ef5c419b1b7f 100644 --- a/drivers/power/supply/acer_a500_battery.c +++ b/drivers/power/supply/acer_a500_battery.c @@ -251,13 +251,11 @@ static int a500_battery_probe(struct platform_device *pdev) return 0; } -static int a500_battery_remove(struct platform_device *pdev) +static void a500_battery_remove(struct platform_device *pdev) { struct a500_battery *bat = dev_get_drvdata(&pdev->dev); cancel_delayed_work_sync(&bat->poll_work); - - return 0; } static int __maybe_unused a500_battery_suspend(struct device *dev) @@ -287,7 +285,7 @@ static struct platform_driver a500_battery_driver = { .pm = &a500_battery_pm_ops, }, .probe = a500_battery_probe, - .remove = a500_battery_remove, + .remove_new = a500_battery_remove, }; module_platform_driver(a500_battery_driver); From 7a9a4966777b8df6e6f97f82073f4736a5274358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:34 +0200 Subject: [PATCH 41/91] power: supply: act8945a_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-7-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/act8945a_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply/act8945a_charger.c index e9b5f4283772..51122bfbf196 100644 --- a/drivers/power/supply/act8945a_charger.c +++ b/drivers/power/supply/act8945a_charger.c @@ -638,14 +638,12 @@ static int act8945a_charger_probe(struct platform_device *pdev) return 0; } -static int act8945a_charger_remove(struct platform_device *pdev) +static void act8945a_charger_remove(struct platform_device *pdev) { struct act8945a_charger *charger = platform_get_drvdata(pdev); charger->init_done = false; cancel_work_sync(&charger->work); - - return 0; } static struct platform_driver act8945a_charger_driver = { @@ -653,7 +651,7 @@ static struct platform_driver act8945a_charger_driver = { .name = "act8945a-charger", }, .probe = act8945a_charger_probe, - .remove = act8945a_charger_remove, + .remove_new = act8945a_charger_remove, }; module_platform_driver(act8945a_charger_driver); From 403eebf95c38302cacc48c127e575461f0e798be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:35 +0200 Subject: [PATCH 42/91] power: supply: charger-manager: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-8-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/charger-manager.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index 5fa6ba7f41e1..3936ff066600 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1628,7 +1628,7 @@ static int charger_manager_probe(struct platform_device *pdev) return ret; } -static int charger_manager_remove(struct platform_device *pdev) +static void charger_manager_remove(struct platform_device *pdev) { struct charger_manager *cm = platform_get_drvdata(pdev); struct charger_desc *desc = cm->desc; @@ -1648,8 +1648,6 @@ static int charger_manager_remove(struct platform_device *pdev) power_supply_unregister(cm->charger_psy); try_charger_enable(cm, false); - - return 0; } static const struct platform_device_id charger_manager_id[] = { @@ -1740,7 +1738,7 @@ static struct platform_driver charger_manager_driver = { .of_match_table = charger_manager_match, }, .probe = charger_manager_probe, - .remove = charger_manager_remove, + .remove_new = charger_manager_remove, .id_table = charger_manager_id, }; From 02fecba679bbac3b16c2245e8e462b19fb36cedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:36 +0200 Subject: [PATCH 43/91] power: supply: cpcap-battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-9-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index 5dd76c0ac98d..30ec76cdf34b 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -1151,7 +1151,7 @@ static int cpcap_battery_probe(struct platform_device *pdev) return 0; } -static int cpcap_battery_remove(struct platform_device *pdev) +static void cpcap_battery_remove(struct platform_device *pdev) { struct cpcap_battery_ddata *ddata = platform_get_drvdata(pdev); int error; @@ -1161,8 +1161,6 @@ static int cpcap_battery_remove(struct platform_device *pdev) 0xffff, 0); if (error) dev_err(&pdev->dev, "could not disable: %i\n", error); - - return 0; } static struct platform_driver cpcap_battery_driver = { @@ -1171,7 +1169,7 @@ static struct platform_driver cpcap_battery_driver = { .of_match_table = of_match_ptr(cpcap_battery_id_table), }, .probe = cpcap_battery_probe, - .remove = cpcap_battery_remove, + .remove_new = cpcap_battery_remove, }; module_platform_driver(cpcap_battery_driver); From 1abbcff9f0c087e88ae542e0d6b0ee0689881027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:37 +0200 Subject: [PATCH 44/91] power: supply: cpcap-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-10-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index be9764541d52..431e951cccf0 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -966,11 +966,9 @@ static void cpcap_charger_shutdown(struct platform_device *pdev) cancel_delayed_work_sync(&ddata->detect_work); } -static int cpcap_charger_remove(struct platform_device *pdev) +static void cpcap_charger_remove(struct platform_device *pdev) { cpcap_charger_shutdown(pdev); - - return 0; } static struct platform_driver cpcap_charger_driver = { @@ -980,7 +978,7 @@ static struct platform_driver cpcap_charger_driver = { .of_match_table = of_match_ptr(cpcap_charger_id_table), }, .shutdown = cpcap_charger_shutdown, - .remove = cpcap_charger_remove, + .remove_new = cpcap_charger_remove, }; module_platform_driver(cpcap_charger_driver); From b5ba26ab7a886567759b793161cdd0aae4a76910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:38 +0200 Subject: [PATCH 45/91] power: supply: da9030_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-11-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/da9030_battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/da9030_battery.c b/drivers/power/supply/da9030_battery.c index 0deba48d22d3..581cf956d2d2 100644 --- a/drivers/power/supply/da9030_battery.c +++ b/drivers/power/supply/da9030_battery.c @@ -552,7 +552,7 @@ static int da9030_battery_probe(struct platform_device *pdev) return ret; } -static int da9030_battery_remove(struct platform_device *dev) +static void da9030_battery_remove(struct platform_device *dev) { struct da9030_charger *charger = platform_get_drvdata(dev); @@ -564,8 +564,6 @@ static int da9030_battery_remove(struct platform_device *dev) cancel_delayed_work_sync(&charger->work); da9030_set_charge(charger, 0); power_supply_unregister(charger->psy); - - return 0; } static struct platform_driver da903x_battery_driver = { @@ -573,7 +571,7 @@ static struct platform_driver da903x_battery_driver = { .name = "da903x-battery", }, .probe = da9030_battery_probe, - .remove = da9030_battery_remove, + .remove_new = da9030_battery_remove, }; module_platform_driver(da903x_battery_driver); From ac67d7fd4e1bad9eac25c3a1a07e4aceda6e1ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:39 +0200 Subject: [PATCH 46/91] power: supply: da9052-battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-12-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/da9052-battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/da9052-battery.c b/drivers/power/supply/da9052-battery.c index d87bdecc9501..6f7c58a41e91 100644 --- a/drivers/power/supply/da9052-battery.c +++ b/drivers/power/supply/da9052-battery.c @@ -637,7 +637,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev) return ret; } -static int da9052_bat_remove(struct platform_device *pdev) +static void da9052_bat_remove(struct platform_device *pdev) { int i; struct da9052_battery *bat = platform_get_drvdata(pdev); @@ -646,13 +646,11 @@ static int da9052_bat_remove(struct platform_device *pdev) da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat); power_supply_unregister(bat->psy); - - return 0; } static struct platform_driver da9052_bat_driver = { .probe = da9052_bat_probe, - .remove = da9052_bat_remove, + .remove_new = da9052_bat_remove, .driver = { .name = "da9052-bat", }, From 749e18a800569e894e82fb5f68edd447311f9675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:40 +0200 Subject: [PATCH 47/91] power: supply: da9150-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-13-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/da9150-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c index 27f897067aa3..37db9e4ed7f3 100644 --- a/drivers/power/supply/da9150-charger.c +++ b/drivers/power/supply/da9150-charger.c @@ -635,7 +635,7 @@ static int da9150_charger_probe(struct platform_device *pdev) return ret; } -static int da9150_charger_remove(struct platform_device *pdev) +static void da9150_charger_remove(struct platform_device *pdev) { struct da9150_charger *charger = platform_get_drvdata(pdev); int irq; @@ -665,8 +665,6 @@ static int da9150_charger_remove(struct platform_device *pdev) iio_channel_release(charger->vbus_chan); iio_channel_release(charger->tjunc_chan); iio_channel_release(charger->vbat_chan); - - return 0; } static struct platform_driver da9150_charger_driver = { @@ -674,7 +672,7 @@ static struct platform_driver da9150_charger_driver = { .name = "da9150-charger", }, .probe = da9150_charger_probe, - .remove = da9150_charger_remove, + .remove_new = da9150_charger_remove, }; module_platform_driver(da9150_charger_driver); From df1953bcb723538faff6ebb403ac321797f3b04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:41 +0200 Subject: [PATCH 48/91] power: supply: goldfish_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-14-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/goldfish_battery.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/goldfish_battery.c b/drivers/power/supply/goldfish_battery.c index a58d713d75ce..8bb645ad1e5d 100644 --- a/drivers/power/supply/goldfish_battery.c +++ b/drivers/power/supply/goldfish_battery.c @@ -249,13 +249,12 @@ static int goldfish_battery_probe(struct platform_device *pdev) return 0; } -static int goldfish_battery_remove(struct platform_device *pdev) +static void goldfish_battery_remove(struct platform_device *pdev) { struct goldfish_battery_data *data = platform_get_drvdata(pdev); power_supply_unregister(data->battery); power_supply_unregister(data->ac); - return 0; } static const struct of_device_id goldfish_battery_of_match[] = { @@ -274,7 +273,7 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match); static struct platform_driver goldfish_battery_device = { .probe = goldfish_battery_probe, - .remove = goldfish_battery_remove, + .remove_new = goldfish_battery_remove, .driver = { .name = "goldfish-battery", .of_match_table = goldfish_battery_of_match, From cbc3e1136d1f8b934cc41b4bc12f5c732d543c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:42 +0200 Subject: [PATCH 49/91] power: supply: ipaq_micro_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-15-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/ipaq_micro_battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/ipaq_micro_battery.c b/drivers/power/supply/ipaq_micro_battery.c index 192d9db0fb00..66cc649f702a 100644 --- a/drivers/power/supply/ipaq_micro_battery.c +++ b/drivers/power/supply/ipaq_micro_battery.c @@ -265,7 +265,7 @@ static int micro_batt_probe(struct platform_device *pdev) return ret; } -static int micro_batt_remove(struct platform_device *pdev) +static void micro_batt_remove(struct platform_device *pdev) { struct micro_battery *mb = platform_get_drvdata(pdev); @@ -274,8 +274,6 @@ static int micro_batt_remove(struct platform_device *pdev) power_supply_unregister(micro_batt_power); cancel_delayed_work_sync(&mb->update); destroy_workqueue(mb->wq); - - return 0; } static int __maybe_unused micro_batt_suspend(struct device *dev) @@ -304,7 +302,7 @@ static struct platform_driver micro_batt_device_driver = { .pm = µ_batt_dev_pm_ops, }, .probe = micro_batt_probe, - .remove = micro_batt_remove, + .remove_new = micro_batt_remove, }; module_platform_driver(micro_batt_device_driver); From cf79047ed4a33704dd465723175041c22091d24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:43 +0200 Subject: [PATCH 50/91] power: supply: isp1704_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-16-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/isp1704_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/isp1704_charger.c b/drivers/power/supply/isp1704_charger.c index b6efc454e4f0..860d8614c98f 100644 --- a/drivers/power/supply/isp1704_charger.c +++ b/drivers/power/supply/isp1704_charger.c @@ -477,15 +477,13 @@ static int isp1704_charger_probe(struct platform_device *pdev) return ret; } -static int isp1704_charger_remove(struct platform_device *pdev) +static void isp1704_charger_remove(struct platform_device *pdev) { struct isp1704_charger *isp = platform_get_drvdata(pdev); usb_unregister_notifier(isp->phy, &isp->nb); power_supply_unregister(isp->psy); isp1704_charger_set_power(isp, 0); - - return 0; } #ifdef CONFIG_OF @@ -503,7 +501,7 @@ static struct platform_driver isp1704_charger_driver = { .of_match_table = of_match_ptr(omap_isp1704_of_match), }, .probe = isp1704_charger_probe, - .remove = isp1704_charger_remove, + .remove_new = isp1704_charger_remove, }; module_platform_driver(isp1704_charger_driver); From 7810ba3c5110ce66652ec6bd2abb92da5d726c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:44 +0200 Subject: [PATCH 51/91] power: supply: lp8788-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-17-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/lp8788-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c index 755b6a4379b8..2c81be82a41a 100644 --- a/drivers/power/supply/lp8788-charger.c +++ b/drivers/power/supply/lp8788-charger.c @@ -714,20 +714,18 @@ static int lp8788_charger_probe(struct platform_device *pdev) return 0; } -static int lp8788_charger_remove(struct platform_device *pdev) +static void lp8788_charger_remove(struct platform_device *pdev) { struct lp8788_charger *pchg = platform_get_drvdata(pdev); flush_work(&pchg->charger_work); lp8788_irq_unregister(pdev, pchg); lp8788_psy_unregister(pchg); - - return 0; } static struct platform_driver lp8788_charger_driver = { .probe = lp8788_charger_probe, - .remove = lp8788_charger_remove, + .remove_new = lp8788_charger_remove, .driver = { .name = LP8788_DEV_CHARGER, }, From 81e487b8a4af24c28a3d5c90a6035356098720bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:45 +0200 Subject: [PATCH 52/91] power: supply: max14577_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-18-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/max14577_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c index 96f9de775043..7c23fa89ea19 100644 --- a/drivers/power/supply/max14577_charger.c +++ b/drivers/power/supply/max14577_charger.c @@ -606,14 +606,12 @@ static int max14577_charger_probe(struct platform_device *pdev) return ret; } -static int max14577_charger_remove(struct platform_device *pdev) +static void max14577_charger_remove(struct platform_device *pdev) { struct max14577_charger *chg = platform_get_drvdata(pdev); device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer); power_supply_unregister(chg->charger); - - return 0; } static const struct platform_device_id max14577_charger_id[] = { @@ -638,7 +636,7 @@ static struct platform_driver max14577_charger_driver = { .of_match_table = of_max14577_charger_dt_match, }, .probe = max14577_charger_probe, - .remove = max14577_charger_remove, + .remove_new = max14577_charger_remove, .id_table = max14577_charger_id, }; module_platform_driver(max14577_charger_driver); From cd25ac3e3200626680dac92c9784cce4d59fdc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:46 +0200 Subject: [PATCH 53/91] power: supply: max77650-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-19-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/max77650-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/max77650-charger.c b/drivers/power/supply/max77650-charger.c index e8c25da40ab2..818e13c613e3 100644 --- a/drivers/power/supply/max77650-charger.c +++ b/drivers/power/supply/max77650-charger.c @@ -345,13 +345,11 @@ static int max77650_charger_probe(struct platform_device *pdev) return max77650_charger_enable(chg); } -static int max77650_charger_remove(struct platform_device *pdev) +static void max77650_charger_remove(struct platform_device *pdev) { struct max77650_charger_data *chg = platform_get_drvdata(pdev); max77650_charger_disable(chg); - - return 0; } static const struct of_device_id max77650_charger_of_match[] = { @@ -366,7 +364,7 @@ static struct platform_driver max77650_charger_driver = { .of_match_table = max77650_charger_of_match, }, .probe = max77650_charger_probe, - .remove = max77650_charger_remove, + .remove_new = max77650_charger_remove, }; module_platform_driver(max77650_charger_driver); From 1d138270d2963b68d71852c363298460ea7435c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:47 +0200 Subject: [PATCH 54/91] power: supply: max77693_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-20-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/max77693_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c index 794c8c054450..d0157e63b8b5 100644 --- a/drivers/power/supply/max77693_charger.c +++ b/drivers/power/supply/max77693_charger.c @@ -728,7 +728,7 @@ static int max77693_charger_probe(struct platform_device *pdev) return ret; } -static int max77693_charger_remove(struct platform_device *pdev) +static void max77693_charger_remove(struct platform_device *pdev) { struct max77693_charger *chg = platform_get_drvdata(pdev); @@ -737,8 +737,6 @@ static int max77693_charger_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer); power_supply_unregister(chg->charger); - - return 0; } static const struct platform_device_id max77693_charger_id[] = { @@ -752,7 +750,7 @@ static struct platform_driver max77693_charger_driver = { .name = "max77693-charger", }, .probe = max77693_charger_probe, - .remove = max77693_charger_remove, + .remove_new = max77693_charger_remove, .id_table = max77693_charger_id, }; module_platform_driver(max77693_charger_driver); From 026f25f221866ea89a33697935995db6a1c25a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:48 +0200 Subject: [PATCH 55/91] power: supply: max8925_power: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-21-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/max8925_power.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/max8925_power.c b/drivers/power/supply/max8925_power.c index 8878f9131184..4a2d6894f94e 100644 --- a/drivers/power/supply/max8925_power.c +++ b/drivers/power/supply/max8925_power.c @@ -566,7 +566,7 @@ static int max8925_power_probe(struct platform_device *pdev) return ret; } -static int max8925_power_remove(struct platform_device *pdev) +static void max8925_power_remove(struct platform_device *pdev) { struct max8925_power_info *info = platform_get_drvdata(pdev); @@ -576,12 +576,11 @@ static int max8925_power_remove(struct platform_device *pdev) power_supply_unregister(info->battery); max8925_deinit_charger(info); } - return 0; } static struct platform_driver max8925_power_driver = { .probe = max8925_power_probe, - .remove = max8925_power_remove, + .remove_new = max8925_power_remove, .driver = { .name = "max8925-power", }, From 6e3ed20e85aacaed7d3deede835a97029ea14560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:49 +0200 Subject: [PATCH 56/91] power: supply: pcf50633-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-22-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/pcf50633-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/pcf50633-charger.c b/drivers/power/supply/pcf50633-charger.c index fd44cb8ac0e2..950e30917c63 100644 --- a/drivers/power/supply/pcf50633-charger.c +++ b/drivers/power/supply/pcf50633-charger.c @@ -441,7 +441,7 @@ static int pcf50633_mbc_probe(struct platform_device *pdev) return 0; } -static int pcf50633_mbc_remove(struct platform_device *pdev) +static void pcf50633_mbc_remove(struct platform_device *pdev) { struct pcf50633_mbc *mbc = platform_get_drvdata(pdev); int i; @@ -453,8 +453,6 @@ static int pcf50633_mbc_remove(struct platform_device *pdev) power_supply_unregister(mbc->usb); power_supply_unregister(mbc->adapter); power_supply_unregister(mbc->ac); - - return 0; } static struct platform_driver pcf50633_mbc_driver = { @@ -462,7 +460,7 @@ static struct platform_driver pcf50633_mbc_driver = { .name = "pcf50633-mbc", }, .probe = pcf50633_mbc_probe, - .remove = pcf50633_mbc_remove, + .remove_new = pcf50633_mbc_remove, }; module_platform_driver(pcf50633_mbc_driver); From 325cb83bbabcafa3e54528d40c86559dde271bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:50 +0200 Subject: [PATCH 57/91] power: supply: qcom_smbb: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-23-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/qcom_smbb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom_smbb.c b/drivers/power/supply/qcom_smbb.c index bd50124eef9f..4e57762e27ba 100644 --- a/drivers/power/supply/qcom_smbb.c +++ b/drivers/power/supply/qcom_smbb.c @@ -1000,15 +1000,13 @@ static int smbb_charger_probe(struct platform_device *pdev) return 0; } -static int smbb_charger_remove(struct platform_device *pdev) +static void smbb_charger_remove(struct platform_device *pdev) { struct smbb_charger *chg; chg = platform_get_drvdata(pdev); regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0); - - return 0; } static const struct of_device_id smbb_charger_id_table[] = { @@ -1020,7 +1018,7 @@ MODULE_DEVICE_TABLE(of, smbb_charger_id_table); static struct platform_driver smbb_charger_driver = { .probe = smbb_charger_probe, - .remove = smbb_charger_remove, + .remove_new = smbb_charger_remove, .driver = { .name = "qcom-smbb", .of_match_table = smbb_charger_id_table, From 9f0da40ae798d3f32d649d1effef246f2c30f13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:51 +0200 Subject: [PATCH 58/91] power: supply: rx51_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-24-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/rx51_battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/rx51_battery.c b/drivers/power/supply/rx51_battery.c index 6e488ecf4dcb..e2bfc81f0fd9 100644 --- a/drivers/power/supply/rx51_battery.c +++ b/drivers/power/supply/rx51_battery.c @@ -246,7 +246,7 @@ static int rx51_battery_probe(struct platform_device *pdev) return ret; } -static int rx51_battery_remove(struct platform_device *pdev) +static void rx51_battery_remove(struct platform_device *pdev) { struct rx51_device_info *di = platform_get_drvdata(pdev); @@ -255,8 +255,6 @@ static int rx51_battery_remove(struct platform_device *pdev) iio_channel_release(di->channel_vbat); iio_channel_release(di->channel_bsi); iio_channel_release(di->channel_temp); - - return 0; } #ifdef CONFIG_OF @@ -269,7 +267,7 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match); static struct platform_driver rx51_battery_driver = { .probe = rx51_battery_probe, - .remove = rx51_battery_remove, + .remove_new = rx51_battery_remove, .driver = { .name = "rx51-battery", .of_match_table = of_match_ptr(n900_battery_of_match), From 0569d4cfa800ba303647dbf8170d1e89bdee3ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:52 +0200 Subject: [PATCH 59/91] power: supply: sc2731_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-25-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/sc2731_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c index 9ac17cf7a126..b3d8b1ca97da 100644 --- a/drivers/power/supply/sc2731_charger.c +++ b/drivers/power/supply/sc2731_charger.c @@ -511,13 +511,11 @@ static int sc2731_charger_probe(struct platform_device *pdev) return 0; } -static int sc2731_charger_remove(struct platform_device *pdev) +static void sc2731_charger_remove(struct platform_device *pdev) { struct sc2731_charger_info *info = platform_get_drvdata(pdev); usb_unregister_notifier(info->usb_phy, &info->usb_notify); - - return 0; } static const struct of_device_id sc2731_charger_of_match[] = { @@ -532,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = { .of_match_table = sc2731_charger_of_match, }, .probe = sc2731_charger_probe, - .remove = sc2731_charger_remove, + .remove_new = sc2731_charger_remove, }; module_platform_driver(sc2731_charger_driver); From 75d8365c94b685dd7377b0251d2407518dc49c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:53 +0200 Subject: [PATCH 60/91] power: supply: tps65090-charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-26-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/tps65090-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/tps65090-charger.c b/drivers/power/supply/tps65090-charger.c index f96c705e0a9f..c59197d2aa87 100644 --- a/drivers/power/supply/tps65090-charger.c +++ b/drivers/power/supply/tps65090-charger.c @@ -328,15 +328,13 @@ static int tps65090_charger_probe(struct platform_device *pdev) return ret; } -static int tps65090_charger_remove(struct platform_device *pdev) +static void tps65090_charger_remove(struct platform_device *pdev) { struct tps65090_charger *cdata = platform_get_drvdata(pdev); if (cdata->irq == -ENXIO) kthread_stop(cdata->poll_task); power_supply_unregister(cdata->ac); - - return 0; } static const struct of_device_id of_tps65090_charger_match[] = { @@ -351,7 +349,7 @@ static struct platform_driver tps65090_charger_driver = { .of_match_table = of_tps65090_charger_match, }, .probe = tps65090_charger_probe, - .remove = tps65090_charger_remove, + .remove_new = tps65090_charger_remove, }; module_platform_driver(tps65090_charger_driver); From 07a9398914327bb16584f24dfba02062a5967ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:54 +0200 Subject: [PATCH 61/91] power: supply: tps65217_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-27-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/tps65217_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/tps65217_charger.c b/drivers/power/supply/tps65217_charger.c index 96341cbde4fa..b3a1ba326a3e 100644 --- a/drivers/power/supply/tps65217_charger.c +++ b/drivers/power/supply/tps65217_charger.c @@ -253,14 +253,12 @@ static int tps65217_charger_probe(struct platform_device *pdev) return 0; } -static int tps65217_charger_remove(struct platform_device *pdev) +static void tps65217_charger_remove(struct platform_device *pdev) { struct tps65217_charger *charger = platform_get_drvdata(pdev); if (charger->poll_task) kthread_stop(charger->poll_task); - - return 0; } static const struct of_device_id tps65217_charger_match_table[] = { @@ -271,7 +269,7 @@ MODULE_DEVICE_TABLE(of, tps65217_charger_match_table); static struct platform_driver tps65217_charger_driver = { .probe = tps65217_charger_probe, - .remove = tps65217_charger_remove, + .remove_new = tps65217_charger_remove, .driver = { .name = "tps65217-charger", .of_match_table = of_match_ptr(tps65217_charger_match_table), From 83ef1dbc0de4a127661a175350696e9cfa88bbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:55 +0200 Subject: [PATCH 62/91] power: supply: twl4030_charger: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-28-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/twl4030_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c index e78d061d8d32..7b9b0b3e164e 100644 --- a/drivers/power/supply/twl4030_charger.c +++ b/drivers/power/supply/twl4030_charger.c @@ -1108,7 +1108,7 @@ static int twl4030_bci_probe(struct platform_device *pdev) return 0; } -static int twl4030_bci_remove(struct platform_device *pdev) +static void twl4030_bci_remove(struct platform_device *pdev) { struct twl4030_bci *bci = platform_get_drvdata(pdev); @@ -1123,8 +1123,6 @@ static int twl4030_bci_remove(struct platform_device *pdev) TWL4030_INTERRUPTS_BCIIMR1A); twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, TWL4030_INTERRUPTS_BCIIMR2A); - - return 0; } static const struct of_device_id twl_bci_of_match[] __maybe_unused = { @@ -1135,7 +1133,7 @@ MODULE_DEVICE_TABLE(of, twl_bci_of_match); static struct platform_driver twl4030_bci_driver = { .probe = twl4030_bci_probe, - .remove = twl4030_bci_remove, + .remove_new = twl4030_bci_remove, .driver = { .name = "twl4030_bci", .of_match_table = of_match_ptr(twl_bci_of_match), From ac51982b04a05eb902a223b3bc83c032903b6ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:56 +0200 Subject: [PATCH 63/91] power: supply: twl4030_madc_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-29-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/twl4030_madc_battery.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/twl4030_madc_battery.c b/drivers/power/supply/twl4030_madc_battery.c index 7fe029673b22..33106476bea2 100644 --- a/drivers/power/supply/twl4030_madc_battery.c +++ b/drivers/power/supply/twl4030_madc_battery.c @@ -244,7 +244,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) return ret; } -static int twl4030_madc_battery_remove(struct platform_device *pdev) +static void twl4030_madc_battery_remove(struct platform_device *pdev) { struct twl4030_madc_battery *bat = platform_get_drvdata(pdev); @@ -253,8 +253,6 @@ static int twl4030_madc_battery_remove(struct platform_device *pdev) iio_channel_release(bat->channel_vbat); iio_channel_release(bat->channel_ichg); iio_channel_release(bat->channel_temp); - - return 0; } static struct platform_driver twl4030_madc_battery_driver = { @@ -262,7 +260,7 @@ static struct platform_driver twl4030_madc_battery_driver = { .name = "twl4030_madc_battery", }, .probe = twl4030_madc_battery_probe, - .remove = twl4030_madc_battery_remove, + .remove_new = twl4030_madc_battery_remove, }; module_platform_driver(twl4030_madc_battery_driver); From fc7b34ae1347f4eb36f065458e53d6065cd85928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:57 +0200 Subject: [PATCH 64/91] power: supply: wm831x_backup: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-30-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm831x_backup.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/wm831x_backup.c b/drivers/power/supply/wm831x_backup.c index ffb265b8526d..1a7265660ade 100644 --- a/drivers/power/supply/wm831x_backup.c +++ b/drivers/power/supply/wm831x_backup.c @@ -197,18 +197,16 @@ static int wm831x_backup_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(devdata->backup); } -static int wm831x_backup_remove(struct platform_device *pdev) +static void wm831x_backup_remove(struct platform_device *pdev) { struct wm831x_backup *devdata = platform_get_drvdata(pdev); power_supply_unregister(devdata->backup); - - return 0; } static struct platform_driver wm831x_backup_driver = { .probe = wm831x_backup_probe, - .remove = wm831x_backup_remove, + .remove_new = wm831x_backup_remove, .driver = { .name = "wm831x-backup", }, From dab68bbb5450ee17c9acf77916ac2ed659b1e2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:58 +0200 Subject: [PATCH 65/91] power: supply: wm831x_power: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-31-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm831x_power.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c index 82e31066c746..e49b01ee5f3e 100644 --- a/drivers/power/supply/wm831x_power.c +++ b/drivers/power/supply/wm831x_power.c @@ -694,7 +694,7 @@ static int wm831x_power_probe(struct platform_device *pdev) return ret; } -static int wm831x_power_remove(struct platform_device *pdev) +static void wm831x_power_remove(struct platform_device *pdev) { struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); struct wm831x *wm831x = wm831x_power->wm831x; @@ -722,12 +722,11 @@ static int wm831x_power_remove(struct platform_device *pdev) power_supply_unregister(wm831x_power->battery); power_supply_unregister(wm831x_power->wall); power_supply_unregister(wm831x_power->usb); - return 0; } static struct platform_driver wm831x_power_driver = { .probe = wm831x_power_probe, - .remove = wm831x_power_remove, + .remove_new = wm831x_power_remove, .driver = { .name = "wm831x-power", }, From 42720969f394dc074ce1c99cd0c425b7dd6017ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:36:59 +0200 Subject: [PATCH 66/91] power: supply: wm8350_power: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-32-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm8350_power.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c index f2786761299c..f23b4f5343bc 100644 --- a/drivers/power/supply/wm8350_power.c +++ b/drivers/power/supply/wm8350_power.c @@ -579,7 +579,7 @@ static int wm8350_power_probe(struct platform_device *pdev) return ret; } -static int wm8350_power_remove(struct platform_device *pdev) +static void wm8350_power_remove(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_power *power = &wm8350->power; @@ -589,12 +589,11 @@ static int wm8350_power_remove(struct platform_device *pdev) power_supply_unregister(power->battery); power_supply_unregister(power->ac); power_supply_unregister(power->usb); - return 0; } static struct platform_driver wm8350_power_driver = { .probe = wm8350_power_probe, - .remove = wm8350_power_remove, + .remove_new = wm8350_power_remove, .driver = { .name = "wm8350-power", }, From 6f9fb8afe649a24c7df50ce2f7095b832713e648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 18 Sep 2023 15:37:00 +0200 Subject: [PATCH 67/91] power: supply: wm97xx_battery: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230918133700.1254499-33-u.kleine-koenig@pengutronix.de Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm97xx_battery.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c index f4b190adb335..1cc38d1437d9 100644 --- a/drivers/power/supply/wm97xx_battery.c +++ b/drivers/power/supply/wm97xx_battery.c @@ -248,14 +248,13 @@ static int wm97xx_bat_probe(struct platform_device *dev) return ret; } -static int wm97xx_bat_remove(struct platform_device *dev) +static void wm97xx_bat_remove(struct platform_device *dev) { if (charge_gpiod) free_irq(gpiod_to_irq(charge_gpiod), dev); cancel_work_sync(&bat_work); power_supply_unregister(bat_psy); kfree(prop); - return 0; } static struct platform_driver wm97xx_bat_driver = { @@ -266,7 +265,7 @@ static struct platform_driver wm97xx_bat_driver = { #endif }, .probe = wm97xx_bat_probe, - .remove = wm97xx_bat_remove, + .remove_new = wm97xx_bat_remove, }; module_platform_driver(wm97xx_bat_driver); From a6c6a5fe2a08172c2e045588531f0e05a6c296cf Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 18 Sep 2023 13:58:25 -0700 Subject: [PATCH 68/91] power: supply: pm8916_lbc: observe EXTCON config setting When CONFIG_EXTCON=m and CONFIG_CHARGER_PM8916_LBC=y, there are build errors. Fix them by having CHARGER_PM8916_LBC depend on the setting of EXTCON. aarch64-linux-ld: drivers/power/supply/pm8916_lbc.o: in function `pm8916_lbc_charger_state_changed_irq': pm8916_lbc.c:(.text+0xe8): undefined reference to `extcon_set_state_sync' aarch64-linux-ld: drivers/power/supply/pm8916_lbc.o: in function `pm8916_lbc_charger_probe': pm8916_lbc.c:(.text+0x638): undefined reference to `devm_extcon_dev_allocate' aarch64-linux-ld: pm8916_lbc.c:(.text+0x650): undefined reference to `devm_extcon_dev_register' aarch64-linux-ld: pm8916_lbc.c:(.text+0x688): undefined reference to `extcon_set_state_sync' Fixes: f8d7a3d21160 ("power: supply: Add driver for pm8916 lbc") Signed-off-by: Randy Dunlap Cc: Nikita Travkin Cc: Sebastian Reichel Cc: linux-pm@vger.kernel.org Link: https://lore.kernel.org/r/20230918205825.25864-1-rdunlap@infradead.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 4bfd5a336163..ff00a7491524 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -643,6 +643,7 @@ config BATTERY_PM8916_BMS_VM config CHARGER_PM8916_LBC tristate "Qualcomm PM8916 Linear Battery Charger support" depends on MFD_SPMI_PMIC || COMPILE_TEST + depends on EXTCON || !EXTCON help Say Y here to add support for Linear Battery Charger block found in some Qualcomm PMICs such as PM8916. This hardware From 7daa3bd4b0b4de1446cd4e6a66bba022101ae9ee Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 22 Sep 2023 10:53:55 -0700 Subject: [PATCH 69/91] power: supply: axp20x_ac_power: Annotate struct axp20x_ac_power with __counted_by Prepare for the coming implementation by GCC and Clang of the __counted_by attribute. Flexible array members annotated with __counted_by can have their accesses bounds-checked at run-time checking via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions). As found with Coccinelle[1], add __counted_by for struct axp20x_ac_power. [1] https://github.com/kees/kernel-tools/blob/trunk/coccinelle/examples/counted_by.cocci Cc: Chen-Yu Tsai Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20230922175355.work.006-kees@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp20x_ac_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/axp20x_ac_power.c b/drivers/power/supply/axp20x_ac_power.c index 19a118633115..e5733cb9e19e 100644 --- a/drivers/power/supply/axp20x_ac_power.c +++ b/drivers/power/supply/axp20x_ac_power.c @@ -45,7 +45,7 @@ struct axp20x_ac_power { struct iio_channel *acin_i; bool has_acin_path_sel; unsigned int num_irqs; - unsigned int irqs[]; + unsigned int irqs[] __counted_by(num_irqs); }; static irqreturn_t axp20x_ac_power_irq(int irq, void *devid) From de1ca06bc0364a58ba0889d97a7a094d87dd5477 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 22 Sep 2023 10:53:58 -0700 Subject: [PATCH 70/91] power: supply: axp20x_usb_power: Annotate struct axp20x_usb_power with __counted_by Prepare for the coming implementation by GCC and Clang of the __counted_by attribute. Flexible array members annotated with __counted_by can have their accesses bounds-checked at run-time checking via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions). As found with Coccinelle[1], add __counted_by for struct axp20x_usb_power. [1] https://github.com/kees/kernel-tools/blob/trunk/coccinelle/examples/counted_by.cocci Cc: Chen-Yu Tsai Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20230922175358.work.774-kees@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp20x_usb_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index bde17406c130..e23308ad4cc7 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -73,7 +73,7 @@ struct axp20x_usb_power { unsigned int old_status; unsigned int online; unsigned int num_irqs; - unsigned int irqs[]; + unsigned int irqs[] __counted_by(num_irqs); }; static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power) From 43ee22422db545800b8bf2c24ef53d040372fc7a Mon Sep 17 00:00:00 2001 From: Harshit Mogalapalli Date: Sat, 23 Sep 2023 04:48:06 -0700 Subject: [PATCH 71/91] power: supply: mm8013: Fix error code in mm8013_probe() The value of ret is zero when passed to dev_error_probe(), we are passing zero to dev_err_probe() is a success which is incorrect. Fix this by getting the error code using PTR_ERR(). Fixes: c75f4bf6800b ("power: supply: Introduce MM8013 fuel gauge driver") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202309190838.eu8WS6sz-lkp@intel.com/ Signed-off-by: Harshit Mogalapalli Link: https://lore.kernel.org/r/20230923114807.2829188-1-harshit.m.mogalapalli@oracle.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/mm8013.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c index ddac40ef9ae5..29fd65fe6545 100644 --- a/drivers/power/supply/mm8013.c +++ b/drivers/power/supply/mm8013.c @@ -273,8 +273,10 @@ static int mm8013_probe(struct i2c_client *client) chip->client = client; chip->regmap = devm_regmap_init_i2c(client, &mm8013_regmap_config); - if (IS_ERR(chip->regmap)) + if (IS_ERR(chip->regmap)) { + ret = PTR_ERR(chip->regmap); return dev_err_probe(dev, ret, "Couldn't initialize regmap\n"); + } ret = mm8013_checkdevice(chip); if (ret) From 8f8e9b7388514d937843337140f18ceb0f3da6eb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 27 Sep 2023 15:41:05 +0300 Subject: [PATCH 72/91] power: supply: mm8013: Fix an error checking issue in mm8013_checkdevice() There is a missing "ret = " assignment so this checks the same "ret" value twice. Fixes: c75f4bf6800b ("power: supply: Introduce MM8013 fuel gauge driver") Signed-off-by: Dan Carpenter Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/c46b4408-bf1d-408d-9e6b-16b0ad272532@moroto.mountain Signed-off-by: Sebastian Reichel --- drivers/power/supply/mm8013.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c index 29fd65fe6545..caa272b03564 100644 --- a/drivers/power/supply/mm8013.c +++ b/drivers/power/supply/mm8013.c @@ -53,7 +53,7 @@ static int mm8013_checkdevice(struct mm8013_chip *chip) if (ret < 0) return ret; - regmap_read(chip->regmap, REG_BATID, &val); + ret = regmap_read(chip->regmap, REG_BATID, &val); if (ret < 0) return ret; From 15a4e422f3c9b041261b6810c90ce09d4ebe2a14 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 26 Sep 2023 11:44:42 -0500 Subject: [PATCH 73/91] dt-bindings: power: supply: sbs-manager: Add missing unevaluatedProperties on child node schemas Just as unevaluatedProperties or additionalProperties are required at the top level of schemas, they should (and will) also be required for child node schemas. That ensures only documented properties are present for any node. Add unevaluatedProperties as needed, and then add any missing properties flagged by the addition. Signed-off-by: Rob Herring Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20230926164446.101327-1-robh@kernel.org Signed-off-by: Sebastian Reichel --- .../devicetree/bindings/power/supply/sbs,sbs-manager.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml b/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml index f255f3858d08..2e21846463ba 100644 --- a/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml +++ b/Documentation/devicetree/bindings/power/supply/sbs,sbs-manager.yaml @@ -47,6 +47,12 @@ patternProperties: "^i2c@[1-4]$": type: object $ref: /schemas/i2c/i2c-controller.yaml# + unevaluatedProperties: false + + properties: + reg: + minimum: 1 + maximum: 4 examples: - | From 0ce51459c8353b2b18ad3a430dbebf29af8b579c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 29 Sep 2023 19:39:00 +0200 Subject: [PATCH 74/91] power: supply: core: remove opencoded string_lower() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit string_lower from string_helpers.h can be used to modify the string in-place. Use it to get rid of the custom str_to_lower(). Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230929-power_supply-string_lower-v1-1-3141a2634d53@weissschuh.net Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_sysfs.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 06e5b6b0e255..09bf9a094c77 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "power_supply.h" @@ -398,14 +399,6 @@ static const struct attribute_group *power_supply_attr_groups[] = { NULL, }; -static void str_to_lower(char *str) -{ - while (*str) { - *str = tolower(*str); - str++; - } -} - void power_supply_init_attrs(struct device_type *dev_type) { int i; @@ -420,7 +413,8 @@ void power_supply_init_attrs(struct device_type *dev_type) __func__, i); sprintf(power_supply_attrs[i].attr_name, "_err_%d", i); } else { - str_to_lower(power_supply_attrs[i].attr_name); + string_lower(power_supply_attrs[i].attr_name, + power_supply_attrs[i].attr_name); } attr = &power_supply_attrs[i].dev_attr; From 8242336dc8a8009b93fb7c4506d79a8c894b3583 Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Sun, 1 Oct 2023 15:17:42 +0200 Subject: [PATCH 75/91] power: supply: rt5033_charger: Add cable detection and USB OTG supply Implement cable detection by extcon and handle the driver according to the connector type. There are basically three types of action: "set_charging", "set_otg" and "set_disconnect". A forth helper function to "unset_otg" was added because this is used in both "set_charging" and "set_disconnect". In the first case it covers the rather rare event that someone changes from OTG to charging without disconnect. In the second case, when disconnecting, the values are set back to the ones from initialization to return into a defined state. Additionally, there is "set_mivr". When connecting to e.g. a laptop/PC, the minimum input voltage regulation (MIVR) shall prevent a voltage drop if the cable or the supply is weak. The MIVR value is set to 4600MV, same as in the Android driver [1]. When disconnecting, MIVR is set back to DISABLED. In the function rt5033_get_charger_state(): When in OTG mode, the chip reports status "charging". Change this to "discharging" because there is no charging going on in OTG mode [2]. Yang Yingliang detected missing mutex_unlock() in some error path and suggested a fix [3]. The suggestion was squashed into this patch. [1] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/battery/rt5033_charger.c#L499 [2] https://github.com/msm8916-mainline/linux-downstream/blob/GT-I9195I/drivers/battery/rt5033_charger.c#L686-L687 [3] https://lore.kernel.org/linux-pm/20230822030207.644738-1-yangyingliang@huawei.com Tested-by: Raymond Hackley Co-developed-by: Yang Yingliang Signed-off-by: Jakob Hauser Link: https://lore.kernel.org/r/cc4e37e510abbb0cdfa7faa8408da48c2cb448a4.1696165240.git.jahau@rocketmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/rt5033_charger.c | 287 +++++++++++++++++++++++++- 1 file changed, 285 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c index c0c516f22c66..091ca4a21f29 100644 --- a/drivers/power/supply/rt5033_charger.c +++ b/drivers/power/supply/rt5033_charger.c @@ -6,8 +6,12 @@ * Author: Beomho Seo */ +#include +#include #include #include +#include +#include #include #include #include @@ -26,6 +30,14 @@ struct rt5033_charger { struct regmap *regmap; struct power_supply *psy; struct rt5033_charger_data *chg; + struct extcon_dev *edev; + struct notifier_block extcon_nb; + struct work_struct extcon_work; + struct mutex lock; + bool online; + bool otg; + bool mivr_enabled; + u8 cv_regval; }; static int rt5033_get_charger_state(struct rt5033_charger *charger) @@ -56,6 +68,10 @@ static int rt5033_get_charger_state(struct rt5033_charger *charger) state = POWER_SUPPLY_STATUS_UNKNOWN; } + /* For OTG mode, RT5033 would still report "charging" */ + if (charger->otg) + state = POWER_SUPPLY_STATUS_DISCHARGING; + return state; } @@ -147,6 +163,9 @@ static inline int rt5033_init_const_charge(struct rt5033_charger *charger) return -EINVAL; } + /* Store that value for later usage */ + charger->cv_regval = reg_data; + /* Set end of charge current */ if (chg->eoc_uamp < RT5033_CHARGER_EOC_MIN || chg->eoc_uamp > RT5033_CHARGER_EOC_MAX) { @@ -330,6 +349,162 @@ static int rt5033_charger_reg_init(struct rt5033_charger *charger) return 0; } +static int rt5033_charger_set_otg(struct rt5033_charger *charger) +{ + int ret; + + mutex_lock(&charger->lock); + + /* Set OTG boost v_out to 5 volts */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2, + RT5033_CHGCTRL2_CV_MASK, + 0x37 << RT5033_CHGCTRL2_CV_SHIFT); + if (ret) { + dev_err(charger->dev, "Failed set OTG boost v_out\n"); + ret = -EINVAL; + goto out_unlock; + } + + /* Set operation mode to OTG */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1, + RT5033_CHGCTRL1_MODE_MASK, RT5033_BOOST_MODE); + if (ret) { + dev_err(charger->dev, "Failed to update OTG mode.\n"); + ret = -EINVAL; + goto out_unlock; + } + + /* In case someone switched from charging to OTG directly */ + if (charger->online) + charger->online = false; + + charger->otg = true; + +out_unlock: + mutex_unlock(&charger->lock); + + return ret; +} + +static int rt5033_charger_unset_otg(struct rt5033_charger *charger) +{ + int ret; + u8 data; + + /* Restore constant voltage for charging */ + data = charger->cv_regval; + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2, + RT5033_CHGCTRL2_CV_MASK, + data << RT5033_CHGCTRL2_CV_SHIFT); + if (ret) { + dev_err(charger->dev, "Failed to restore constant voltage\n"); + return -EINVAL; + } + + /* Set operation mode to charging */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1, + RT5033_CHGCTRL1_MODE_MASK, RT5033_CHARGER_MODE); + if (ret) { + dev_err(charger->dev, "Failed to update charger mode.\n"); + return -EINVAL; + } + + charger->otg = false; + + return 0; +} + +static int rt5033_charger_set_charging(struct rt5033_charger *charger) +{ + int ret; + + mutex_lock(&charger->lock); + + /* In case someone switched from OTG to charging directly */ + if (charger->otg) { + ret = rt5033_charger_unset_otg(charger); + if (ret) { + mutex_unlock(&charger->lock); + return -EINVAL; + } + } + + charger->online = true; + + mutex_unlock(&charger->lock); + + return 0; +} + +static int rt5033_charger_set_mivr(struct rt5033_charger *charger) +{ + int ret; + + mutex_lock(&charger->lock); + + /* + * When connected via USB connector type SDP (Standard Downstream Port), + * the minimum input voltage regulation (MIVR) should be enabled. It + * prevents an input voltage drop due to insufficient current provided + * by the adapter or USB input. As a downside, it may reduces the + * charging current and thus slows the charging. + */ + ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4, + RT5033_CHGCTRL4_MIVR_MASK, RT5033_CHARGER_MIVR_4600MV); + if (ret) { + dev_err(charger->dev, "Failed to set MIVR level.\n"); + mutex_unlock(&charger->lock); + return -EINVAL; + } + + charger->mivr_enabled = true; + + mutex_unlock(&charger->lock); + + /* Beyond this, do the same steps like setting charging */ + rt5033_charger_set_charging(charger); + + return 0; +} + +static int rt5033_charger_set_disconnect(struct rt5033_charger *charger) +{ + int ret = 0; + + mutex_lock(&charger->lock); + + /* Disable MIVR if enabled */ + if (charger->mivr_enabled) { + ret = regmap_update_bits(charger->regmap, + RT5033_REG_CHG_CTRL4, + RT5033_CHGCTRL4_MIVR_MASK, + RT5033_CHARGER_MIVR_DISABLE); + if (ret) { + dev_err(charger->dev, "Failed to disable MIVR.\n"); + ret = -EINVAL; + goto out_unlock; + } + + charger->mivr_enabled = false; + } + + if (charger->otg) { + ret = rt5033_charger_unset_otg(charger); + if (ret) { + ret = -EINVAL; + goto out_unlock; + } + } + + if (charger->online) + charger->online = false; + +out_unlock: + mutex_unlock(&charger->lock); + + return ret; +} + static enum power_supply_property rt5033_charger_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CHARGE_TYPE, @@ -366,8 +541,7 @@ static int rt5033_charger_get_property(struct power_supply *psy, val->strval = RT5033_MANUFACTURER; break; case POWER_SUPPLY_PROP_ONLINE: - val->intval = (rt5033_get_charger_state(charger) == - POWER_SUPPLY_STATUS_CHARGING); + val->intval = charger->online; break; default: return -EINVAL; @@ -402,6 +576,86 @@ static struct rt5033_charger_data *rt5033_charger_dt_init( return chg; } +static void rt5033_charger_extcon_work(struct work_struct *work) +{ + struct rt5033_charger *charger = + container_of(work, struct rt5033_charger, extcon_work); + struct extcon_dev *edev = charger->edev; + int connector, state; + int ret; + + for (connector = EXTCON_USB_HOST; connector <= EXTCON_CHG_USB_PD; + connector++) { + state = extcon_get_state(edev, connector); + if (state == 1) + break; + } + + /* + * Adding a delay between extcon notification and extcon action. This + * makes extcon action execution more reliable. Without the delay the + * execution sometimes fails, possibly because the chip is busy or not + * ready. + */ + msleep(100); + + switch (connector) { + case EXTCON_CHG_USB_SDP: + ret = rt5033_charger_set_mivr(charger); + if (ret) { + dev_err(charger->dev, "failed to set USB mode\n"); + break; + } + dev_info(charger->dev, "USB mode. connector type: %d\n", + connector); + break; + case EXTCON_CHG_USB_DCP: + case EXTCON_CHG_USB_CDP: + case EXTCON_CHG_USB_ACA: + case EXTCON_CHG_USB_FAST: + case EXTCON_CHG_USB_SLOW: + case EXTCON_CHG_WPT: + case EXTCON_CHG_USB_PD: + ret = rt5033_charger_set_charging(charger); + if (ret) { + dev_err(charger->dev, "failed to set charging\n"); + break; + } + dev_info(charger->dev, "charging. connector type: %d\n", + connector); + break; + case EXTCON_USB_HOST: + ret = rt5033_charger_set_otg(charger); + if (ret) { + dev_err(charger->dev, "failed to set OTG\n"); + break; + } + dev_info(charger->dev, "OTG enabled\n"); + break; + default: + ret = rt5033_charger_set_disconnect(charger); + if (ret) { + dev_err(charger->dev, "failed to set disconnect\n"); + break; + } + dev_info(charger->dev, "disconnected\n"); + break; + } + + power_supply_changed(charger->psy); +} + +static int rt5033_charger_extcon_notifier(struct notifier_block *nb, + unsigned long event, void *param) +{ + struct rt5033_charger *charger = + container_of(nb, struct rt5033_charger, extcon_nb); + + schedule_work(&charger->extcon_work); + + return NOTIFY_OK; +} + static const struct power_supply_desc rt5033_charger_desc = { .name = "rt5033-charger", .type = POWER_SUPPLY_TYPE_USB, @@ -414,6 +668,7 @@ static int rt5033_charger_probe(struct platform_device *pdev) { struct rt5033_charger *charger; struct power_supply_config psy_cfg = {}; + struct device_node *np_conn, *np_edev; int ret; charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); @@ -423,6 +678,7 @@ static int rt5033_charger_probe(struct platform_device *pdev) platform_set_drvdata(pdev, charger); charger->dev = &pdev->dev; charger->regmap = dev_get_regmap(pdev->dev.parent, NULL); + mutex_init(&charger->lock); psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = charger; @@ -442,6 +698,33 @@ static int rt5033_charger_probe(struct platform_device *pdev) if (ret) return ret; + /* + * Extcon support is not vital for the charger to work. If no extcon + * is available, just emit a warning and leave the probe function. + */ + np_conn = of_parse_phandle(pdev->dev.of_node, "richtek,usb-connector", 0); + np_edev = of_get_parent(np_conn); + charger->edev = extcon_find_edev_by_node(np_edev); + if (IS_ERR(charger->edev)) { + dev_warn(&pdev->dev, "no extcon device found in device-tree\n"); + goto out; + } + + ret = devm_work_autocancel(&pdev->dev, &charger->extcon_work, + rt5033_charger_extcon_work); + if (ret) { + dev_err(&pdev->dev, "failed to initialize extcon work\n"); + return ret; + } + + charger->extcon_nb.notifier_call = rt5033_charger_extcon_notifier; + ret = devm_extcon_register_notifier_all(&pdev->dev, charger->edev, + &charger->extcon_nb); + if (ret) { + dev_err(&pdev->dev, "failed to register extcon notifier\n"); + return ret; + } +out: return 0; } From 1c6877f1768a34c04e3a82f9f950f78488a1753b Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Sun, 1 Oct 2023 15:17:43 +0200 Subject: [PATCH 76/91] power: supply: rt5033_charger: Simplify initialization of rt5033_charger_data Currently the struct "rt5033_charger_data" is initialized rather complicated. The cause lies inside of the struct "rt5033_charger", where struct "rt5033_charger_data" is implemented as a pointer *chg. Therefore, inside of struct "rt5033_charger" change the struct "rt5033_charger_data" to non-pointer "chg". It is then initialized right away and can be accessed more easily. Signed-off-by: Jakob Hauser Link: https://lore.kernel.org/r/0aff8c2a18cf4b88ec3333f6679a8419dd76ca29.1696165240.git.jahau@rocketmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/rt5033_charger.c | 29 +++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c index 091ca4a21f29..b34ef0ea6f8a 100644 --- a/drivers/power/supply/rt5033_charger.c +++ b/drivers/power/supply/rt5033_charger.c @@ -29,7 +29,7 @@ struct rt5033_charger { struct device *dev; struct regmap *regmap; struct power_supply *psy; - struct rt5033_charger_data *chg; + struct rt5033_charger_data chg; struct extcon_dev *edev; struct notifier_block extcon_nb; struct work_struct extcon_work; @@ -131,7 +131,7 @@ static int rt5033_get_charger_const_voltage(struct rt5033_charger *charger) static inline int rt5033_init_const_charge(struct rt5033_charger *charger) { - struct rt5033_charger_data *chg = charger->chg; + struct rt5033_charger_data *chg = &charger->chg; int ret; unsigned int val; u8 reg_data; @@ -205,7 +205,7 @@ static inline int rt5033_init_const_charge(struct rt5033_charger *charger) static inline int rt5033_init_fast_charge(struct rt5033_charger *charger) { - struct rt5033_charger_data *chg = charger->chg; + struct rt5033_charger_data *chg = &charger->chg; int ret; unsigned int val; u8 reg_data; @@ -250,7 +250,7 @@ static inline int rt5033_init_fast_charge(struct rt5033_charger *charger) static inline int rt5033_init_pre_charge(struct rt5033_charger *charger) { - struct rt5033_charger_data *chg = charger->chg; + struct rt5033_charger_data *chg = &charger->chg; int ret; unsigned int val; u8 reg_data; @@ -550,21 +550,16 @@ static int rt5033_charger_get_property(struct power_supply *psy, return 0; } -static struct rt5033_charger_data *rt5033_charger_dt_init( - struct rt5033_charger *charger) +static int rt5033_charger_dt_init(struct rt5033_charger *charger) { - struct rt5033_charger_data *chg; + struct rt5033_charger_data *chg = &charger->chg; struct power_supply_battery_info *info; int ret; - chg = devm_kzalloc(charger->dev, sizeof(*chg), GFP_KERNEL); - if (!chg) - return ERR_PTR(-ENOMEM); - ret = power_supply_get_battery_info(charger->psy, &info); if (ret) - return ERR_PTR(dev_err_probe(charger->dev, -EINVAL, - "missing battery info\n")); + return dev_err_probe(charger->dev, -EINVAL, + "missing battery info\n"); /* Assign data. Validity will be checked in the init functions. */ chg->pre_uamp = info->precharge_current_ua; @@ -573,7 +568,7 @@ static struct rt5033_charger_data *rt5033_charger_dt_init( chg->pre_uvolt = info->precharge_voltage_max_uv; chg->const_uvolt = info->constant_charge_voltage_max_uv; - return chg; + return 0; } static void rt5033_charger_extcon_work(struct work_struct *work) @@ -690,9 +685,9 @@ static int rt5033_charger_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(charger->psy), "Failed to register power supply\n"); - charger->chg = rt5033_charger_dt_init(charger); - if (IS_ERR_OR_NULL(charger->chg)) - return PTR_ERR(charger->chg); + ret = rt5033_charger_dt_init(charger); + if (ret) + return ret; ret = rt5033_charger_reg_init(charger); if (ret) From 3f26d8b6d1cbd41c5fa663c9ea48a2b832cfb58f Mon Sep 17 00:00:00 2001 From: Jakob Hauser Date: Sun, 1 Oct 2023 15:17:44 +0200 Subject: [PATCH 77/91] power: supply: rt5033_charger: Replace "&pdev->dev" by "charger->dev" in probe At the beginning of the probe function, "charger->dev" is set equal to "&pdev->dev". Therefore it's more clear to subsequently use "charger->dev" instead of "&pdev->dev". Signed-off-by: Jakob Hauser Link: https://lore.kernel.org/r/39b4f00e010446e453905c8dc3ca1e47e9f2c5f8.1696165240.git.jahau@rocketmail.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/rt5033_charger.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c index b34ef0ea6f8a..d19c7e80a92a 100644 --- a/drivers/power/supply/rt5033_charger.c +++ b/drivers/power/supply/rt5033_charger.c @@ -678,11 +678,11 @@ static int rt5033_charger_probe(struct platform_device *pdev) psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = charger; - charger->psy = devm_power_supply_register(&pdev->dev, + charger->psy = devm_power_supply_register(charger->dev, &rt5033_charger_desc, &psy_cfg); if (IS_ERR(charger->psy)) - return dev_err_probe(&pdev->dev, PTR_ERR(charger->psy), + return dev_err_probe(charger->dev, PTR_ERR(charger->psy), "Failed to register power supply\n"); ret = rt5033_charger_dt_init(charger); @@ -701,22 +701,22 @@ static int rt5033_charger_probe(struct platform_device *pdev) np_edev = of_get_parent(np_conn); charger->edev = extcon_find_edev_by_node(np_edev); if (IS_ERR(charger->edev)) { - dev_warn(&pdev->dev, "no extcon device found in device-tree\n"); + dev_warn(charger->dev, "no extcon device found in device-tree\n"); goto out; } - ret = devm_work_autocancel(&pdev->dev, &charger->extcon_work, + ret = devm_work_autocancel(charger->dev, &charger->extcon_work, rt5033_charger_extcon_work); if (ret) { - dev_err(&pdev->dev, "failed to initialize extcon work\n"); + dev_err(charger->dev, "failed to initialize extcon work\n"); return ret; } charger->extcon_nb.notifier_call = rt5033_charger_extcon_notifier; - ret = devm_extcon_register_notifier_all(&pdev->dev, charger->edev, + ret = devm_extcon_register_notifier_all(charger->dev, charger->edev, &charger->extcon_nb); if (ret) { - dev_err(&pdev->dev, "failed to register extcon notifier\n"); + dev_err(charger->dev, "failed to register extcon notifier\n"); return ret; } out: From 13b4c6964665cadb9b06c085029710c43a0c662e Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Fri, 6 Oct 2023 10:04:25 -0300 Subject: [PATCH 78/91] power: reset: gpio-poweroff: use a struct to store the module variables Use a struct to store the module variables. This is required to later move to notifier_blocks where we can have several instances. Signed-off-by: Stefan Eichenberger Signed-off-by: Francesco Dolcini Link: https://lore.kernel.org/r/20231006130428.11259-2-francesco@dolcini.it Signed-off-by: Sebastian Reichel --- drivers/power/reset/gpio-poweroff.c | 50 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index b28f24da1b3c..dea550e422f3 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -17,32 +17,37 @@ #include #define DEFAULT_TIMEOUT_MS 3000 + +struct gpio_poweroff { + struct gpio_desc *reset_gpio; + u32 timeout_ms; + u32 active_delay_ms; + u32 inactive_delay_ms; +}; + /* * Hold configuration here, cannot be more than one instance of the driver * since pm_power_off itself is global. */ -static struct gpio_desc *reset_gpio; -static u32 timeout = DEFAULT_TIMEOUT_MS; -static u32 active_delay = 100; -static u32 inactive_delay = 100; +static struct gpio_poweroff *gpio_poweroff; static void gpio_poweroff_do_poweroff(void) { - BUG_ON(!reset_gpio); + BUG_ON(!gpio_poweroff); /* drive it active, also inactive->active edge */ - gpiod_direction_output(reset_gpio, 1); - mdelay(active_delay); + gpiod_direction_output(gpio_poweroff->reset_gpio, 1); + mdelay(gpio_poweroff->active_delay_ms); /* drive inactive, also active->inactive edge */ - gpiod_set_value_cansleep(reset_gpio, 0); - mdelay(inactive_delay); + gpiod_set_value_cansleep(gpio_poweroff->reset_gpio, 0); + mdelay(gpio_poweroff->inactive_delay_ms); /* drive it active, also inactive->active edge */ - gpiod_set_value_cansleep(reset_gpio, 1); + gpiod_set_value_cansleep(gpio_poweroff->reset_gpio, 1); /* give it some time */ - mdelay(timeout); + mdelay(gpio_poweroff->timeout_ms); WARN_ON(1); } @@ -60,20 +65,29 @@ static int gpio_poweroff_probe(struct platform_device *pdev) return -EBUSY; } + gpio_poweroff = devm_kzalloc(&pdev->dev, sizeof(*gpio_poweroff), GFP_KERNEL); + if (!gpio_poweroff) + return -ENOMEM; + input = device_property_read_bool(&pdev->dev, "input"); if (input) flags = GPIOD_IN; else flags = GPIOD_OUT_LOW; - device_property_read_u32(&pdev->dev, "active-delay-ms", &active_delay); - device_property_read_u32(&pdev->dev, "inactive-delay-ms", - &inactive_delay); - device_property_read_u32(&pdev->dev, "timeout-ms", &timeout); - reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags); - if (IS_ERR(reset_gpio)) - return PTR_ERR(reset_gpio); + gpio_poweroff->active_delay_ms = 100; + gpio_poweroff->inactive_delay_ms = 100; + gpio_poweroff->timeout_ms = DEFAULT_TIMEOUT_MS; + + device_property_read_u32(&pdev->dev, "active-delay-ms", &gpio_poweroff->active_delay_ms); + device_property_read_u32(&pdev->dev, "inactive-delay-ms", + &gpio_poweroff->inactive_delay_ms); + device_property_read_u32(&pdev->dev, "timeout-ms", &gpio_poweroff->timeout_ms); + + gpio_poweroff->reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags); + if (IS_ERR(gpio_poweroff->reset_gpio)) + return PTR_ERR(gpio_poweroff->reset_gpio); pm_power_off = &gpio_poweroff_do_poweroff; return 0; From b16d9f49735f3d26e23f0ba4a2cf21668fc6b66b Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Fri, 6 Oct 2023 10:04:26 -0300 Subject: [PATCH 79/91] power: reset: gpio-poweroff: use sys-off handler API Use the new sys-off handler API for gpio-poweroff. This allows us to have more than one poweroff handler and prioritise them. Signed-off-by: Stefan Eichenberger Signed-off-by: Francesco Dolcini Link: https://lore.kernel.org/r/20231006130428.11259-3-francesco@dolcini.it Signed-off-by: Sebastian Reichel --- drivers/power/reset/gpio-poweroff.c | 37 ++++++++++------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index dea550e422f3..0deb293eb2d6 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -15,6 +15,7 @@ #include #include #include +#include #define DEFAULT_TIMEOUT_MS 3000 @@ -25,15 +26,9 @@ struct gpio_poweroff { u32 inactive_delay_ms; }; -/* - * Hold configuration here, cannot be more than one instance of the driver - * since pm_power_off itself is global. - */ -static struct gpio_poweroff *gpio_poweroff; - -static void gpio_poweroff_do_poweroff(void) +static int gpio_poweroff_do_poweroff(struct sys_off_data *data) { - BUG_ON(!gpio_poweroff); + struct gpio_poweroff *gpio_poweroff = data->cb_data; /* drive it active, also inactive->active edge */ gpiod_direction_output(gpio_poweroff->reset_gpio, 1); @@ -50,20 +45,16 @@ static void gpio_poweroff_do_poweroff(void) mdelay(gpio_poweroff->timeout_ms); WARN_ON(1); + + return NOTIFY_DONE; } static int gpio_poweroff_probe(struct platform_device *pdev) { + struct gpio_poweroff *gpio_poweroff; bool input = false; enum gpiod_flags flags; - - /* If a pm_power_off function has already been added, leave it alone */ - if (pm_power_off != NULL) { - dev_err(&pdev->dev, - "%s: pm_power_off function already registered\n", - __func__); - return -EBUSY; - } + int ret; gpio_poweroff = devm_kzalloc(&pdev->dev, sizeof(*gpio_poweroff), GFP_KERNEL); if (!gpio_poweroff) @@ -89,14 +80,11 @@ static int gpio_poweroff_probe(struct platform_device *pdev) if (IS_ERR(gpio_poweroff->reset_gpio)) return PTR_ERR(gpio_poweroff->reset_gpio); - pm_power_off = &gpio_poweroff_do_poweroff; - return 0; -} - -static int gpio_poweroff_remove(struct platform_device *pdev) -{ - if (pm_power_off == &gpio_poweroff_do_poweroff) - pm_power_off = NULL; + ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, gpio_poweroff_do_poweroff, + gpio_poweroff); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Cannot register poweroff handler\n"); return 0; } @@ -109,7 +97,6 @@ MODULE_DEVICE_TABLE(of, of_gpio_poweroff_match); static struct platform_driver gpio_poweroff_driver = { .probe = gpio_poweroff_probe, - .remove = gpio_poweroff_remove, .driver = { .name = "poweroff-gpio", .of_match_table = of_gpio_poweroff_match, From 4ee17bd30788496a279ceaabc7ecaaf39f61cfc4 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Fri, 6 Oct 2023 10:04:27 -0300 Subject: [PATCH 80/91] dt-bindings: power: reset: gpio-poweroff: Add priority property Add the priority property to the gpio-poweroff bindings description. Signed-off-by: Stefan Eichenberger Signed-off-by: Francesco Dolcini Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20231006130428.11259-4-francesco@dolcini.it Signed-off-by: Sebastian Reichel --- .../devicetree/bindings/power/reset/gpio-poweroff.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml index b54ec003a1e0..a4b437fce37c 100644 --- a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml +++ b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.yaml @@ -18,6 +18,9 @@ description: > Finally the operating system assumes the power off failed if the system is still running after waiting some time (timeout-ms). +allOf: + - $ref: restart-handler.yaml# + properties: compatible: const: gpio-poweroff @@ -40,6 +43,9 @@ properties: default: 100 description: Delay to wait after driving gpio inactive + priority: + default: 0 + timeout-ms: default: 3000 description: Time to wait before assuming the power off sequence failed. From d03d2a8cdefe86f04cfb53934a708620e7dfbfcb Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Fri, 6 Oct 2023 10:04:28 -0300 Subject: [PATCH 81/91] power: reset: gpio-poweroff: make sys handler priority configurable Add a priority property equal to gpio-restart to allow increasing the priority of the gpio-poweroff handler. Signed-off-by: Stefan Eichenberger Signed-off-by: Francesco Dolcini Link: https://lore.kernel.org/r/20231006130428.11259-5-francesco@dolcini.it Signed-off-by: Sebastian Reichel --- drivers/power/reset/gpio-poweroff.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index 0deb293eb2d6..52cfeee2cb28 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -54,6 +54,7 @@ static int gpio_poweroff_probe(struct platform_device *pdev) struct gpio_poweroff *gpio_poweroff; bool input = false; enum gpiod_flags flags; + int priority = SYS_OFF_PRIO_DEFAULT; int ret; gpio_poweroff = devm_kzalloc(&pdev->dev, sizeof(*gpio_poweroff), GFP_KERNEL); @@ -75,14 +76,18 @@ static int gpio_poweroff_probe(struct platform_device *pdev) device_property_read_u32(&pdev->dev, "inactive-delay-ms", &gpio_poweroff->inactive_delay_ms); device_property_read_u32(&pdev->dev, "timeout-ms", &gpio_poweroff->timeout_ms); + device_property_read_u32(&pdev->dev, "priority", &priority); + if (priority > 255) { + dev_err(&pdev->dev, "Invalid priority property: %u\n", priority); + return -EINVAL; + } gpio_poweroff->reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags); if (IS_ERR(gpio_poweroff->reset_gpio)) return PTR_ERR(gpio_poweroff->reset_gpio); ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF, - SYS_OFF_PRIO_DEFAULT, gpio_poweroff_do_poweroff, - gpio_poweroff); + priority, gpio_poweroff_do_poweroff, gpio_poweroff); if (ret) return dev_err_probe(&pdev->dev, ret, "Cannot register poweroff handler\n"); From 3c693ac29e3fb4e1d88652e633a9dc16e1dd76e4 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 9 Oct 2023 14:58:18 +0100 Subject: [PATCH 82/91] power: reset: brcmstb: Depend on actual SoC dependencies Depend on the explicit SoC defines rather than generic architectures like most of the rest of the HW drivers do. This makes the drivers only available for the HW and for compile testing. Signed-off-by: Peter Robinson Cc: Sebastian Reichel Cc: linux-pm@vger.kernel.org Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20231009135833.17880-3-pbrobinson@gmail.com Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 59e1ebb7842e..b9733fa40276 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -66,7 +66,7 @@ config POWER_RESET_BRCMKONA config POWER_RESET_BRCMSTB bool "Broadcom STB reset driver" - depends on ARM || ARM64 || MIPS || COMPILE_TEST + depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST depends on MFD_SYSCON default ARCH_BRCMSTB || BMIPS_GENERIC help From b3c3a197baf23ca445ba74e3c7c40cfacfedd9fb Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 9 Oct 2023 12:29:15 -0500 Subject: [PATCH 83/91] power: supply: cpcap: Drop non-DT driver matching Only DT based probing is used for the Motorola CPCAP charger driver, so drop the !CONFIG_OF parts and redundant of_match_device() call. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20231009172923.2457844-20-robh@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/supply/cpcap-charger.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index 431e951cccf0..cebca34ff872 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -17,8 +17,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -865,7 +864,6 @@ static const struct power_supply_desc cpcap_charger_usb_desc = { .property_is_writeable = cpcap_charger_property_is_writeable, }; -#ifdef CONFIG_OF static const struct of_device_id cpcap_charger_id_table[] = { { .compatible = "motorola,mapphone-cpcap-charger", @@ -873,20 +871,13 @@ static const struct of_device_id cpcap_charger_id_table[] = { {}, }; MODULE_DEVICE_TABLE(of, cpcap_charger_id_table); -#endif static int cpcap_charger_probe(struct platform_device *pdev) { struct cpcap_charger_ddata *ddata; - const struct of_device_id *of_id; struct power_supply_config psy_cfg = {}; int error; - of_id = of_match_device(of_match_ptr(cpcap_charger_id_table), - &pdev->dev); - if (!of_id) - return -EINVAL; - ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); if (!ddata) return -ENOMEM; @@ -975,7 +966,7 @@ static struct platform_driver cpcap_charger_driver = { .probe = cpcap_charger_probe, .driver = { .name = "cpcap-charger", - .of_match_table = of_match_ptr(cpcap_charger_id_table), + .of_match_table = cpcap_charger_id_table, }, .shutdown = cpcap_charger_shutdown, .remove_new = cpcap_charger_remove, From b0009b8bed98bd5d59449af48781703df261c247 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 18:14:47 +0000 Subject: [PATCH 84/91] power: supply: bq24190_charger: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect bdi->model_name to be NUL-terminated based on its usage with sysfs_emit and format strings: val->strval is assigned to bdi->model_name in bq24190_charger_get_property(): 1186 | val->strval = bdi->model_name; ... then in power_supply_sysfs.c we use value.strval with a format string: 311 | ret = sysfs_emit(buf, "%s\n", value.strval); we assigned value.strval via: 285 | ret = power_supply_get_property(psy, psp, &value); ... which invokes psy->desc->get_property(): 1210 | return psy->desc->get_property(psy, psp, val); with bq24190_charger_get_property(): 1320 | static const struct power_supply_desc bq24190_charger_desc = { ... 1325 | .get_property = bq24190_charger_get_property, Moreover, no NUL-padding is required as bdi is zero-allocated in bq24190_charger.c: 1798 | bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL); Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-bq24190_charger-c-v1-1-e896223cb795@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24190_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 3f99cb9590ba..1db290ee2591 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1803,7 +1803,7 @@ static int bq24190_probe(struct i2c_client *client) bdi->client = client; bdi->dev = dev; - strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); + strscpy(bdi->model_name, id->name, sizeof(bdi->model_name)); mutex_init(&bdi->f_reg_lock); bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST; bdi->f_reg = 0; From e3c2af5d49bb96ad460ef6aa873975fb0f7c7f17 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 18:59:34 +0000 Subject: [PATCH 85/91] power: supply: bq2515x: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect bq2515x->model_name to be NUL-terminated based on its usage with sysfs_emit and format strings: val->strval is assigned to bq2515x->model_name in bq2515x_mains_get_property(): | val->strval = bq2515x->model_name; ... then in power_supply_sysfs.c we use value.strval with a format string: | ret = sysfs_emit(buf, "%s\n", value.strval); we assigned value.strval via: | ret = power_supply_get_property(psy, psp, &value); ... which invokes psy->desc->get_property(): | return psy->desc->get_property(psy, psp, val); with bq2515x_mains_get_property(): | static const struct power_supply_desc bq2515x_mains_desc = { ... | .get_property = bq2515x_mains_get_property, Moreover, no NUL-padding is required as bq2515x is zero-allocated in bq2515x_charger.c: | bq2515x = devm_kzalloc(dev, sizeof(*bq2515x), GFP_KERNEL); Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt to use the more idiomatic strscpy() usage of (dest, src, sizeof(dest)) as this more closely ties the destination buffer and the length. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt Similar-to: https://lore.kernel.org/all/20231020-strncpy-drivers-power-supply-bq24190_charger-c-v1-1-e896223cb795@google.com/ Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-bq2515x_charger-c-v1-1-46664c6edf78@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq2515x_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq2515x_charger.c b/drivers/power/supply/bq2515x_charger.c index 49fa6386a509..a3424f67f2b1 100644 --- a/drivers/power/supply/bq2515x_charger.c +++ b/drivers/power/supply/bq2515x_charger.c @@ -1089,7 +1089,7 @@ static int bq2515x_probe(struct i2c_client *client) bq2515x->dev = dev; - strncpy(bq2515x->model_name, id->name, I2C_NAME_SIZE); + strscpy(bq2515x->model_name, id->name, sizeof(bq2515x->model_name)); bq2515x->info = i2c_get_match_data(client); bq2515x->regmap = devm_regmap_init_i2c(client, From 056a75599f5e676d497bbf9b29157877f542e56b Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 19:05:25 +0000 Subject: [PATCH 86/91] power: supply: bq256xx: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect bq->model_name to be NUL-terminated based on its usage with sysfs_emit and format strings: val->strval is assigned to bq->model_name in bq256xx_get_charger_property(): | val->strval = bq->model_name; ... then in power_supply_sysfs.c we use value.strval with a format string: | ret = sysfs_emit(buf, "%s\n", value.strval); we assigned value.strval via: | ret = power_supply_get_property(psy, psp, &value); ... which invokes psy->desc->get_property(): | return psy->desc->get_property(psy, psp, val); with bq256xx_get_charger_property(): | static const struct power_supply_desc bq256xx_power_supply_desc = { ... | .get_property = bq256xx_get_charger_property, Moreover, no NUL-padding is required as bq is zero-allocated in bq256xx_charger.c: | bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt to use the more idiomatic strscpy() usage of (dest, src, sizeof(dest)) as this more closely ties the destination buffer and the length. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Similar-to: https://lore.kernel.org/all/20231020-strncpy-drivers-power-supply-bq24190_charger-c-v1-1-e896223cb795@google.com/ Similar-to: https://lore.kernel.org/all/20231020-strncpy-drivers-power-supply-bq2515x_charger-c-v1-1-46664c6edf78@google.com/ Signed-off-by: Justin Stitt Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-bq256xx_charger-c-v1-1-2fad856124f9@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq256xx_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c index 474201815a27..789a31bd70c3 100644 --- a/drivers/power/supply/bq256xx_charger.c +++ b/drivers/power/supply/bq256xx_charger.c @@ -1706,7 +1706,7 @@ static int bq256xx_probe(struct i2c_client *client) mutex_init(&bq->lock); - strncpy(bq->model_name, id->name, I2C_NAME_SIZE); + strscpy(bq->model_name, id->name, sizeof(bq->model_name)); bq->regmap = devm_regmap_init_i2c(client, bq->chip_info->bq256xx_regmap_config); From afb0379b0f6657b9f626d23c3bb00b4e8823bd2d Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 19:11:07 +0000 Subject: [PATCH 87/91] power: supply: bq25980: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect bq->model_name to be NUL-terminated based on its usage with sysfs_emit and format strings: val->strval is assigned to bq->model_name in bq25980_get_charger_property(): | val->strval = bq->model_name; ... then in power_supply_sysfs.c we use value.strval with a format string: | ret = sysfs_emit(buf, "%s\n", value.strval); we assigned value.strval via: | ret = power_supply_get_property(psy, psp, &value); ... which invokes psy->desc->get_property(): | return psy->desc->get_property(psy, psp, val); with bq25980_get_charger_property(): | static const struct power_supply_desc bq25980_power_supply_desc = { ... | .get_property = bq25980_get_charger_property, Moreover, no NUL-padding is required as bq is zero-allocated in bq25980_charger.c: | bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt to use the more idiomatic strscpy() usage of (dest, src, sizeof(dest)) as this more closely ties the destination buffer and the length. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Similar-to: https://lore.kernel.org/all/20231020-strncpy-drivers-power-supply-bq24190_charger-c-v1-1-e896223cb795@google.com/ Similar-to: https://lore.kernel.org/all/20231020-strncpy-drivers-power-supply-bq2515x_charger-c-v1-1-46664c6edf78@google.com/ Signed-off-by: Justin Stitt Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-bq25980_charger-c-v1-1-7b93be54537b@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq25980_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c index d8411722266f..0c5e2938bb36 100644 --- a/drivers/power/supply/bq25980_charger.c +++ b/drivers/power/supply/bq25980_charger.c @@ -1223,7 +1223,7 @@ static int bq25980_probe(struct i2c_client *client) mutex_init(&bq->lock); - strncpy(bq->model_name, id->name, I2C_NAME_SIZE); + strscpy(bq->model_name, id->name, sizeof(bq->model_name)); bq->chip_info = &bq25980_chip_info_tbl[id->driver_data]; bq->regmap = devm_regmap_init_i2c(client, From e1402bd297a3477c16eca4c1e4094372237f40a7 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 19:21:46 +0000 Subject: [PATCH 88/91] power: supply: charger-manager: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect cm->psy_name_buf to be NUL-terminated based on its usage with format strings: 1522: cm->charger_psy_desc.name = cm->psy_name_buf; ... 1587: dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", 1587: cm->charger_psy_desc.name); Moreover, NUL-padding is not required as `cm` is already zero-allocated and thus any future NUL-byte assignments (like what strncpy() will do) are redundant: 1437: cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL); Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt for the more idiomatic strscpy() usage of: strscpy(dest, src, sizeof(dest)). Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-charger-manager-c-v1-1-698f73bcad2a@google.com 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 3936ff066600..96f0a7fbf105 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1516,9 +1516,11 @@ static int charger_manager_probe(struct platform_device *pdev) memcpy(&cm->charger_psy_desc, &psy_default, sizeof(psy_default)); if (!desc->psy_name) - strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX); + strscpy(cm->psy_name_buf, psy_default.name, + sizeof(cm->psy_name_buf)); else - strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX); + strscpy(cm->psy_name_buf, desc->psy_name, + sizeof(cm->psy_name_buf)); cm->charger_psy_desc.name = cm->psy_name_buf; /* Allocate for psy properties because they may vary */ From 81f07d2b0c4db3b6e53d90419db915c75beb6326 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 19:39:02 +0000 Subject: [PATCH 89/91] power: supply: surface_battery: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect bat->name to be NUL-terminated based on its usage with strcmp(): power_supply_core.c: 445: return strcmp(psy->desc->name, name) == 0; ... and also by the manual `... - 1` for the length argument of the original strncpy() invocation. Furthermore, no NUL-padding is needed as bat is zero-allocated before calling spwr_battery_init(): 826: bat = devm_kzalloc(&sdev->dev, sizeof(*bat), GFP_KERNEL); 827: if (!bat) 828: return -ENOMEM; 829: 830: spwr_battery_init(bat, sdev, p->registry, p->name); ... this means any further NUL-byte assignments (like the ones that strncpy() does) are redundant. Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt to use the more idiomatic strscpy() usage of: (dest, src, sizeof(dest)). Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-surface_battery-c-v2-1-29ed16b2caf1@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/surface_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/surface_battery.c b/drivers/power/supply/surface_battery.c index 19d2f8834e56..196d290dc596 100644 --- a/drivers/power/supply/surface_battery.c +++ b/drivers/power/supply/surface_battery.c @@ -722,7 +722,7 @@ static void spwr_battery_init(struct spwr_battery_device *bat, struct ssam_devic struct ssam_event_registry registry, const char *name) { mutex_init(&bat->lock); - strncpy(bat->name, name, ARRAY_SIZE(bat->name) - 1); + strscpy(bat->name, name, sizeof(bat->name)); bat->sdev = sdev; From afc88dfda013970bb1e214b331e99adca2f98312 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Fri, 20 Oct 2023 19:46:11 +0000 Subject: [PATCH 90/91] power: supply: surface-charger: replace deprecated strncpy with strscpy strncpy() is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We expect ac->name to be NUL-terminated based on its usage with format strings: surface_charger.c: 190: ac->psy_desc.name = ac->name; ... power_supply_core.c: 174: dev_dbg(&psy->dev, "%s: Found supply : %s\n", 175: psy->desc->name, epsy->desc->name); Moreover, NUL-padding is not required as ac is already zero-allocated before being passed to spwr_ac_init(): surface_charger.c: 240: ac = devm_kzalloc(&sdev->dev, sizeof(*ac), GFP_KERNEL); 241: if (!ac) 242: return -ENOMEM; 243: 244: spwr_ac_init(ac, sdev, p->registry, p->name); ... this means any future NUL-byte assignments (like the ones that strncpy() does) are redundant. Considering the above, a suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on the destination buffer without unnecessarily NUL-padding. Let's also opt for the more idiomatic strscpy() usage of: (dest, src, sizeof(dest)) Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt Link: https://lore.kernel.org/r/20231020-strncpy-drivers-power-supply-surface_charger-c-v1-1-93ddbf668e10@google.com Signed-off-by: Sebastian Reichel --- drivers/power/supply/surface_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/surface_charger.c b/drivers/power/supply/surface_charger.c index cabdd8da12d0..7a6c62d6f883 100644 --- a/drivers/power/supply/surface_charger.c +++ b/drivers/power/supply/surface_charger.c @@ -175,7 +175,7 @@ static void spwr_ac_init(struct spwr_ac_device *ac, struct ssam_device *sdev, struct ssam_event_registry registry, const char *name) { mutex_init(&ac->lock); - strncpy(ac->name, name, ARRAY_SIZE(ac->name) - 1); + strscpy(ac->name, name, sizeof(ac->name)); ac->sdev = sdev; From 469d31745b9fb3a87424b311abb7cb530611404f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 9 Oct 2023 12:29:14 -0500 Subject: [PATCH 91/91] power: reset: vexpress: Use device_get_match_data() Use preferred device_get_match_data() instead of of_match_device() to get the driver match data. With this, adjust the includes to explicitly include the correct headers. Signed-off-by: Rob Herring Acked-by: Sudeep Holla Link: https://lore.kernel.org/r/20231009172923.2457844-19-robh@kernel.org Signed-off-by: Sebastian Reichel --- drivers/power/reset/vexpress-poweroff.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 17064d7b19f6..bb22b2db5907 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -7,8 +7,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -108,20 +108,17 @@ static int _vexpress_register_restart_handler(struct device *dev) static int vexpress_reset_probe(struct platform_device *pdev) { - const struct of_device_id *match = - of_match_device(vexpress_reset_of_match, &pdev->dev); + enum vexpress_reset_func func; struct regmap *regmap; int ret = 0; - if (!match) - return -EINVAL; - regmap = devm_regmap_init_vexpress_config(&pdev->dev); if (IS_ERR(regmap)) return PTR_ERR(regmap); dev_set_drvdata(&pdev->dev, regmap); - switch ((uintptr_t)match->data) { + func = (uintptr_t)device_get_match_data(&pdev->dev); + switch (func) { case FUNC_SHUTDOWN: vexpress_power_off_device = &pdev->dev; pm_power_off = vexpress_power_off;