summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power/reset/ocelot-reset.txt4
-rw-r--r--Documentation/devicetree/bindings/power/reset/regulator-poweroff.yaml37
-rw-r--r--arch/arm/mach-s3c/mach-h1940.c12
-rw-r--r--arch/arm/mach-s3c/mach-rx1950.c11
-rw-r--r--arch/arm/mach-sa1100/collie.c21
-rw-r--r--drivers/power/reset/Kconfig7
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/ocelot-reset.c30
-rw-r--r--drivers/power/reset/qnap-poweroff.c8
-rw-r--r--drivers/power/reset/regulator-poweroff.c82
-rw-r--r--drivers/power/reset/syscon-poweroff.c8
-rw-r--r--drivers/power/supply/ab8500_btemp.c68
-rw-r--r--drivers/power/supply/ab8500_charger.c99
-rw-r--r--drivers/power/supply/ab8500_fg.c106
-rw-r--r--drivers/power/supply/abx500_chargalg.c19
-rw-r--r--drivers/power/supply/axp20x_usb_power.c10
-rw-r--r--drivers/power/supply/axp288_charger.c28
-rw-r--r--drivers/power/supply/bq24190_charger.c21
-rw-r--r--drivers/power/supply/bq24735-charger.c1
-rw-r--r--drivers/power/supply/bq25890_charger.c2
-rw-r--r--drivers/power/supply/collie_battery.c151
-rw-r--r--drivers/power/supply/generic-adc-battery.c31
-rw-r--r--drivers/power/supply/max17042_battery.c23
-rw-r--r--drivers/power/supply/max8997_charger.c67
-rw-r--r--drivers/power/supply/pm2301_charger.c3
-rw-r--r--drivers/power/supply/power_supply_sysfs.c2
-rw-r--r--drivers/power/supply/s3c_adc_battery.c57
-rw-r--r--drivers/power/supply/wm831x_power.c1
-rw-r--r--include/linux/power/generic-adc-battery.h4
-rw-r--r--include/linux/s3c_adc_battery.h3
30 files changed, 562 insertions, 355 deletions
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 {
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 <michael@fossekall.de>
+
+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 = <&reg_vcc1v2>;
+ };
+...
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/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/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/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
}, {
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 <linux/module.h>
#include <linux/platform_device.h>
#include <linux/serial_reg.h>
-#include <linux/kallsyms.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/clk.h>
@@ -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/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 <michael@fossekall.de>
+ *
+ * Copyright (C) 2020 Michael Klein
+ *
+ * Based on the gpio-poweroff driver.
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+
+#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 = &regulator_poweroff_do_poweroff;
+ return 0;
+}
+
+static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev)
+{
+ if (pm_power_off == &regulator_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 <michael@fossekall.de>");
+MODULE_DESCRIPTION("Regulator poweroff driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:poweroff-regulator");
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 <moritz.fischer@ettus.com>
*/
-#include <linux/kallsyms.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/notifier.h>
@@ -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;
}
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index 909f0242bacb..d20345386b1e 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)
{
@@ -999,48 +993,45 @@ 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");
- 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(&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");
- 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;
@@ -1053,7 +1044,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 +1056,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 +1079,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;
}
@@ -1105,15 +1096,15 @@ 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) {
- 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);
}
@@ -1138,6 +1129,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", },
{ },
@@ -1146,11 +1139,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 db65be026920..ac77c8882d17 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,
@@ -3354,23 +3348,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,40 +3371,33 @@ 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,
- "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(&pdev->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(&pdev->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(&pdev->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(&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");
- 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(&pdev->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(&pdev->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 */
@@ -3467,7 +3453,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 +3512,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 +3523,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 +3541,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 +3553,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;
}
@@ -3603,15 +3589,15 @@ 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) {
- 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);
}
@@ -3659,6 +3645,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", },
{ },
@@ -3667,11 +3655,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 592a73d4dde6..3873e4857e3d 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 <<END>> */
-#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)
{
@@ -3007,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},
};
@@ -3037,26 +3028,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,15 +3054,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");
- 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;
@@ -3094,7 +3083,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 +3118,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 +3127,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;
}
@@ -3156,45 +3145,26 @@ 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(di->dev, "failed to request %s IRQ %d: %d\n",
- ab8500_fg_irq_th[i].name, irq, ret);
- goto free_irq_th;
+ dev_err(dev, "failed to request %s IRQ %d: %d\n",
+ ab8500_fg_irq[i].name, irq, ret);
+ goto free_irq;
}
- dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
- ab8500_fg_irq_th[i].name, irq, ret);
+ dev_dbg(dev, "Requested %s IRQ %d: %d\n",
+ ab8500_fg_irq[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(di->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",
- ab8500_fg_irq_bh[0].name, irq, ret);
-
di->irq = platform_get_irq_byname(pdev, "CCEOC");
disable_irq(di->irq);
di->nbr_cceoc_irq_cnt = 0;
@@ -3203,13 +3173,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;
}
@@ -3230,12 +3200,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);
}
@@ -3245,6 +3212,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", },
{ },
@@ -3253,11 +3222,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 <<END>> */
-#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,
},
};
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 0eaa86c52874..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)
@@ -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
@@ -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;
}
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 */
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index d14186525e1e..4841e14a5bfb 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -16,7 +16,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/workqueue.h>
-#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/extcon-provider.h>
@@ -448,8 +447,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 +1078,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 +1152,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 +1415,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 +1463,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:
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 <linux/err.h>
-#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
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 */
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 <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio/consumer.h>
#include <linux/mfd/ucb1x00.h>
#include <asm/mach/sharpsl_param.h>
@@ -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 = {
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 <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
@@ -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/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index f284547913d6..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,
@@ -85,9 +86,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)
@@ -353,7 +355,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);
@@ -394,8 +397,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;
}
@@ -406,12 +409,20 @@ 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;
}
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)
diff --git a/drivers/power/supply/max8997_charger.c b/drivers/power/supply/max8997_charger.c
index f5e84cd47924..1947af25879a 100644
--- a/drivers/power/supply/max8997_charger.c
+++ b/drivers/power/supply/max8997_charger.c
@@ -13,6 +13,20 @@
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
+/* 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, &reg);
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, &reg);
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 max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ 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;
@@ -168,18 +186,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 <myungjoo.ham@samsung.com>");
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)
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 {
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 <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/leds.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
@@ -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/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;
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;
};
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;