From 01b8f5b53e4df5d22d0e273fea5124a972e8d5c4 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 25 Nov 2020 08:19:18 +0100 Subject: dt-bindings: reset: ocelot: Add Luton and Jaguar2 support This adds the support for 2 others MIPS based VCore III SoCs: Luton and Jaguar2. Signed-off-by: Gregory CLEMENT Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/power/reset/ocelot-reset.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/power/reset/ocelot-reset.txt b/Documentation/devicetree/bindings/power/reset/ocelot-reset.txt index 4d530d815484..c5de7b555feb 100644 --- a/Documentation/devicetree/bindings/power/reset/ocelot-reset.txt +++ b/Documentation/devicetree/bindings/power/reset/ocelot-reset.txt @@ -7,7 +7,9 @@ The reset registers are both present in the MSCC vcoreiii MIPS and microchip Sparx5 armv8 SoC's. Required Properties: - - compatible: "mscc,ocelot-chip-reset" or "microchip,sparx5-chip-reset" + + - compatible: "mscc,ocelot-chip-reset", "mscc,luton-chip-reset", + "mscc,jaguar2-chip-reset" or "microchip,sparx5-chip-reset" Example: reset@1070008 { -- cgit v1.2.3 From aa4302c4933a419baf0546d7f6e59f27d4250797 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 25 Nov 2020 08:19:19 +0100 Subject: power: reset: ocelot: Add support 2 other MIPS based SoCs This adds reset support for Luton and Jaguar2 in the ocelot-reset driver. They are both MIPS based belonging to the Vcore III family. Acked-by: Alexandre Belloni Signed-off-by: Gregory CLEMENT Signed-off-by: Sebastian Reichel --- drivers/power/reset/ocelot-reset.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/power/reset/ocelot-reset.c b/drivers/power/reset/ocelot-reset.c index f74e1dbb4ba3..8caa90cb58fc 100644 --- a/drivers/power/reset/ocelot-reset.c +++ b/drivers/power/reset/ocelot-reset.c @@ -29,6 +29,8 @@ struct ocelot_reset_context { struct notifier_block restart_handler; }; +#define BIT_OFF_INVALID 32 + #define SOFT_CHIP_RST BIT(0) #define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 @@ -50,9 +52,11 @@ static int ocelot_restart_handle(struct notifier_block *this, ctx->props->vcore_protect, 0); /* Make the SI back to boot mode */ - regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, - IF_SI_OWNER_MASK << if_si_owner_bit, - IF_SI_OWNER_SIBM << if_si_owner_bit); + if (if_si_owner_bit != BIT_OFF_INVALID) + regmap_update_bits(ctx->cpu_ctrl, + ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, + IF_SI_OWNER_MASK << if_si_owner_bit, + IF_SI_OWNER_SIBM << if_si_owner_bit); pr_emerg("Resetting SoC\n"); @@ -96,6 +100,20 @@ static int ocelot_reset_probe(struct platform_device *pdev) return err; } +static const struct reset_props reset_props_jaguar2 = { + .syscon = "mscc,ocelot-cpu-syscon", + .protect_reg = 0x20, + .vcore_protect = BIT(2), + .if_si_owner_bit = 6, +}; + +static const struct reset_props reset_props_luton = { + .syscon = "mscc,ocelot-cpu-syscon", + .protect_reg = 0x20, + .vcore_protect = BIT(2), + .if_si_owner_bit = BIT_OFF_INVALID, /* n/a */ +}; + static const struct reset_props reset_props_ocelot = { .syscon = "mscc,ocelot-cpu-syscon", .protect_reg = 0x20, @@ -112,6 +130,12 @@ static const struct reset_props reset_props_sparx5 = { static const struct of_device_id ocelot_reset_of_match[] = { { + .compatible = "mscc,jaguar2-chip-reset", + .data = &reset_props_jaguar2 + }, { + .compatible = "mscc,luton-chip-reset", + .data = &reset_props_luton + }, { .compatible = "mscc,ocelot-chip-reset", .data = &reset_props_ocelot }, { -- cgit v1.2.3 From d4e9e7b6f7ae37a99bc11ce9efe6e8bdc711362f Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Wed, 25 Nov 2020 04:48:05 +0100 Subject: power: supply: bq25890: Use the correct range for IILIM register I've checked bq25890, bq25892, bq25895 and bq25896 datasheets and they all define IILIM to be between 100mA-3.25A with 50mA steps. Fixes: 478efc79ee32 ("power: bq25890: implement INPUT_CURRENT_LIMIT property") Signed-off-by: Sebastian Krzyszkowiak Reviewed-by: Michał Mirosław Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq25890_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 34c21c51bac1..945c3257ca93 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -299,7 +299,7 @@ static const union { /* TODO: BQ25896 has max ICHG 3008 mA */ [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ - [TBL_IILIM] = { .rt = {50000, 3200000, 50000} }, /* uA */ + [TBL_IILIM] = { .rt = {100000, 3250000, 50000} }, /* uA */ [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ -- cgit v1.2.3 From 4b0a56e692503692da6555337a697c17feabbb3e Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Wed, 25 Nov 2020 05:44:44 +0100 Subject: power: supply: max17042_battery: Fix current_{avg,now} hiding with no current sense When current sense is disabled, max17042_no_current_sense_psy_desc gets used which ignores two last properties from the list. Fixes: 21b01cc879cc ("power: supply: max17042_battery: Add support for the TTE_NOW prop") Reported-by: Timon Baetz Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index f284547913d6..2e9672fe4df1 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -85,9 +85,10 @@ static enum power_supply_property max17042_battery_props[] = { POWER_SUPPLY_PROP_TEMP_MAX, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_SCOPE, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, + // these two have to be at the end on the list POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_AVG, - POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, }; static int max17042_get_temperature(struct max17042_chip *chip, int *temp) -- cgit v1.2.3 From 9e39ef148777727360dabebacd70d60f3e0edc48 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Wed, 25 Nov 2020 05:46:17 +0100 Subject: power: supply: max17042_battery: Improve accuracy of current_now and current_avg readings Dividing 1562500 by r_sns value usually doesn't result in an integer. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 2e9672fe4df1..86adccb0f32d 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -395,8 +395,8 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - val->intval = sign_extend32(data, 15); - val->intval *= 1562500 / chip->pdata->r_sns; + data64 = sign_extend64(data, 15) * 1562500ll; + val->intval = div_s64(data64, chip->pdata->r_sns); } else { return -EINVAL; } @@ -407,8 +407,8 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - val->intval = sign_extend32(data, 15); - val->intval *= 1562500 / chip->pdata->r_sns; + data64 = sign_extend64(data, 15) * 1562500ll; + val->intval = div_s64(data64, chip->pdata->r_sns); } else { return -EINVAL; } -- cgit v1.2.3 From 6dcfa009f8a96273f074032c888409ee2b26f498 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Wed, 25 Nov 2020 05:47:04 +0100 Subject: power: supply: max17042_battery: Take r_sns value into account in charge_counter The default r_sns value was hardcoded there, so let's change it to the actually configured one. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 86adccb0f32d..26f6f89eb648 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -354,7 +354,8 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - val->intval = data * 1000 / 2; + data64 = sign_extend64(data, 15) * 5000000ll; + val->intval = div_s64(data64, chip->pdata->r_sns); break; case POWER_SUPPLY_PROP_TEMP: ret = max17042_get_temperature(chip, &val->intval); -- cgit v1.2.3 From 5225371e56c512abe5c5acc271256c2c390903c5 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Wed, 25 Nov 2020 05:48:30 +0100 Subject: power: supply: max17042_battery: Export charge termination current property The value is there, so let's export it. Signed-off-by: Sebastian Krzyszkowiak Signed-off-by: Sebastian Reichel --- drivers/power/supply/max17042_battery.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 26f6f89eb648..79d4b5988360 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -78,6 +78,7 @@ static enum power_supply_property max17042_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TEMP_ALERT_MIN, POWER_SUPPLY_PROP_TEMP_ALERT_MAX, @@ -414,6 +415,14 @@ static int max17042_get_property(struct power_supply *psy, return -EINVAL; } break; + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + ret = regmap_read(map, MAX17042_ICHGTerm, &data); + if (ret < 0) + return ret; + + data64 = data * 1562500ll; + val->intval = div_s64(data64, chip->pdata->r_sns); + break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: ret = regmap_read(map, MAX17042_TTE, &data); if (ret < 0) -- cgit v1.2.3 From a0f1ccd96c7049377d892a4299b6d5e47ec9179d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 18 Nov 2020 13:13:12 +0100 Subject: power: supply: axp288_charger: Fix HP Pavilion x2 10 DMI matching Commit 9c80662a74cd ("power: supply: axp288_charger: Add special handling for HP Pavilion x2 10") added special handling for HP Pavilion x2 10 models which use the weird combination of a Type-C connector and the non Type-C aware AXP288 PMIC. This special handling was activated by a DMI match a the product-name of "HP Pavilion x2 Detachable". Recently I've learned that there are also older "HP Pavilion x2 Detachable" models with an AXP288 PMIC + a micro-usb connector where we should not activate the special handling for the Type-C connectors. Extend the matching to also match on the DMI board-name and match on the 2 boards (one Bay Trail based one Cherry Trail based) of which we are certain that they use the AXP288 + Type-C connector combination. Note the DSDT code from these older (AXP288 + micro-USB) models contains some AML code (which never runs under Linux) which reads the micro-USB connector id-pin and if it is pulled to ground, which would normally mean the port is in host mode!, then it sets the input-current-limit to 3A, it seems HP is using the micro-USB port as a charging only connector and identifies their own 3A capable charger though this hack which is a major violation of the USB specs. Note HP also hardcodes a 2A limit when the id-pin is not pulled to ground, which is also in violation of the specs. I've no intention to add support for HP's hack to support 3A charging on these older models. By making the DMI matches for the Type-C equipped models workaround more tighter, these older models will be treated just like any other AXP288 + micro-USB equipped device and the input-current limit will follow the BC 1.2 spec (using the defacto standard values there where the BC 1.2 spec defines a range). Fixes: 9c80662a74cd ("power: supply: axp288_charger: Add special handling for HP Pavilion x2 10") BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1896924 Signed-off-by: Hans de Goede Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp288_charger.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 9d981b76c1e7..a4df1ea92386 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -548,14 +548,15 @@ out: /* * The HP Pavilion x2 10 series comes in a number of variants: - * Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D" - * Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E" - * Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4" + * Bay Trail SoC + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021" + * Bay Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "815D" + * Cherry Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "813E" + * Cherry Trail SoC + TI PMIC, Type-C, DMI_BOARD_NAME: "827C" or "82F4" * - * The variants with the AXP288 PMIC are all kinds of special: + * The variants with the AXP288 + Type-C connector are all kinds of special: * - * 1. All variants use a Type-C connector which the AXP288 does not support, so - * when using a Type-C charger it is not recognized. Unlike most AXP288 devices, + * 1. They use a Type-C connector which the AXP288 does not support, so when + * using a Type-C charger it is not recognized. Unlike most AXP288 devices, * this model actually has mostly working ACPI AC / Battery code, the ACPI code * "solves" this by simply setting the input_current_limit to 3A. * There are still some issues with the ACPI code, so we use this native driver, @@ -578,12 +579,17 @@ out: */ static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = { { - /* - * Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry - * Trail model has "HP", so we only match on product_name. - */ .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"), + }, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"), }, }, {} /* Terminating entry */ -- cgit v1.2.3 From df12470ce775cd126f26c96d240959b0c1929e23 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 16 Nov 2020 09:07:19 +0800 Subject: power: supply: Fix missing IRQF_ONESHOT as only threaded handler Coccinelle noticed: drivers/power/supply/ab8500_btemp.c:1107:8-28: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT. Signed-off-by: Tian Tao Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_btemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 909f0242bacb..e0b662b82255 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -1105,7 +1105,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { -- cgit v1.2.3 From 91bc9e1938c4682972541cba784f335af2b81f66 Mon Sep 17 00:00:00 2001 From: Nigel Christian Date: Fri, 13 Nov 2020 23:57:47 -0500 Subject: power: supply: pm2301_charger: remove unnecessary variable The variable "ret" is initialized to zero and then returned. Remove it and return zero. Signed-off-by: Nigel Christian Signed-off-by: Sebastian Reichel --- drivers/power/supply/pm2301_charger.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/power/supply/pm2301_charger.c b/drivers/power/supply/pm2301_charger.c index 2df6a2459d1f..ac06ecf7fc9c 100644 --- a/drivers/power/supply/pm2301_charger.c +++ b/drivers/power/supply/pm2301_charger.c @@ -455,7 +455,6 @@ static int pm2_int_reg4(void *pm2_data, int val) static int pm2_int_reg5(void *pm2_data, int val) { struct pm2xxx_charger *pm2 = pm2_data; - int ret = 0; if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) { dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n"); @@ -468,7 +467,7 @@ static int pm2_int_reg5(void *pm2_data, int val) dev_dbg(pm2->dev, "Falling/Rising edge on WPWR1/2\n"); } - return ret; + return 0; } static irqreturn_t pm2xxx_irq_int(int irq, void *data) -- cgit v1.2.3 From 70bd58fff29dc4c53cfea2da01f05d2377d2ffa9 Mon Sep 17 00:00:00 2001 From: Timon Baetz Date: Mon, 9 Nov 2020 19:43:12 +0000 Subject: power: supply: max8997-charger: Use module_platform_driver() Replace register and unregister function calls with module_platform_driver(). Signed-off-by: Timon Baetz Signed-off-by: Sebastian Reichel --- drivers/power/supply/max8997_charger.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index f5e84cd47924..94d1ade047a7 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c @@ -168,18 +168,7 @@ static struct platform_driver max8997_battery_driver = { .probe = max8997_battery_probe, .id_table = max8997_battery_id, }; - -static int __init max8997_battery_init(void) -{ - return platform_driver_register(&max8997_battery_driver); -} -subsys_initcall(max8997_battery_init); - -static void __exit max8997_battery_cleanup(void) -{ - platform_driver_unregister(&max8997_battery_driver); -} -module_exit(max8997_battery_cleanup); +module_platform_driver(max8997_battery_driver); MODULE_DESCRIPTION("MAXIM 8997/8966 battery control driver"); MODULE_AUTHOR("MyungJoo Ham "); -- cgit v1.2.3 From 5976a8d0bd4796ef6a0cb1f567a0d82967c62408 Mon Sep 17 00:00:00 2001 From: Timon Baetz Date: Mon, 9 Nov 2020 19:43:28 +0000 Subject: power: supply: max8997-charger: Fix platform data retrieval Use pdata field of max8998_dev struct to obtain platform data. Signed-off-by: Timon Baetz Signed-off-by: Sebastian Reichel --- drivers/power/supply/max8997_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index 94d1ade047a7..8fccd58dac67 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c @@ -84,7 +84,7 @@ static int max8997_battery_probe(struct platform_device *pdev) int ret = 0; struct charger_data *charger; struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); + struct max8997_platform_data *pdata = iodev->pdata; struct power_supply_config psy_cfg = {}; if (!pdata) -- cgit v1.2.3 From 9c65f6c4482d0e3e3681c113f77f82ac571ceaa7 Mon Sep 17 00:00:00 2001 From: Timon Baetz Date: Mon, 9 Nov 2020 19:43:55 +0000 Subject: power: supply: max8997-charger: Improve getting charger status Detect charging and discharging state. Ported from downstream Samsung Galaxy S2 (i9100) kernel fork. Signed-off-by: Timon Baetz Signed-off-by: Sebastian Reichel --- drivers/power/supply/max8997_charger.c | 52 +++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c index 8fccd58dac67..1947af25879a 100644 --- a/drivers/power/supply/max8997_charger.c +++ b/drivers/power/supply/max8997_charger.c @@ -13,6 +13,20 @@ #include #include +/* MAX8997_REG_STATUS4 */ +#define DCINOK_SHIFT 1 +#define DCINOK_MASK (1 << DCINOK_SHIFT) +#define DETBAT_SHIFT 2 +#define DETBAT_MASK (1 << DETBAT_SHIFT) + +/* MAX8997_REG_MBCCTRL1 */ +#define TFCH_SHIFT 4 +#define TFCH_MASK (7 << TFCH_SHIFT) + +/* MAX8997_REG_MBCCTRL5 */ +#define ITOPOFF_SHIFT 0 +#define ITOPOFF_MASK (0xF << ITOPOFF_SHIFT) + struct charger_data { struct device *dev; struct max8997_dev *iodev; @@ -20,7 +34,7 @@ struct charger_data { }; static enum power_supply_property max8997_battery_props[] = { - POWER_SUPPLY_PROP_STATUS, /* "FULL" or "NOT FULL" only. */ + POWER_SUPPLY_PROP_STATUS, /* "FULL", "CHARGING" or "DISCHARGING". */ POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */ POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */ }; @@ -43,6 +57,10 @@ static int max8997_battery_get_property(struct power_supply *psy, return ret; if ((reg & (1 << 0)) == 0x1) val->intval = POWER_SUPPLY_STATUS_FULL; + else if ((reg & DCINOK_MASK)) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; case POWER_SUPPLY_PROP_PRESENT: @@ -50,7 +68,7 @@ static int max8997_battery_get_property(struct power_supply *psy, ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®); if (ret) return ret; - if ((reg & (1 << 2)) == 0x0) + if ((reg & DETBAT_MASK) == 0x0) val->intval = 1; break; @@ -59,8 +77,7 @@ static int max8997_battery_get_property(struct power_supply *psy, ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, ®); if (ret) return ret; - /* DCINOK */ - if (reg & (1 << 1)) + if (reg & DCINOK_MASK) val->intval = 1; break; @@ -84,11 +101,14 @@ static int max8997_battery_probe(struct platform_device *pdev) int ret = 0; struct charger_data *charger; struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *i2c = iodev->i2c; struct max8997_platform_data *pdata = iodev->pdata; struct power_supply_config psy_cfg = {}; - if (!pdata) + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied.\n"); return -EINVAL; + } if (pdata->eoc_mA) { int val = (pdata->eoc_mA - 50) / 10; @@ -97,30 +117,29 @@ static int max8997_battery_probe(struct platform_device *pdev) if (val > 0xf) val = 0xf; - ret = max8997_update_reg(iodev->i2c, - MAX8997_REG_MBCCTRL5, val, 0xf); + ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL5, + val << ITOPOFF_SHIFT, ITOPOFF_MASK); if (ret < 0) { dev_err(&pdev->dev, "Cannot use i2c bus.\n"); return ret; } } - switch (pdata->timeout) { case 5: - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, - 0x2 << 4, 0x7 << 4); + ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1, + 0x2 << TFCH_SHIFT, TFCH_MASK); break; case 6: - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, - 0x3 << 4, 0x7 << 4); + ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1, + 0x3 << TFCH_SHIFT, TFCH_MASK); break; case 7: - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, - 0x4 << 4, 0x7 << 4); + ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1, + 0x4 << TFCH_SHIFT, TFCH_MASK); break; case 0: - ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1, - 0x7 << 4, 0x7 << 4); + ret = max8997_update_reg(i2c, MAX8997_REG_MBCCTRL1, + 0x7 << TFCH_SHIFT, TFCH_MASK); break; default: dev_err(&pdev->dev, "incorrect timeout value (%d)\n", @@ -138,7 +157,6 @@ static int max8997_battery_probe(struct platform_device *pdev) platform_set_drvdata(pdev, charger); - charger->dev = &pdev->dev; charger->iodev = iodev; -- cgit v1.2.3 From fbda05f7c6487ac88c5f273a74735c3afe414db6 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 9 Nov 2020 20:10:38 +0800 Subject: power: supply: axp20x_usb_power: fix typo s/on on/on Signed-off-by: Yangtao Li 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 0eaa86c52874..3b4fd710347d 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -397,7 +397,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy, struct axp20x_usb_power *power = power_supply_get_drvdata(psy); /* - * The VBUS path select flag works differently on on AXP288 and newer: + * The VBUS path select flag works differently on AXP288 and newer: * - On AXP20x and AXP22x, the flag enables VBUS (ignoring N_VBUSEN). * - On AXP288 and AXP8xx, the flag disables VBUS (ignoring N_VBUSEN). * We only expose the control on variants where it can be used to force -- cgit v1.2.3 From 0dd713ef2134bac2ee25562990dd6ecbc6feb615 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Mon, 9 Nov 2020 20:11:04 +0800 Subject: power: supply: axp20x_usb_power: Use power efficient workqueue for debounce The debounce timeout is generally quite long and the work not performance critical so allow the scheduler to run the work anywhere rather than in the normal per-CPU workqueue. Signed-off-by: Yangtao Li Signed-off-by: Sebastian Reichel --- drivers/power/supply/axp20x_usb_power.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index 3b4fd710347d..70b28b699a80 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -92,7 +92,7 @@ static irqreturn_t axp20x_usb_power_irq(int irq, void *devid) power_supply_changed(power->supply); - mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME); + mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); return IRQ_HANDLED; } @@ -117,7 +117,7 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work) out: if (axp20x_usb_vbus_needs_polling(power)) - mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME); + mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); } static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val) @@ -525,7 +525,7 @@ static int axp20x_usb_power_resume(struct device *dev) while (i < power->num_irqs) enable_irq(power->irqs[i++]); - mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME); + mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); return 0; } @@ -647,7 +647,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&power->vbus_detect, axp20x_usb_power_poll_vbus); if (axp20x_usb_vbus_needs_polling(power)) - queue_delayed_work(system_wq, &power->vbus_detect, 0); + queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0); return 0; } -- cgit v1.2.3 From 36dbca148bf8e3b8658982aa2256bdc7ef040256 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 5 Nov 2020 14:32:50 +0100 Subject: power: reset: Use printk format symbol resolver Instead of looking up a symbol name by hand, use the %ps printk format specifier. Signed-off-by: Helge Deller Signed-off-by: Sebastian Reichel --- drivers/power/reset/qnap-poweroff.c | 8 ++------ drivers/power/reset/syscon-poweroff.c | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c index 52b7dc61d870..0ddf7f25f7b8 100644 --- a/drivers/power/reset/qnap-poweroff.c +++ b/drivers/power/reset/qnap-poweroff.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -75,7 +74,6 @@ static int qnap_power_off_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct resource *res; struct clk *clk; - char symname[KSYM_NAME_LEN]; const struct of_device_id *match = of_match_node(qnap_power_off_of_match_table, np); @@ -104,10 +102,8 @@ static int qnap_power_off_probe(struct platform_device *pdev) /* Check that nothing else has already setup a handler */ if (pm_power_off) { - lookup_symbol_name((ulong)pm_power_off, symname); - dev_err(&pdev->dev, - "pm_power_off already claimed %p %s", - pm_power_off, symname); + dev_err(&pdev->dev, "pm_power_off already claimed for %ps", + pm_power_off); return -EBUSY; } pm_power_off = qnap_power_off; diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index 4d6923b102b6..ed58bdf41e27 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -6,7 +6,6 @@ * Author: Moritz Fischer */ -#include #include #include #include @@ -34,7 +33,6 @@ static void syscon_poweroff(void) static int syscon_poweroff_probe(struct platform_device *pdev) { - char symname[KSYM_NAME_LEN]; int mask_err, value_err; map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap"); @@ -65,10 +63,8 @@ static int syscon_poweroff_probe(struct platform_device *pdev) } if (pm_power_off) { - lookup_symbol_name((ulong)pm_power_off, symname); - dev_err(&pdev->dev, - "pm_power_off already claimed %p %s", - pm_power_off, symname); + dev_err(&pdev->dev, "pm_power_off already claimed for %ps", + pm_power_off); return -EBUSY; } -- cgit v1.2.3 From 7776bcd241e08e13ef009926c6dea84dc3b2f8ff Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 3 Nov 2020 00:48:44 +0100 Subject: power: supply: s3c-adc-battery: Convert to GPIO descriptors This converts the S3C ADC battery to use GPIO descriptors instead of a global GPIO number for the charging completed GPIO. Using the pattern from the GPIO charger we name this GPIO line "charge-status" in the board file. Cc: linux-samsung-soc@vger.kernel.org Cc: Sergiy Kibrik Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- arch/arm/mach-s3c/mach-h1940.c | 12 +++++-- arch/arm/mach-s3c/mach-rx1950.c | 11 ++++++- drivers/power/supply/s3c_adc_battery.c | 57 +++++++++++++++++----------------- include/linux/s3c_adc_battery.h | 3 -- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/arch/arm/mach-s3c/mach-h1940.c b/arch/arm/mach-s3c/mach-h1940.c index 53d51aa83200..8a43ed1c4c4d 100644 --- a/arch/arm/mach-s3c/mach-h1940.c +++ b/arch/arm/mach-s3c/mach-h1940.c @@ -297,6 +297,15 @@ static const struct s3c_adc_bat_thresh bat_lut_acin[] = { { .volt = 3841, .cur = 0, .level = 0}, }; +static struct gpiod_lookup_table h1940_bat_gpio_table = { + .dev_id = "s3c-adc-battery", + .table = { + /* Charge status S3C2410_GPF(3) */ + GPIO_LOOKUP("GPIOF", 3, "charge-status", GPIO_ACTIVE_LOW), + { }, + }, +}; + static int h1940_bat_init(void) { int ret; @@ -330,8 +339,6 @@ static struct s3c_adc_bat_pdata h1940_bat_cfg = { .exit = h1940_bat_exit, .enable_charger = h1940_enable_charger, .disable_charger = h1940_disable_charger, - .gpio_charge_finished = S3C2410_GPF(3), - .gpio_inverted = 1, .lut_noac = bat_lut_noac, .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac), .lut_acin = bat_lut_acin, @@ -720,6 +727,7 @@ static void __init h1940_init(void) s3c24xx_fb_set_platdata(&h1940_fb_info); gpiod_add_lookup_table(&h1940_mmc_gpio_table); gpiod_add_lookup_table(&h1940_audio_gpio_table); + gpiod_add_lookup_table(&h1940_bat_gpio_table); /* Configure the I2S pins (GPE0...GPE4) in correct mode */ s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), S3C_GPIO_PULL_NONE); diff --git a/arch/arm/mach-s3c/mach-rx1950.c b/arch/arm/mach-s3c/mach-rx1950.c index b9758f0a9a14..6e19add158a9 100644 --- a/arch/arm/mach-s3c/mach-rx1950.c +++ b/arch/arm/mach-s3c/mach-rx1950.c @@ -206,6 +206,15 @@ static const struct s3c_adc_bat_thresh bat_lut_acin[] = { { .volt = 3820, .cur = 0, .level = 0}, }; +static struct gpiod_lookup_table rx1950_bat_gpio_table = { + .dev_id = "s3c-adc-battery", + .table = { + /* Charge status S3C2410_GPF(3) */ + GPIO_LOOKUP("GPIOF", 3, "charge-status", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static int rx1950_bat_init(void) { int ret; @@ -331,7 +340,6 @@ static struct s3c_adc_bat_pdata rx1950_bat_cfg = { .exit = rx1950_bat_exit, .enable_charger = rx1950_enable_charger, .disable_charger = rx1950_disable_charger, - .gpio_charge_finished = S3C2410_GPF(3), .lut_noac = bat_lut_noac, .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac), .lut_acin = bat_lut_acin, @@ -840,6 +848,7 @@ static void __init rx1950_init_machine(void) pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup)); gpiod_add_lookup_table(&rx1950_audio_gpio_table); + gpiod_add_lookup_table(&rx1950_bat_gpio_table); /* Configure the I2S pins (GPE0...GPE4) in correct mode */ s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), S3C_GPIO_PULL_NONE); diff --git a/drivers/power/supply/s3c_adc_battery.c b/drivers/power/supply/s3c_adc_battery.c index 60b7f41ab063..a2addc24ee8b 100644 --- a/drivers/power/supply/s3c_adc_battery.c +++ b/drivers/power/supply/s3c_adc_battery.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,6 +31,7 @@ struct s3c_adc_bat { struct power_supply *psy; struct s3c_adc_client *client; struct s3c_adc_bat_pdata *pdata; + struct gpio_desc *charge_finished; int volt_value; int cur_value; unsigned int timestamp; @@ -132,9 +133,7 @@ static int calc_full_volt(int volt_val, int cur_val, int impedance) static int charge_finished(struct s3c_adc_bat *bat) { - return bat->pdata->gpio_inverted ? - !gpio_get_value(bat->pdata->gpio_charge_finished) : - gpio_get_value(bat->pdata->gpio_charge_finished); + return gpiod_get_value(bat->charge_finished); } static int s3c_adc_bat_get_property(struct power_supply *psy, @@ -169,7 +168,7 @@ static int s3c_adc_bat_get_property(struct power_supply *psy, } if (bat->cable_plugged && - ((bat->pdata->gpio_charge_finished < 0) || + (!bat->charge_finished || !charge_finished(bat))) { lut = bat->pdata->lut_acin; lut_size = bat->pdata->lut_acin_cnt; @@ -206,7 +205,7 @@ static int s3c_adc_bat_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_STATUS: - if (bat->pdata->gpio_charge_finished < 0) + if (!bat->charge_finished) val->intval = bat->level == 100000 ? POWER_SUPPLY_STATUS_FULL : bat->status; else @@ -265,7 +264,7 @@ static void s3c_adc_bat_work(struct work_struct *work) bat->status = POWER_SUPPLY_STATUS_DISCHARGING; } } else { - if ((bat->pdata->gpio_charge_finished >= 0) && is_plugged) { + if (bat->charge_finished && is_plugged) { is_charged = charge_finished(&main_bat); if (is_charged) { if (bat->pdata->disable_charger) @@ -294,6 +293,7 @@ static int s3c_adc_bat_probe(struct platform_device *pdev) struct s3c_adc_client *client; struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; + struct gpio_desc *gpiod; int ret; client = s3c_adc_register(pdev, NULL, NULL, 0); @@ -304,8 +304,17 @@ static int s3c_adc_bat_probe(struct platform_device *pdev) platform_set_drvdata(pdev, client); + gpiod = devm_gpiod_get_optional(&pdev->dev, "charge-status", GPIOD_IN); + if (IS_ERR(gpiod)) { + /* Could be probe deferral etc */ + ret = PTR_ERR(gpiod); + dev_err(&pdev->dev, "no GPIO %d\n", ret); + return ret; + } + main_bat.client = client; main_bat.pdata = pdata; + main_bat.charge_finished = gpiod; main_bat.volt_value = -1; main_bat.cur_value = -1; main_bat.cable_plugged = 0; @@ -323,6 +332,7 @@ static int s3c_adc_bat_probe(struct platform_device *pdev) backup_bat.client = client; backup_bat.pdata = pdev->dev.platform_data; + backup_bat.charge_finished = gpiod; backup_bat.volt_value = -1; backup_bat.psy = power_supply_register(&pdev->dev, &backup_bat_desc, @@ -335,12 +345,8 @@ static int s3c_adc_bat_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work); - if (pdata->gpio_charge_finished >= 0) { - ret = gpio_request(pdata->gpio_charge_finished, "charged"); - if (ret) - goto err_gpio; - - ret = request_irq(gpio_to_irq(pdata->gpio_charge_finished), + if (gpiod) { + ret = request_irq(gpiod_to_irq(gpiod), s3c_adc_bat_charged, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "battery charged", NULL); @@ -364,12 +370,9 @@ static int s3c_adc_bat_probe(struct platform_device *pdev) return 0; err_platform: - if (pdata->gpio_charge_finished >= 0) - free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); + if (gpiod) + free_irq(gpiod_to_irq(gpiod), NULL); err_irq: - if (pdata->gpio_charge_finished >= 0) - gpio_free(pdata->gpio_charge_finished); -err_gpio: if (pdata->backup_volt_mult) power_supply_unregister(backup_bat.psy); err_reg_backup: @@ -389,10 +392,8 @@ static int s3c_adc_bat_remove(struct platform_device *pdev) s3c_adc_release(client); - if (pdata->gpio_charge_finished >= 0) { - free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); - gpio_free(pdata->gpio_charge_finished); - } + if (main_bat.charge_finished) + free_irq(gpiod_to_irq(main_bat.charge_finished), NULL); cancel_delayed_work(&bat_work); @@ -408,12 +409,12 @@ static int s3c_adc_bat_suspend(struct platform_device *pdev, { struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; - if (pdata->gpio_charge_finished >= 0) { + if (main_bat.charge_finished) { if (device_may_wakeup(&pdev->dev)) enable_irq_wake( - gpio_to_irq(pdata->gpio_charge_finished)); + gpiod_to_irq(main_bat.charge_finished)); else { - disable_irq(gpio_to_irq(pdata->gpio_charge_finished)); + disable_irq(gpiod_to_irq(main_bat.charge_finished)); main_bat.pdata->disable_charger(); } } @@ -425,12 +426,12 @@ static int s3c_adc_bat_resume(struct platform_device *pdev) { struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; - if (pdata->gpio_charge_finished >= 0) { + if (main_bat.charge_finished) { if (device_may_wakeup(&pdev->dev)) disable_irq_wake( - gpio_to_irq(pdata->gpio_charge_finished)); + gpiod_to_irq(main_bat.charge_finished)); else - enable_irq(gpio_to_irq(pdata->gpio_charge_finished)); + enable_irq(gpiod_to_irq(main_bat.charge_finished)); } /* Schedule timer to check current status */ diff --git a/include/linux/s3c_adc_battery.h b/include/linux/s3c_adc_battery.h index 833871dcf6fd..57f982c375f8 100644 --- a/include/linux/s3c_adc_battery.h +++ b/include/linux/s3c_adc_battery.h @@ -14,9 +14,6 @@ struct s3c_adc_bat_pdata { void (*enable_charger)(void); void (*disable_charger)(void); - int gpio_charge_finished; - int gpio_inverted; - const struct s3c_adc_bat_thresh *lut_noac; unsigned int lut_noac_cnt; const struct s3c_adc_bat_thresh *lut_acin; -- cgit v1.2.3 From b2f6cb78eaa1cad57dd3fe11d0458cd4fae9a584 Mon Sep 17 00:00:00 2001 From: Zhang Qilong Date: Mon, 2 Nov 2020 22:33:21 +0800 Subject: power: supply: bq24190_charger: fix reference leak pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to call pm_runtime_put_noidle will result in reference leak in callers(bq24190_sysfs_show, bq24190_charger_get_property, bq24190_charger_set_property, bq24190_battery_get_property, bq24190_battery_set_property), so we should fix it. Fixes: f385e6e2a1532 ("power: bq24190_charger: Use PM runtime autosuspend") Signed-off-by: Zhang Qilong Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24190_charger.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index d14186525e1e..845af0f44c02 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -448,8 +448,10 @@ static ssize_t bq24190_sysfs_show(struct device *dev, return -EINVAL; ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v); if (ret) @@ -1077,8 +1079,10 @@ static int bq24190_charger_get_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_CHARGE_TYPE: @@ -1149,8 +1153,10 @@ static int bq24190_charger_set_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_ONLINE: @@ -1410,8 +1416,10 @@ static int bq24190_battery_get_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_STATUS: @@ -1456,8 +1464,10 @@ static int bq24190_battery_set_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_ONLINE: -- cgit v1.2.3 From ba940ed83218f034f728184439c7e87795237752 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2020 15:34:01 +0100 Subject: power: supply: collie_battery: Convert to GPIO descriptors This converts the Collie battery driver to use GPIO descriptors. We use a mixture of 3 GPIOs defined in the machine and 3 GPIOs requested directly from the ucb1x00 chip. Cc: Robert Jarzmik Cc: Dmitry Eremin-Solenikov Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- arch/arm/mach-sa1100/collie.c | 21 +++++ drivers/power/supply/collie_battery.c | 151 ++++++++++++++++++++++++---------- 2 files changed, 130 insertions(+), 42 deletions(-) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index bd3a52fd09ce..d4e89a02c8c8 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -98,6 +98,26 @@ static struct mcp_plat_data collie_mcp_data = { .codec_pdata = &collie_ucb1x00_data, }; +/* Battery management GPIOs */ +static struct gpiod_lookup_table collie_battery_gpiod_table = { + /* the MCP codec mcp0 has the ucb1x00 as attached device */ + .dev_id = "ucb1x00", + .table = { + /* This is found on the main GPIO on the SA1100 */ + GPIO_LOOKUP("gpio", COLLIE_GPIO_CO, + "main battery full", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio", COLLIE_GPIO_MAIN_BAT_LOW, + "main battery low", GPIO_ACTIVE_HIGH), + /* + * This is GPIO 0 on the Scoop expander, which is registered + * from common/scoop.c with this gpio chip label. + */ + GPIO_LOOKUP("sharp-scoop", 0, + "main charge on", GPIO_ACTIVE_HIGH), + { }, + }, +}; + static int collie_ir_startup(struct device *dev) { int rc = gpio_request(COLLIE_GPIO_IR_ON, "IrDA"); @@ -395,6 +415,7 @@ static void __init collie_init(void) platform_scoop_config = &collie_pcmcia_config; gpiod_add_lookup_table(&collie_power_gpiod_table); + gpiod_add_lookup_table(&collie_battery_gpiod_table); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); if (ret) { diff --git a/drivers/power/supply/collie_battery.c b/drivers/power/supply/collie_battery.c index cbd588e9e233..7fb9b549f2de 100644 --- a/drivers/power/supply/collie_battery.c +++ b/drivers/power/supply/collie_battery.c @@ -12,7 +12,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -31,18 +33,18 @@ struct collie_bat { struct mutex work_lock; /* protects data */ bool (*is_present)(struct collie_bat *bat); - int gpio_full; - int gpio_charge_on; + struct gpio_desc *gpio_full; + struct gpio_desc *gpio_charge_on; int technology; - int gpio_bat; + struct gpio_desc *gpio_bat; int adc_bat; int adc_bat_divider; int bat_max; int bat_min; - int gpio_temp; + struct gpio_desc *gpio_temp; int adc_temp; int adc_temp_divider; }; @@ -53,15 +55,15 @@ static unsigned long collie_read_bat(struct collie_bat *bat) { unsigned long value = 0; - if (bat->gpio_bat < 0 || bat->adc_bat < 0) + if (!bat->gpio_bat || bat->adc_bat < 0) return 0; mutex_lock(&bat_lock); - gpio_set_value(bat->gpio_bat, 1); + gpiod_set_value(bat->gpio_bat, 1); msleep(5); ucb1x00_adc_enable(ucb); value = ucb1x00_adc_read(ucb, bat->adc_bat, UCB_SYNC); ucb1x00_adc_disable(ucb); - gpio_set_value(bat->gpio_bat, 0); + gpiod_set_value(bat->gpio_bat, 0); mutex_unlock(&bat_lock); value = value * 1000000 / bat->adc_bat_divider; @@ -71,16 +73,16 @@ static unsigned long collie_read_bat(struct collie_bat *bat) static unsigned long collie_read_temp(struct collie_bat *bat) { unsigned long value = 0; - if (bat->gpio_temp < 0 || bat->adc_temp < 0) + if (!bat->gpio_temp || bat->adc_temp < 0) return 0; mutex_lock(&bat_lock); - gpio_set_value(bat->gpio_temp, 1); + gpiod_set_value(bat->gpio_temp, 1); msleep(5); ucb1x00_adc_enable(ucb); value = ucb1x00_adc_read(ucb, bat->adc_temp, UCB_SYNC); ucb1x00_adc_disable(ucb); - gpio_set_value(bat->gpio_temp, 0); + gpiod_set_value(bat->gpio_temp, 0); mutex_unlock(&bat_lock); value = value * 10000 / bat->adc_temp_divider; @@ -162,23 +164,23 @@ static void collie_bat_update(struct collie_bat *bat) bat->full_chrg = -1; } else if (power_supply_am_i_supplied(psy)) { if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) { - gpio_set_value(bat->gpio_charge_on, 1); + gpiod_set_value(bat->gpio_charge_on, 1); mdelay(15); } - if (gpio_get_value(bat->gpio_full)) { + if (gpiod_get_value(bat->gpio_full)) { if (old == POWER_SUPPLY_STATUS_CHARGING || bat->full_chrg == -1) bat->full_chrg = collie_read_bat(bat); - gpio_set_value(bat->gpio_charge_on, 0); + gpiod_set_value(bat->gpio_charge_on, 0); bat->status = POWER_SUPPLY_STATUS_FULL; } else { - gpio_set_value(bat->gpio_charge_on, 1); + gpiod_set_value(bat->gpio_charge_on, 1); bat->status = POWER_SUPPLY_STATUS_CHARGING; } } else { - gpio_set_value(bat->gpio_charge_on, 0); + gpiod_set_value(bat->gpio_charge_on, 0); bat->status = POWER_SUPPLY_STATUS_DISCHARGING; } @@ -230,18 +232,18 @@ static struct collie_bat collie_bat_main = { .full_chrg = -1, .psy = NULL, - .gpio_full = COLLIE_GPIO_CO, - .gpio_charge_on = COLLIE_GPIO_CHARGE_ON, + .gpio_full = NULL, + .gpio_charge_on = NULL, .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, - .gpio_bat = COLLIE_GPIO_MBAT_ON, + .gpio_bat = NULL, .adc_bat = UCB_ADC_INP_AD1, .adc_bat_divider = 155, .bat_max = 4310000, .bat_min = 1551 * 1000000 / 414, - .gpio_temp = COLLIE_GPIO_TMP_ON, + .gpio_temp = NULL, .adc_temp = UCB_ADC_INP_AD0, .adc_temp_divider = 10000, }; @@ -260,30 +262,24 @@ static struct collie_bat collie_bat_bu = { .full_chrg = -1, .psy = NULL, - .gpio_full = -1, - .gpio_charge_on = -1, + .gpio_full = NULL, + .gpio_charge_on = NULL, .technology = POWER_SUPPLY_TECHNOLOGY_LiMn, - .gpio_bat = COLLIE_GPIO_BBAT_ON, + .gpio_bat = NULL, .adc_bat = UCB_ADC_INP_AD1, .adc_bat_divider = 155, .bat_max = 3000000, .bat_min = 1900000, - .gpio_temp = -1, + .gpio_temp = NULL, .adc_temp = -1, .adc_temp_divider = -1, }; -static struct gpio collie_batt_gpios[] = { - { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" }, - { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" }, - { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" }, - { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" }, - { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" }, - { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" }, -}; +/* Obtained but unused GPIO */ +static struct gpio_desc *collie_mbat_low; #ifdef CONFIG_PM static int wakeup_enabled; @@ -295,7 +291,7 @@ static int collie_bat_suspend(struct ucb1x00_dev *dev) if (device_may_wakeup(&dev->ucb->dev) && collie_bat_main.status == POWER_SUPPLY_STATUS_CHARGING) - wakeup_enabled = !enable_irq_wake(gpio_to_irq(COLLIE_GPIO_CO)); + wakeup_enabled = !enable_irq_wake(gpiod_to_irq(collie_bat_main.gpio_full)); else wakeup_enabled = 0; @@ -305,7 +301,7 @@ static int collie_bat_suspend(struct ucb1x00_dev *dev) static int collie_bat_resume(struct ucb1x00_dev *dev) { if (wakeup_enabled) - disable_irq_wake(gpio_to_irq(COLLIE_GPIO_CO)); + disable_irq_wake(gpiod_to_irq(collie_bat_main.gpio_full)); /* things may have changed while we were away */ schedule_work(&bat_work); @@ -320,16 +316,71 @@ static int collie_bat_probe(struct ucb1x00_dev *dev) { int ret; struct power_supply_config psy_main_cfg = {}, psy_bu_cfg = {}; + struct gpio_chip *gc = &dev->ucb->gpio; if (!machine_is_collie()) return -ENODEV; ucb = dev->ucb; - ret = gpio_request_array(collie_batt_gpios, - ARRAY_SIZE(collie_batt_gpios)); - if (ret) - return ret; + /* Obtain all the main battery GPIOs */ + collie_bat_main.gpio_full = gpiod_get(&dev->ucb->dev, + "main battery full", + GPIOD_IN); + if (IS_ERR(collie_bat_main.gpio_full)) + return PTR_ERR(collie_bat_main.gpio_full); + + collie_mbat_low = gpiod_get(&dev->ucb->dev, + "main battery low", + GPIOD_IN); + if (IS_ERR(collie_mbat_low)) { + ret = PTR_ERR(collie_mbat_low); + goto err_put_gpio_full; + } + + collie_bat_main.gpio_charge_on = gpiod_get(&dev->ucb->dev, + "main charge on", + GPIOD_OUT_LOW); + if (IS_ERR(collie_bat_main.gpio_charge_on)) { + ret = PTR_ERR(collie_bat_main.gpio_charge_on); + goto err_put_mbat_low; + } + + /* COLLIE_GPIO_MBAT_ON = GPIO 7 on the UCB (TC35143) */ + collie_bat_main.gpio_bat = gpiochip_request_own_desc(gc, + 7, + "main battery", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_LOW); + if (IS_ERR(collie_bat_main.gpio_bat)) { + ret = PTR_ERR(collie_bat_main.gpio_bat); + goto err_put_gpio_charge_on; + } + + /* COLLIE_GPIO_TMP_ON = GPIO 9 on the UCB (TC35143) */ + collie_bat_main.gpio_temp = gpiochip_request_own_desc(gc, + 9, + "main battery temp", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_LOW); + if (IS_ERR(collie_bat_main.gpio_temp)) { + ret = PTR_ERR(collie_bat_main.gpio_temp); + goto err_free_gpio_bat; + } + + /* + * Obtain the backup battery COLLIE_GPIO_BBAT_ON which is + * GPIO 8 on the UCB (TC35143) + */ + collie_bat_bu.gpio_bat = gpiochip_request_own_desc(gc, + 8, + "backup battery", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_LOW); + if (IS_ERR(collie_bat_bu.gpio_bat)) { + ret = PTR_ERR(collie_bat_bu.gpio_bat); + goto err_free_gpio_temp; + } mutex_init(&collie_bat_main.work_lock); @@ -370,27 +421,43 @@ err_irq: err_psy_reg_bu: power_supply_unregister(collie_bat_main.psy); err_psy_reg_main: - /* see comment in collie_bat_remove */ cancel_work_sync(&bat_work); - gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); + gpiochip_free_own_desc(collie_bat_bu.gpio_bat); +err_free_gpio_temp: + gpiochip_free_own_desc(collie_bat_main.gpio_temp); +err_free_gpio_bat: + gpiochip_free_own_desc(collie_bat_main.gpio_bat); +err_put_gpio_charge_on: + gpiod_put(collie_bat_main.gpio_charge_on); +err_put_mbat_low: + gpiod_put(collie_mbat_low); +err_put_gpio_full: + gpiod_put(collie_bat_main.gpio_full); + return ret; } static void collie_bat_remove(struct ucb1x00_dev *dev) { free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); - power_supply_unregister(collie_bat_bu.psy); power_supply_unregister(collie_bat_main.psy); + /* These are obtained from the machine */ + gpiod_put(collie_bat_main.gpio_full); + gpiod_put(collie_mbat_low); + gpiod_put(collie_bat_main.gpio_charge_on); + /* These are directly from the UCB so let's free them */ + gpiochip_free_own_desc(collie_bat_main.gpio_bat); + gpiochip_free_own_desc(collie_bat_main.gpio_temp); + gpiochip_free_own_desc(collie_bat_bu.gpio_bat); /* * Now cancel the bat_work. We won't get any more schedules, * since all sources (isr and external_power_changed) are * unregistered now. */ cancel_work_sync(&bat_work); - gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios)); } static struct ucb1x00_driver collie_bat_driver = { -- cgit v1.2.3 From b0327ffb133fb2148fc3bc2afb39af2871ab21cb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2020 13:24:24 +0100 Subject: power: supply: generic-adc-battery: Use GPIO descriptors This driver uses platform data to pass GPIO lines using the deprecated global GPIO numbers. There are no in-tree users of this platform data. Any out-of-tree or coming users of this driver can easily be migrated to use machine descriptor tables as described in Documentation/driver-api/gpio/board.rst section "platform data". Cc: Anish Kumar Cc: H. Nikolaus Schaller Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/generic-adc-battery.c | 31 +++++++++++------------------- include/linux/power/generic-adc-battery.h | 4 ---- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c index caa829738ef7..0032069fbc2b 100644 --- a/drivers/power/supply/generic-adc-battery.c +++ b/drivers/power/supply/generic-adc-battery.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,6 +52,7 @@ struct gab { int level; int status; bool cable_plugged; + struct gpio_desc *charge_finished; }; static struct gab *to_generic_bat(struct power_supply *psy) @@ -91,13 +92,9 @@ static const enum power_supply_property gab_dyn_props[] = { static bool gab_charge_finished(struct gab *adc_bat) { - struct gab_platform_data *pdata = adc_bat->pdata; - bool ret = gpio_get_value(pdata->gpio_charge_finished); - bool inv = pdata->gpio_inverted; - - if (!gpio_is_valid(pdata->gpio_charge_finished)) + if (!adc_bat->charge_finished) return false; - return ret ^ inv; + return gpiod_get_value(adc_bat->charge_finished); } static int gab_get_status(struct gab *adc_bat) @@ -327,18 +324,17 @@ static int gab_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work); - if (gpio_is_valid(pdata->gpio_charge_finished)) { + adc_bat->charge_finished = devm_gpiod_get_optional(&pdev->dev, + "charged", GPIOD_IN); + if (adc_bat->charge_finished) { int irq; - ret = gpio_request(pdata->gpio_charge_finished, "charged"); - if (ret) - goto gpio_req_fail; - irq = gpio_to_irq(pdata->gpio_charge_finished); + irq = gpiod_to_irq(adc_bat->charge_finished); ret = request_any_context_irq(irq, gab_charged, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "battery charged", adc_bat); if (ret < 0) - goto err_gpio; + goto gpio_req_fail; } platform_set_drvdata(pdev, adc_bat); @@ -348,8 +344,6 @@ static int gab_probe(struct platform_device *pdev) msecs_to_jiffies(0)); return 0; -err_gpio: - gpio_free(pdata->gpio_charge_finished); gpio_req_fail: power_supply_unregister(adc_bat->psy); err_reg_fail: @@ -367,14 +361,11 @@ static int gab_remove(struct platform_device *pdev) { int chan; struct gab *adc_bat = platform_get_drvdata(pdev); - struct gab_platform_data *pdata = adc_bat->pdata; power_supply_unregister(adc_bat->psy); - if (gpio_is_valid(pdata->gpio_charge_finished)) { - free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat); - gpio_free(pdata->gpio_charge_finished); - } + if (adc_bat->charge_finished) + free_irq(gpiod_to_irq(adc_bat->charge_finished), adc_bat); for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { if (adc_bat->channel[chan]) diff --git a/include/linux/power/generic-adc-battery.h b/include/linux/power/generic-adc-battery.h index 40f9c7628f7b..c68cbf34cd34 100644 --- a/include/linux/power/generic-adc-battery.h +++ b/include/linux/power/generic-adc-battery.h @@ -11,16 +11,12 @@ * @battery_info: recommended structure to specify static power supply * parameters * @cal_charge: calculate charge level. - * @gpio_charge_finished: gpio for the charger. - * @gpio_inverted: Should be 1 if the GPIO is active low otherwise 0 * @jitter_delay: delay required after the interrupt to check battery * status.Default set is 10ms. */ struct gab_platform_data { struct power_supply_info battery_info; int (*cal_charge)(long value); - int gpio_charge_finished; - bool gpio_inverted; int jitter_delay; }; -- cgit v1.2.3 From 846651bf976fee3900e0ddab57bab5bb1b5d3d16 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2020 01:33:36 +0100 Subject: power: supply: bq24190_charger: Drop unused include The driver includes but fails to use any symbols from the file. Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24190_charger.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index 845af0f44c02..4841e14a5bfb 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 4e586fe990b199bdcb9d9f32071a13388cbae23b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 30 Oct 2020 01:37:32 +0100 Subject: power: supply: bq24735: Drop unused include The driver include but actually only use which is includes below. Drop the surplus legacy header include. Cc: Peter Rosin Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/bq24735-charger.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c index 6931e1d826f5..ab2f4bf8f603 100644 --- a/drivers/power/supply/bq24735-charger.c +++ b/drivers/power/supply/bq24735-charger.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include -- cgit v1.2.3 From faa2cec66798b17aea9c53756a1354e8a7ea54ef Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Mon, 19 Oct 2020 11:59:37 -0700 Subject: power: supply: wm831x_power: remove unneeded break A break is not needed if it is preceded by a goto. Signed-off-by: Tom Rix Acked-by: Charles Keepax Signed-off-by: Sebastian Reichel --- drivers/power/supply/wm831x_power.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c index 18b33f14dfee..4cd2dd870039 100644 --- a/drivers/power/supply/wm831x_power.c +++ b/drivers/power/supply/wm831x_power.c @@ -668,7 +668,6 @@ static int wm831x_power_probe(struct platform_device *pdev) fallthrough; case -EPROBE_DEFER: goto err_bat_irq; - break; } return ret; -- cgit v1.2.3 From ad89cb5f0a1ffad6ae9ba277f99fea830d135e7c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 12 Dec 2020 11:57:08 +0100 Subject: power: supply: ab8500: Use local helper Use a local "dev" helper variable to make the probe() code easier to read in the ab8500 subdrivers. Drop out-of-memory messages as these should come from the slab core. Cc: Marcus Cooper Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_btemp.c | 37 ++++++++++++----------- drivers/power/supply/ab8500_charger.c | 55 +++++++++++++++++------------------ drivers/power/supply/ab8500_fg.c | 39 ++++++++++++------------- 3 files changed, 64 insertions(+), 67 deletions(-) diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index e0b662b82255..56bfc7e03d03 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -999,47 +999,46 @@ static int ab8500_btemp_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct abx500_bm_data *plat = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; + struct device *dev = &pdev->dev; struct ab8500_btemp *di; int irq, i, ret = 0; u8 val; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } } /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); /* Get ADC channels */ - di->btemp_ball = devm_iio_channel_get(&pdev->dev, "btemp_ball"); + di->btemp_ball = devm_iio_channel_get(dev, "btemp_ball"); if (IS_ERR(di->btemp_ball)) { if (PTR_ERR(di->btemp_ball) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get BTEMP BALL ADC channel\n"); + dev_err(dev, "failed to get BTEMP BALL ADC channel\n"); return PTR_ERR(di->btemp_ball); } - di->bat_ctrl = devm_iio_channel_get(&pdev->dev, "bat_ctrl"); + di->bat_ctrl = devm_iio_channel_get(dev, "bat_ctrl"); if (IS_ERR(di->bat_ctrl)) { if (PTR_ERR(di->bat_ctrl) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get BAT CTRL ADC channel\n"); + dev_err(dev, "failed to get BAT CTRL ADC channel\n"); return PTR_ERR(di->bat_ctrl); } @@ -1053,7 +1052,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) di->btemp_wq = alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); if (di->btemp_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -1065,10 +1064,10 @@ static int ab8500_btemp_probe(struct platform_device *pdev) di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; - ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, + ret = abx500_get_register_interruptible(dev, AB8500_CHARGER, AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { - dev_err(di->dev, "%s ab8500 read failed\n", __func__); + dev_err(dev, "%s ab8500 read failed\n", __func__); goto free_btemp_wq; } switch (val) { @@ -1088,10 +1087,10 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(di->dev, &ab8500_btemp_desc, + di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, &psy_cfg); if (IS_ERR(di->btemp_psy)) { - dev_err(di->dev, "failed to register BTEMP psy\n"); + dev_err(dev, "failed to register BTEMP psy\n"); ret = PTR_ERR(di->btemp_psy); goto free_btemp_wq; } @@ -1109,11 +1108,11 @@ static int ab8500_btemp_probe(struct platform_device *pdev) ab8500_btemp_irq[i].name, di); if (ret) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); goto free_irq; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); } diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index db65be026920..7e28ac1b171b 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3354,23 +3354,22 @@ static int ab8500_charger_probe(struct platform_device *pdev) struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; int irq, i, charger_status, ret = 0, ch_stat; + struct device *dev = &pdev->dev; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); @@ -3378,39 +3377,39 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->autopower_cfg = false; /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); /* Get ADC channels */ - di->adc_main_charger_v = devm_iio_channel_get(&pdev->dev, + di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v"); if (IS_ERR(di->adc_main_charger_v)) { if (PTR_ERR(di->adc_main_charger_v) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC main charger voltage\n"); + dev_err(dev, "failed to get ADC main charger voltage\n"); return PTR_ERR(di->adc_main_charger_v); } - di->adc_main_charger_c = devm_iio_channel_get(&pdev->dev, + di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c"); if (IS_ERR(di->adc_main_charger_c)) { if (PTR_ERR(di->adc_main_charger_c) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC main charger current\n"); + dev_err(dev, "failed to get ADC main charger current\n"); return PTR_ERR(di->adc_main_charger_c); } - di->adc_vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v"); + di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v"); if (IS_ERR(di->adc_vbus_v)) { if (PTR_ERR(di->adc_vbus_v) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC USB charger voltage\n"); + dev_err(dev, "failed to get ADC USB charger voltage\n"); return PTR_ERR(di->adc_vbus_v); } - di->adc_usb_charger_c = devm_iio_channel_get(&pdev->dev, + di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c"); if (IS_ERR(di->adc_usb_charger_c)) { if (PTR_ERR(di->adc_usb_charger_c) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC USB charger current\n"); + dev_err(dev, "failed to get ADC USB charger current\n"); return PTR_ERR(di->adc_usb_charger_c); } @@ -3467,7 +3466,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", WQ_MEM_RECLAIM); if (di->charger_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -3526,10 +3525,10 @@ static int ab8500_charger_probe(struct platform_device *pdev) * is a charger connected to avoid erroneous BTEMP_HIGH/LOW * interrupts during charging */ - di->regu = devm_regulator_get(di->dev, "vddadc"); + di->regu = devm_regulator_get(dev, "vddadc"); if (IS_ERR(di->regu)) { ret = PTR_ERR(di->regu); - dev_err(di->dev, "failed to get vddadc regulator\n"); + dev_err(dev, "failed to get vddadc regulator\n"); goto free_charger_wq; } @@ -3537,17 +3536,17 @@ static int ab8500_charger_probe(struct platform_device *pdev) /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { - dev_err(di->dev, "failed to initialize ABB registers\n"); + dev_err(dev, "failed to initialize ABB registers\n"); goto free_charger_wq; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(di->dev, + di->ac_chg.psy = power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { - dev_err(di->dev, "failed to register AC charger\n"); + dev_err(dev, "failed to register AC charger\n"); ret = PTR_ERR(di->ac_chg.psy); goto free_charger_wq; } @@ -3555,11 +3554,11 @@ static int ab8500_charger_probe(struct platform_device *pdev) /* Register USB charger class */ if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(di->dev, + di->usb_chg.psy = power_supply_register(dev, &ab8500_usb_chg_desc, &usb_psy_cfg); if (IS_ERR(di->usb_chg.psy)) { - dev_err(di->dev, "failed to register USB charger\n"); + dev_err(dev, "failed to register USB charger\n"); ret = PTR_ERR(di->usb_chg.psy); goto free_ac; } @@ -3567,14 +3566,14 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(di->dev, "failed to get usb transceiver\n"); + dev_err(dev, "failed to get usb transceiver\n"); ret = -EINVAL; goto free_usb; } di->nb.notifier_call = ab8500_charger_usb_notifier_call; ret = usb_register_notifier(di->usb_phy, &di->nb); if (ret) { - dev_err(di->dev, "failed to register usb notifier\n"); + dev_err(dev, "failed to register usb notifier\n"); goto put_usb_phy; } @@ -3607,11 +3606,11 @@ static int ab8500_charger_probe(struct platform_device *pdev) ab8500_charger_irq[i].name, di); if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_charger_irq[i].name, irq, ret); goto free_irq; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_charger_irq[i].name, irq, ret); } diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 592a73d4dde6..56997353c175 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -3037,26 +3037,25 @@ static int ab8500_fg_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct abx500_bm_data *plat = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; + struct device *dev = &pdev->dev; struct ab8500_fg *di; int i, irq; int ret = 0; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } } @@ -3064,14 +3063,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) mutex_init(&di->cc_lock); /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); - di->main_bat_v = devm_iio_channel_get(&pdev->dev, "main_bat_v"); + di->main_bat_v = devm_iio_channel_get(dev, "main_bat_v"); if (IS_ERR(di->main_bat_v)) { if (PTR_ERR(di->main_bat_v) == -ENODEV) return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get main battery ADC channel\n"); + dev_err(dev, "failed to get main battery ADC channel\n"); return PTR_ERR(di->main_bat_v); } @@ -3094,7 +3093,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Create a work queue for running the FG algorithm */ di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); if (di->fg_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -3129,7 +3128,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Initialize OVV, and other registers */ ret = ab8500_fg_init_hw_registers(di); if (ret) { - dev_err(di->dev, "failed to initialize registers\n"); + dev_err(dev, "failed to initialize registers\n"); goto free_inst_curr_wq; } @@ -3138,9 +3137,9 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(di->dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { - dev_err(di->dev, "failed to register FG psy\n"); + dev_err(dev, "failed to register FG psy\n"); ret = PTR_ERR(di->fg_psy); goto free_inst_curr_wq; } @@ -3168,11 +3167,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_irq_th[i].name, di); if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n", + dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq_th[i].name, irq, ret); goto free_irq_th; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq_th[i].name, irq, ret); } @@ -3188,11 +3187,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_irq_bh[0].name, di); if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n", + dev_err(dev, "failed to request %s IRQ %d: %d\n", ab8500_fg_irq_bh[0].name, irq, ret); goto free_irq_th; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_fg_irq_bh[0].name, irq, ret); di->irq = platform_get_irq_byname(pdev, "CCEOC"); @@ -3203,13 +3202,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { - dev_err(di->dev, "failed to create sysfs entry\n"); + dev_err(dev, "failed to create sysfs entry\n"); goto free_irq; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { - dev_err(di->dev, "failed to create FG psy\n"); + dev_err(dev, "failed to create FG psy\n"); ab8500_fg_sysfs_exit(di); goto free_irq; } -- cgit v1.2.3 From f8efa0a881e2504d55a1d8d9e8dff847a378d717 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 12 Dec 2020 11:57:09 +0100 Subject: power: supply: ab8500: Convert to dev_pm_ops Switch over to using generic dev_pm_ops since these drivers aren't even using the special power state passed to the legacy call. Cc: Marcus Cooper Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_btemp.c | 19 +++++++------------ drivers/power/supply/ab8500_charger.c | 19 +++++++------------ drivers/power/supply/ab8500_fg.c | 19 +++++++------------ drivers/power/supply/abx500_chargalg.c | 19 +++++++------------ 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 56bfc7e03d03..660720a52712 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -936,29 +936,23 @@ static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = { {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler}, }; -#if defined(CONFIG_PM) -static int ab8500_btemp_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_btemp_resume(struct device *dev) { - struct ab8500_btemp *di = platform_get_drvdata(pdev); + struct ab8500_btemp *di = dev_get_drvdata(dev); ab8500_btemp_periodic(di, true); return 0; } -static int ab8500_btemp_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_btemp_suspend(struct device *dev) { - struct ab8500_btemp *di = platform_get_drvdata(pdev); + struct ab8500_btemp *di = dev_get_drvdata(dev); ab8500_btemp_periodic(di, false); return 0; } -#else -#define ab8500_btemp_suspend NULL -#define ab8500_btemp_resume NULL -#endif static int ab8500_btemp_remove(struct platform_device *pdev) { @@ -1137,6 +1131,8 @@ free_btemp_wq: return ret; } +static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); + static const struct of_device_id ab8500_btemp_match[] = { { .compatible = "stericsson,ab8500-btemp", }, { }, @@ -1145,11 +1141,10 @@ static const struct of_device_id ab8500_btemp_match[] = { static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, - .suspend = ab8500_btemp_suspend, - .resume = ab8500_btemp_resume, .driver = { .name = "ab8500-btemp", .of_match_table = ab8500_btemp_match, + .pm = &ab8500_btemp_pm_ops, }, }; diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index 7e28ac1b171b..47f1ce1012f4 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3209,11 +3209,10 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, return NOTIFY_OK; } -#if defined(CONFIG_PM) -static int ab8500_charger_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_charger_resume(struct device *dev) { int ret; - struct ab8500_charger *di = platform_get_drvdata(pdev); + struct ab8500_charger *di = dev_get_drvdata(dev); /* * For ABB revision 1.0 and 1.1 there is a bug in the watchdog @@ -3247,10 +3246,9 @@ static int ab8500_charger_resume(struct platform_device *pdev) return 0; } -static int ab8500_charger_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_charger_suspend(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); + struct ab8500_charger *di = dev_get_drvdata(dev); /* Cancel any pending jobs */ cancel_delayed_work(&di->check_hw_failure_work); @@ -3272,10 +3270,6 @@ static int ab8500_charger_suspend(struct platform_device *pdev, return 0; } -#else -#define ab8500_charger_suspend NULL -#define ab8500_charger_resume NULL -#endif static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, @@ -3658,6 +3652,8 @@ free_charger_wq: return ret; } +static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); + static const struct of_device_id ab8500_charger_match[] = { { .compatible = "stericsson,ab8500-charger", }, { }, @@ -3666,11 +3662,10 @@ static const struct of_device_id ab8500_charger_match[] = { static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, .remove = ab8500_charger_remove, - .suspend = ab8500_charger_suspend, - .resume = ab8500_charger_resume, .driver = { .name = "ab8500-charger", .of_match_table = ab8500_charger_match, + .pm = &ab8500_charger_pm_ops, }, }; diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 56997353c175..ba8dba0d6395 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -2942,10 +2942,9 @@ static void ab8500_fg_sysfs_psy_remove_attrs(struct ab8500_fg *di) /* Exposure to the sysfs interface <> */ -#if defined(CONFIG_PM) -static int ab8500_fg_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_fg_resume(struct device *dev) { - struct ab8500_fg *di = platform_get_drvdata(pdev); + struct ab8500_fg *di = dev_get_drvdata(dev); /* * Change state if we're not charging. If we're charging we will wake @@ -2959,10 +2958,9 @@ static int ab8500_fg_resume(struct platform_device *pdev) return 0; } -static int ab8500_fg_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_fg_suspend(struct device *dev) { - struct ab8500_fg *di = platform_get_drvdata(pdev); + struct ab8500_fg *di = dev_get_drvdata(dev); flush_delayed_work(&di->fg_periodic_work); flush_work(&di->fg_work); @@ -2980,10 +2978,6 @@ static int ab8500_fg_suspend(struct platform_device *pdev, return 0; } -#else -#define ab8500_fg_suspend NULL -#define ab8500_fg_resume NULL -#endif static int ab8500_fg_remove(struct platform_device *pdev) { @@ -3244,6 +3238,8 @@ free_inst_curr_wq: return ret; } +static SIMPLE_DEV_PM_OPS(ab8500_fg_pm_ops, ab8500_fg_suspend, ab8500_fg_resume); + static const struct of_device_id ab8500_fg_match[] = { { .compatible = "stericsson,ab8500-fg", }, { }, @@ -3252,11 +3248,10 @@ static const struct of_device_id ab8500_fg_match[] = { static struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, .remove = ab8500_fg_remove, - .suspend = ab8500_fg_suspend, - .resume = ab8500_fg_resume, .driver = { .name = "ab8500-fg", .of_match_table = ab8500_fg_match, + .pm = &ab8500_fg_pm_ops, }, }; diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index 175c4f3d7955..a9d84d845f24 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -1913,10 +1913,9 @@ static int abx500_chargalg_sysfs_init(struct abx500_chargalg *di) } /* Exposure to the sysfs interface <> */ -#if defined(CONFIG_PM) -static int abx500_chargalg_resume(struct platform_device *pdev) +static int __maybe_unused abx500_chargalg_resume(struct device *dev) { - struct abx500_chargalg *di = platform_get_drvdata(pdev); + struct abx500_chargalg *di = dev_get_drvdata(dev); /* Kick charger watchdog if charging (any charger online) */ if (di->chg_info.online_chg) @@ -1931,10 +1930,9 @@ static int abx500_chargalg_resume(struct platform_device *pdev) return 0; } -static int abx500_chargalg_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused abx500_chargalg_suspend(struct device *dev) { - struct abx500_chargalg *di = platform_get_drvdata(pdev); + struct abx500_chargalg *di = dev_get_drvdata(dev); if (di->chg_info.online_chg) cancel_delayed_work_sync(&di->chargalg_wd_work); @@ -1943,10 +1941,6 @@ static int abx500_chargalg_suspend(struct platform_device *pdev, return 0; } -#else -#define abx500_chargalg_suspend NULL -#define abx500_chargalg_resume NULL -#endif static int abx500_chargalg_remove(struct platform_device *pdev) { @@ -2080,6 +2074,8 @@ free_chargalg_wq: return ret; } +static SIMPLE_DEV_PM_OPS(abx500_chargalg_pm_ops, abx500_chargalg_suspend, abx500_chargalg_resume); + static const struct of_device_id ab8500_chargalg_match[] = { { .compatible = "stericsson,ab8500-chargalg", }, { }, @@ -2088,11 +2084,10 @@ static const struct of_device_id ab8500_chargalg_match[] = { static struct platform_driver abx500_chargalg_driver = { .probe = abx500_chargalg_probe, .remove = abx500_chargalg_remove, - .suspend = abx500_chargalg_suspend, - .resume = abx500_chargalg_resume, .driver = { .name = "ab8500-chargalg", .of_match_table = ab8500_chargalg_match, + .pm = &abx500_chargalg_pm_ops, }, }; -- cgit v1.2.3 From 532b623f3c86d5166a8bb8acaa94fc3629d8ba97 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 12 Dec 2020 11:57:10 +0100 Subject: power: supply: ab8500_charger: Oneshot threaded IRQs Make sure the threaded IRQs requested by the charger are flagged as "oneshot". Usually this is what you want, and since the interrupts are shared with the USB phy on the AB8500 we will get a conflict like this if we don't, since the phy request them threaded oneshot: genirq: Flags mismatch irq 83. 00004084 (USB_LINK_STATUS vs. 00006084 (usb-link-status) ab8500-charger ab8500-charger.0: failed to request USB_LINK_STATUS IRQ 83: -16 Cc: Marcus Cooper Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index 47f1ce1012f4..d4b7bd68451b 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3596,7 +3596,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) } ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_charger_irq[i].name, di); if (ret != 0) { -- cgit v1.2.3 From 807042539d8ed11299c9278e55d2cb6df8d04a39 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 12 Dec 2020 11:57:11 +0100 Subject: power: supply: ab8500_fg: Request all IRQs as threaded Since these IRQs are cascaded from a nested IRQ, the generic IRQ system detects this and refuse to deliver a fastpath IRQ in response to request_irq(): nested = irq_settings_is_nested_thread(desc); if (nested) { if (!new->thread_fn) { ret = -EINVAL; goto out_mput; } (...) Threaded IRQs work just as well so let's just request threaded IRQs. One of the IRQs are alread requested as threaded anyways. Cc: Marcus Cooper Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_fg.c | 47 ++++++++++------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index ba8dba0d6395..d1b68acac427 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -3001,14 +3001,11 @@ static int ab8500_fg_remove(struct platform_device *pdev) } /* ab8500 fg driver interrupts and their respective isr */ -static struct ab8500_fg_interrupts ab8500_fg_irq_th[] = { +static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, {"BATT_OVV", ab8500_fg_batt_ovv_handler}, {"LOW_BAT_F", ab8500_fg_lowbatf_handler}, {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler}, -}; - -static struct ab8500_fg_interrupts ab8500_fg_irq_bh[] = { {"CCEOC", ab8500_fg_cc_data_end_handler}, }; @@ -3149,44 +3146,25 @@ static int ab8500_fg_probe(struct platform_device *pdev) init_completion(&di->ab8500_fg_complete); /* Register primary interrupt handlers */ - for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq_th); i++) { - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name); + for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); if (irq < 0) { ret = irq; - goto free_irq_th; + goto free_irq; } - ret = request_irq(irq, ab8500_fg_irq_th[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, - ab8500_fg_irq_th[i].name, di); + ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_fg_irq[i].name, di); if (ret != 0) { dev_err(dev, "failed to request %s IRQ %d: %d\n", - ab8500_fg_irq_th[i].name, irq, ret); - goto free_irq_th; + ab8500_fg_irq[i].name, irq, ret); + goto free_irq; } dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_fg_irq_th[i].name, irq, ret); - } - - /* Register threaded interrupt handler */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name); - if (irq < 0) { - ret = irq; - goto free_irq_th; - } - - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq_bh[0].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_fg_irq_bh[0].name, di); - - if (ret != 0) { - dev_err(dev, "failed to request %s IRQ %d: %d\n", - ab8500_fg_irq_bh[0].name, irq, ret); - goto free_irq_th; + ab8500_fg_irq[i].name, irq, ret); } - dev_dbg(dev, "Requested %s IRQ %d: %d\n", - ab8500_fg_irq_bh[0].name, irq, ret); di->irq = platform_get_irq_byname(pdev, "CCEOC"); disable_irq(di->irq); @@ -3223,12 +3201,9 @@ static int ab8500_fg_probe(struct platform_device *pdev) free_irq: /* We also have to free all registered irqs */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name); - free_irq(irq, di); -free_irq_th: while (--i >= 0) { /* Last assignment of i from primary interrupt handlers */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name); + irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); free_irq(irq, di); } -- cgit v1.2.3 From 36f1de0d5c463092485c73ab639c348d1e28e356 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 12 Dec 2020 11:57:12 +0100 Subject: power: supply: ab8500: Use dev_err_probe() for IIO channels The code obtaining the ADC channels is outdated: it is trying to work around the IIO subsystem not returning the right -EPROBE_DEFER error code. Fix this up by using the dev_err_probe() helper so we defer silently where appropriate and not bail out if the IIO core returns -EPROBE_DEFER as happens now. Cc: Marcus Cooper Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/supply/ab8500_btemp.c | 14 ++++++------- drivers/power/supply/ab8500_charger.c | 37 ++++++++++++++--------------------- drivers/power/supply/ab8500_fg.c | 7 +++---- 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 660720a52712..d20345386b1e 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -1023,17 +1023,15 @@ static int ab8500_btemp_probe(struct platform_device *pdev) /* Get ADC channels */ di->btemp_ball = devm_iio_channel_get(dev, "btemp_ball"); if (IS_ERR(di->btemp_ball)) { - if (PTR_ERR(di->btemp_ball) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get BTEMP BALL ADC channel\n"); - return PTR_ERR(di->btemp_ball); + ret = dev_err_probe(dev, PTR_ERR(di->btemp_ball), + "failed to get BTEMP BALL ADC channel\n"); + return ret; } di->bat_ctrl = devm_iio_channel_get(dev, "bat_ctrl"); if (IS_ERR(di->bat_ctrl)) { - if (PTR_ERR(di->bat_ctrl) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get BAT CTRL ADC channel\n"); - return PTR_ERR(di->bat_ctrl); + ret = dev_err_probe(dev, PTR_ERR(di->bat_ctrl), + "failed to get BAT CTRL ADC channel\n"); + return ret; } di->initialized = false; diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index d4b7bd68451b..ac77c8882d17 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3375,36 +3375,29 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->parent = dev_get_drvdata(pdev->dev.parent); /* Get ADC channels */ - di->adc_main_charger_v = devm_iio_channel_get(dev, - "main_charger_v"); + di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v"); if (IS_ERR(di->adc_main_charger_v)) { - if (PTR_ERR(di->adc_main_charger_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get ADC main charger voltage\n"); - return PTR_ERR(di->adc_main_charger_v); + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v), + "failed to get ADC main charger voltage\n"); + return ret; } - di->adc_main_charger_c = devm_iio_channel_get(dev, - "main_charger_c"); + di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c"); if (IS_ERR(di->adc_main_charger_c)) { - if (PTR_ERR(di->adc_main_charger_c) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get ADC main charger current\n"); - return PTR_ERR(di->adc_main_charger_c); + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c), + "failed to get ADC main charger current\n"); + return ret; } di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v"); if (IS_ERR(di->adc_vbus_v)) { - if (PTR_ERR(di->adc_vbus_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get ADC USB charger voltage\n"); - return PTR_ERR(di->adc_vbus_v); + ret = dev_err_probe(dev, PTR_ERR(di->adc_vbus_v), + "failed to get ADC USB charger voltage\n"); + return ret; } - di->adc_usb_charger_c = devm_iio_channel_get(dev, - "usb_charger_c"); + di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c"); if (IS_ERR(di->adc_usb_charger_c)) { - if (PTR_ERR(di->adc_usb_charger_c) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get ADC USB charger current\n"); - return PTR_ERR(di->adc_usb_charger_c); + ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c), + "failed to get ADC USB charger current\n"); + return ret; } /* initialize lock */ diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index d1b68acac427..3873e4857e3d 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -3059,10 +3059,9 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->main_bat_v = devm_iio_channel_get(dev, "main_bat_v"); if (IS_ERR(di->main_bat_v)) { - if (PTR_ERR(di->main_bat_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(dev, "failed to get main battery ADC channel\n"); - return PTR_ERR(di->main_bat_v); + ret = dev_err_probe(dev, PTR_ERR(di->main_bat_v), + "failed to get main battery ADC channel\n"); + return ret; } psy_cfg.supplied_to = supply_interface; -- cgit v1.2.3 From ec66096b7696d40c8d321d2b1c6cdb856a9767be Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Fri, 11 Dec 2020 16:14:43 +0100 Subject: power: reset: new driver regulator-poweroff This driver registers a pm_power_off function to turn off the board by force-disabling a devicetree-defined regulator. Signed-off-by: Michael Klein Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 7 +++ drivers/power/reset/Makefile | 1 + drivers/power/reset/regulator-poweroff.c | 82 ++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 drivers/power/reset/regulator-poweroff.c diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index d55b3727e00e..b22c4fdb2561 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -177,6 +177,13 @@ config POWER_RESET_QNAP Say Y if you have a QNAP NAS. +config POWER_RESET_REGULATOR + bool "Regulator subsystem power-off driver" + depends on OF && REGULATOR + help + This driver supports turning off your board by disabling a + power regulator defined in the devicetree. + config POWER_RESET_RESTART bool "Restart power-off driver" help diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index c51eceba9ea3..9dc49d3a57ff 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o +obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c new file mode 100644 index 000000000000..f697088e0ad1 --- /dev/null +++ b/drivers/power/reset/regulator-poweroff.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Force-disables a regulator to power down a device + * + * Michael Klein + * + * Copyright (C) 2020 Michael Klein + * + * Based on the gpio-poweroff driver. + */ +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_MS 3000 + +/* + * Hold configuration here, cannot be more than one instance of the driver + * since pm_power_off itself is global. + */ +static struct regulator *cpu_regulator; + +static void regulator_poweroff_do_poweroff(void) +{ + if (cpu_regulator && regulator_is_enabled(cpu_regulator)) + regulator_force_disable(cpu_regulator); + + /* give it some time */ + mdelay(TIMEOUT_MS); + + WARN_ON(1); +} + +static int regulator_poweroff_probe(struct platform_device *pdev) +{ + /* 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; + } + + cpu_regulator = devm_regulator_get(&pdev->dev, "cpu"); + if (IS_ERR(cpu_regulator)) + return PTR_ERR(cpu_regulator); + + pm_power_off = ®ulator_poweroff_do_poweroff; + return 0; +} + +static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev) +{ + if (pm_power_off == ®ulator_poweroff_do_poweroff) + pm_power_off = NULL; + + return 0; +} + +static const struct of_device_id of_regulator_poweroff_match[] = { + { .compatible = "regulator-poweroff", }, + {}, +}; + +static struct platform_driver regulator_poweroff_driver = { + .probe = regulator_poweroff_probe, + .remove = regulator_poweroff_remove, + .driver = { + .name = "poweroff-regulator", + .of_match_table = of_regulator_poweroff_match, + }, +}; + +module_platform_driver(regulator_poweroff_driver); + +MODULE_AUTHOR("Michael Klein "); +MODULE_DESCRIPTION("Regulator poweroff driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:poweroff-regulator"); -- cgit v1.2.3 From d6e33fc89e0f81571b7f8d6b365eb8748a97e041 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Fri, 11 Dec 2020 16:14:44 +0100 Subject: Documentation: DT: binding documentation for regulator-poweroff Add devicetree binding documentation for regulator-poweroff driver. Signed-off-by: Michael Klein Reviewed-by: Rob Herring Signed-off-by: Sebastian Reichel --- .../bindings/power/reset/regulator-poweroff.yaml | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml diff --git a/Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml b/Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml new file mode 100644 index 000000000000..03bd1fa5a623 --- /dev/null +++ b/Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/reset/regulator-poweroff.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Force-disable power regulator to turn the power off. + +maintainers: + - Michael Klein + +description: | + When the power-off handler is called, a power regulator is disabled by + calling regulator_force_disable(). If the power is still on and the + CPU still running after a 3000ms delay, a warning is emitted. + +properties: + compatible: + const: "regulator-poweroff" + + cpu-supply: + description: + regulator to disable on power-down + +required: + - compatible + - cpu-supply + +additionalProperties: false + +examples: + - | + regulator-poweroff { + compatible = "regulator-poweroff"; + cpu-supply = <®_vcc1v2>; + }; +... -- cgit v1.2.3 From c2362519a04a7307e386e43bc567780d0d7631c7 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 5 Dec 2020 10:25:32 +0900 Subject: power: supply: Fix a typo in warning message This patch fix a warning messages in power_supply_sysfs.c Signed-off-by: Masanari Iida Signed-off-by: Sebastian Reichel --- drivers/power/supply/power_supply_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index a616b9d8f43c..92dd63171193 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -402,7 +402,7 @@ void power_supply_init_attrs(struct device_type *dev_type) struct device_attribute *attr; if (!power_supply_attrs[i].prop_name) { - pr_warn("%s: Property %d skipped because is is missing from power_supply_attrs\n", + pr_warn("%s: Property %d skipped because it is missing from power_supply_attrs\n", __func__, i); sprintf(power_supply_attrs[i].attr_name, "_err_%d", i); } else { -- cgit v1.2.3