diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 20:19:48 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-03-14 20:19:48 +0300 |
commit | 44f89c6d3c54761114b2bc0509144e3e5ced40b0 (patch) | |
tree | 48a879ce4109c82e23d0e14f992200b7d22bce78 /drivers/power | |
parent | 80d80de4b75edb7c83c68107098aa338364dfa62 (diff) | |
parent | 4e61f1e9d58fb0765f59f47d4d1f318b36c14d95 (diff) | |
download | linux-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')
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 = ®ulator_poweroff_do_poweroff; - return 0; -} - -static void regulator_poweroff_remove(struct platform_device *pdev) -{ - if (pm_power_off == ®ulator_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, ®); + 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, ®val); - if (ret < 0) - return ret; - - if (regval & MM8013_FLAG_CHG_INH) - val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; - else - val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO; - break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val); if (ret < 0) @@ -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 = { |