summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 20:19:48 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 20:19:48 +0300
commit44f89c6d3c54761114b2bc0509144e3e5ced40b0 (patch)
tree48a879ce4109c82e23d0e14f992200b7d22bce78 /drivers/power
parent80d80de4b75edb7c83c68107098aa338364dfa62 (diff)
parent4e61f1e9d58fb0765f59f47d4d1f318b36c14d95 (diff)
downloadlinux-44f89c6d3c54761114b2bc0509144e3e5ced40b0.tar.xz
Merge tag 'for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel: "New features: - axp20x_usb_power: report USB type Cleanups: - convert lots of drivers to use devm_power_supply_register() - convert lots of reset drivers to use devm_register_sys_off_handler() - constify device_type and power_supply_class - axp20x_usb_power: use correct property to report input current limit - mm8013: correct handling of "not charging" status register - core: fix charge_behaviour formatting - minor fixes cleanups" * tag 'for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (66 commits) power: supply: core: fix charge_behaviour formatting power: supply: core: ease special formatting implementations power: supply: mm8013: fix "not charging" detection power: supply: move power_supply_attr_groups definition back to sysfs power: supply: core: simplify power_supply_class_init power: supply: core: add power_supply_for_each_device() power: supply: core: make power_supply_class constant power: supply: bq2415x_charger: report online status power: supply: core: move power_supply_attr_group into #ifdef block power: supply: core: Fix power_supply_init_attrs() stub power: supply: bq27xxx: Report charge full state correctly power: reset: rmobile-reset: Make sysc_base2 local power: supply: core: constify the struct device_type usage power: supply: axp288_fuel_gauge: Deny ROCK Pi X power: reset: rmobile-reset: Map correct MMIO resource power: reset: xgene-reboot: Fix a NULL vs IS_ERR() test power: supply: axp288_fuel_gauge: Add STCK1A* Intel Compute Sticks to the deny-list power: reset: syscon-poweroff: Use devm_register_sys_off_handler(POWER_OFF) power: reset: syscon-poweroff: Move device data into a struct power: reset: restart-poweroff: Use devm_register_sys_off_handler(POWER_OFF) ...
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/reset/as3722-poweroff.c30
-rw-r--r--drivers/power/reset/atc260x-poweroff.c55
-rw-r--r--drivers/power/reset/axxia-reset.c16
-rw-r--r--drivers/power/reset/brcm-kona-reset.c11
-rw-r--r--drivers/power/reset/gemini-poweroff.c16
-rw-r--r--drivers/power/reset/msm-poweroff.c21
-rw-r--r--drivers/power/reset/mt6323-poweroff.c26
-rw-r--r--drivers/power/reset/regulator-poweroff.c36
-rw-r--r--drivers/power/reset/restart-poweroff.c25
-rw-r--r--drivers/power/reset/rmobile-reset.c38
-rw-r--r--drivers/power/reset/syscon-poweroff.c66
-rw-r--r--drivers/power/reset/tps65086-restart.c58
-rw-r--r--drivers/power/reset/xgene-reboot.c25
-rw-r--r--drivers/power/supply/ab8500_btemp.c3
-rw-r--r--drivers/power/supply/ab8500_chargalg.c3
-rw-r--r--drivers/power/supply/ab8500_charger.c3
-rw-r--r--drivers/power/supply/ab8500_fg.c3
-rw-r--r--drivers/power/supply/apm_power.c3
-rw-r--r--drivers/power/supply/axp20x_usb_power.c147
-rw-r--r--drivers/power/supply/axp288_fuel_gauge.c18
-rw-r--r--drivers/power/supply/bq2415x_charger.c10
-rw-r--r--drivers/power/supply/bq27xxx_battery.c56
-rw-r--r--drivers/power/supply/bq27xxx_battery_i2c.c46
-rw-r--r--drivers/power/supply/da9030_battery.c6
-rw-r--r--drivers/power/supply/da9052-battery.c4
-rw-r--r--drivers/power/supply/da9150-charger.c72
-rw-r--r--drivers/power/supply/ds2760_battery.c4
-rw-r--r--drivers/power/supply/goldfish_battery.c24
-rw-r--r--drivers/power/supply/lp8727_charger.c35
-rw-r--r--drivers/power/supply/lp8788-charger.c21
-rw-r--r--drivers/power/supply/max14577_charger.c8
-rw-r--r--drivers/power/supply/max77693_charger.c10
-rw-r--r--drivers/power/supply/max8925_power.c37
-rw-r--r--drivers/power/supply/mm8013.c13
-rw-r--r--drivers/power/supply/pcf50633-charger.c23
-rw-r--r--drivers/power/supply/power_supply.h6
-rw-r--r--drivers/power/supply/power_supply_core.c65
-rw-r--r--drivers/power/supply/power_supply_sysfs.c40
-rw-r--r--drivers/power/supply/rt5033_battery.c14
-rw-r--r--drivers/power/supply/rx51_battery.c57
-rw-r--r--drivers/power/supply/tps65090-charger.c18
-rw-r--r--drivers/power/supply/twl4030_madc_battery.c59
-rw-r--r--drivers/power/supply/wm831x_backup.c13
-rw-r--r--drivers/power/supply/wm831x_power.c24
-rw-r--r--drivers/power/supply/wm8350_power.c30
45 files changed, 556 insertions, 742 deletions
diff --git a/drivers/power/reset/as3722-poweroff.c b/drivers/power/reset/as3722-poweroff.c
index ab3350ce2d62..bb26fa6fa67c 100644
--- a/drivers/power/reset/as3722-poweroff.c
+++ b/drivers/power/reset/as3722-poweroff.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/reboot.h>
#include <linux/slab.h>
struct as3722_poweroff {
@@ -18,22 +19,18 @@ struct as3722_poweroff {
struct as3722 *as3722;
};
-static struct as3722_poweroff *as3722_pm_poweroff;
-
-static void as3722_pm_power_off(void)
+static int as3722_pm_power_off(struct sys_off_data *data)
{
+ struct as3722_poweroff *as3722_pm_poweroff = data->cb_data;
int ret;
- if (!as3722_pm_poweroff) {
- pr_err("AS3722 poweroff is not initialised\n");
- return;
- }
-
ret = as3722_update_bits(as3722_pm_poweroff->as3722,
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
if (ret < 0)
dev_err(as3722_pm_poweroff->dev,
"RESET_CONTROL_REG update failed, %d\n", ret);
+
+ return NOTIFY_DONE;
}
static int as3722_poweroff_probe(struct platform_device *pdev)
@@ -54,18 +51,14 @@ static int as3722_poweroff_probe(struct platform_device *pdev)
as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
as3722_poweroff->dev = &pdev->dev;
- as3722_pm_poweroff = as3722_poweroff;
- if (!pm_power_off)
- pm_power_off = as3722_pm_power_off;
- return 0;
-}
+ return devm_register_sys_off_handler(as3722_poweroff->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ as3722_pm_power_off,
+ as3722_poweroff);
-static void as3722_poweroff_remove(struct platform_device *pdev)
-{
- if (pm_power_off == as3722_pm_power_off)
- pm_power_off = NULL;
- as3722_pm_poweroff = NULL;
+ return 0;
}
static struct platform_driver as3722_poweroff_driver = {
@@ -73,7 +66,6 @@ static struct platform_driver as3722_poweroff_driver = {
.name = "as3722-power-off",
},
.probe = as3722_poweroff_probe,
- .remove_new = as3722_poweroff_remove,
};
module_platform_driver(as3722_poweroff_driver);
diff --git a/drivers/power/reset/atc260x-poweroff.c b/drivers/power/reset/atc260x-poweroff.c
index b4aa50e9685e..e3e4621ccb1d 100644
--- a/drivers/power/reset/atc260x-poweroff.c
+++ b/drivers/power/reset/atc260x-poweroff.c
@@ -16,13 +16,9 @@
struct atc260x_pwrc {
struct device *dev;
struct regmap *regmap;
- struct notifier_block restart_nb;
int (*do_poweroff)(const struct atc260x_pwrc *pwrc, bool restart);
};
-/* Global variable needed only for pm_power_off */
-static struct atc260x_pwrc *atc260x_pwrc_data;
-
static int atc2603c_do_poweroff(const struct atc260x_pwrc *pwrc, bool restart)
{
int ret, deep_sleep = 0;
@@ -165,18 +161,20 @@ static int atc2609a_init(const struct atc260x_pwrc *pwrc)
return ret;
}
-static void atc260x_pwrc_pm_handler(void)
+static int atc260x_pwrc_pm_handler(struct sys_off_data *data)
{
- atc260x_pwrc_data->do_poweroff(atc260x_pwrc_data, false);
+ struct atc260x_pwrc *pwrc = data->cb_data;
+
+ pwrc->do_poweroff(pwrc, false);
WARN_ONCE(1, "Unable to power off system\n");
+
+ return NOTIFY_DONE;
}
-static int atc260x_pwrc_restart_handler(struct notifier_block *nb,
- unsigned long mode, void *cmd)
+static int atc260x_pwrc_restart_handler(struct sys_off_data *data)
{
- struct atc260x_pwrc *pwrc = container_of(nb, struct atc260x_pwrc,
- restart_nb);
+ struct atc260x_pwrc *pwrc = data->cb_data;
pwrc->do_poweroff(pwrc, true);
return NOTIFY_DONE;
@@ -194,8 +192,6 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
priv->regmap = atc260x->regmap;
- priv->restart_nb.notifier_call = atc260x_pwrc_restart_handler;
- priv->restart_nb.priority = 192;
switch (atc260x->ic_type) {
case ATC2603C:
@@ -216,16 +212,20 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
if (ret)
return ret;
- platform_set_drvdata(pdev, priv);
-
- if (!pm_power_off) {
- atc260x_pwrc_data = priv;
- pm_power_off = atc260x_pwrc_pm_handler;
- } else {
- dev_warn(priv->dev, "Poweroff callback already assigned\n");
- }
+ ret = devm_register_sys_off_handler(priv->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ atc260x_pwrc_pm_handler,
+ priv);
+ if (ret)
+ dev_err(priv->dev, "failed to register power-off handler: %d\n",
+ ret);
- ret = register_restart_handler(&priv->restart_nb);
+ ret = devm_register_sys_off_handler(priv->dev,
+ SYS_OFF_MODE_RESTART,
+ SYS_OFF_PRIO_HIGH,
+ atc260x_pwrc_restart_handler,
+ priv);
if (ret)
dev_err(priv->dev, "failed to register restart handler: %d\n",
ret);
@@ -233,21 +233,8 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
return ret;
}
-static void atc260x_pwrc_remove(struct platform_device *pdev)
-{
- struct atc260x_pwrc *priv = platform_get_drvdata(pdev);
-
- if (atc260x_pwrc_data == priv) {
- pm_power_off = NULL;
- atc260x_pwrc_data = NULL;
- }
-
- unregister_restart_handler(&priv->restart_nb);
-}
-
static struct platform_driver atc260x_pwrc_driver = {
.probe = atc260x_pwrc_probe,
- .remove_new = atc260x_pwrc_remove,
.driver = {
.name = "atc260x-pwrc",
},
diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c
index 24946766760c..797bf6773860 100644
--- a/drivers/power/reset/axxia-reset.c
+++ b/drivers/power/reset/axxia-reset.c
@@ -26,11 +26,10 @@
#define SC_EFUSE_INT_STATUS 0x180c
#define EFUSE_READ_DONE (1<<31)
-static struct regmap *syscon;
-
-static int axxia_restart_handler(struct notifier_block *this,
- unsigned long mode, void *cmd)
+static int axxia_restart_handler(struct sys_off_data *data)
{
+ struct regmap *syscon = data->cb_data;
+
/* Access Key (0xab) */
regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab);
/* Select internal boot from 0xffff0000 */
@@ -44,14 +43,10 @@ static int axxia_restart_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block axxia_restart_nb = {
- .notifier_call = axxia_restart_handler,
- .priority = 128,
-};
-
static int axxia_reset_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct regmap *syscon;
int err;
syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
@@ -60,7 +55,8 @@ static int axxia_reset_probe(struct platform_device *pdev)
return PTR_ERR(syscon);
}
- err = register_restart_handler(&axxia_restart_nb);
+ err = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
+ 128, axxia_restart_handler, syscon);
if (err)
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c
index d05728b1db09..ee3f1bb97653 100644
--- a/drivers/power/reset/brcm-kona-reset.c
+++ b/drivers/power/reset/brcm-kona-reset.c
@@ -15,8 +15,7 @@
static void __iomem *kona_reset_base;
-static int kona_reset_handler(struct notifier_block *this,
- unsigned long mode, void *cmd)
+static int kona_reset_handler(struct sys_off_data *data)
{
/*
* A soft reset is triggered by writing a 0 to bit 0 of the soft reset
@@ -31,18 +30,14 @@ static int kona_reset_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block kona_reset_nb = {
- .notifier_call = kona_reset_handler,
- .priority = 128,
-};
-
static int kona_reset_probe(struct platform_device *pdev)
{
kona_reset_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(kona_reset_base))
return PTR_ERR(kona_reset_base);
- return register_restart_handler(&kona_reset_nb);
+ return devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
+ 128, kona_reset_handler, NULL);
}
static const struct of_device_id of_match[] = {
diff --git a/drivers/power/reset/gemini-poweroff.c b/drivers/power/reset/gemini-poweroff.c
index d309b610142c..06d6992dec89 100644
--- a/drivers/power/reset/gemini-poweroff.c
+++ b/drivers/power/reset/gemini-poweroff.c
@@ -70,12 +70,9 @@ static irqreturn_t gemini_powerbutton_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-/* This callback needs this static local as it has void as argument */
-static struct gemini_powercon *gpw_poweroff;
-
-static void gemini_poweroff(void)
+static int gemini_poweroff(struct sys_off_data *data)
{
- struct gemini_powercon *gpw = gpw_poweroff;
+ struct gemini_powercon *gpw = data->cb_data;
u32 val;
dev_crit(gpw->dev, "Gemini power off\n");
@@ -86,6 +83,8 @@ static void gemini_poweroff(void)
val &= ~GEMINI_CTRL_ENABLE;
val |= GEMINI_CTRL_SHUTDOWN;
writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+ return NOTIFY_DONE;
}
static int gemini_poweroff_probe(struct platform_device *pdev)
@@ -148,8 +147,11 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
if (ret)
return ret;
- pm_power_off = gemini_poweroff;
- gpw_poweroff = gpw;
+ ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ gemini_poweroff, gpw);
+ if (ret)
+ return ret;
dev_info(dev, "Gemini poweroff driver registered\n");
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index d96d248a6e25..c7eb6dc8e90a 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -14,8 +14,8 @@
#include <linux/pm.h>
static void __iomem *msm_ps_hold;
-static int deassert_pshold(struct notifier_block *nb, unsigned long action,
- void *data)
+
+static int do_msm_poweroff(struct sys_off_data *data)
{
writel(0, msm_ps_hold);
mdelay(10000);
@@ -23,25 +23,18 @@ static int deassert_pshold(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE;
}
-static struct notifier_block restart_nb = {
- .notifier_call = deassert_pshold,
- .priority = 128,
-};
-
-static void do_msm_poweroff(void)
-{
- deassert_pshold(&restart_nb, 0, NULL);
-}
-
static int msm_restart_probe(struct platform_device *pdev)
{
msm_ps_hold = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(msm_ps_hold))
return PTR_ERR(msm_ps_hold);
- register_restart_handler(&restart_nb);
+ devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
+ 128, do_msm_poweroff, NULL);
- pm_power_off = do_msm_poweroff;
+ devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT, do_msm_poweroff,
+ NULL);
return 0;
}
diff --git a/drivers/power/reset/mt6323-poweroff.c b/drivers/power/reset/mt6323-poweroff.c
index 57a63c0ab7fb..c663347547f9 100644
--- a/drivers/power/reset/mt6323-poweroff.c
+++ b/drivers/power/reset/mt6323-poweroff.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/rtc.h>
+#include <linux/reboot.h>
struct mt6323_pwrc {
struct device *dev;
@@ -21,11 +22,9 @@ struct mt6323_pwrc {
u32 base;
};
-static struct mt6323_pwrc *mt_pwrc;
-
-static void mt6323_do_pwroff(void)
+static int mt6323_do_pwroff(struct sys_off_data *data)
{
- struct mt6323_pwrc *pwrc = mt_pwrc;
+ struct mt6323_pwrc *pwrc = data->cb_data;
unsigned int val;
int ret;
@@ -44,6 +43,8 @@ static void mt6323_do_pwroff(void)
mdelay(1000);
WARN_ONCE(1, "Unable to power off system\n");
+
+ return NOTIFY_DONE;
}
static int mt6323_pwrc_probe(struct platform_device *pdev)
@@ -51,6 +52,7 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
struct mt6323_pwrc *pwrc;
struct resource *res;
+ int ret;
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc)
@@ -63,19 +65,18 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
- mt_pwrc = pwrc;
- pm_power_off = &mt6323_do_pwroff;
+ ret = devm_register_sys_off_handler(pwrc->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ mt6323_do_pwroff,
+ pwrc);
+ if (ret)
+ return dev_err_probe(pwrc->dev, ret, "failed to register power-off handler\n");
return 0;
}
-static void mt6323_pwrc_remove(struct platform_device *pdev)
-{
- if (pm_power_off == &mt6323_do_pwroff)
- pm_power_off = NULL;
-}
-
static const struct of_device_id mt6323_pwrc_dt_match[] = {
{ .compatible = "mediatek,mt6323-pwrc" },
{},
@@ -84,7 +85,6 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe,
- .remove_new = mt6323_pwrc_remove,
.driver = {
.name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match,
diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c
index 15160809c423..fed4978e3858 100644
--- a/drivers/power/reset/regulator-poweroff.c
+++ b/drivers/power/reset/regulator-poweroff.c
@@ -13,18 +13,15 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/reboot.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)
+static int regulator_poweroff_do_poweroff(struct sys_off_data *data)
{
+ struct regulator *cpu_regulator = data->cb_data;
+
if (cpu_regulator && regulator_is_enabled(cpu_regulator))
regulator_force_disable(cpu_regulator);
@@ -32,30 +29,24 @@ static void regulator_poweroff_do_poweroff(void)
mdelay(TIMEOUT_MS);
WARN_ON(1);
+
+ return NOTIFY_DONE;
}
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;
- }
+ struct regulator *cpu_regulator;
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 void regulator_poweroff_remove(struct platform_device *pdev)
-{
- if (pm_power_off == &regulator_poweroff_do_poweroff)
- pm_power_off = NULL;
+ /* Set this handler to low priority to not override an existing handler */
+ return devm_register_sys_off_handler(&pdev->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_LOW,
+ regulator_poweroff_do_poweroff,
+ cpu_regulator);
}
static const struct of_device_id of_regulator_poweroff_match[] = {
@@ -66,7 +57,6 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);
static struct platform_driver regulator_poweroff_driver = {
.probe = regulator_poweroff_probe,
- .remove_new = regulator_poweroff_remove,
.driver = {
.name = "poweroff-regulator",
.of_match_table = of_regulator_poweroff_match,
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index f4d6004793d3..fcd588f9ae9d 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -14,29 +14,21 @@
#include <linux/module.h>
#include <linux/reboot.h>
-static void restart_poweroff_do_poweroff(void)
+static int restart_poweroff_do_poweroff(struct sys_off_data *data)
{
reboot_mode = REBOOT_HARD;
machine_restart(NULL);
+ return NOTIFY_DONE;
}
static int restart_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,
- "pm_power_off function already registered");
- return -EBUSY;
- }
-
- pm_power_off = &restart_poweroff_do_poweroff;
- return 0;
-}
-
-static void restart_poweroff_remove(struct platform_device *pdev)
-{
- if (pm_power_off == &restart_poweroff_do_poweroff)
- pm_power_off = NULL;
+ /* Set this handler to low priority to not override an existing handler */
+ return devm_register_sys_off_handler(&pdev->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_LOW,
+ restart_poweroff_do_poweroff,
+ NULL);
}
static const struct of_device_id of_restart_poweroff_match[] = {
@@ -47,7 +39,6 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match);
static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe,
- .remove_new = restart_poweroff_remove,
.driver = {
.name = "poweroff-restart",
.of_match_table = of_restart_poweroff_match,
diff --git a/drivers/power/reset/rmobile-reset.c b/drivers/power/reset/rmobile-reset.c
index 5df9b41c68c7..7dbc51c32b0e 100644
--- a/drivers/power/reset/rmobile-reset.c
+++ b/drivers/power/reset/rmobile-reset.c
@@ -19,12 +19,9 @@
/* Reset Control Register 2 */
#define RESCNT2_PRES 0x80000000 /* Soft power-on reset */
-static void __iomem *sysc_base2;
-
-static int rmobile_reset_handler(struct notifier_block *this,
- unsigned long mode, void *cmd)
+static int rmobile_reset_handler(struct sys_off_data *data)
{
- pr_debug("%s %lu\n", __func__, mode);
+ void __iomem *sysc_base2 = (void __iomem *)data->cb_data;
/* Let's assume we have acquired the HPB semaphore */
writel(RESCNT2_PRES, sysc_base2 + RESCNT2);
@@ -32,37 +29,27 @@ static int rmobile_reset_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block rmobile_reset_nb = {
- .notifier_call = rmobile_reset_handler,
- .priority = 192,
-};
-
static int rmobile_reset_probe(struct platform_device *pdev)
{
+ void __iomem *sysc_base2;
int error;
- sysc_base2 = of_iomap(pdev->dev.of_node, 1);
- if (!sysc_base2)
- return -ENODEV;
+ sysc_base2 = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(sysc_base2))
+ return PTR_ERR(sysc_base2);
- error = register_restart_handler(&rmobile_reset_nb);
+ error = devm_register_sys_off_handler(&pdev->dev,
+ SYS_OFF_MODE_RESTART,
+ SYS_OFF_PRIO_HIGH,
+ rmobile_reset_handler,
+ (__force void *)sysc_base2);
if (error) {
dev_err(&pdev->dev,
"cannot register restart handler (err=%d)\n", error);
- goto fail_unmap;
+ return error;
}
return 0;
-
-fail_unmap:
- iounmap(sysc_base2);
- return error;
-}
-
-static void rmobile_reset_remove(struct platform_device *pdev)
-{
- unregister_restart_handler(&rmobile_reset_nb);
- iounmap(sysc_base2);
}
static const struct of_device_id rmobile_reset_of_match[] = {
@@ -73,7 +60,6 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match);
static struct platform_driver rmobile_reset_driver = {
.probe = rmobile_reset_probe,
- .remove_new = rmobile_reset_remove,
.driver = {
.name = "rmobile_reset",
.of_match_table = rmobile_reset_of_match,
diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c
index 1b2ce7734260..203936f4c544 100644
--- a/drivers/power/reset/syscon-poweroff.c
+++ b/drivers/power/reset/syscon-poweroff.c
@@ -13,44 +13,56 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/reboot.h>
#include <linux/regmap.h>
-static struct regmap *map;
-static u32 offset;
-static u32 value;
-static u32 mask;
+struct syscon_poweroff_data {
+ struct regmap *map;
+ u32 offset;
+ u32 value;
+ u32 mask;
+};
-static void syscon_poweroff(void)
+static int syscon_poweroff(struct sys_off_data *off_data)
{
+ struct syscon_poweroff_data *data = off_data->cb_data;
+
/* Issue the poweroff */
- regmap_update_bits(map, offset, mask, value);
+ regmap_update_bits(data->map, data->offset, data->mask, data->value);
mdelay(1000);
pr_emerg("Unable to poweroff system\n");
+
+ return NOTIFY_DONE;
}
static int syscon_poweroff_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct syscon_poweroff_data *data;
int mask_err, value_err;
- map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
- if (IS_ERR(map)) {
- map = syscon_node_to_regmap(dev->parent->of_node);
- if (IS_ERR(map)) {
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
+ if (IS_ERR(data->map)) {
+ data->map = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(data->map)) {
dev_err(dev, "unable to get syscon");
- return PTR_ERR(map);
+ return PTR_ERR(data->map);
}
}
- if (of_property_read_u32(dev->of_node, "offset", &offset)) {
+ if (of_property_read_u32(dev->of_node, "offset", &data->offset)) {
dev_err(dev, "unable to read 'offset'");
return -EINVAL;
}
- value_err = of_property_read_u32(dev->of_node, "value", &value);
- mask_err = of_property_read_u32(dev->of_node, "mask", &mask);
+ value_err = of_property_read_u32(dev->of_node, "value", &data->value);
+ mask_err = of_property_read_u32(dev->of_node, "mask", &data->mask);
if (value_err && mask_err) {
dev_err(dev, "unable to read 'value' and 'mask'");
return -EINVAL;
@@ -58,28 +70,17 @@ static int syscon_poweroff_probe(struct platform_device *pdev)
if (value_err) {
/* support old binding */
- value = mask;
- mask = 0xFFFFFFFF;
+ data->value = data->mask;
+ data->mask = 0xFFFFFFFF;
} else if (mask_err) {
/* support value without mask*/
- mask = 0xFFFFFFFF;
- }
-
- if (pm_power_off) {
- dev_err(dev, "pm_power_off already claimed for %ps",
- pm_power_off);
- return -EBUSY;
+ data->mask = 0xFFFFFFFF;
}
- pm_power_off = syscon_poweroff;
-
- return 0;
-}
-
-static void syscon_poweroff_remove(struct platform_device *pdev)
-{
- if (pm_power_off == syscon_poweroff)
- pm_power_off = NULL;
+ return devm_register_sys_off_handler(&pdev->dev,
+ SYS_OFF_MODE_POWER_OFF,
+ SYS_OFF_PRIO_DEFAULT,
+ syscon_poweroff, data);
}
static const struct of_device_id syscon_poweroff_of_match[] = {
@@ -89,7 +90,6 @@ static const struct of_device_id syscon_poweroff_of_match[] = {
static struct platform_driver syscon_poweroff_driver = {
.probe = syscon_poweroff_probe,
- .remove_new = syscon_poweroff_remove,
.driver = {
.name = "syscon-poweroff",
.of_match_table = syscon_poweroff_of_match,
diff --git a/drivers/power/reset/tps65086-restart.c b/drivers/power/reset/tps65086-restart.c
index ee8e9f4b837e..6976dbcac74f 100644
--- a/drivers/power/reset/tps65086-restart.c
+++ b/drivers/power/reset/tps65086-restart.c
@@ -9,22 +9,14 @@
#include <linux/platform_device.h>
#include <linux/reboot.h>
-struct tps65086_restart {
- struct notifier_block handler;
- struct device *dev;
-};
-
-static int tps65086_restart_notify(struct notifier_block *this,
- unsigned long mode, void *cmd)
+static int tps65086_restart_notify(struct sys_off_data *data)
{
- struct tps65086_restart *tps65086_restart =
- container_of(this, struct tps65086_restart, handler);
- struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent);
+ struct tps65086 *tps65086 = data->cb_data;
int ret;
ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1);
if (ret) {
- dev_err(tps65086_restart->dev, "%s: error writing to tps65086 pmic: %d\n",
+ dev_err(tps65086->dev, "%s: error writing to tps65086 pmic: %d\n",
__func__, ret);
return NOTIFY_DONE;
}
@@ -39,44 +31,13 @@ static int tps65086_restart_notify(struct notifier_block *this,
static int tps65086_restart_probe(struct platform_device *pdev)
{
- struct tps65086_restart *tps65086_restart;
- int ret;
-
- tps65086_restart = devm_kzalloc(&pdev->dev, sizeof(*tps65086_restart), GFP_KERNEL);
- if (!tps65086_restart)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, tps65086_restart);
-
- tps65086_restart->handler.notifier_call = tps65086_restart_notify;
- tps65086_restart->handler.priority = 192;
- tps65086_restart->dev = &pdev->dev;
-
- ret = register_restart_handler(&tps65086_restart->handler);
- if (ret) {
- dev_err(&pdev->dev, "%s: cannot register restart handler: %d\n",
- __func__, ret);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void tps65086_restart_remove(struct platform_device *pdev)
-{
- struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev);
- int ret;
+ struct tps65086 *tps65086 = dev_get_drvdata(pdev->dev.parent);
- ret = unregister_restart_handler(&tps65086_restart->handler);
- if (ret) {
- /*
- * tps65086_restart_probe() registered the restart handler. So
- * unregistering should work fine. Checking the error code
- * shouldn't be needed, still doing it for completeness.
- */
- dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n",
- __func__, ret);
- }
+ return devm_register_sys_off_handler(&pdev->dev,
+ SYS_OFF_MODE_RESTART,
+ SYS_OFF_PRIO_HIGH,
+ tps65086_restart_notify,
+ tps65086);
}
static const struct platform_device_id tps65086_restart_id_table[] = {
@@ -90,7 +51,6 @@ static struct platform_driver tps65086_restart_driver = {
.name = "tps65086-restart",
},
.probe = tps65086_restart_probe,
- .remove_new = tps65086_restart_remove,
.id_table = tps65086_restart_id_table,
};
module_platform_driver(tps65086_restart_driver);
diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c
index c2e5a99940d3..b5eee19bac42 100644
--- a/drivers/power/reset/xgene-reboot.c
+++ b/drivers/power/reset/xgene-reboot.c
@@ -22,17 +22,13 @@
struct xgene_reboot_context {
struct device *dev;
- void *csr;
+ void __iomem *csr;
u32 mask;
- struct notifier_block restart_handler;
};
-static int xgene_restart_handler(struct notifier_block *this,
- unsigned long mode, void *cmd)
+static int xgene_restart_handler(struct sys_off_data *data)
{
- struct xgene_reboot_context *ctx =
- container_of(this, struct xgene_reboot_context,
- restart_handler);
+ struct xgene_reboot_context *ctx = data->cb_data;
/* Issue the reboot */
writel(ctx->mask, ctx->csr);
@@ -54,23 +50,20 @@ static int xgene_reboot_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
- ctx->csr = of_iomap(dev->of_node, 0);
- if (!ctx->csr) {
+ ctx->csr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ctx->csr)) {
dev_err(dev, "can not map resource\n");
- return -ENODEV;
+ return PTR_ERR(ctx->csr);
}
if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
ctx->mask = 0xFFFFFFFF;
ctx->dev = dev;
- ctx->restart_handler.notifier_call = xgene_restart_handler;
- ctx->restart_handler.priority = 128;
- err = register_restart_handler(&ctx->restart_handler);
- if (err) {
- iounmap(ctx->csr);
+ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 128,
+ xgene_restart_handler, ctx);
+ if (err)
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
- }
return err;
}
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index 7905eba93dea..56f136b2d071 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -617,8 +617,7 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
*/
static void ab8500_btemp_external_power_changed(struct power_supply *psy)
{
- class_for_each_device(power_supply_class, NULL, psy,
- ab8500_btemp_get_ext_psy_data);
+ power_supply_for_each_device(psy, ab8500_btemp_get_ext_psy_data);
}
/* ab8500 btemp driver interrupts and their respective isr */
diff --git a/drivers/power/supply/ab8500_chargalg.c b/drivers/power/supply/ab8500_chargalg.c
index de912658facb..55ab7a28056e 100644
--- a/drivers/power/supply/ab8500_chargalg.c
+++ b/drivers/power/supply/ab8500_chargalg.c
@@ -1231,8 +1231,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
int ret;
/* Collect data from all power_supply class devices */
- class_for_each_device(power_supply_class, NULL,
- di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
+ power_supply_for_each_device(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
ab8500_chargalg_end_of_charge(di);
ab8500_chargalg_check_temp(di);
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index d72f32c663bc..9b34d1a60f66 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -1949,8 +1949,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
struct ab8500_charger *di = container_of(work,
struct ab8500_charger, check_vbat_work.work);
- class_for_each_device(power_supply_class, NULL,
- &di->usb_chg, ab8500_charger_get_ext_psy_data);
+ power_supply_for_each_device(&di->usb_chg, ab8500_charger_get_ext_psy_data);
/* First run old_vbat is 0. */
if (di->old_vbat == 0)
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 8c593fbdd45a..2ccaf6116c09 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2407,8 +2407,7 @@ out:
*/
static void ab8500_fg_external_power_changed(struct power_supply *psy)
{
- class_for_each_device(power_supply_class, NULL, psy,
- ab8500_fg_get_ext_psy_data);
+ power_supply_for_each_device(psy, ab8500_fg_get_ext_psy_data);
}
/**
diff --git a/drivers/power/supply/apm_power.c b/drivers/power/supply/apm_power.c
index 9d1a7fbcaed4..8ef1b6f1f787 100644
--- a/drivers/power/supply/apm_power.c
+++ b/drivers/power/supply/apm_power.c
@@ -79,8 +79,7 @@ static void find_main_battery(void)
main_battery = NULL;
bp.main = main_battery;
- error = class_for_each_device(power_supply_class, NULL, &bp,
- __find_main_battery);
+ error = power_supply_for_each_device(&bp, __find_main_battery);
if (error) {
main_battery = bp.main;
return;
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index e23308ad4cc7..dae7e5cfc54e 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -50,20 +50,24 @@ struct axp_data {
const char * const *irq_names;
unsigned int num_irq_names;
const int *curr_lim_table;
+ int curr_lim_table_size;
struct reg_field curr_lim_fld;
struct reg_field vbus_valid_bit;
struct reg_field vbus_mon_bit;
struct reg_field usb_bc_en_bit;
+ struct reg_field usb_bc_det_fld;
struct reg_field vbus_disable_bit;
bool vbus_needs_polling: 1;
};
struct axp20x_usb_power {
+ struct device *dev;
struct regmap *regmap;
struct regmap_field *curr_lim_fld;
struct regmap_field *vbus_valid_bit;
struct regmap_field *vbus_mon_bit;
struct regmap_field *usb_bc_en_bit;
+ struct regmap_field *usb_bc_det_fld;
struct regmap_field *vbus_disable_bit;
struct power_supply *supply;
const struct axp_data *axp_data;
@@ -115,6 +119,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
if (val != power->old_status)
power_supply_changed(power->supply);
+ if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=
+ (power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
+ dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");
+ ret = regmap_field_write(power->usb_bc_en_bit, 1);
+ if (ret)
+ dev_err(power->dev, "failed to enable USB BC: errno %d",
+ ret);
+ }
+
power->old_status = val;
power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
@@ -123,6 +136,37 @@ out:
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
}
+static int axp20x_get_usb_type(struct axp20x_usb_power *power,
+ union power_supply_propval *val)
+{
+ unsigned int reg;
+ int ret;
+
+ if (!power->usb_bc_det_fld)
+ return -EINVAL;
+
+ ret = regmap_field_read(power->usb_bc_det_fld, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg) {
+ case 1:
+ val->intval = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case 2:
+ val->intval = POWER_SUPPLY_USB_TYPE_CDP;
+ break;
+ case 3:
+ val->intval = POWER_SUPPLY_USB_TYPE_DCP;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ break;
+ }
+
+ return 0;
+}
+
static int axp20x_usb_power_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
@@ -160,12 +204,16 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 1700; /* 1 step = 1.7 mV */
return 0;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
ret = regmap_field_read(power->curr_lim_fld, &v);
if (ret)
return ret;
- val->intval = power->axp_data->curr_lim_table[v];
+ if (v < power->axp_data->curr_lim_table_size)
+ val->intval = power->axp_data->curr_lim_table[v];
+ else
+ val->intval = power->axp_data->curr_lim_table[
+ power->axp_data->curr_lim_table_size - 1];
return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
@@ -189,6 +237,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 375; /* 1 step = 0.375 mA */
return 0;
+
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ return axp20x_get_usb_type(power, val);
default:
break;
}
@@ -256,19 +307,37 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
-static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval)
+static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
+ int intval)
{
- const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb,
- power->axp_data->curr_lim_fld.lsb);
+ int ret;
+ unsigned int reg;
+ const unsigned int max = power->axp_data->curr_lim_table_size;
if (intval == -1)
return -EINVAL;
- for (unsigned int i = 0; i <= max; ++i)
- if (power->axp_data->curr_lim_table[i] == intval)
- return regmap_field_write(power->curr_lim_fld, i);
+ /*
+ * BC1.2 detection can cause a race condition if we try to set a current
+ * limit while it's in progress. When it finishes it will overwrite the
+ * current limit we just set.
+ */
+ if (power->usb_bc_en_bit) {
+ dev_dbg(power->dev,
+ "disabling BC1.2 detection because current limit was set");
+ ret = regmap_field_write(power->usb_bc_en_bit, 0);
+ if (ret)
+ return ret;
+ }
+
+ for (reg = max - 1; reg > 0; reg--)
+ if (power->axp_data->curr_lim_table[reg] <= intval)
+ break;
+
+ dev_dbg(power->dev, "setting input current limit reg to %d (%d uA), requested %d uA",
+ reg, power->axp_data->curr_lim_table[reg], intval);
- return -EINVAL;
+ return regmap_field_write(power->curr_lim_fld, reg);
}
static int axp20x_usb_power_set_property(struct power_supply *psy,
@@ -287,8 +356,8 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_usb_power_set_voltage_min(power, val->intval);
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- return axp20x_usb_power_set_current_max(power, val->intval);
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return axp20x_usb_power_set_input_current_limit(power, val->intval);
default:
return -EINVAL;
@@ -313,7 +382,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
return power->vbus_disable_bit != NULL;
return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
- psp == POWER_SUPPLY_PROP_CURRENT_MAX;
+ psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
}
static enum power_supply_property axp20x_usb_power_properties[] = {
@@ -322,7 +391,7 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_CURRENT_NOW,
};
@@ -331,7 +400,23 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
- POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+};
+
+static enum power_supply_property axp813_usb_power_properties[] = {
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_USB_TYPE,
+};
+
+static enum power_supply_usb_type axp813_usb_types[] = {
+ POWER_SUPPLY_USB_TYPE_SDP,
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_CDP,
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const struct power_supply_desc axp20x_usb_power_desc = {
@@ -354,6 +439,18 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.set_property = axp20x_usb_power_set_property,
};
+static const struct power_supply_desc axp813_usb_power_desc = {
+ .name = "axp20x-usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = axp813_usb_power_properties,
+ .num_properties = ARRAY_SIZE(axp813_usb_power_properties),
+ .property_is_writeable = axp20x_usb_power_prop_writeable,
+ .get_property = axp20x_usb_power_get_property,
+ .set_property = axp20x_usb_power_set_property,
+ .usb_types = axp813_usb_types,
+ .num_usb_types = ARRAY_SIZE(axp813_usb_types),
+};
+
static const char * const axp20x_irq_names[] = {
"VBUS_PLUGIN",
"VBUS_REMOVAL",
@@ -388,10 +485,15 @@ static int axp221_usb_curr_lim_table[] = {
};
static int axp813_usb_curr_lim_table[] = {
+ 100000,
+ 500000,
900000,
1500000,
2000000,
2500000,
+ 3000000,
+ 3500000,
+ 4000000,
};
static const struct axp_data axp192_data = {
@@ -399,6 +501,7 @@ static const struct axp_data axp192_data = {
.irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp192_usb_curr_lim_table,
+ .curr_lim_table_size = ARRAY_SIZE(axp192_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@@ -409,6 +512,7 @@ static const struct axp_data axp202_data = {
.irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table,
+ .curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@@ -419,6 +523,7 @@ static const struct axp_data axp221_data = {
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp221_usb_curr_lim_table,
+ .curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
};
@@ -428,17 +533,20 @@ static const struct axp_data axp223_data = {
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table,
+ .curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
};
static const struct axp_data axp813_data = {
- .power_desc = &axp22x_usb_power_desc,
+ .power_desc = &axp813_usb_power_desc,
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp813_usb_curr_lim_table,
- .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+ .curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table),
+ .curr_lim_fld = REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7),
.usb_bc_en_bit = REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
+ .usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
.vbus_needs_polling = true,
};
@@ -558,6 +666,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, power);
+ power->dev = &pdev->dev;
power->axp_data = axp_data;
power->regmap = axp20x->regmap;
power->num_irqs = axp_data->num_irq_names;
@@ -586,6 +695,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+ axp_data->usb_bc_det_fld,
+ &power->usb_bc_det_fld);
+ if (ret)
+ return ret;
+
+ ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->vbus_disable_bit,
&power->vbus_disable_bit);
if (ret)
diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 3be6f3b10ea4..95d9a35243c2 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -550,18 +550,20 @@ static const struct dmi_system_id axp288_quirks[] = {
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
{
- /* Intel Cherry Trail Compute Stick, Windows version */
+ /* Intel Bay Trail Compute Stick */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
- DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"),
+ /* Partial match for STCK1A32WFC STCK1A32FC, STCK1A8LFC variants */
+ DMI_MATCH(DMI_PRODUCT_NAME, "STCK1A"),
},
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
{
- /* Intel Cherry Trail Compute Stick, version without an OS */
+ /* Intel Cherry Trail Compute Stick */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
- DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"),
+ /* Partial match for STK1AW32SC and STK1A32SC variants */
+ DMI_MATCH(DMI_PRODUCT_NAME, "STK1A"),
},
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
@@ -600,6 +602,14 @@ static const struct dmi_system_id axp288_quirks[] = {
.driver_data = NULL,
},
{
+ /* Radxa ROCK Pi X Single Board Computer */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "ROCK Pi X"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Radxa"),
+ },
+ .driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
+ },
+ {
/*
* Various Ace PC/Meegopad/MinisForum/Wintel Mini-PCs/HDMI-sticks
* This entry must be last because it is generic, this allows
diff --git a/drivers/power/supply/bq2415x_charger.c b/drivers/power/supply/bq2415x_charger.c
index 6a4798a62588..25e28dac900d 100644
--- a/drivers/power/supply/bq2415x_charger.c
+++ b/drivers/power/supply/bq2415x_charger.c
@@ -991,6 +991,7 @@ static enum power_supply_property bq2415x_power_supply_props[] = {
/* TODO: maybe add more power supply properties */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_ONLINE,
};
static int bq2415x_power_supply_get_property(struct power_supply *psy,
@@ -1017,6 +1018,15 @@ static int bq2415x_power_supply_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = bq->model;
break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ /* VBUS is present for all charging and fault states,
+ * except the 'Ready' state.
+ */
+ ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS);
+ if (ret < 0)
+ return ret;
+ val->intval = ret > 0;
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 1c4a9d137744..abca56834468 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -1595,17 +1595,24 @@ static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
* Return the Design Capacity in µAh
* Or < 0 if something fails.
*/
-static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
+static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di,
+ union power_supply_propval *val)
{
int dcap;
+ /* We only have to read charge design full once */
+ if (di->charge_design_full > 0) {
+ val->intval = di->charge_design_full;
+ return 0;
+ }
+
if (di->opts & BQ27XXX_O_ZERO)
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true);
else
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
if (dcap < 0) {
- dev_dbg(di->dev, "error reading initial last measured discharge\n");
+ dev_dbg(di->dev, "error reading design capacity\n");
return dcap;
}
@@ -1614,7 +1621,12 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
else
dcap *= 1000;
- return dcap;
+ /* Save for later reads */
+ di->charge_design_full = dcap;
+
+ val->intval = dcap;
+
+ return 0;
}
/*
@@ -1816,17 +1828,14 @@ static int bq27xxx_battery_current_and_status(
val_curr->intval = curr;
if (val_status) {
- if (curr > 0) {
+ if (bq27xxx_battery_is_full(di, flags))
+ val_status->intval = POWER_SUPPLY_STATUS_FULL;
+ else if (curr > 0)
val_status->intval = POWER_SUPPLY_STATUS_CHARGING;
- } else if (curr < 0) {
+ else if (curr < 0)
val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING;
- } else {
- if (bq27xxx_battery_is_full(di, flags))
- val_status->intval = POWER_SUPPLY_STATUS_FULL;
- else
- val_status->intval =
- POWER_SUPPLY_STATUS_NOT_CHARGING;
- }
+ else
+ val_status->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
return 0;
@@ -1865,10 +1874,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
*/
if (!(di->opts & BQ27XXX_O_ZERO))
bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
-
- /* We only have to read charge design full once */
- if (di->charge_design_full <= 0)
- di->charge_design_full = bq27xxx_battery_read_dcap(di);
}
if ((di->cache.capacity != cache.capacity) ||
@@ -2062,7 +2067,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
ret = bq27xxx_simple_value(di->cache.charge_full, val);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
- ret = bq27xxx_simple_value(di->charge_design_full, val);
+ ret = bq27xxx_battery_read_dcap(di, val);
break;
/*
* TODO: Implement these to make registers set from
@@ -2101,6 +2106,13 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
mod_delayed_work(system_wq, &di->work, HZ / 2);
}
+static void bq27xxx_battery_mutex_destroy(void *data)
+{
+ struct mutex *lock = data;
+
+ mutex_destroy(lock);
+}
+
int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{
struct power_supply_desc *psy_desc;
@@ -2108,9 +2120,14 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
.of_node = di->dev->of_node,
.drv_data = di,
};
+ int ret;
INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
mutex_init(&di->lock);
+ ret = devm_add_action_or_reset(di->dev, bq27xxx_battery_mutex_destroy,
+ &di->lock);
+ if (ret)
+ return ret;
di->regs = bq27xxx_chip_data[di->chip].regs;
di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key;
@@ -2128,7 +2145,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
psy_desc->get_property = bq27xxx_battery_get_property;
psy_desc->external_power_changed = bq27xxx_external_power_changed;
- di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
+ di->bat = devm_power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
if (IS_ERR(di->bat))
return dev_err_probe(di->dev, PTR_ERR(di->bat),
"failed to register battery\n");
@@ -2156,9 +2173,6 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
mutex_unlock(&di->lock);
cancel_delayed_work_sync(&di->work);
-
- power_supply_unregister(di->bat);
- mutex_destroy(&di->lock);
}
EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
index 9910c600743e..c1737f964840 100644
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -13,8 +13,7 @@
#include <linux/power/bq27xxx_battery.h>
-static DEFINE_IDR(battery_id);
-static DEFINE_MUTEX(battery_mutex);
+static DEFINE_IDA(battery_id);
static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
{
@@ -136,30 +135,39 @@ static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
return 0;
}
+static void bq27xxx_battery_i2c_devm_ida_free(void *data)
+{
+ int num = (long)data;
+
+ ida_free(&battery_id, num);
+}
+
static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct bq27xxx_device_info *di;
int ret;
char *name;
- int num;
+ long num;
/* Get new ID for the new battery device */
- mutex_lock(&battery_mutex);
- num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
- mutex_unlock(&battery_mutex);
+ num = ida_alloc(&battery_id, GFP_KERNEL);
if (num < 0)
return num;
+ ret = devm_add_action_or_reset(&client->dev,
+ bq27xxx_battery_i2c_devm_ida_free,
+ (void *)num);
+ if (ret)
+ return ret;
- name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
+ name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%ld", id->name, num);
if (!name)
- goto err_mem;
+ return -ENOMEM;
di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
if (!di)
- goto err_mem;
+ return -ENOMEM;
- di->id = num;
di->dev = &client->dev;
di->chip = id->driver_data;
di->name = name;
@@ -171,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
ret = bq27xxx_battery_setup(di);
if (ret)
- goto err_failed;
+ return ret;
/* Schedule a polling after about 1 min */
schedule_delayed_work(&di->work, 60 * HZ);
@@ -188,21 +196,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
"Unable to register IRQ %d error %d\n",
client->irq, ret);
bq27xxx_battery_teardown(di);
- goto err_failed;
+ return ret;
}
}
return 0;
-
-err_mem:
- ret = -ENOMEM;
-
-err_failed:
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, num);
- mutex_unlock(&battery_mutex);
-
- return ret;
}
static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
@@ -213,10 +211,6 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
free_irq(client->irq, di);
bq27xxx_battery_teardown(di);
-
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, di->id);
- mutex_unlock(&battery_mutex);
}
static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
diff --git a/drivers/power/supply/da9030_battery.c b/drivers/power/supply/da9030_battery.c
index 581cf956d2d2..04e0f4162d42 100644
--- a/drivers/power/supply/da9030_battery.c
+++ b/drivers/power/supply/da9030_battery.c
@@ -530,8 +530,9 @@ static int da9030_battery_probe(struct platform_device *pdev)
da9030_battery_setup_psy(charger);
psy_cfg.drv_data = charger;
- charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc,
- &psy_cfg);
+ charger->psy = devm_power_supply_register(&pdev->dev,
+ &charger->psy_desc,
+ &psy_cfg);
if (IS_ERR(charger->psy)) {
ret = PTR_ERR(charger->psy);
goto err_ps_register;
@@ -563,7 +564,6 @@ static void da9030_battery_remove(struct platform_device *dev)
DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
cancel_delayed_work_sync(&charger->work);
da9030_set_charge(charger, 0);
- power_supply_unregister(charger->psy);
}
static struct platform_driver da903x_battery_driver = {
diff --git a/drivers/power/supply/da9052-battery.c b/drivers/power/supply/da9052-battery.c
index 6f7c58a41e91..0d84c42c624e 100644
--- a/drivers/power/supply/da9052-battery.c
+++ b/drivers/power/supply/da9052-battery.c
@@ -622,7 +622,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
}
}
- bat->psy = power_supply_register(&pdev->dev, &psy_desc, &psy_cfg);
+ bat->psy = devm_power_supply_register(&pdev->dev, &psy_desc, &psy_cfg);
if (IS_ERR(bat->psy)) {
ret = PTR_ERR(bat->psy);
goto err;
@@ -644,8 +644,6 @@ static void da9052_bat_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++)
da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
-
- power_supply_unregister(bat->psy);
}
static struct platform_driver da9052_bat_driver = {
diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c
index 37db9e4ed7f3..b13cecd84f58 100644
--- a/drivers/power/supply/da9150-charger.c
+++ b/drivers/power/supply/da9150-charger.c
@@ -521,42 +521,30 @@ static int da9150_charger_probe(struct platform_device *pdev)
charger->dev = dev;
/* Acquire ADC channels */
- charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS");
- if (IS_ERR(charger->ibus_chan)) {
- ret = PTR_ERR(charger->ibus_chan);
- goto ibus_chan_fail;
- }
+ charger->ibus_chan = devm_iio_channel_get(dev, "CHAN_IBUS");
+ if (IS_ERR(charger->ibus_chan))
+ return PTR_ERR(charger->ibus_chan);
- charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS");
- if (IS_ERR(charger->vbus_chan)) {
- ret = PTR_ERR(charger->vbus_chan);
- goto vbus_chan_fail;
- }
+ charger->vbus_chan = devm_iio_channel_get(dev, "CHAN_VBUS");
+ if (IS_ERR(charger->vbus_chan))
+ return PTR_ERR(charger->vbus_chan);
- charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC");
- if (IS_ERR(charger->tjunc_chan)) {
- ret = PTR_ERR(charger->tjunc_chan);
- goto tjunc_chan_fail;
- }
+ charger->tjunc_chan = devm_iio_channel_get(dev, "CHAN_TJUNC");
+ if (IS_ERR(charger->tjunc_chan))
+ return PTR_ERR(charger->tjunc_chan);
- charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT");
- if (IS_ERR(charger->vbat_chan)) {
- ret = PTR_ERR(charger->vbat_chan);
- goto vbat_chan_fail;
- }
+ charger->vbat_chan = devm_iio_channel_get(dev, "CHAN_VBAT");
+ if (IS_ERR(charger->vbat_chan))
+ return PTR_ERR(charger->vbat_chan);
/* Register power supplies */
- charger->usb = power_supply_register(dev, &usb_desc, NULL);
- if (IS_ERR(charger->usb)) {
- ret = PTR_ERR(charger->usb);
- goto usb_fail;
- }
+ charger->usb = devm_power_supply_register(dev, &usb_desc, NULL);
+ if (IS_ERR(charger->usb))
+ return PTR_ERR(charger->usb);
- charger->battery = power_supply_register(dev, &battery_desc, NULL);
- if (IS_ERR(charger->battery)) {
- ret = PTR_ERR(charger->battery);
- goto battery_fail;
- }
+ charger->battery = devm_power_supply_register(dev, &battery_desc, NULL);
+ if (IS_ERR(charger->battery))
+ return PTR_ERR(charger->battery);
/* Get initial online supply */
reg = da9150_reg_read(da9150, DA9150_STATUS_H);
@@ -616,22 +604,7 @@ tjunc_irq_fail:
chg_irq_fail:
if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
-battery_fail:
- power_supply_unregister(charger->usb);
-usb_fail:
- iio_channel_release(charger->vbat_chan);
-
-vbat_chan_fail:
- iio_channel_release(charger->tjunc_chan);
-
-tjunc_chan_fail:
- iio_channel_release(charger->vbus_chan);
-
-vbus_chan_fail:
- iio_channel_release(charger->ibus_chan);
-
-ibus_chan_fail:
return ret;
}
@@ -656,15 +629,6 @@ static void da9150_charger_remove(struct platform_device *pdev)
if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
cancel_work_sync(&charger->otg_work);
-
- power_supply_unregister(charger->battery);
- power_supply_unregister(charger->usb);
-
- /* Release ADC channels */
- iio_channel_release(charger->ibus_chan);
- iio_channel_release(charger->vbus_chan);
- iio_channel_release(charger->tjunc_chan);
- iio_channel_release(charger->vbat_chan);
}
static struct platform_driver da9150_charger_driver = {
diff --git a/drivers/power/supply/ds2760_battery.c b/drivers/power/supply/ds2760_battery.c
index 40fba31be174..7cf4ea06b500 100644
--- a/drivers/power/supply/ds2760_battery.c
+++ b/drivers/power/supply/ds2760_battery.c
@@ -739,7 +739,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
if (current_accum)
ds2760_battery_set_current_accum(di, current_accum);
- di->bat = power_supply_register(dev, &di->bat_desc, &psy_cfg);
+ di->bat = devm_power_supply_register(dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n");
retval = PTR_ERR(di->bat);
@@ -762,7 +762,6 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
goto success;
workqueue_failed:
- power_supply_unregister(di->bat);
batt_failed:
di_alloc_failed:
success:
@@ -777,7 +776,6 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
cancel_delayed_work_sync(&di->monitor_work);
cancel_delayed_work_sync(&di->set_charged_work);
destroy_workqueue(di->monitor_wqueue);
- power_supply_unregister(di->bat);
}
#ifdef CONFIG_OF
diff --git a/drivers/power/supply/goldfish_battery.c b/drivers/power/supply/goldfish_battery.c
index 8bb645ad1e5d..479195e35d73 100644
--- a/drivers/power/supply/goldfish_battery.c
+++ b/drivers/power/supply/goldfish_battery.c
@@ -232,31 +232,22 @@ static int goldfish_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = data;
- data->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
+ data->ac = devm_power_supply_register(&pdev->dev,
+ &ac_desc,
+ &psy_cfg);
if (IS_ERR(data->ac))
return PTR_ERR(data->ac);
- data->battery = power_supply_register(&pdev->dev, &battery_desc,
- &psy_cfg);
- if (IS_ERR(data->battery)) {
- power_supply_unregister(data->ac);
+ data->battery = devm_power_supply_register(&pdev->dev,
+ &battery_desc,
+ &psy_cfg);
+ if (IS_ERR(data->battery))
return PTR_ERR(data->battery);
- }
-
- platform_set_drvdata(pdev, data);
GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
return 0;
}
-static void goldfish_battery_remove(struct platform_device *pdev)
-{
- struct goldfish_battery_data *data = platform_get_drvdata(pdev);
-
- power_supply_unregister(data->battery);
- power_supply_unregister(data->ac);
-}
-
static const struct of_device_id goldfish_battery_of_match[] = {
{ .compatible = "google,goldfish-battery", },
{},
@@ -273,7 +264,6 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match);
static struct platform_driver goldfish_battery_device = {
.probe = goldfish_battery_probe,
- .remove_new = goldfish_battery_remove,
.driver = {
.name = "goldfish-battery",
.of_match_table = goldfish_battery_of_match,
diff --git a/drivers/power/supply/lp8727_charger.c b/drivers/power/supply/lp8727_charger.c
index 0875391f7ac6..34548a4da90b 100644
--- a/drivers/power/supply/lp8727_charger.c
+++ b/drivers/power/supply/lp8727_charger.c
@@ -453,39 +453,20 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
psy_cfg.supplied_to = battery_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
- psy->ac = power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
+ psy->ac = devm_power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
if (IS_ERR(psy->ac))
- goto err_psy_ac;
+ return -EPERM;
- psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc,
- &psy_cfg);
+ psy->usb = devm_power_supply_register(pchg->dev, &lp8727_usb_desc,
+ &psy_cfg);
if (IS_ERR(psy->usb))
- goto err_psy_usb;
+ return -EPERM;
- psy->batt = power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
+ psy->batt = devm_power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
if (IS_ERR(psy->batt))
- goto err_psy_batt;
+ return -EPERM;
return 0;
-
-err_psy_batt:
- power_supply_unregister(psy->usb);
-err_psy_usb:
- power_supply_unregister(psy->ac);
-err_psy_ac:
- return -EPERM;
-}
-
-static void lp8727_unregister_psy(struct lp8727_chg *pchg)
-{
- struct lp8727_psy *psy = pchg->psy;
-
- if (!psy)
- return;
-
- power_supply_unregister(psy->ac);
- power_supply_unregister(psy->usb);
- power_supply_unregister(psy->batt);
}
#ifdef CONFIG_OF
@@ -583,7 +564,6 @@ static int lp8727_probe(struct i2c_client *cl)
ret = lp8727_setup_irq(pchg);
if (ret) {
dev_err(pchg->dev, "irq handler err: %d", ret);
- lp8727_unregister_psy(pchg);
return ret;
}
@@ -595,7 +575,6 @@ static void lp8727_remove(struct i2c_client *cl)
struct lp8727_chg *pchg = i2c_get_clientdata(cl);
lp8727_release_irq(pchg);
- lp8727_unregister_psy(pchg);
}
static const struct of_device_id lp8727_dt_ids[] __maybe_unused = {
diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c
index 2c81be82a41a..72b170b4ac46 100644
--- a/drivers/power/supply/lp8788-charger.c
+++ b/drivers/power/supply/lp8788-charger.c
@@ -406,12 +406,6 @@ static const struct power_supply_desc lp8788_psy_battery_desc = {
.get_property = lp8788_battery_get_property,
};
-static void lp8788_psy_unregister(struct lp8788_charger *pchg)
-{
- power_supply_unregister(pchg->battery);
- power_supply_unregister(pchg->charger);
-}
-
static void lp8788_charger_event(struct work_struct *work)
{
struct lp8788_charger *pchg =
@@ -666,18 +660,16 @@ static int lp8788_psy_register(struct platform_device *pdev,
charger_cfg.supplied_to = battery_supplied_to;
charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
- pchg->charger = power_supply_register(&pdev->dev,
- &lp8788_psy_charger_desc,
- &charger_cfg);
+ pchg->charger = devm_power_supply_register(&pdev->dev,
+ &lp8788_psy_charger_desc,
+ &charger_cfg);
if (IS_ERR(pchg->charger))
return -EPERM;
- pchg->battery = power_supply_register(&pdev->dev,
- &lp8788_psy_battery_desc, NULL);
- if (IS_ERR(pchg->battery)) {
- power_supply_unregister(pchg->charger);
+ pchg->battery = devm_power_supply_register(&pdev->dev,
+ &lp8788_psy_battery_desc, NULL);
+ if (IS_ERR(pchg->battery))
return -EPERM;
- }
return 0;
}
@@ -720,7 +712,6 @@ static void lp8788_charger_remove(struct platform_device *pdev)
flush_work(&pchg->charger_work);
lp8788_irq_unregister(pdev, pchg);
- lp8788_psy_unregister(pchg);
}
static struct platform_driver lp8788_charger_driver = {
diff --git a/drivers/power/supply/max14577_charger.c b/drivers/power/supply/max14577_charger.c
index 7c23fa89ea19..b28c04157709 100644
--- a/drivers/power/supply/max14577_charger.c
+++ b/drivers/power/supply/max14577_charger.c
@@ -586,8 +586,9 @@ static int max14577_charger_probe(struct platform_device *pdev)
}
psy_cfg.drv_data = chg;
- chg->charger = power_supply_register(&pdev->dev, &max14577_charger_desc,
- &psy_cfg);
+ chg->charger = devm_power_supply_register(&pdev->dev,
+ &max14577_charger_desc,
+ &psy_cfg);
if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger);
@@ -608,10 +609,7 @@ err:
static void max14577_charger_remove(struct platform_device *pdev)
{
- struct max14577_charger *chg = platform_get_drvdata(pdev);
-
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
- power_supply_unregister(chg->charger);
}
static const struct platform_device_id max14577_charger_id[] = {
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c
index d0157e63b8b5..2001e12c9f7d 100644
--- a/drivers/power/supply/max77693_charger.c
+++ b/drivers/power/supply/max77693_charger.c
@@ -709,9 +709,9 @@ static int max77693_charger_probe(struct platform_device *pdev)
goto err;
}
- chg->charger = power_supply_register(&pdev->dev,
- &max77693_charger_desc,
- &psy_cfg);
+ chg->charger = devm_power_supply_register(&pdev->dev,
+ &max77693_charger_desc,
+ &psy_cfg);
if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger);
@@ -730,13 +730,9 @@ err:
static void max77693_charger_remove(struct platform_device *pdev)
{
- struct max77693_charger *chg = platform_get_drvdata(pdev);
-
device_remove_file(&pdev->dev, &dev_attr_top_off_timer);
device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
-
- power_supply_unregister(chg->charger);
}
static const struct platform_device_id max77693_charger_id[] = {
diff --git a/drivers/power/supply/max8925_power.c b/drivers/power/supply/max8925_power.c
index 4a2d6894f94e..621a006d52a9 100644
--- a/drivers/power/supply/max8925_power.c
+++ b/drivers/power/supply/max8925_power.c
@@ -507,7 +507,6 @@ static int max8925_power_probe(struct platform_device *pdev)
struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
struct max8925_power_pdata *pdata = NULL;
struct max8925_power_info *info;
- int ret;
pdata = max8925_power_dt_init(pdev);
if (!pdata) {
@@ -528,25 +527,19 @@ static int max8925_power_probe(struct platform_device *pdev)
psy_cfg.supplied_to = pdata->supplied_to;
psy_cfg.num_supplicants = pdata->num_supplicants;
- info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
- if (IS_ERR(info->ac)) {
- ret = PTR_ERR(info->ac);
- goto out;
- }
+ info->ac = devm_power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
+ if (IS_ERR(info->ac))
+ return PTR_ERR(info->ac);
info->ac->dev.parent = &pdev->dev;
- info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
- if (IS_ERR(info->usb)) {
- ret = PTR_ERR(info->usb);
- goto out_unregister_ac;
- }
+ info->usb = devm_power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
+ if (IS_ERR(info->usb))
+ return PTR_ERR(info->usb);
info->usb->dev.parent = &pdev->dev;
- info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL);
- if (IS_ERR(info->battery)) {
- ret = PTR_ERR(info->battery);
- goto out_unregister_usb;
- }
+ info->battery = devm_power_supply_register(&pdev->dev, &battery_desc, NULL);
+ if (IS_ERR(info->battery))
+ return PTR_ERR(info->battery);
info->battery->dev.parent = &pdev->dev;
info->batt_detect = pdata->batt_detect;
@@ -558,24 +551,14 @@ static int max8925_power_probe(struct platform_device *pdev)
max8925_init_charger(chip, info);
return 0;
-out_unregister_usb:
- power_supply_unregister(info->usb);
-out_unregister_ac:
- power_supply_unregister(info->ac);
-out:
- return ret;
}
static void max8925_power_remove(struct platform_device *pdev)
{
struct max8925_power_info *info = platform_get_drvdata(pdev);
- if (info) {
- power_supply_unregister(info->ac);
- power_supply_unregister(info->usb);
- power_supply_unregister(info->battery);
+ if (info)
max8925_deinit_charger(info);
- }
}
static struct platform_driver max8925_power_driver = {
diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c
index caa272b03564..20c1651ca38e 100644
--- a/drivers/power/supply/mm8013.c
+++ b/drivers/power/supply/mm8013.c
@@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip)
static enum power_supply_property mm8013_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_NOW,
@@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy,
val->intval = regval;
break;
- case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
- ret = regmap_read(chip->regmap, REG_FLAGS, &regval);
- if (ret < 0)
- return ret;
-
- if (regval & MM8013_FLAG_CHG_INH)
- val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
- else
- val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
- break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, &regval);
if (ret < 0)
@@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy,
if (regval & MM8013_FLAG_DSG)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (regval & MM8013_FLAG_CHG_INH)
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
else if (regval & MM8013_FLAG_CHG)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (regval & MM8013_FLAG_FC)
diff --git a/drivers/power/supply/pcf50633-charger.c b/drivers/power/supply/pcf50633-charger.c
index 950e30917c63..0e980522fee5 100644
--- a/drivers/power/supply/pcf50633-charger.c
+++ b/drivers/power/supply/pcf50633-charger.c
@@ -404,9 +404,9 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
psy_cfg.drv_data = mbc;
/* Create power supplies */
- mbc->adapter = power_supply_register(&pdev->dev,
- &pcf50633_mbc_adapter_desc,
- &psy_cfg);
+ mbc->adapter = devm_power_supply_register(&pdev->dev,
+ &pcf50633_mbc_adapter_desc,
+ &psy_cfg);
if (IS_ERR(mbc->adapter)) {
dev_err(mbc->pcf->dev, "failed to register adapter\n");
return PTR_ERR(mbc->adapter);
@@ -415,20 +415,19 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
usb_psy_cfg = psy_cfg;
usb_psy_cfg.attr_grp = pcf50633_mbc_sysfs_groups;
- mbc->usb = power_supply_register(&pdev->dev, &pcf50633_mbc_usb_desc,
- &usb_psy_cfg);
+ mbc->usb = devm_power_supply_register(&pdev->dev,
+ &pcf50633_mbc_usb_desc,
+ &usb_psy_cfg);
if (IS_ERR(mbc->usb)) {
dev_err(mbc->pcf->dev, "failed to register usb\n");
- power_supply_unregister(mbc->adapter);
return PTR_ERR(mbc->usb);
}
- mbc->ac = power_supply_register(&pdev->dev, &pcf50633_mbc_ac_desc,
- &psy_cfg);
+ mbc->ac = devm_power_supply_register(&pdev->dev,
+ &pcf50633_mbc_ac_desc,
+ &psy_cfg);
if (IS_ERR(mbc->ac)) {
dev_err(mbc->pcf->dev, "failed to register ac\n");
- power_supply_unregister(mbc->adapter);
- power_supply_unregister(mbc->usb);
return PTR_ERR(mbc->ac);
}
@@ -449,10 +448,6 @@ static void pcf50633_mbc_remove(struct platform_device *pdev)
/* Remove IRQ handlers */
for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
-
- power_supply_unregister(mbc->usb);
- power_supply_unregister(mbc->adapter);
- power_supply_unregister(mbc->ac);
}
static struct platform_driver pcf50633_mbc_driver = {
diff --git a/drivers/power/supply/power_supply.h b/drivers/power/supply/power_supply.h
index 645eee4d6b6a..3cbafc58bdad 100644
--- a/drivers/power/supply/power_supply.h
+++ b/drivers/power/supply/power_supply.h
@@ -15,12 +15,14 @@ struct power_supply;
#ifdef CONFIG_SYSFS
-extern void power_supply_init_attrs(struct device_type *dev_type);
+extern void power_supply_init_attrs(void);
extern int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env);
+extern const struct attribute_group *power_supply_attr_groups[];
#else
-static inline void power_supply_init_attrs(struct device_type *dev_type) {}
+static inline void power_supply_init_attrs(void) {}
+#define power_supply_attr_groups NULL
#define power_supply_uevent NULL
#endif /* CONFIG_SYSFS */
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index ecef35ac3b7e..fefe938c9342 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -25,13 +25,17 @@
#include "power_supply.h"
#include "samsung-sdi-battery.h"
-/* exported for the APM Power driver, APM emulation */
-struct class *power_supply_class;
-EXPORT_SYMBOL_GPL(power_supply_class);
+static const struct class power_supply_class = {
+ .name = "power_supply",
+ .dev_uevent = power_supply_uevent,
+};
static BLOCKING_NOTIFIER_HEAD(power_supply_notifier);
-static struct device_type power_supply_dev_type;
+static const struct device_type power_supply_dev_type = {
+ .name = "power_supply",
+ .groups = power_supply_attr_groups,
+};
#define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10)
@@ -93,8 +97,7 @@ static void power_supply_changed_work(struct work_struct *work)
if (likely(psy->changed)) {
psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags);
- class_for_each_device(power_supply_class, NULL, psy,
- __power_supply_changed_work);
+ power_supply_for_each_device(psy, __power_supply_changed_work);
power_supply_update_leds(psy);
blocking_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy);
@@ -112,6 +115,12 @@ static void power_supply_changed_work(struct work_struct *work)
spin_unlock_irqrestore(&psy->changed_lock, flags);
}
+int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data))
+{
+ return class_for_each_device(&power_supply_class, NULL, data, fn);
+}
+EXPORT_SYMBOL_GPL(power_supply_for_each_device);
+
void power_supply_changed(struct power_supply *psy)
{
unsigned long flags;
@@ -187,8 +196,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
{
int error;
- error = class_for_each_device(power_supply_class, NULL, psy,
- __power_supply_populate_supplied_from);
+ error = power_supply_for_each_device(psy, __power_supply_populate_supplied_from);
dev_dbg(&psy->dev, "%s %d\n", __func__, error);
@@ -201,7 +209,7 @@ static int __power_supply_find_supply_from_node(struct device *dev,
struct device_node *np = data;
struct power_supply *epsy = dev_get_drvdata(dev);
- /* returning non-zero breaks out of class_for_each_device loop */
+ /* returning non-zero breaks out of power_supply_for_each_device loop */
if (epsy->of_node == np)
return 1;
@@ -213,17 +221,16 @@ static int power_supply_find_supply_from_node(struct device_node *supply_node)
int error;
/*
- * class_for_each_device() either returns its own errors or values
+ * power_supply_for_each_device() either returns its own errors or values
* returned by __power_supply_find_supply_from_node().
*
* __power_supply_find_supply_from_node() will return 0 (no match)
* or 1 (match).
*
- * We return 0 if class_for_each_device() returned 1, -EPROBE_DEFER if
+ * We return 0 if power_supply_for_each_device() returned 1, -EPROBE_DEFER if
* it returned 0, or error as returned by it.
*/
- error = class_for_each_device(power_supply_class, NULL, supply_node,
- __power_supply_find_supply_from_node);
+ error = power_supply_for_each_device(supply_node, __power_supply_find_supply_from_node);
return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER;
}
@@ -329,8 +336,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
struct psy_am_i_supplied_data data = { psy, 0 };
int error;
- error = class_for_each_device(power_supply_class, NULL, &data,
- __power_supply_am_i_supplied);
+ error = power_supply_for_each_device(&data, __power_supply_am_i_supplied);
dev_dbg(&psy->dev, "%s count %u err %d\n", __func__, data.count, error);
@@ -365,8 +371,7 @@ int power_supply_is_system_supplied(void)
int error;
unsigned int count = 0;
- error = class_for_each_device(power_supply_class, NULL, &count,
- __power_supply_is_system_supplied);
+ error = power_supply_for_each_device(&count, __power_supply_is_system_supplied);
/*
* If no system scope power class device was found at all, most probably we
@@ -412,8 +417,7 @@ int power_supply_get_property_from_supplier(struct power_supply *psy,
* This function is not intended for use with a supply with multiple
* suppliers, we simply pick the first supply to report the psp.
*/
- ret = class_for_each_device(power_supply_class, NULL, &data,
- __power_supply_get_supplier_property);
+ ret = power_supply_for_each_device(&data, __power_supply_get_supplier_property);
if (ret < 0)
return ret;
if (ret == 0)
@@ -458,8 +462,8 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
struct power_supply *power_supply_get_by_name(const char *name)
{
struct power_supply *psy = NULL;
- struct device *dev = class_find_device(power_supply_class, NULL, name,
- power_supply_match_device_by_name);
+ struct device *dev = class_find_device(&power_supply_class, NULL, name,
+ power_supply_match_device_by_name);
if (dev) {
psy = dev_get_drvdata(dev);
@@ -515,8 +519,8 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
if (!power_supply_np)
return ERR_PTR(-ENODEV);
- dev = class_find_device(power_supply_class, NULL, power_supply_np,
- power_supply_match_device_node);
+ dev = class_find_device(&power_supply_class, NULL, power_supply_np,
+ power_supply_match_device_node);
of_node_put(power_supply_np);
@@ -1369,7 +1373,7 @@ __power_supply_register(struct device *parent,
device_initialize(dev);
- dev->class = power_supply_class;
+ dev->class = &power_supply_class;
dev->type = &power_supply_dev_type;
dev->parent = parent;
dev->release = power_supply_dev_release;
@@ -1617,20 +1621,13 @@ EXPORT_SYMBOL_GPL(power_supply_get_drvdata);
static int __init power_supply_class_init(void)
{
- power_supply_class = class_create("power_supply");
-
- if (IS_ERR(power_supply_class))
- return PTR_ERR(power_supply_class);
-
- power_supply_class->dev_uevent = power_supply_uevent;
- power_supply_init_attrs(&power_supply_dev_type);
-
- return 0;
+ power_supply_init_attrs();
+ return class_register(&power_supply_class);
}
static void __exit power_supply_class_exit(void)
{
- class_destroy(power_supply_class);
+ class_unregister(&power_supply_class);
}
subsys_initcall(power_supply_class_init);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 977611e16373..0d2c3724d0bc 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -271,6 +271,23 @@ static ssize_t power_supply_show_usb_type(struct device *dev,
return count;
}
+static ssize_t power_supply_show_charge_behaviour(struct device *dev,
+ struct power_supply *psy,
+ union power_supply_propval *value,
+ char *buf)
+{
+ int ret;
+
+ ret = power_supply_get_property(psy,
+ POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
+ value);
+ if (ret < 0)
+ return ret;
+
+ return power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours,
+ value->intval, buf);
+}
+
static ssize_t power_supply_show_property(struct device *dev,
struct device_attribute *attr,
char *buf) {
@@ -298,21 +315,24 @@ static ssize_t power_supply_show_property(struct device *dev,
}
}
- if (ps_attr->text_values_len > 0 &&
- value.intval < ps_attr->text_values_len && value.intval >= 0) {
- return sysfs_emit(buf, "%s\n", ps_attr->text_values[value.intval]);
- }
-
switch (psp) {
case POWER_SUPPLY_PROP_USB_TYPE:
ret = power_supply_show_usb_type(dev, psy->desc,
&value, buf);
break;
+ case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+ ret = power_supply_show_charge_behaviour(dev, psy, &value, buf);
+ break;
case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = sysfs_emit(buf, "%s\n", value.strval);
break;
default:
- ret = sysfs_emit(buf, "%d\n", value.intval);
+ if (ps_attr->text_values_len > 0 &&
+ value.intval < ps_attr->text_values_len && value.intval >= 0) {
+ ret = sysfs_emit(buf, "%s\n", ps_attr->text_values[value.intval]);
+ } else {
+ ret = sysfs_emit(buf, "%d\n", value.intval);
+ }
}
return ret;
@@ -394,17 +414,15 @@ static const struct attribute_group power_supply_attr_group = {
.is_visible = power_supply_attr_is_visible,
};
-static const struct attribute_group *power_supply_attr_groups[] = {
+const struct attribute_group *power_supply_attr_groups[] = {
&power_supply_attr_group,
- NULL,
+ NULL
};
-void power_supply_init_attrs(struct device_type *dev_type)
+void power_supply_init_attrs(void)
{
int i;
- dev_type->groups = power_supply_attr_groups;
-
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
struct device_attribute *attr;
diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c
index d90b96df8e73..32eafe2c00af 100644
--- a/drivers/power/supply/rt5033_battery.c
+++ b/drivers/power/supply/rt5033_battery.c
@@ -159,12 +159,12 @@ static int rt5033_battery_probe(struct i2c_client *client)
return -EINVAL;
}
- i2c_set_clientdata(client, battery);
psy_cfg.of_node = client->dev.of_node;
psy_cfg.drv_data = battery;
- battery->psy = power_supply_register(&client->dev,
- &rt5033_battery_desc, &psy_cfg);
+ battery->psy = devm_power_supply_register(&client->dev,
+ &rt5033_battery_desc,
+ &psy_cfg);
if (IS_ERR(battery->psy))
return dev_err_probe(&client->dev, PTR_ERR(battery->psy),
"Failed to register power supply\n");
@@ -172,13 +172,6 @@ static int rt5033_battery_probe(struct i2c_client *client)
return 0;
}
-static void rt5033_battery_remove(struct i2c_client *client)
-{
- struct rt5033_battery *battery = i2c_get_clientdata(client);
-
- power_supply_unregister(battery->psy);
-}
-
static const struct i2c_device_id rt5033_battery_id[] = {
{ "rt5033-battery", },
{ }
@@ -197,7 +190,6 @@ static struct i2c_driver rt5033_battery_driver = {
.of_match_table = rt5033_battery_of_match,
},
.probe = rt5033_battery_probe,
- .remove = rt5033_battery_remove,
.id_table = rt5033_battery_id,
};
module_i2c_driver(rt5033_battery_driver);
diff --git a/drivers/power/supply/rx51_battery.c b/drivers/power/supply/rx51_battery.c
index e2bfc81f0fd9..7cdcd415e868 100644
--- a/drivers/power/supply/rx51_battery.c
+++ b/drivers/power/supply/rx51_battery.c
@@ -192,14 +192,11 @@ static int rx51_battery_probe(struct platform_device *pdev)
{
struct power_supply_config psy_cfg = {};
struct rx51_device_info *di;
- int ret;
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
- platform_set_drvdata(pdev, di);
-
di->dev = &pdev->dev;
di->bat_desc.name = "rx51-battery";
di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -209,52 +206,23 @@ static int rx51_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = di;
- di->channel_temp = iio_channel_get(di->dev, "temp");
- if (IS_ERR(di->channel_temp)) {
- ret = PTR_ERR(di->channel_temp);
- goto error;
- }
+ di->channel_temp = devm_iio_channel_get(di->dev, "temp");
+ if (IS_ERR(di->channel_temp))
+ return PTR_ERR(di->channel_temp);
- di->channel_bsi = iio_channel_get(di->dev, "bsi");
- if (IS_ERR(di->channel_bsi)) {
- ret = PTR_ERR(di->channel_bsi);
- goto error_channel_temp;
- }
+ di->channel_bsi = devm_iio_channel_get(di->dev, "bsi");
+ if (IS_ERR(di->channel_bsi))
+ return PTR_ERR(di->channel_bsi);
- di->channel_vbat = iio_channel_get(di->dev, "vbat");
- if (IS_ERR(di->channel_vbat)) {
- ret = PTR_ERR(di->channel_vbat);
- goto error_channel_bsi;
- }
+ di->channel_vbat = devm_iio_channel_get(di->dev, "vbat");
+ if (IS_ERR(di->channel_vbat))
+ return PTR_ERR(di->channel_vbat);
- di->bat = power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
- if (IS_ERR(di->bat)) {
- ret = PTR_ERR(di->bat);
- goto error_channel_vbat;
- }
+ di->bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
+ if (IS_ERR(di->bat))
+ return PTR_ERR(di->bat);
return 0;
-
-error_channel_vbat:
- iio_channel_release(di->channel_vbat);
-error_channel_bsi:
- iio_channel_release(di->channel_bsi);
-error_channel_temp:
- iio_channel_release(di->channel_temp);
-error:
-
- return ret;
-}
-
-static void rx51_battery_remove(struct platform_device *pdev)
-{
- struct rx51_device_info *di = platform_get_drvdata(pdev);
-
- power_supply_unregister(di->bat);
-
- iio_channel_release(di->channel_vbat);
- iio_channel_release(di->channel_bsi);
- iio_channel_release(di->channel_temp);
}
#ifdef CONFIG_OF
@@ -267,7 +235,6 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match);
static struct platform_driver rx51_battery_driver = {
.probe = rx51_battery_probe,
- .remove_new = rx51_battery_remove,
.driver = {
.name = "rx51-battery",
.of_match_table = of_match_ptr(n900_battery_of_match),
diff --git a/drivers/power/supply/tps65090-charger.c b/drivers/power/supply/tps65090-charger.c
index c59197d2aa87..d41595764caa 100644
--- a/drivers/power/supply/tps65090-charger.c
+++ b/drivers/power/supply/tps65090-charger.c
@@ -262,7 +262,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.of_node;
psy_cfg.drv_data = cdata;
- cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
+ cdata->ac = devm_power_supply_register(&pdev->dev, &tps65090_charger_desc,
&psy_cfg);
if (IS_ERR(cdata->ac)) {
dev_err(&pdev->dev, "failed: power supply register\n");
@@ -277,7 +277,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = tps65090_config_charger(cdata);
if (ret < 0) {
dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
- goto fail_unregister_supply;
+ return ret;
}
/* Check for charger presence */
@@ -286,14 +286,14 @@ static int tps65090_charger_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
TPS65090_REG_CG_STATUS1);
- goto fail_unregister_supply;
+ return ret;
}
if (status1 != 0) {
ret = tps65090_enable_charging(cdata);
if (ret < 0) {
dev_err(cdata->dev, "error enabling charger\n");
- goto fail_unregister_supply;
+ return ret;
}
cdata->ac_online = 1;
power_supply_changed(cdata->ac);
@@ -306,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
dev_err(cdata->dev,
"Unable to register irq %d err %d\n", irq,
ret);
- goto fail_unregister_supply;
+ return ret;
}
} else {
cdata->poll_task = kthread_run(tps65090_charger_poll_task,
@@ -316,16 +316,11 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = PTR_ERR(cdata->poll_task);
dev_err(cdata->dev,
"Unable to run kthread err %d\n", ret);
- goto fail_unregister_supply;
+ return ret;
}
}
return 0;
-
-fail_unregister_supply:
- power_supply_unregister(cdata->ac);
-
- return ret;
}
static void tps65090_charger_remove(struct platform_device *pdev)
@@ -334,7 +329,6 @@ static void tps65090_charger_remove(struct platform_device *pdev)
if (cdata->irq == -ENXIO)
kthread_stop(cdata->poll_task);
- power_supply_unregister(cdata->ac);
}
static const struct of_device_id of_tps65090_charger_match[] = {
diff --git a/drivers/power/supply/twl4030_madc_battery.c b/drivers/power/supply/twl4030_madc_battery.c
index 33106476bea2..3935162e350b 100644
--- a/drivers/power/supply/twl4030_madc_battery.c
+++ b/drivers/power/supply/twl4030_madc_battery.c
@@ -188,30 +188,23 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
struct twl4030_madc_battery *twl4030_madc_bat;
struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {};
- int ret = 0;
twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat),
GFP_KERNEL);
if (!twl4030_madc_bat)
return -ENOMEM;
- twl4030_madc_bat->channel_temp = iio_channel_get(&pdev->dev, "temp");
- if (IS_ERR(twl4030_madc_bat->channel_temp)) {
- ret = PTR_ERR(twl4030_madc_bat->channel_temp);
- goto err;
- }
+ twl4030_madc_bat->channel_temp = devm_iio_channel_get(&pdev->dev, "temp");
+ if (IS_ERR(twl4030_madc_bat->channel_temp))
+ return PTR_ERR(twl4030_madc_bat->channel_temp);
- twl4030_madc_bat->channel_ichg = iio_channel_get(&pdev->dev, "ichg");
- if (IS_ERR(twl4030_madc_bat->channel_ichg)) {
- ret = PTR_ERR(twl4030_madc_bat->channel_ichg);
- goto err_temp;
- }
+ twl4030_madc_bat->channel_ichg = devm_iio_channel_get(&pdev->dev, "ichg");
+ if (IS_ERR(twl4030_madc_bat->channel_ichg))
+ return PTR_ERR(twl4030_madc_bat->channel_ichg);
- twl4030_madc_bat->channel_vbat = iio_channel_get(&pdev->dev, "vbat");
- if (IS_ERR(twl4030_madc_bat->channel_vbat)) {
- ret = PTR_ERR(twl4030_madc_bat->channel_vbat);
- goto err_ichg;
- }
+ twl4030_madc_bat->channel_vbat = devm_iio_channel_get(&pdev->dev, "vbat");
+ if (IS_ERR(twl4030_madc_bat->channel_vbat))
+ return PTR_ERR(twl4030_madc_bat->channel_vbat);
/* sort charging and discharging calibration data */
sort(pdata->charging, pdata->charging_size,
@@ -222,37 +215,14 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
twl4030_cmp, NULL);
twl4030_madc_bat->pdata = pdata;
- platform_set_drvdata(pdev, twl4030_madc_bat);
psy_cfg.drv_data = twl4030_madc_bat;
- twl4030_madc_bat->psy = power_supply_register(&pdev->dev,
- &twl4030_madc_bat_desc,
- &psy_cfg);
- if (IS_ERR(twl4030_madc_bat->psy)) {
- ret = PTR_ERR(twl4030_madc_bat->psy);
- goto err_vbat;
- }
+ twl4030_madc_bat->psy = devm_power_supply_register(&pdev->dev,
+ &twl4030_madc_bat_desc,
+ &psy_cfg);
+ if (IS_ERR(twl4030_madc_bat->psy))
+ return PTR_ERR(twl4030_madc_bat->psy);
return 0;
-
-err_vbat:
- iio_channel_release(twl4030_madc_bat->channel_vbat);
-err_ichg:
- iio_channel_release(twl4030_madc_bat->channel_ichg);
-err_temp:
- iio_channel_release(twl4030_madc_bat->channel_temp);
-err:
- return ret;
-}
-
-static void twl4030_madc_battery_remove(struct platform_device *pdev)
-{
- struct twl4030_madc_battery *bat = platform_get_drvdata(pdev);
-
- power_supply_unregister(bat->psy);
-
- iio_channel_release(bat->channel_vbat);
- iio_channel_release(bat->channel_ichg);
- iio_channel_release(bat->channel_temp);
}
static struct platform_driver twl4030_madc_battery_driver = {
@@ -260,7 +230,6 @@ static struct platform_driver twl4030_madc_battery_driver = {
.name = "twl4030_madc_battery",
},
.probe = twl4030_madc_battery_probe,
- .remove_new = twl4030_madc_battery_remove,
};
module_platform_driver(twl4030_madc_battery_driver);
diff --git a/drivers/power/supply/wm831x_backup.c b/drivers/power/supply/wm831x_backup.c
index 1a7265660ade..9673fcf7f3af 100644
--- a/drivers/power/supply/wm831x_backup.c
+++ b/drivers/power/supply/wm831x_backup.c
@@ -171,7 +171,6 @@ static int wm831x_backup_probe(struct platform_device *pdev)
return -ENOMEM;
devdata->wm831x = wm831x;
- platform_set_drvdata(pdev, devdata);
/* We ignore configuration failures since we can still read
* back the status without enabling the charger (which may
@@ -191,22 +190,14 @@ static int wm831x_backup_probe(struct platform_device *pdev)
devdata->backup_desc.properties = wm831x_backup_props;
devdata->backup_desc.num_properties = ARRAY_SIZE(wm831x_backup_props);
devdata->backup_desc.get_property = wm831x_backup_get_prop;
- devdata->backup = power_supply_register(&pdev->dev,
- &devdata->backup_desc, NULL);
+ devdata->backup = devm_power_supply_register(&pdev->dev,
+ &devdata->backup_desc, NULL);
return PTR_ERR_OR_ZERO(devdata->backup);
}
-static void wm831x_backup_remove(struct platform_device *pdev)
-{
- struct wm831x_backup *devdata = platform_get_drvdata(pdev);
-
- power_supply_unregister(devdata->backup);
-}
-
static struct platform_driver wm831x_backup_driver = {
.probe = wm831x_backup_probe,
- .remove_new = wm831x_backup_remove,
.driver = {
.name = "wm831x-backup",
},
diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c
index e49b01ee5f3e..d56e499ac59f 100644
--- a/drivers/power/supply/wm831x_power.c
+++ b/drivers/power/supply/wm831x_power.c
@@ -570,8 +570,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->wall_desc.properties = wm831x_wall_props;
power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props);
power->wall_desc.get_property = wm831x_wall_get_prop;
- power->wall = power_supply_register(&pdev->dev, &power->wall_desc,
- NULL);
+ power->wall = devm_power_supply_register(&pdev->dev,
+ &power->wall_desc,
+ NULL);
if (IS_ERR(power->wall)) {
ret = PTR_ERR(power->wall);
goto err;
@@ -582,7 +583,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->usb_desc.properties = wm831x_usb_props;
power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props);
power->usb_desc.get_property = wm831x_usb_get_prop;
- power->usb = power_supply_register(&pdev->dev, &power->usb_desc, NULL);
+ power->usb = devm_power_supply_register(&pdev->dev,
+ &power->usb_desc,
+ NULL);
if (IS_ERR(power->usb)) {
ret = PTR_ERR(power->usb);
goto err_wall;
@@ -599,9 +602,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->battery_desc.num_properties = ARRAY_SIZE(wm831x_bat_props);
power->battery_desc.get_property = wm831x_bat_get_prop;
power->battery_desc.use_for_apm = 1;
- power->battery = power_supply_register(&pdev->dev,
- &power->battery_desc,
- NULL);
+ power->battery = devm_power_supply_register(&pdev->dev,
+ &power->battery_desc,
+ NULL);
if (IS_ERR(power->battery)) {
ret = PTR_ERR(power->battery);
goto err_usb;
@@ -684,12 +687,8 @@ err_syslo:
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, power);
err_battery:
- if (power->have_battery)
- power_supply_unregister(power->battery);
err_usb:
- power_supply_unregister(power->usb);
err_wall:
- power_supply_unregister(power->wall);
err:
return ret;
}
@@ -717,11 +716,6 @@ static void wm831x_power_remove(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, wm831x_power);
-
- if (wm831x_power->have_battery)
- power_supply_unregister(wm831x_power->battery);
- power_supply_unregister(wm831x_power->wall);
- power_supply_unregister(wm831x_power->usb);
}
static struct platform_driver wm831x_power_driver = {
diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c
index f23b4f5343bc..3f79ab6f6abf 100644
--- a/drivers/power/supply/wm8350_power.c
+++ b/drivers/power/supply/wm8350_power.c
@@ -540,22 +540,17 @@ static int wm8350_power_probe(struct platform_device *pdev)
struct wm8350_charger_policy *policy = power->policy;
int ret;
- power->ac = power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
+ power->ac = devm_power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
if (IS_ERR(power->ac))
return PTR_ERR(power->ac);
- power->battery = power_supply_register(&pdev->dev, &wm8350_battery_desc,
- NULL);
- if (IS_ERR(power->battery)) {
- ret = PTR_ERR(power->battery);
- goto battery_failed;
- }
+ power->battery = devm_power_supply_register(&pdev->dev, &wm8350_battery_desc, NULL);
+ if (IS_ERR(power->battery))
+ return PTR_ERR(power->battery);
- power->usb = power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
- if (IS_ERR(power->usb)) {
- ret = PTR_ERR(power->usb);
- goto usb_failed;
- }
+ power->usb = devm_power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
+ if (IS_ERR(power->usb))
+ return PTR_ERR(power->usb);
ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
if (ret < 0)
@@ -570,25 +565,14 @@ static int wm8350_power_probe(struct platform_device *pdev)
}
return ret;
-
-usb_failed:
- power_supply_unregister(power->battery);
-battery_failed:
- power_supply_unregister(power->ac);
-
- return ret;
}
static void wm8350_power_remove(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
- struct wm8350_power *power = &wm8350->power;
free_charger_irq(wm8350);
device_remove_file(&pdev->dev, &dev_attr_charger_state);
- power_supply_unregister(power->battery);
- power_supply_unregister(power->ac);
- power_supply_unregister(power->usb);
}
static struct platform_driver wm8350_power_driver = {