Merge tag 'for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:19:48 +0000 (10:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:19:48 +0000 (10:19 -0700)
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)
  ...

47 files changed:
drivers/power/reset/as3722-poweroff.c
drivers/power/reset/atc260x-poweroff.c
drivers/power/reset/axxia-reset.c
drivers/power/reset/brcm-kona-reset.c
drivers/power/reset/gemini-poweroff.c
drivers/power/reset/msm-poweroff.c
drivers/power/reset/mt6323-poweroff.c
drivers/power/reset/regulator-poweroff.c
drivers/power/reset/restart-poweroff.c
drivers/power/reset/rmobile-reset.c
drivers/power/reset/syscon-poweroff.c
drivers/power/reset/tps65086-restart.c
drivers/power/reset/xgene-reboot.c
drivers/power/supply/ab8500_btemp.c
drivers/power/supply/ab8500_chargalg.c
drivers/power/supply/ab8500_charger.c
drivers/power/supply/ab8500_fg.c
drivers/power/supply/apm_power.c
drivers/power/supply/axp20x_usb_power.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq2415x_charger.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/bq27xxx_battery_i2c.c
drivers/power/supply/da9030_battery.c
drivers/power/supply/da9052-battery.c
drivers/power/supply/da9150-charger.c
drivers/power/supply/ds2760_battery.c
drivers/power/supply/goldfish_battery.c
drivers/power/supply/lp8727_charger.c
drivers/power/supply/lp8788-charger.c
drivers/power/supply/max14577_charger.c
drivers/power/supply/max77693_charger.c
drivers/power/supply/max8925_power.c
drivers/power/supply/mm8013.c
drivers/power/supply/pcf50633-charger.c
drivers/power/supply/power_supply.h
drivers/power/supply/power_supply_core.c
drivers/power/supply/power_supply_sysfs.c
drivers/power/supply/rt5033_battery.c
drivers/power/supply/rx51_battery.c
drivers/power/supply/tps65090-charger.c
drivers/power/supply/twl4030_madc_battery.c
drivers/power/supply/wm831x_backup.c
drivers/power/supply/wm831x_power.c
drivers/power/supply/wm8350_power.c
include/linux/power/bq27xxx_battery.h
include/linux/power_supply.h

index ab3350ce2d6214416a211e3fe3cf11936164688f..bb26fa6fa67ca720e131bae4a5a7f178fc5c6d9c 100644 (file)
@@ -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);
index b4aa50e9685e1fbb496901a4d75bd9bce64779cb..e3e4621ccb1dd2337341969fd1fce3f81c539e92 100644 (file)
 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",
        },
index 24946766760c387ae2423690b53964e0dfdb9431..797bf6773860ed5da68b3a2df389e517db71742e 100644 (file)
 #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);
 
index d05728b1db097e5432a3d60c29c6eeaf0482b449..ee3f1bb976530eefc67eaf5e4734fabf487948b3 100644 (file)
@@ -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[] = {
index d309b610142ce6ee02913cdb27dcbb0d1ce88ca0..06d6992dec892ba1c8936942f7e9c08b78db0db2 100644 (file)
@@ -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");
 
index d96d248a6e25b9da15f4dea2a4953152e4fdb5e0..c7eb6dc8e90ae5e7821bb09692dc3855d9793ad8 100644 (file)
@@ -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;
 }
index 57a63c0ab7fb702e4c15aea74f3d5b36d21b57fd..c663347547f978e5c4824a2abf2aa6c8e1e1f4c6 100644 (file)
@@ -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,
index 15160809c423a5d4e67fa07cea9f9b1c20cdd06f..fed4978e38580e6adf6e929ba46c11431258ce95 100644 (file)
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/reboot.h>
 #include <linux/regulator/consumer.h>
 
 #define TIMEOUT_MS 3000
 
-/*
- * Hold configuration here, cannot be more than one instance of the driver
- * since pm_power_off itself is global.
- */
-static struct regulator *cpu_regulator;
-
-static void regulator_poweroff_do_poweroff(void)
+static int regulator_poweroff_do_poweroff(struct sys_off_data *data)
 {
+       struct regulator *cpu_regulator = data->cb_data;
+
        if (cpu_regulator && regulator_is_enabled(cpu_regulator))
                regulator_force_disable(cpu_regulator);
 
@@ -32,30 +29,24 @@ static void regulator_poweroff_do_poweroff(void)
        mdelay(TIMEOUT_MS);
 
        WARN_ON(1);
+
+       return NOTIFY_DONE;
 }
 
 static int regulator_poweroff_probe(struct platform_device *pdev)
 {
-       /* If a pm_power_off function has already been added, leave it alone */
-       if (pm_power_off != NULL) {
-               dev_err(&pdev->dev,
-                       "%s: pm_power_off function already registered\n",
-                       __func__);
-               return -EBUSY;
-       }
+       struct regulator *cpu_regulator;
 
        cpu_regulator = devm_regulator_get(&pdev->dev, "cpu");
        if (IS_ERR(cpu_regulator))
                return PTR_ERR(cpu_regulator);
 
-       pm_power_off = &regulator_poweroff_do_poweroff;
-       return 0;
-}
-
-static void regulator_poweroff_remove(struct platform_device *pdev)
-{
-       if (pm_power_off == &regulator_poweroff_do_poweroff)
-               pm_power_off = NULL;
+       /* Set this handler to low priority to not override an existing handler */
+       return devm_register_sys_off_handler(&pdev->dev,
+                                            SYS_OFF_MODE_POWER_OFF,
+                                            SYS_OFF_PRIO_LOW,
+                                            regulator_poweroff_do_poweroff,
+                                            cpu_regulator);
 }
 
 static const struct of_device_id of_regulator_poweroff_match[] = {
@@ -66,7 +57,6 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);
 
 static struct platform_driver regulator_poweroff_driver = {
        .probe = regulator_poweroff_probe,
-       .remove_new = regulator_poweroff_remove,
        .driver = {
                .name = "poweroff-regulator",
                .of_match_table = of_regulator_poweroff_match,
index f4d6004793d3aa0cd5af28fa05e2de5df234c812..fcd588f9ae9d3bfefb753b880e1f2c4be1784051 100644 (file)
 #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,
index 5df9b41c68c79cc93f9f1a28dc4e3ec85522b992..7dbc51c32b0eb4b09b66ebc6fd84beadc073dee5 100644 (file)
 /* 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,
index 1b2ce7734260c7170803371449b94e9e53ce7677..203936f4c544f1c5008af9fd6eb662711b80e786 100644 (file)
 #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,
index ee8e9f4b837eaee09f2224c6cda81cfe08f296f8..6976dbcac74fa3e9b529abc18d1463a4ebfd1db9 100644 (file)
@@ -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);
index c2e5a99940d3754c6625d8033c905aed64abd6fe..b5eee19bac4261f83fe199c370339834e684c7e9 100644 (file)
 
 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;
 }
index 7905eba93dead1b6be92875edf0685838bb64b0e..56f136b2d071d3a1d10a54455edd314ebabe6272 100644 (file)
@@ -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 */
index de912658facb921a5f90fd78c17b1a7f2190b530..55ab7a28056e5fa4f636556157af9a2167ab7033 100644 (file)
@@ -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);
index d72f32c663bc0ea240f5fff5dfe49049f2d98e2b..9b34d1a60f6625a8b558dce193e67bc3bbb884aa 100644 (file)
@@ -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)
index 8c593fbdd45a7317f7e8ce85cfe7af8fcd509318..2ccaf6116c09abb2def00a3bed0de5dc4a0bd7dd 100644 (file)
@@ -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);
 }
 
 /**
index 9d1a7fbcaed4226d1893ea610299dcff31687f07..8ef1b6f1f78793a6ec0dea524c2c21f08bd6bb35 100644 (file)
@@ -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;
index e23308ad4cc79fbaa514e109ccf33215fe6d8b6e..dae7e5cfc54e1b3226881303e48c1bcbef1d411a 100644 (file)
@@ -50,20 +50,24 @@ struct axp_data {
        const char * const              *irq_names;
        unsigned int                    num_irq_names;
        const int                       *curr_lim_table;
+       int                             curr_lim_table_size;
        struct reg_field                curr_lim_fld;
        struct reg_field                vbus_valid_bit;
        struct reg_field                vbus_mon_bit;
        struct reg_field                usb_bc_en_bit;
+       struct reg_field                usb_bc_det_fld;
        struct reg_field                vbus_disable_bit;
        bool                            vbus_needs_polling: 1;
 };
 
 struct axp20x_usb_power {
+       struct device *dev;
        struct regmap *regmap;
        struct regmap_field *curr_lim_fld;
        struct regmap_field *vbus_valid_bit;
        struct regmap_field *vbus_mon_bit;
        struct regmap_field *usb_bc_en_bit;
+       struct regmap_field *usb_bc_det_fld;
        struct regmap_field *vbus_disable_bit;
        struct power_supply *supply;
        const struct axp_data *axp_data;
@@ -115,6 +119,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
        if (val != power->old_status)
                power_supply_changed(power->supply);
 
+       if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=
+               (power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
+               dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");
+               ret = regmap_field_write(power->usb_bc_en_bit, 1);
+               if (ret)
+                       dev_err(power->dev, "failed to enable USB BC: errno %d",
+                               ret);
+       }
+
        power->old_status = val;
        power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
 
@@ -123,6 +136,37 @@ out:
                mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 }
 
+static int axp20x_get_usb_type(struct axp20x_usb_power *power,
+                              union power_supply_propval *val)
+{
+       unsigned int reg;
+       int ret;
+
+       if (!power->usb_bc_det_fld)
+               return -EINVAL;
+
+       ret = regmap_field_read(power->usb_bc_det_fld, &reg);
+       if (ret)
+               return ret;
+
+       switch (reg) {
+       case 1:
+               val->intval = POWER_SUPPLY_USB_TYPE_SDP;
+               break;
+       case 2:
+               val->intval = POWER_SUPPLY_USB_TYPE_CDP;
+               break;
+       case 3:
+               val->intval = POWER_SUPPLY_USB_TYPE_DCP;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+               break;
+       }
+
+       return 0;
+}
+
 static int axp20x_usb_power_get_property(struct power_supply *psy,
        enum power_supply_property psp, union power_supply_propval *val)
 {
@@ -160,12 +204,16 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 
                val->intval = ret * 1700; /* 1 step = 1.7 mV */
                return 0;
-       case POWER_SUPPLY_PROP_CURRENT_MAX:
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
                ret = regmap_field_read(power->curr_lim_fld, &v);
                if (ret)
                        return ret;
 
-               val->intval = power->axp_data->curr_lim_table[v];
+               if (v < power->axp_data->curr_lim_table_size)
+                       val->intval = power->axp_data->curr_lim_table[v];
+               else
+                       val->intval = power->axp_data->curr_lim_table[
+                               power->axp_data->curr_lim_table_size - 1];
                return 0;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
                if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
@@ -189,6 +237,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 
                val->intval = ret * 375; /* 1 step = 0.375 mA */
                return 0;
+
+       case POWER_SUPPLY_PROP_USB_TYPE:
+               return axp20x_get_usb_type(power, val);
        default:
                break;
        }
@@ -256,19 +307,37 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
        return -EINVAL;
 }
 
-static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval)
+static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
+                                                   int intval)
 {
-       const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb,
-                                        power->axp_data->curr_lim_fld.lsb);
+       int ret;
+       unsigned int reg;
+       const unsigned int max = power->axp_data->curr_lim_table_size;
 
        if (intval == -1)
                return -EINVAL;
 
-       for (unsigned int i = 0; i <= max; ++i)
-               if (power->axp_data->curr_lim_table[i] == intval)
-                       return regmap_field_write(power->curr_lim_fld, i);
+       /*
+        * BC1.2 detection can cause a race condition if we try to set a current
+        * limit while it's in progress. When it finishes it will overwrite the
+        * current limit we just set.
+        */
+       if (power->usb_bc_en_bit) {
+               dev_dbg(power->dev,
+                       "disabling BC1.2 detection because current limit was set");
+               ret = regmap_field_write(power->usb_bc_en_bit, 0);
+               if (ret)
+                       return ret;
+       }
+
+       for (reg = max - 1; reg > 0; reg--)
+               if (power->axp_data->curr_lim_table[reg] <= intval)
+                       break;
+
+       dev_dbg(power->dev, "setting input current limit reg to %d (%d uA), requested %d uA",
+               reg, power->axp_data->curr_lim_table[reg], intval);
 
-       return -EINVAL;
+       return regmap_field_write(power->curr_lim_fld, reg);
 }
 
 static int axp20x_usb_power_set_property(struct power_supply *psy,
@@ -287,8 +356,8 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_VOLTAGE_MIN:
                return axp20x_usb_power_set_voltage_min(power, val->intval);
 
-       case POWER_SUPPLY_PROP_CURRENT_MAX:
-               return axp20x_usb_power_set_current_max(power, val->intval);
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               return axp20x_usb_power_set_input_current_limit(power, val->intval);
 
        default:
                return -EINVAL;
@@ -313,7 +382,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
                return power->vbus_disable_bit != NULL;
 
        return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
-              psp == POWER_SUPPLY_PROP_CURRENT_MAX;
+              psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
 }
 
 static enum power_supply_property axp20x_usb_power_properties[] = {
@@ -322,7 +391,7 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_VOLTAGE_MIN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
-       POWER_SUPPLY_PROP_CURRENT_MAX,
+       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
        POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
@@ -331,7 +400,23 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_VOLTAGE_MIN,
-       POWER_SUPPLY_PROP_CURRENT_MAX,
+       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+};
+
+static enum power_supply_property axp813_usb_power_properties[] = {
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN,
+       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+       POWER_SUPPLY_PROP_USB_TYPE,
+};
+
+static enum power_supply_usb_type axp813_usb_types[] = {
+       POWER_SUPPLY_USB_TYPE_SDP,
+       POWER_SUPPLY_USB_TYPE_DCP,
+       POWER_SUPPLY_USB_TYPE_CDP,
+       POWER_SUPPLY_USB_TYPE_UNKNOWN,
 };
 
 static const struct power_supply_desc axp20x_usb_power_desc = {
@@ -354,6 +439,18 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
        .set_property = axp20x_usb_power_set_property,
 };
 
+static const struct power_supply_desc axp813_usb_power_desc = {
+       .name = "axp20x-usb",
+       .type = POWER_SUPPLY_TYPE_USB,
+       .properties = axp813_usb_power_properties,
+       .num_properties = ARRAY_SIZE(axp813_usb_power_properties),
+       .property_is_writeable = axp20x_usb_power_prop_writeable,
+       .get_property = axp20x_usb_power_get_property,
+       .set_property = axp20x_usb_power_set_property,
+       .usb_types = axp813_usb_types,
+       .num_usb_types = ARRAY_SIZE(axp813_usb_types),
+};
+
 static const char * const axp20x_irq_names[] = {
        "VBUS_PLUGIN",
        "VBUS_REMOVAL",
@@ -388,10 +485,15 @@ static int axp221_usb_curr_lim_table[] = {
 };
 
 static int axp813_usb_curr_lim_table[] = {
+       100000,
+       500000,
        900000,
        1500000,
        2000000,
        2500000,
+       3000000,
+       3500000,
+       4000000,
 };
 
 static const struct axp_data axp192_data = {
@@ -399,6 +501,7 @@ static const struct axp_data axp192_data = {
        .irq_names      = axp20x_irq_names,
        .num_irq_names  = ARRAY_SIZE(axp20x_irq_names),
        .curr_lim_table = axp192_usb_curr_lim_table,
+       .curr_lim_table_size = ARRAY_SIZE(axp192_usb_curr_lim_table),
        .curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
        .vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
        .vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@@ -409,6 +512,7 @@ static const struct axp_data axp202_data = {
        .irq_names      = axp20x_irq_names,
        .num_irq_names  = ARRAY_SIZE(axp20x_irq_names),
        .curr_lim_table = axp20x_usb_curr_lim_table,
+       .curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
        .curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
        .vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
        .vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@@ -419,6 +523,7 @@ static const struct axp_data axp221_data = {
        .irq_names      = axp22x_irq_names,
        .num_irq_names  = ARRAY_SIZE(axp22x_irq_names),
        .curr_lim_table = axp221_usb_curr_lim_table,
+       .curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
        .curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
        .vbus_needs_polling = true,
 };
@@ -428,17 +533,20 @@ static const struct axp_data axp223_data = {
        .irq_names      = axp22x_irq_names,
        .num_irq_names  = ARRAY_SIZE(axp22x_irq_names),
        .curr_lim_table = axp20x_usb_curr_lim_table,
+       .curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
        .curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
        .vbus_needs_polling = true,
 };
 
 static const struct axp_data axp813_data = {
-       .power_desc     = &axp22x_usb_power_desc,
+       .power_desc     = &axp813_usb_power_desc,
        .irq_names      = axp22x_irq_names,
        .num_irq_names  = ARRAY_SIZE(axp22x_irq_names),
        .curr_lim_table = axp813_usb_curr_lim_table,
-       .curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+       .curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table),
+       .curr_lim_fld   = REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7),
        .usb_bc_en_bit  = REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
+       .usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
        .vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
        .vbus_needs_polling = true,
 };
@@ -558,6 +666,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, power);
 
+       power->dev = &pdev->dev;
        power->axp_data = axp_data;
        power->regmap = axp20x->regmap;
        power->num_irqs = axp_data->num_irq_names;
@@ -585,6 +694,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
        if (ret)
                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);
index 3be6f3b10ea4286e218f876798a0c7f0b99e4aa0..95d9a35243c2df9ce6cc898aec8b07df190c62ab 100644 (file)
@@ -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,
        },
@@ -599,6 +601,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
index 6a4798a62588b4fbb9f86dbcfdda9cfe2cb22f59..25e28dac900deae8c3ab605f1fdab53c397c8ecb 100644 (file)
@@ -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;
        }
index 1c4a9d1377442ad98f4e3fcb3b1215bf3e49b20b..abca5683446862551bf83b5f2fdc6a67104c57f0 100644 (file)
@@ -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);
 
index 9910c600743ebd9b9e01a1cb393c0378ae837807..c1737f964840a1e036b0f9eafdffaafe5da5a2c7 100644 (file)
@@ -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[] = {
index 581cf956d2d25811ee03fd7f0e7a4dfae0067a24..04e0f4162d42b82bb4bb45beedf1cf7e346f3aae 100644 (file)
@@ -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 = {
index 6f7c58a41e91850e9fc90f0ca522917c49f42f29..0d84c42c624e080595b715b3d4459629c7bb9dd5 100644 (file)
@@ -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 = {
index 37db9e4ed7f3090011f6b085f370d1223e215d3d..b13cecd84f58912093eea5d7a4070c4b5861b446 100644 (file)
@@ -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 = {
index 40fba31be1744fb0f38ee4659f4797c1275c653d..7cf4ea06b5003427ac9719043c9a5a4361cb5341 100644 (file)
@@ -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
index 8bb645ad1e5d515d53e4bd783570f13b531af97a..479195e35d734aa44c0eaa7164c6a0afb82e8064 100644 (file)
@@ -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,
index 0875391f7ac6b4e11be854c74ad6dba0a3bbfcbd..34548a4da90b28de31f8f95cbfbf5109400f9048 100644 (file)
@@ -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 = {
index 2c81be82a41a43834bd32d6f2a9d062960ac5f5b..72b170b4ac46a7dfac94668accefecd763fc980f 100644 (file)
@@ -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 = {
index 7c23fa89ea199702b945d5e83f6efabc6462c11e..b28c04157709a75881d63b73b0714e3b76433c48 100644 (file)
@@ -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[] = {
index d0157e63b8b502aaedf5950b1e2d0d3ec7c5bed3..2001e12c9f7de91de4e4d0b2aec04fb1d5b5c53d 100644 (file)
@@ -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[] = {
index 4a2d6894f94ee0be8f9f1431d88d6e01da88fcbc..621a006d52a96051829f764ca07984ce1aabe76d 100644 (file)
@@ -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 = {
index caa272b035649c4352f8e04d739a12dd0c5ca486..20c1651ca38e03a0d05c8110307766e2ba45fe49 100644 (file)
@@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip)
 
 static enum power_supply_property mm8013_battery_props[] = {
        POWER_SUPPLY_PROP_CAPACITY,
-       POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
        POWER_SUPPLY_PROP_CHARGE_FULL,
        POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
        POWER_SUPPLY_PROP_CHARGE_NOW,
@@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy,
 
                val->intval = regval;
                break;
-       case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
-               ret = regmap_read(chip->regmap, REG_FLAGS, &regval);
-               if (ret < 0)
-                       return ret;
-
-               if (regval & MM8013_FLAG_CHG_INH)
-                       val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
-               else
-                       val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
-               break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
                ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, &regval);
                if (ret < 0)
@@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy,
 
                if (regval & MM8013_FLAG_DSG)
                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               else if (regval & MM8013_FLAG_CHG_INH)
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
                else if (regval & MM8013_FLAG_CHG)
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
                else if (regval & MM8013_FLAG_FC)
index 950e30917c638a498d9fda1e8b9905b448418137..0e980522fee513d2ef053f4b2a2f4e8e39710e02 100644 (file)
@@ -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 = {
index 645eee4d6b6aebb709ce327bda6d5b6541bff26d..3cbafc58bdad0b9766441fa22981e5cf15870c80 100644 (file)
@@ -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 */
index ecef35ac3b7e48550afd0cde054d61f45fab53b6..fefe938c93424fc61fa5f8d9b26456e38bc8d430 100644 (file)
 #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);
index 977611e163739c047b7ed64a1ec55a8a4c611e1c..0d2c3724d0bc0e7fd7022d71d67f166df0d14d6c 100644 (file)
@@ -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;
 
index d90b96df8e73da19a219d828b77a3e089e28a71a..32eafe2c00af5177e0db8a31eab0d8d892e0d86c 100644 (file)
@@ -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);
index e2bfc81f0fd970d6a094cc77327e304306e7973d..7cdcd415e8684d0da1abee517b089066818c63dd 100644 (file)
@@ -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),
index c59197d2aa87d9fc2be3099dbbb3590f47bb764b..d41595764caa52baeb731449661fba516c5de743 100644 (file)
@@ -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[] = {
index 33106476bea2ce410cfade40319e76e3d41f03bb..3935162e350b5a8a09af167093aff725e5d4cddc 100644 (file)
@@ -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);
 
index 1a7265660adeb1d1b43eeeb98540134ad886e1bb..9673fcf7f3afba0019434634174e87f2b187f480 100644 (file)
@@ -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",
        },
index e49b01ee5f3efe949d3a5a5878af8821a66ae588..d56e499ac59fb19e268cce89e48488fd835cf5a8 100644 (file)
@@ -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 = {
index f23b4f5343bc14927813f0408b86ec86c050bf64..3f79ab6f6abf1c7081e9493079ba58c2784ea3df 100644 (file)
@@ -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)
@@ -569,26 +564,15 @@ static int wm8350_power_probe(struct platform_device *pdev)
                wm8350_reg_lock(wm8350);
        }
 
-       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 = {
index 7d8025fb74b701d6ac64cd3add0f7ca297fe5413..b9e5bd2b42d3614962e69a46170775f2974218e9 100644 (file)
@@ -61,7 +61,6 @@ struct bq27xxx_reg_cache {
 
 struct bq27xxx_device_info {
        struct device *dev;
-       int id;
        enum bq27xxx_chip chip;
        u32 opts;
        const char *name;
index c0992a77feeaad8e44c7cdfcf5da9196dab39826..8e5705a56b85feee415e4c3051d2f86e78fb8fc9 100644 (file)
@@ -242,6 +242,7 @@ struct power_supply_config {
 struct power_supply_desc {
        const char *name;
        enum power_supply_type type;
+       u8 charge_behaviours;
        const enum power_supply_usb_type *usb_types;
        size_t num_usb_types;
        const enum power_supply_property *properties;
@@ -894,8 +895,7 @@ extern int power_supply_powers(struct power_supply *psy, struct device *dev);
 #define to_power_supply(device) container_of(device, struct power_supply, dev)
 
 extern void *power_supply_get_drvdata(struct power_supply *psy);
-/* For APM emulation, think legacy userspace. */
-extern struct class *power_supply_class;
+extern int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data));
 
 static inline bool power_supply_is_amp_property(enum power_supply_property psp)
 {