Commit 44f89c6d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
 "New features:
   - axp20x_usb_power: report USB type

  Cleanups:
   - convert lots of drivers to use devm_power_supply_register()
   - convert lots of reset drivers to use devm_register_sys_off_handler()
   - constify device_type and power_supply_class
   - axp20x_usb_power: use correct property to report input current limit
   - mm8013: correct handling of "not charging" status register
   - core: fix charge_behaviour formatting
   - minor fixes cleanups"

* tag 'for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (66 commits)
  power: supply: core: fix charge_behaviour formatting
  power: supply: core: ease special formatting implementations
  power: supply: mm8013: fix "not charging" detection
  power: supply: move power_supply_attr_groups definition back to sysfs
  power: supply: core: simplify power_supply_class_init
  power: supply: core: add power_supply_for_each_device()
  power: supply: core: make power_supply_class constant
  power: supply: bq2415x_charger: report online status
  power: supply: core: move power_supply_attr_group into #ifdef block
  power: supply: core: Fix power_supply_init_attrs() stub
  power: supply: bq27xxx: Report charge full state correctly
  power: reset: rmobile-reset: Make sysc_base2 local
  power: supply: core: constify the struct device_type usage
  power: supply: axp288_fuel_gauge: Deny ROCK Pi X
  power: reset: rmobile-reset: Map correct MMIO resource
  power: reset: xgene-reboot: Fix a NULL vs IS_ERR() test
  power: supply: axp288_fuel_gauge: Add STCK1A* Intel Compute Sticks to the deny-list
  power: reset: syscon-poweroff: Use devm_register_sys_off_handler(POWER_OFF)
  power: reset: syscon-poweroff: Move device data into a struct
  power: reset: restart-poweroff: Use devm_register_sys_off_handler(POWER_OFF)
  ...
parents 80d80de4 4e61f1e9
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/slab.h> #include <linux/slab.h>
struct as3722_poweroff { struct as3722_poweroff {
...@@ -18,22 +19,18 @@ struct as3722_poweroff { ...@@ -18,22 +19,18 @@ struct as3722_poweroff {
struct as3722 *as3722; struct as3722 *as3722;
}; };
static struct as3722_poweroff *as3722_pm_poweroff; static int as3722_pm_power_off(struct sys_off_data *data)
static void as3722_pm_power_off(void)
{ {
struct as3722_poweroff *as3722_pm_poweroff = data->cb_data;
int ret; int ret;
if (!as3722_pm_poweroff) {
pr_err("AS3722 poweroff is not initialised\n");
return;
}
ret = as3722_update_bits(as3722_pm_poweroff->as3722, ret = as3722_update_bits(as3722_pm_poweroff->as3722,
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF); AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
if (ret < 0) if (ret < 0)
dev_err(as3722_pm_poweroff->dev, dev_err(as3722_pm_poweroff->dev,
"RESET_CONTROL_REG update failed, %d\n", ret); "RESET_CONTROL_REG update failed, %d\n", ret);
return NOTIFY_DONE;
} }
static int as3722_poweroff_probe(struct platform_device *pdev) static int as3722_poweroff_probe(struct platform_device *pdev)
...@@ -54,18 +51,14 @@ 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->as3722 = dev_get_drvdata(pdev->dev.parent);
as3722_poweroff->dev = &pdev->dev; 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) return 0;
{
if (pm_power_off == as3722_pm_power_off)
pm_power_off = NULL;
as3722_pm_poweroff = NULL;
} }
static struct platform_driver as3722_poweroff_driver = { static struct platform_driver as3722_poweroff_driver = {
...@@ -73,7 +66,6 @@ static struct platform_driver as3722_poweroff_driver = { ...@@ -73,7 +66,6 @@ static struct platform_driver as3722_poweroff_driver = {
.name = "as3722-power-off", .name = "as3722-power-off",
}, },
.probe = as3722_poweroff_probe, .probe = as3722_poweroff_probe,
.remove_new = as3722_poweroff_remove,
}; };
module_platform_driver(as3722_poweroff_driver); module_platform_driver(as3722_poweroff_driver);
......
...@@ -16,13 +16,9 @@ ...@@ -16,13 +16,9 @@
struct atc260x_pwrc { struct atc260x_pwrc {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct notifier_block restart_nb;
int (*do_poweroff)(const struct atc260x_pwrc *pwrc, bool restart); 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) static int atc2603c_do_poweroff(const struct atc260x_pwrc *pwrc, bool restart)
{ {
int ret, deep_sleep = 0; int ret, deep_sleep = 0;
...@@ -165,18 +161,20 @@ static int atc2609a_init(const struct atc260x_pwrc *pwrc) ...@@ -165,18 +161,20 @@ static int atc2609a_init(const struct atc260x_pwrc *pwrc)
return ret; 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"); WARN_ONCE(1, "Unable to power off system\n");
return NOTIFY_DONE;
} }
static int atc260x_pwrc_restart_handler(struct notifier_block *nb, static int atc260x_pwrc_restart_handler(struct sys_off_data *data)
unsigned long mode, void *cmd)
{ {
struct atc260x_pwrc *pwrc = container_of(nb, struct atc260x_pwrc, struct atc260x_pwrc *pwrc = data->cb_data;
restart_nb);
pwrc->do_poweroff(pwrc, true); pwrc->do_poweroff(pwrc, true);
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -194,8 +192,6 @@ static int atc260x_pwrc_probe(struct platform_device *pdev) ...@@ -194,8 +192,6 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
priv->dev = &pdev->dev; priv->dev = &pdev->dev;
priv->regmap = atc260x->regmap; priv->regmap = atc260x->regmap;
priv->restart_nb.notifier_call = atc260x_pwrc_restart_handler;
priv->restart_nb.priority = 192;
switch (atc260x->ic_type) { switch (atc260x->ic_type) {
case ATC2603C: case ATC2603C:
...@@ -216,16 +212,20 @@ static int atc260x_pwrc_probe(struct platform_device *pdev) ...@@ -216,16 +212,20 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
platform_set_drvdata(pdev, priv); ret = devm_register_sys_off_handler(priv->dev,
SYS_OFF_MODE_POWER_OFF,
if (!pm_power_off) { SYS_OFF_PRIO_DEFAULT,
atc260x_pwrc_data = priv; atc260x_pwrc_pm_handler,
pm_power_off = atc260x_pwrc_pm_handler; priv);
} else { if (ret)
dev_warn(priv->dev, "Poweroff callback already assigned\n"); 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) if (ret)
dev_err(priv->dev, "failed to register restart handler: %d\n", dev_err(priv->dev, "failed to register restart handler: %d\n",
ret); ret);
...@@ -233,21 +233,8 @@ static int atc260x_pwrc_probe(struct platform_device *pdev) ...@@ -233,21 +233,8 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
return ret; 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 = { static struct platform_driver atc260x_pwrc_driver = {
.probe = atc260x_pwrc_probe, .probe = atc260x_pwrc_probe,
.remove_new = atc260x_pwrc_remove,
.driver = { .driver = {
.name = "atc260x-pwrc", .name = "atc260x-pwrc",
}, },
......
...@@ -26,11 +26,10 @@ ...@@ -26,11 +26,10 @@
#define SC_EFUSE_INT_STATUS 0x180c #define SC_EFUSE_INT_STATUS 0x180c
#define EFUSE_READ_DONE (1<<31) #define EFUSE_READ_DONE (1<<31)
static struct regmap *syscon; static int axxia_restart_handler(struct sys_off_data *data)
static int axxia_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
{ {
struct regmap *syscon = data->cb_data;
/* Access Key (0xab) */ /* Access Key (0xab) */
regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab); regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab);
/* Select internal boot from 0xffff0000 */ /* Select internal boot from 0xffff0000 */
...@@ -44,14 +43,10 @@ static int axxia_restart_handler(struct notifier_block *this, ...@@ -44,14 +43,10 @@ static int axxia_restart_handler(struct notifier_block *this,
return NOTIFY_DONE; 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) static int axxia_reset_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct regmap *syscon;
int err; int err;
syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
...@@ -60,7 +55,8 @@ static int axxia_reset_probe(struct platform_device *pdev) ...@@ -60,7 +55,8 @@ static int axxia_reset_probe(struct platform_device *pdev)
return PTR_ERR(syscon); 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) if (err)
dev_err(dev, "cannot register restart handler (err=%d)\n", err); dev_err(dev, "cannot register restart handler (err=%d)\n", err);
......
...@@ -15,8 +15,7 @@ ...@@ -15,8 +15,7 @@
static void __iomem *kona_reset_base; static void __iomem *kona_reset_base;
static int kona_reset_handler(struct notifier_block *this, static int kona_reset_handler(struct sys_off_data *data)
unsigned long mode, void *cmd)
{ {
/* /*
* A soft reset is triggered by writing a 0 to bit 0 of the soft reset * 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, ...@@ -31,18 +30,14 @@ static int kona_reset_handler(struct notifier_block *this,
return NOTIFY_DONE; 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) static int kona_reset_probe(struct platform_device *pdev)
{ {
kona_reset_base = devm_platform_ioremap_resource(pdev, 0); kona_reset_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(kona_reset_base)) if (IS_ERR(kona_reset_base))
return PTR_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[] = { static const struct of_device_id of_match[] = {
......
...@@ -70,12 +70,9 @@ static irqreturn_t gemini_powerbutton_interrupt(int irq, void *data) ...@@ -70,12 +70,9 @@ static irqreturn_t gemini_powerbutton_interrupt(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* This callback needs this static local as it has void as argument */ static int gemini_poweroff(struct sys_off_data *data)
static struct gemini_powercon *gpw_poweroff;
static void gemini_poweroff(void)
{ {
struct gemini_powercon *gpw = gpw_poweroff; struct gemini_powercon *gpw = data->cb_data;
u32 val; u32 val;
dev_crit(gpw->dev, "Gemini power off\n"); dev_crit(gpw->dev, "Gemini power off\n");
...@@ -86,6 +83,8 @@ static void gemini_poweroff(void) ...@@ -86,6 +83,8 @@ static void gemini_poweroff(void)
val &= ~GEMINI_CTRL_ENABLE; val &= ~GEMINI_CTRL_ENABLE;
val |= GEMINI_CTRL_SHUTDOWN; val |= GEMINI_CTRL_SHUTDOWN;
writel(val, gpw->base + GEMINI_PWC_CTRLREG); writel(val, gpw->base + GEMINI_PWC_CTRLREG);
return NOTIFY_DONE;
} }
static int gemini_poweroff_probe(struct platform_device *pdev) static int gemini_poweroff_probe(struct platform_device *pdev)
...@@ -148,8 +147,11 @@ static int gemini_poweroff_probe(struct platform_device *pdev) ...@@ -148,8 +147,11 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
pm_power_off = gemini_poweroff; ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
gpw_poweroff = gpw; SYS_OFF_PRIO_DEFAULT,
gemini_poweroff, gpw);
if (ret)
return ret;
dev_info(dev, "Gemini poweroff driver registered\n"); dev_info(dev, "Gemini poweroff driver registered\n");
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
#include <linux/pm.h> #include <linux/pm.h>
static void __iomem *msm_ps_hold; 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); writel(0, msm_ps_hold);
mdelay(10000); mdelay(10000);
...@@ -23,25 +23,18 @@ static int deassert_pshold(struct notifier_block *nb, unsigned long action, ...@@ -23,25 +23,18 @@ static int deassert_pshold(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE; 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) static int msm_restart_probe(struct platform_device *pdev)
{ {
msm_ps_hold = devm_platform_ioremap_resource(pdev, 0); msm_ps_hold = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(msm_ps_hold)) if (IS_ERR(msm_ps_hold))
return PTR_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; return 0;
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/mt6397/core.h> #include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/rtc.h> #include <linux/mfd/mt6397/rtc.h>
#include <linux/reboot.h>
struct mt6323_pwrc { struct mt6323_pwrc {
struct device *dev; struct device *dev;
...@@ -21,11 +22,9 @@ struct mt6323_pwrc { ...@@ -21,11 +22,9 @@ struct mt6323_pwrc {
u32 base; u32 base;
}; };
static struct mt6323_pwrc *mt_pwrc; static int mt6323_do_pwroff(struct sys_off_data *data)
static void mt6323_do_pwroff(void)
{ {
struct mt6323_pwrc *pwrc = mt_pwrc; struct mt6323_pwrc *pwrc = data->cb_data;
unsigned int val; unsigned int val;
int ret; int ret;
...@@ -44,6 +43,8 @@ static void mt6323_do_pwroff(void) ...@@ -44,6 +43,8 @@ static void mt6323_do_pwroff(void)
mdelay(1000); mdelay(1000);
WARN_ONCE(1, "Unable to power off system\n"); WARN_ONCE(1, "Unable to power off system\n");
return NOTIFY_DONE;
} }
static int mt6323_pwrc_probe(struct platform_device *pdev) static int mt6323_pwrc_probe(struct platform_device *pdev)
...@@ -51,6 +52,7 @@ 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 mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
struct mt6323_pwrc *pwrc; struct mt6323_pwrc *pwrc;
struct resource *res; struct resource *res;
int ret;
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc) if (!pwrc)
...@@ -63,19 +65,18 @@ static int mt6323_pwrc_probe(struct platform_device *pdev) ...@@ -63,19 +65,18 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
pwrc->base = res->start; pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap; pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev; 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; 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[] = { static const struct of_device_id mt6323_pwrc_dt_match[] = {
{ .compatible = "mediatek,mt6323-pwrc" }, { .compatible = "mediatek,mt6323-pwrc" },
{}, {},
...@@ -84,7 +85,6 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match); ...@@ -84,7 +85,6 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = { static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe, .probe = mt6323_pwrc_probe,
.remove_new = mt6323_pwrc_remove,
.driver = { .driver = {
.name = "mt6323-pwrc", .name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match, .of_match_table = mt6323_pwrc_dt_match,
......
...@@ -13,18 +13,15 @@ ...@@ -13,18 +13,15 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#define TIMEOUT_MS 3000 #define TIMEOUT_MS 3000
/* static int regulator_poweroff_do_poweroff(struct sys_off_data *data)
* 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)
{ {
struct regulator *cpu_regulator = data->cb_data;
if (cpu_regulator && regulator_is_enabled(cpu_regulator)) if (cpu_regulator && regulator_is_enabled(cpu_regulator))
regulator_force_disable(cpu_regulator); regulator_force_disable(cpu_regulator);
...@@ -32,30 +29,24 @@ static void regulator_poweroff_do_poweroff(void) ...@@ -32,30 +29,24 @@ static void regulator_poweroff_do_poweroff(void)
mdelay(TIMEOUT_MS); mdelay(TIMEOUT_MS);
WARN_ON(1); WARN_ON(1);
return NOTIFY_DONE;
} }
static int regulator_poweroff_probe(struct platform_device *pdev) static int regulator_poweroff_probe(struct platform_device *pdev)
{ {
/* If a pm_power_off function has already been added, leave it alone */ struct regulator *cpu_regulator;
if (pm_power_off != NULL) {
dev_err(&pdev->dev,
"%s: pm_power_off function already registered\n",
__func__);
return -EBUSY;
}
cpu_regulator = devm_regulator_get(&pdev->dev, "cpu"); cpu_regulator = devm_regulator_get(&pdev->dev, "cpu");
if (IS_ERR(cpu_regulator)) if (IS_ERR(cpu_regulator))
return PTR_ERR(cpu_regulator); return PTR_ERR(cpu_regulator);
pm_power_off = &regulator_poweroff_do_poweroff; /* Set this handler to low priority to not override an existing handler */
return 0; return devm_register_sys_off_handler(&pdev->dev,
} SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_LOW,
static void regulator_poweroff_remove(struct platform_device *pdev) regulator_poweroff_do_poweroff,
{ cpu_regulator);
if (pm_power_off == &regulator_poweroff_do_poweroff)
pm_power_off = NULL;
} }
static const struct of_device_id of_regulator_poweroff_match[] = { static const struct of_device_id of_regulator_poweroff_match[] = {
...@@ -66,7 +57,6 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match); ...@@ -66,7 +57,6 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);
static struct platform_driver regulator_poweroff_driver = { static struct platform_driver regulator_poweroff_driver = {
.probe = regulator_poweroff_probe, .probe = regulator_poweroff_probe,
.remove_new = regulator_poweroff_remove,
.driver = { .driver = {
.name = "poweroff-regulator", .name = "poweroff-regulator",
.of_match_table = of_regulator_poweroff_match, .of_match_table = of_regulator_poweroff_match,
......
...@@ -14,29 +14,21 @@ ...@@ -14,29 +14,21 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/reboot.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; reboot_mode = REBOOT_HARD;
machine_restart(NULL); machine_restart(NULL);
return NOTIFY_DONE;
} }
static int restart_poweroff_probe(struct platform_device *pdev) static int restart_poweroff_probe(struct platform_device *pdev)
{ {
/* If a pm_power_off function has already been added, leave it alone */ /* Set this handler to low priority to not override an existing handler */
if (pm_power_off != NULL) { return devm_register_sys_off_handler(&pdev->dev,
dev_err(&pdev->dev, SYS_OFF_MODE_POWER_OFF,
"pm_power_off function already registered"); SYS_OFF_PRIO_LOW,
return -EBUSY; restart_poweroff_do_poweroff,
} NULL);
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;
} }
static const struct of_device_id of_restart_poweroff_match[] = { static const struct of_device_id of_restart_poweroff_match[] = {
...@@ -47,7 +39,6 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match); ...@@ -47,7 +39,6 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match);
static struct platform_driver restart_poweroff_driver = { static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe, .probe = restart_poweroff_probe,
.remove_new = restart_poweroff_remove,
.driver = { .driver = {
.name = "poweroff-restart", .name = "poweroff-restart",
.of_match_table = of_restart_poweroff_match, .of_match_table = of_restart_poweroff_match,
......
...@@ -19,12 +19,9 @@ ...@@ -19,12 +19,9 @@
/* Reset Control Register 2 */ /* Reset Control Register 2 */
#define RESCNT2_PRES 0x80000000 /* Soft power-on reset */ #define RESCNT2_PRES 0x80000000 /* Soft power-on reset */
static void __iomem *sysc_base2; static int rmobile_reset_handler(struct sys_off_data *data)
static int rmobile_reset_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
{ {
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 */ /* Let's assume we have acquired the HPB semaphore */
writel(RESCNT2_PRES, sysc_base2 + RESCNT2); writel(RESCNT2_PRES, sysc_base2 + RESCNT2);
...@@ -32,37 +29,27 @@ static int rmobile_reset_handler(struct notifier_block *this, ...@@ -32,37 +29,27 @@ static int rmobile_reset_handler(struct notifier_block *this,
return NOTIFY_DONE; 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) static int rmobile_reset_probe(struct platform_device *pdev)
{ {
void __iomem *sysc_base2;
int error; int error;
sysc_base2 = of_iomap(pdev->dev.of_node, 1); sysc_base2 = devm_platform_ioremap_resource(pdev, 1);
if (!sysc_base2) if (IS_ERR(sysc_base2))
return -ENODEV; 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) { if (error) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"cannot register restart handler (err=%d)\n", error); "cannot register restart handler (err=%d)\n", error);
goto fail_unmap; return error;
} }
return 0; 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[] = { static const struct of_device_id rmobile_reset_of_match[] = {
...@@ -73,7 +60,6 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match); ...@@ -73,7 +60,6 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match);
static struct platform_driver rmobile_reset_driver = { static struct platform_driver rmobile_reset_driver = {
.probe = rmobile_reset_probe, .probe = rmobile_reset_probe,
.remove_new = rmobile_reset_remove,
.driver = { .driver = {
.name = "rmobile_reset", .name = "rmobile_reset",
.of_match_table = rmobile_reset_of_match, .of_match_table = rmobile_reset_of_match,
......
...@@ -13,44 +13,56 @@ ...@@ -13,44 +13,56 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/regmap.h> #include <linux/regmap.h>
static struct regmap *map; struct syscon_poweroff_data {
static u32 offset; struct regmap *map;
static u32 value; u32 offset;
static u32 mask; 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 */ /* Issue the poweroff */
regmap_update_bits(map, offset, mask, value); regmap_update_bits(data->map, data->offset, data->mask, data->value);
mdelay(1000); mdelay(1000);
pr_emerg("Unable to poweroff system\n"); pr_emerg("Unable to poweroff system\n");
return NOTIFY_DONE;
} }
static int syscon_poweroff_probe(struct platform_device *pdev) static int syscon_poweroff_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct syscon_poweroff_data *data;
int mask_err, value_err; int mask_err, value_err;
map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap"); data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (IS_ERR(map)) { if (!data)
map = syscon_node_to_regmap(dev->parent->of_node); return -ENOMEM;
if (IS_ERR(map)) {
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"); 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'"); dev_err(dev, "unable to read 'offset'");
return -EINVAL; return -EINVAL;
} }
value_err = of_property_read_u32(dev->of_node, "value", &value); value_err = of_property_read_u32(dev->of_node, "value", &data->value);
mask_err = of_property_read_u32(dev->of_node, "mask", &mask); mask_err = of_property_read_u32(dev->of_node, "mask", &data->mask);
if (value_err && mask_err) { if (value_err && mask_err) {
dev_err(dev, "unable to read 'value' and 'mask'"); dev_err(dev, "unable to read 'value' and 'mask'");
return -EINVAL; return -EINVAL;
...@@ -58,28 +70,17 @@ static int syscon_poweroff_probe(struct platform_device *pdev) ...@@ -58,28 +70,17 @@ static int syscon_poweroff_probe(struct platform_device *pdev)
if (value_err) { if (value_err) {
/* support old binding */ /* support old binding */
value = mask; data->value = data->mask;
mask = 0xFFFFFFFF; data->mask = 0xFFFFFFFF;
} else if (mask_err) { } else if (mask_err) {
/* support value without mask*/ /* support value without mask*/
mask = 0xFFFFFFFF; data->mask = 0xFFFFFFFF;
}
if (pm_power_off) {
dev_err(dev, "pm_power_off already claimed for %ps",
pm_power_off);
return -EBUSY;
} }
pm_power_off = syscon_poweroff; return devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_POWER_OFF,
return 0; SYS_OFF_PRIO_DEFAULT,
} syscon_poweroff, data);
static void syscon_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == syscon_poweroff)
pm_power_off = NULL;
} }
static const struct of_device_id syscon_poweroff_of_match[] = { static const struct of_device_id syscon_poweroff_of_match[] = {
...@@ -89,7 +90,6 @@ 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 = { static struct platform_driver syscon_poweroff_driver = {
.probe = syscon_poweroff_probe, .probe = syscon_poweroff_probe,
.remove_new = syscon_poweroff_remove,
.driver = { .driver = {
.name = "syscon-poweroff", .name = "syscon-poweroff",
.of_match_table = syscon_poweroff_of_match, .of_match_table = syscon_poweroff_of_match,
......
...@@ -9,22 +9,14 @@ ...@@ -9,22 +9,14 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reboot.h> #include <linux/reboot.h>
struct tps65086_restart { static int tps65086_restart_notify(struct sys_off_data *data)
struct notifier_block handler;
struct device *dev;
};
static int tps65086_restart_notify(struct notifier_block *this,
unsigned long mode, void *cmd)
{ {
struct tps65086_restart *tps65086_restart = struct tps65086 *tps65086 = data->cb_data;
container_of(this, struct tps65086_restart, handler);
struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent);
int ret; int ret;
ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1); ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1);
if (ret) { 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); __func__, ret);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -39,44 +31,13 @@ static int tps65086_restart_notify(struct notifier_block *this, ...@@ -39,44 +31,13 @@ static int tps65086_restart_notify(struct notifier_block *this,
static int tps65086_restart_probe(struct platform_device *pdev) static int tps65086_restart_probe(struct platform_device *pdev)
{ {
struct tps65086_restart *tps65086_restart; struct tps65086 *tps65086 = dev_get_drvdata(pdev->dev.parent);
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;
ret = unregister_restart_handler(&tps65086_restart->handler); return devm_register_sys_off_handler(&pdev->dev,
if (ret) { SYS_OFF_MODE_RESTART,
/* SYS_OFF_PRIO_HIGH,
* tps65086_restart_probe() registered the restart handler. So tps65086_restart_notify,
* unregistering should work fine. Checking the error code tps65086);
* shouldn't be needed, still doing it for completeness.
*/
dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n",
__func__, ret);
}
} }
static const struct platform_device_id tps65086_restart_id_table[] = { static const struct platform_device_id tps65086_restart_id_table[] = {
...@@ -90,7 +51,6 @@ static struct platform_driver tps65086_restart_driver = { ...@@ -90,7 +51,6 @@ static struct platform_driver tps65086_restart_driver = {
.name = "tps65086-restart", .name = "tps65086-restart",
}, },
.probe = tps65086_restart_probe, .probe = tps65086_restart_probe,
.remove_new = tps65086_restart_remove,
.id_table = tps65086_restart_id_table, .id_table = tps65086_restart_id_table,
}; };
module_platform_driver(tps65086_restart_driver); module_platform_driver(tps65086_restart_driver);
......
...@@ -22,17 +22,13 @@ ...@@ -22,17 +22,13 @@
struct xgene_reboot_context { struct xgene_reboot_context {
struct device *dev; struct device *dev;
void *csr; void __iomem *csr;
u32 mask; u32 mask;
struct notifier_block restart_handler;
}; };
static int xgene_restart_handler(struct notifier_block *this, static int xgene_restart_handler(struct sys_off_data *data)
unsigned long mode, void *cmd)
{ {
struct xgene_reboot_context *ctx = struct xgene_reboot_context *ctx = data->cb_data;
container_of(this, struct xgene_reboot_context,
restart_handler);
/* Issue the reboot */ /* Issue the reboot */
writel(ctx->mask, ctx->csr); writel(ctx->mask, ctx->csr);
...@@ -54,23 +50,20 @@ static int xgene_reboot_probe(struct platform_device *pdev) ...@@ -54,23 +50,20 @@ static int xgene_reboot_probe(struct platform_device *pdev)
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->csr = of_iomap(dev->of_node, 0); ctx->csr = devm_platform_ioremap_resource(pdev, 0);
if (!ctx->csr) { if (IS_ERR(ctx->csr)) {
dev_err(dev, "can not map resource\n"); 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)) if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
ctx->mask = 0xFFFFFFFF; ctx->mask = 0xFFFFFFFF;
ctx->dev = dev; ctx->dev = dev;
ctx->restart_handler.notifier_call = xgene_restart_handler; err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 128,
ctx->restart_handler.priority = 128; xgene_restart_handler, ctx);
err = register_restart_handler(&ctx->restart_handler); if (err)
if (err) {
iounmap(ctx->csr);
dev_err(dev, "cannot register restart handler (err=%d)\n", err); dev_err(dev, "cannot register restart handler (err=%d)\n", err);
}
return err; return err;
} }
......
...@@ -617,8 +617,7 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data) ...@@ -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) static void ab8500_btemp_external_power_changed(struct power_supply *psy)
{ {
class_for_each_device(power_supply_class, NULL, psy, power_supply_for_each_device(psy, ab8500_btemp_get_ext_psy_data);
ab8500_btemp_get_ext_psy_data);
} }
/* ab8500 btemp driver interrupts and their respective isr */ /* ab8500 btemp driver interrupts and their respective isr */
......
...@@ -1231,8 +1231,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ...@@ -1231,8 +1231,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
int ret; int ret;
/* Collect data from all power_supply class devices */ /* Collect data from all power_supply class devices */
class_for_each_device(power_supply_class, NULL, power_supply_for_each_device(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
ab8500_chargalg_end_of_charge(di); ab8500_chargalg_end_of_charge(di);
ab8500_chargalg_check_temp(di); ab8500_chargalg_check_temp(di);
......
...@@ -1949,8 +1949,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work) ...@@ -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 *di = container_of(work,
struct ab8500_charger, check_vbat_work.work); struct ab8500_charger, check_vbat_work.work);
class_for_each_device(power_supply_class, NULL, power_supply_for_each_device(&di->usb_chg, ab8500_charger_get_ext_psy_data);
&di->usb_chg, ab8500_charger_get_ext_psy_data);
/* First run old_vbat is 0. */ /* First run old_vbat is 0. */
if (di->old_vbat == 0) if (di->old_vbat == 0)
......
...@@ -2407,8 +2407,7 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) ...@@ -2407,8 +2407,7 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
*/ */
static void ab8500_fg_external_power_changed(struct power_supply *psy) static void ab8500_fg_external_power_changed(struct power_supply *psy)
{ {
class_for_each_device(power_supply_class, NULL, psy, power_supply_for_each_device(psy, ab8500_fg_get_ext_psy_data);
ab8500_fg_get_ext_psy_data);
} }
/** /**
......
...@@ -79,8 +79,7 @@ static void find_main_battery(void) ...@@ -79,8 +79,7 @@ static void find_main_battery(void)
main_battery = NULL; main_battery = NULL;
bp.main = main_battery; bp.main = main_battery;
error = class_for_each_device(power_supply_class, NULL, &bp, error = power_supply_for_each_device(&bp, __find_main_battery);
__find_main_battery);
if (error) { if (error) {
main_battery = bp.main; main_battery = bp.main;
return; return;
......
...@@ -50,20 +50,24 @@ struct axp_data { ...@@ -50,20 +50,24 @@ struct axp_data {
const char * const *irq_names; const char * const *irq_names;
unsigned int num_irq_names; unsigned int num_irq_names;
const int *curr_lim_table; const int *curr_lim_table;
int curr_lim_table_size;
struct reg_field curr_lim_fld; struct reg_field curr_lim_fld;
struct reg_field vbus_valid_bit; struct reg_field vbus_valid_bit;
struct reg_field vbus_mon_bit; struct reg_field vbus_mon_bit;
struct reg_field usb_bc_en_bit; struct reg_field usb_bc_en_bit;
struct reg_field usb_bc_det_fld;
struct reg_field vbus_disable_bit; struct reg_field vbus_disable_bit;
bool vbus_needs_polling: 1; bool vbus_needs_polling: 1;
}; };
struct axp20x_usb_power { struct axp20x_usb_power {
struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct regmap_field *curr_lim_fld; struct regmap_field *curr_lim_fld;
struct regmap_field *vbus_valid_bit; struct regmap_field *vbus_valid_bit;
struct regmap_field *vbus_mon_bit; struct regmap_field *vbus_mon_bit;
struct regmap_field *usb_bc_en_bit; struct regmap_field *usb_bc_en_bit;
struct regmap_field *usb_bc_det_fld;
struct regmap_field *vbus_disable_bit; struct regmap_field *vbus_disable_bit;
struct power_supply *supply; struct power_supply *supply;
const struct axp_data *axp_data; const struct axp_data *axp_data;
...@@ -115,6 +119,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work) ...@@ -115,6 +119,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
if (val != power->old_status) if (val != power->old_status)
power_supply_changed(power->supply); 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->old_status = val;
power->online = val & AXP20X_PWR_STATUS_VBUS_USED; power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
...@@ -123,6 +136,37 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work) ...@@ -123,6 +136,37 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); 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, static int axp20x_usb_power_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val) 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, ...@@ -160,12 +204,16 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 1700; /* 1 step = 1.7 mV */ val->intval = ret * 1700; /* 1 step = 1.7 mV */
return 0; return 0;
case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
ret = regmap_field_read(power->curr_lim_fld, &v); ret = regmap_field_read(power->curr_lim_fld, &v);
if (ret) if (ret)
return 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; return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) { if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
...@@ -189,6 +237,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy, ...@@ -189,6 +237,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 375; /* 1 step = 0.375 mA */ val->intval = ret * 375; /* 1 step = 0.375 mA */
return 0; return 0;
case POWER_SUPPLY_PROP_USB_TYPE:
return axp20x_get_usb_type(power, val);
default: default:
break; break;
} }
...@@ -256,19 +307,37 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power, ...@@ -256,19 +307,37 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL; 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, int ret;
power->axp_data->curr_lim_fld.lsb); unsigned int reg;
const unsigned int max = power->axp_data->curr_lim_table_size;
if (intval == -1) if (intval == -1)
return -EINVAL; return -EINVAL;
for (unsigned int i = 0; i <= max; ++i) /*
if (power->axp_data->curr_lim_table[i] == intval) * BC1.2 detection can cause a race condition if we try to set a current
return regmap_field_write(power->curr_lim_fld, i); * 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, 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, ...@@ -287,8 +356,8 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MIN: case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_usb_power_set_voltage_min(power, val->intval); return axp20x_usb_power_set_voltage_min(power, val->intval);
case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return axp20x_usb_power_set_current_max(power, val->intval); return axp20x_usb_power_set_input_current_limit(power, val->intval);
default: default:
return -EINVAL; return -EINVAL;
...@@ -313,7 +382,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy, ...@@ -313,7 +382,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
return power->vbus_disable_bit != NULL; return power->vbus_disable_bit != NULL;
return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || 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[] = { static enum power_supply_property axp20x_usb_power_properties[] = {
...@@ -322,7 +391,7 @@ 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_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN, POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_NOW,
}; };
...@@ -331,7 +400,23 @@ static enum power_supply_property axp22x_usb_power_properties[] = { ...@@ -331,7 +400,23 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN, 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 = { static const struct power_supply_desc axp20x_usb_power_desc = {
...@@ -354,6 +439,18 @@ static const struct power_supply_desc axp22x_usb_power_desc = { ...@@ -354,6 +439,18 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.set_property = axp20x_usb_power_set_property, .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[] = { static const char * const axp20x_irq_names[] = {
"VBUS_PLUGIN", "VBUS_PLUGIN",
"VBUS_REMOVAL", "VBUS_REMOVAL",
...@@ -388,10 +485,15 @@ static int axp221_usb_curr_lim_table[] = { ...@@ -388,10 +485,15 @@ static int axp221_usb_curr_lim_table[] = {
}; };
static int axp813_usb_curr_lim_table[] = { static int axp813_usb_curr_lim_table[] = {
100000,
500000,
900000, 900000,
1500000, 1500000,
2000000, 2000000,
2500000, 2500000,
3000000,
3500000,
4000000,
}; };
static const struct axp_data axp192_data = { static const struct axp_data axp192_data = {
...@@ -399,6 +501,7 @@ static const struct axp_data axp192_data = { ...@@ -399,6 +501,7 @@ static const struct axp_data axp192_data = {
.irq_names = axp20x_irq_names, .irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names), .num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp192_usb_curr_lim_table, .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), .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2), .vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3), .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
...@@ -409,6 +512,7 @@ static const struct axp_data axp202_data = { ...@@ -409,6 +512,7 @@ static const struct axp_data axp202_data = {
.irq_names = axp20x_irq_names, .irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names), .num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table, .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), .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2), .vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3), .vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
...@@ -419,6 +523,7 @@ static const struct axp_data axp221_data = { ...@@ -419,6 +523,7 @@ static const struct axp_data axp221_data = {
.irq_names = axp22x_irq_names, .irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names), .num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp221_usb_curr_lim_table, .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), .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true, .vbus_needs_polling = true,
}; };
...@@ -428,17 +533,20 @@ static const struct axp_data axp223_data = { ...@@ -428,17 +533,20 @@ static const struct axp_data axp223_data = {
.irq_names = axp22x_irq_names, .irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names), .num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table, .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), .curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true, .vbus_needs_polling = true,
}; };
static const struct axp_data axp813_data = { static const struct axp_data axp813_data = {
.power_desc = &axp22x_usb_power_desc, .power_desc = &axp813_usb_power_desc,
.irq_names = axp22x_irq_names, .irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names), .num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp813_usb_curr_lim_table, .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_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_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
.vbus_needs_polling = true, .vbus_needs_polling = true,
}; };
...@@ -558,6 +666,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) ...@@ -558,6 +666,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, power); platform_set_drvdata(pdev, power);
power->dev = &pdev->dev;
power->axp_data = axp_data; power->axp_data = axp_data;
power->regmap = axp20x->regmap; power->regmap = axp20x->regmap;
power->num_irqs = axp_data->num_irq_names; power->num_irqs = axp_data->num_irq_names;
...@@ -585,6 +694,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) ...@@ -585,6 +694,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
if (ret) if (ret)
return 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, ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->vbus_disable_bit, axp_data->vbus_disable_bit,
&power->vbus_disable_bit); &power->vbus_disable_bit);
......
...@@ -550,18 +550,20 @@ static const struct dmi_system_id axp288_quirks[] = { ...@@ -550,18 +550,20 @@ static const struct dmi_system_id axp288_quirks[] = {
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY, .driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
}, },
{ {
/* Intel Cherry Trail Compute Stick, Windows version */ /* Intel Bay Trail Compute Stick */
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"), 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, .driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
}, },
{ {
/* Intel Cherry Trail Compute Stick, version without an OS */ /* Intel Cherry Trail Compute Stick */
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"), 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, .driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
}, },
...@@ -599,6 +601,14 @@ static const struct dmi_system_id axp288_quirks[] = { ...@@ -599,6 +601,14 @@ static const struct dmi_system_id axp288_quirks[] = {
}, },
.driver_data = NULL, .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 * Various Ace PC/Meegopad/MinisForum/Wintel Mini-PCs/HDMI-sticks
......
...@@ -991,6 +991,7 @@ static enum power_supply_property bq2415x_power_supply_props[] = { ...@@ -991,6 +991,7 @@ static enum power_supply_property bq2415x_power_supply_props[] = {
/* TODO: maybe add more power supply properties */ /* TODO: maybe add more power supply properties */
POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_ONLINE,
}; };
static int bq2415x_power_supply_get_property(struct power_supply *psy, 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, ...@@ -1017,6 +1018,15 @@ static int bq2415x_power_supply_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MODEL_NAME: case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = bq->model; val->strval = bq->model;
break; 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: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -1595,17 +1595,24 @@ static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di) ...@@ -1595,17 +1595,24 @@ static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
* Return the Design Capacity in µAh * Return the Design Capacity in µAh
* Or < 0 if something fails. * 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; 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) if (di->opts & BQ27XXX_O_ZERO)
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true); dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true);
else else
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
if (dcap < 0) { 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; return dcap;
} }
...@@ -1614,7 +1621,12 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) ...@@ -1614,7 +1621,12 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
else else
dcap *= 1000; 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( ...@@ -1816,17 +1828,14 @@ static int bq27xxx_battery_current_and_status(
val_curr->intval = curr; val_curr->intval = curr;
if (val_status) { 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; val_status->intval = POWER_SUPPLY_STATUS_CHARGING;
} else if (curr < 0) { else if (curr < 0)
val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING; val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING;
} else { else
if (bq27xxx_battery_is_full(di, flags)) val_status->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
val_status->intval = POWER_SUPPLY_STATUS_FULL;
else
val_status->intval =
POWER_SUPPLY_STATUS_NOT_CHARGING;
}
} }
return 0; return 0;
...@@ -1865,10 +1874,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) ...@@ -1865,10 +1874,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
*/ */
if (!(di->opts & BQ27XXX_O_ZERO)) if (!(di->opts & BQ27XXX_O_ZERO))
bq27xxx_battery_current_and_status(di, NULL, &status, &cache); 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) || if ((di->cache.capacity != cache.capacity) ||
...@@ -2062,7 +2067,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, ...@@ -2062,7 +2067,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
ret = bq27xxx_simple_value(di->cache.charge_full, val); ret = bq27xxx_simple_value(di->cache.charge_full, val);
break; break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = bq27xxx_simple_value(di->charge_design_full, val); ret = bq27xxx_battery_read_dcap(di, val);
break; break;
/* /*
* TODO: Implement these to make registers set from * TODO: Implement these to make registers set from
...@@ -2101,6 +2106,13 @@ static void bq27xxx_external_power_changed(struct power_supply *psy) ...@@ -2101,6 +2106,13 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
mod_delayed_work(system_wq, &di->work, HZ / 2); 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) int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{ {
struct power_supply_desc *psy_desc; struct power_supply_desc *psy_desc;
...@@ -2108,9 +2120,14 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) ...@@ -2108,9 +2120,14 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
.of_node = di->dev->of_node, .of_node = di->dev->of_node,
.drv_data = di, .drv_data = di,
}; };
int ret;
INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
mutex_init(&di->lock); 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->regs = bq27xxx_chip_data[di->chip].regs;
di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key; di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key;
...@@ -2128,7 +2145,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) ...@@ -2128,7 +2145,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
psy_desc->get_property = bq27xxx_battery_get_property; psy_desc->get_property = bq27xxx_battery_get_property;
psy_desc->external_power_changed = bq27xxx_external_power_changed; 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)) if (IS_ERR(di->bat))
return dev_err_probe(di->dev, PTR_ERR(di->bat), return dev_err_probe(di->dev, PTR_ERR(di->bat),
"failed to register battery\n"); "failed to register battery\n");
...@@ -2156,9 +2173,6 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) ...@@ -2156,9 +2173,6 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
mutex_unlock(&di->lock); mutex_unlock(&di->lock);
cancel_delayed_work_sync(&di->work); cancel_delayed_work_sync(&di->work);
power_supply_unregister(di->bat);
mutex_destroy(&di->lock);
} }
EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
......
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
#include <linux/power/bq27xxx_battery.h> #include <linux/power/bq27xxx_battery.h>
static DEFINE_IDR(battery_id); static DEFINE_IDA(battery_id);
static DEFINE_MUTEX(battery_mutex);
static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) 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, ...@@ -136,30 +135,39 @@ static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
return 0; 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) static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
{ {
const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct bq27xxx_device_info *di; struct bq27xxx_device_info *di;
int ret; int ret;
char *name; char *name;
int num; long num;
/* Get new ID for the new battery device */ /* Get new ID for the new battery device */
mutex_lock(&battery_mutex); num = ida_alloc(&battery_id, GFP_KERNEL);
num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
mutex_unlock(&battery_mutex);
if (num < 0) if (num < 0)
return num; 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) if (!name)
goto err_mem; return -ENOMEM;
di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
if (!di) if (!di)
goto err_mem; return -ENOMEM;
di->id = num;
di->dev = &client->dev; di->dev = &client->dev;
di->chip = id->driver_data; di->chip = id->driver_data;
di->name = name; di->name = name;
...@@ -171,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client) ...@@ -171,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
ret = bq27xxx_battery_setup(di); ret = bq27xxx_battery_setup(di);
if (ret) if (ret)
goto err_failed; return ret;
/* Schedule a polling after about 1 min */ /* Schedule a polling after about 1 min */
schedule_delayed_work(&di->work, 60 * HZ); schedule_delayed_work(&di->work, 60 * HZ);
...@@ -188,21 +196,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client) ...@@ -188,21 +196,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
"Unable to register IRQ %d error %d\n", "Unable to register IRQ %d error %d\n",
client->irq, ret); client->irq, ret);
bq27xxx_battery_teardown(di); bq27xxx_battery_teardown(di);
goto err_failed; return ret;
} }
} }
return 0; 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) static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
...@@ -213,10 +211,6 @@ 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); free_irq(client->irq, di);
bq27xxx_battery_teardown(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[] = { static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
......
...@@ -530,8 +530,9 @@ static int da9030_battery_probe(struct platform_device *pdev) ...@@ -530,8 +530,9 @@ static int da9030_battery_probe(struct platform_device *pdev)
da9030_battery_setup_psy(charger); da9030_battery_setup_psy(charger);
psy_cfg.drv_data = charger; psy_cfg.drv_data = charger;
charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc, charger->psy = devm_power_supply_register(&pdev->dev,
&psy_cfg); &charger->psy_desc,
&psy_cfg);
if (IS_ERR(charger->psy)) { if (IS_ERR(charger->psy)) {
ret = PTR_ERR(charger->psy); ret = PTR_ERR(charger->psy);
goto err_ps_register; goto err_ps_register;
...@@ -563,7 +564,6 @@ static void da9030_battery_remove(struct platform_device *dev) ...@@ -563,7 +564,6 @@ static void da9030_battery_remove(struct platform_device *dev)
DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
cancel_delayed_work_sync(&charger->work); cancel_delayed_work_sync(&charger->work);
da9030_set_charge(charger, 0); da9030_set_charge(charger, 0);
power_supply_unregister(charger->psy);
} }
static struct platform_driver da903x_battery_driver = { static struct platform_driver da903x_battery_driver = {
......
...@@ -622,7 +622,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev) ...@@ -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)) { if (IS_ERR(bat->psy)) {
ret = PTR_ERR(bat->psy); ret = PTR_ERR(bat->psy);
goto err; goto err;
...@@ -644,8 +644,6 @@ static void da9052_bat_remove(struct platform_device *pdev) ...@@ -644,8 +644,6 @@ static void da9052_bat_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++)
da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat); da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
power_supply_unregister(bat->psy);
} }
static struct platform_driver da9052_bat_driver = { static struct platform_driver da9052_bat_driver = {
......
...@@ -521,42 +521,30 @@ static int da9150_charger_probe(struct platform_device *pdev) ...@@ -521,42 +521,30 @@ static int da9150_charger_probe(struct platform_device *pdev)
charger->dev = dev; charger->dev = dev;
/* Acquire ADC channels */ /* Acquire ADC channels */
charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS"); charger->ibus_chan = devm_iio_channel_get(dev, "CHAN_IBUS");
if (IS_ERR(charger->ibus_chan)) { if (IS_ERR(charger->ibus_chan))
ret = PTR_ERR(charger->ibus_chan); return PTR_ERR(charger->ibus_chan);
goto ibus_chan_fail;
}
charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS"); charger->vbus_chan = devm_iio_channel_get(dev, "CHAN_VBUS");
if (IS_ERR(charger->vbus_chan)) { if (IS_ERR(charger->vbus_chan))
ret = PTR_ERR(charger->vbus_chan); return PTR_ERR(charger->vbus_chan);
goto vbus_chan_fail;
}
charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC"); charger->tjunc_chan = devm_iio_channel_get(dev, "CHAN_TJUNC");
if (IS_ERR(charger->tjunc_chan)) { if (IS_ERR(charger->tjunc_chan))
ret = PTR_ERR(charger->tjunc_chan); return PTR_ERR(charger->tjunc_chan);
goto tjunc_chan_fail;
}
charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT"); charger->vbat_chan = devm_iio_channel_get(dev, "CHAN_VBAT");
if (IS_ERR(charger->vbat_chan)) { if (IS_ERR(charger->vbat_chan))
ret = PTR_ERR(charger->vbat_chan); return PTR_ERR(charger->vbat_chan);
goto vbat_chan_fail;
}
/* Register power supplies */ /* Register power supplies */
charger->usb = power_supply_register(dev, &usb_desc, NULL); charger->usb = devm_power_supply_register(dev, &usb_desc, NULL);
if (IS_ERR(charger->usb)) { if (IS_ERR(charger->usb))
ret = PTR_ERR(charger->usb); return PTR_ERR(charger->usb);
goto usb_fail;
}
charger->battery = power_supply_register(dev, &battery_desc, NULL); charger->battery = devm_power_supply_register(dev, &battery_desc, NULL);
if (IS_ERR(charger->battery)) { if (IS_ERR(charger->battery))
ret = PTR_ERR(charger->battery); return PTR_ERR(charger->battery);
goto battery_fail;
}
/* Get initial online supply */ /* Get initial online supply */
reg = da9150_reg_read(da9150, DA9150_STATUS_H); reg = da9150_reg_read(da9150, DA9150_STATUS_H);
...@@ -616,22 +604,7 @@ static int da9150_charger_probe(struct platform_device *pdev) ...@@ -616,22 +604,7 @@ static int da9150_charger_probe(struct platform_device *pdev)
chg_irq_fail: chg_irq_fail:
if (!IS_ERR_OR_NULL(charger->usb_phy)) if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb); 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; return ret;
} }
...@@ -656,15 +629,6 @@ static void da9150_charger_remove(struct platform_device *pdev) ...@@ -656,15 +629,6 @@ static void da9150_charger_remove(struct platform_device *pdev)
if (!IS_ERR_OR_NULL(charger->usb_phy)) if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb); usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
cancel_work_sync(&charger->otg_work); 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 = { static struct platform_driver da9150_charger_driver = {
......
...@@ -739,7 +739,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl) ...@@ -739,7 +739,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
if (current_accum) if (current_accum)
ds2760_battery_set_current_accum(di, 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)) { if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n"); dev_err(di->dev, "failed to register battery\n");
retval = PTR_ERR(di->bat); retval = PTR_ERR(di->bat);
...@@ -762,7 +762,6 @@ static int w1_ds2760_add_slave(struct w1_slave *sl) ...@@ -762,7 +762,6 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
goto success; goto success;
workqueue_failed: workqueue_failed:
power_supply_unregister(di->bat);
batt_failed: batt_failed:
di_alloc_failed: di_alloc_failed:
success: success:
...@@ -777,7 +776,6 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl) ...@@ -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->monitor_work);
cancel_delayed_work_sync(&di->set_charged_work); cancel_delayed_work_sync(&di->set_charged_work);
destroy_workqueue(di->monitor_wqueue); destroy_workqueue(di->monitor_wqueue);
power_supply_unregister(di->bat);
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -232,31 +232,22 @@ static int goldfish_battery_probe(struct platform_device *pdev) ...@@ -232,31 +232,22 @@ static int goldfish_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = data; 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)) if (IS_ERR(data->ac))
return PTR_ERR(data->ac); return PTR_ERR(data->ac);
data->battery = power_supply_register(&pdev->dev, &battery_desc, data->battery = devm_power_supply_register(&pdev->dev,
&psy_cfg); &battery_desc,
if (IS_ERR(data->battery)) { &psy_cfg);
power_supply_unregister(data->ac); if (IS_ERR(data->battery))
return PTR_ERR(data->battery); return PTR_ERR(data->battery);
}
platform_set_drvdata(pdev, data);
GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK); GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
return 0; 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[] = { static const struct of_device_id goldfish_battery_of_match[] = {
{ .compatible = "google,goldfish-battery", }, { .compatible = "google,goldfish-battery", },
{}, {},
...@@ -273,7 +264,6 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match); ...@@ -273,7 +264,6 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match);
static struct platform_driver goldfish_battery_device = { static struct platform_driver goldfish_battery_device = {
.probe = goldfish_battery_probe, .probe = goldfish_battery_probe,
.remove_new = goldfish_battery_remove,
.driver = { .driver = {
.name = "goldfish-battery", .name = "goldfish-battery",
.of_match_table = goldfish_battery_of_match, .of_match_table = goldfish_battery_of_match,
......
...@@ -453,39 +453,20 @@ static int lp8727_register_psy(struct lp8727_chg *pchg) ...@@ -453,39 +453,20 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
psy_cfg.supplied_to = battery_supplied_to; psy_cfg.supplied_to = battery_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(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)) if (IS_ERR(psy->ac))
goto err_psy_ac; return -EPERM;
psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc, psy->usb = devm_power_supply_register(pchg->dev, &lp8727_usb_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(psy->usb)) 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)) if (IS_ERR(psy->batt))
goto err_psy_batt; return -EPERM;
return 0; 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 #ifdef CONFIG_OF
...@@ -583,7 +564,6 @@ static int lp8727_probe(struct i2c_client *cl) ...@@ -583,7 +564,6 @@ static int lp8727_probe(struct i2c_client *cl)
ret = lp8727_setup_irq(pchg); ret = lp8727_setup_irq(pchg);
if (ret) { if (ret) {
dev_err(pchg->dev, "irq handler err: %d", ret); dev_err(pchg->dev, "irq handler err: %d", ret);
lp8727_unregister_psy(pchg);
return ret; return ret;
} }
...@@ -595,7 +575,6 @@ static void lp8727_remove(struct i2c_client *cl) ...@@ -595,7 +575,6 @@ static void lp8727_remove(struct i2c_client *cl)
struct lp8727_chg *pchg = i2c_get_clientdata(cl); struct lp8727_chg *pchg = i2c_get_clientdata(cl);
lp8727_release_irq(pchg); lp8727_release_irq(pchg);
lp8727_unregister_psy(pchg);
} }
static const struct of_device_id lp8727_dt_ids[] __maybe_unused = { static const struct of_device_id lp8727_dt_ids[] __maybe_unused = {
......
...@@ -406,12 +406,6 @@ static const struct power_supply_desc lp8788_psy_battery_desc = { ...@@ -406,12 +406,6 @@ static const struct power_supply_desc lp8788_psy_battery_desc = {
.get_property = lp8788_battery_get_property, .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) static void lp8788_charger_event(struct work_struct *work)
{ {
struct lp8788_charger *pchg = struct lp8788_charger *pchg =
...@@ -666,18 +660,16 @@ static int lp8788_psy_register(struct platform_device *pdev, ...@@ -666,18 +660,16 @@ static int lp8788_psy_register(struct platform_device *pdev,
charger_cfg.supplied_to = battery_supplied_to; charger_cfg.supplied_to = battery_supplied_to;
charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to); charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
pchg->charger = power_supply_register(&pdev->dev, pchg->charger = devm_power_supply_register(&pdev->dev,
&lp8788_psy_charger_desc, &lp8788_psy_charger_desc,
&charger_cfg); &charger_cfg);
if (IS_ERR(pchg->charger)) if (IS_ERR(pchg->charger))
return -EPERM; return -EPERM;
pchg->battery = power_supply_register(&pdev->dev, pchg->battery = devm_power_supply_register(&pdev->dev,
&lp8788_psy_battery_desc, NULL); &lp8788_psy_battery_desc, NULL);
if (IS_ERR(pchg->battery)) { if (IS_ERR(pchg->battery))
power_supply_unregister(pchg->charger);
return -EPERM; return -EPERM;
}
return 0; return 0;
} }
...@@ -720,7 +712,6 @@ static void lp8788_charger_remove(struct platform_device *pdev) ...@@ -720,7 +712,6 @@ static void lp8788_charger_remove(struct platform_device *pdev)
flush_work(&pchg->charger_work); flush_work(&pchg->charger_work);
lp8788_irq_unregister(pdev, pchg); lp8788_irq_unregister(pdev, pchg);
lp8788_psy_unregister(pchg);
} }
static struct platform_driver lp8788_charger_driver = { static struct platform_driver lp8788_charger_driver = {
......
...@@ -586,8 +586,9 @@ static int max14577_charger_probe(struct platform_device *pdev) ...@@ -586,8 +586,9 @@ static int max14577_charger_probe(struct platform_device *pdev)
} }
psy_cfg.drv_data = chg; psy_cfg.drv_data = chg;
chg->charger = power_supply_register(&pdev->dev, &max14577_charger_desc, chg->charger = devm_power_supply_register(&pdev->dev,
&psy_cfg); &max14577_charger_desc,
&psy_cfg);
if (IS_ERR(chg->charger)) { if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n"); dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger); ret = PTR_ERR(chg->charger);
...@@ -608,10 +609,7 @@ static int max14577_charger_probe(struct platform_device *pdev) ...@@ -608,10 +609,7 @@ static int max14577_charger_probe(struct platform_device *pdev)
static void max14577_charger_remove(struct platform_device *pdev) 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); device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
power_supply_unregister(chg->charger);
} }
static const struct platform_device_id max14577_charger_id[] = { static const struct platform_device_id max14577_charger_id[] = {
......
...@@ -709,9 +709,9 @@ static int max77693_charger_probe(struct platform_device *pdev) ...@@ -709,9 +709,9 @@ static int max77693_charger_probe(struct platform_device *pdev)
goto err; goto err;
} }
chg->charger = power_supply_register(&pdev->dev, chg->charger = devm_power_supply_register(&pdev->dev,
&max77693_charger_desc, &max77693_charger_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(chg->charger)) { if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n"); dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger); ret = PTR_ERR(chg->charger);
...@@ -730,13 +730,9 @@ static int max77693_charger_probe(struct platform_device *pdev) ...@@ -730,13 +730,9 @@ static int max77693_charger_probe(struct platform_device *pdev)
static void max77693_charger_remove(struct platform_device *pdev) 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_timer);
device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current); device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer); device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
power_supply_unregister(chg->charger);
} }
static const struct platform_device_id max77693_charger_id[] = { static const struct platform_device_id max77693_charger_id[] = {
......
...@@ -507,7 +507,6 @@ static int max8925_power_probe(struct platform_device *pdev) ...@@ -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 power_supply_config psy_cfg = {}; /* Only for ac and usb */
struct max8925_power_pdata *pdata = NULL; struct max8925_power_pdata *pdata = NULL;
struct max8925_power_info *info; struct max8925_power_info *info;
int ret;
pdata = max8925_power_dt_init(pdev); pdata = max8925_power_dt_init(pdev);
if (!pdata) { if (!pdata) {
...@@ -528,25 +527,19 @@ static int max8925_power_probe(struct platform_device *pdev) ...@@ -528,25 +527,19 @@ static int max8925_power_probe(struct platform_device *pdev)
psy_cfg.supplied_to = pdata->supplied_to; psy_cfg.supplied_to = pdata->supplied_to;
psy_cfg.num_supplicants = pdata->num_supplicants; psy_cfg.num_supplicants = pdata->num_supplicants;
info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg); info->ac = devm_power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
if (IS_ERR(info->ac)) { if (IS_ERR(info->ac))
ret = PTR_ERR(info->ac); return PTR_ERR(info->ac);
goto out;
}
info->ac->dev.parent = &pdev->dev; info->ac->dev.parent = &pdev->dev;
info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg); info->usb = devm_power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
if (IS_ERR(info->usb)) { if (IS_ERR(info->usb))
ret = PTR_ERR(info->usb); return PTR_ERR(info->usb);
goto out_unregister_ac;
}
info->usb->dev.parent = &pdev->dev; info->usb->dev.parent = &pdev->dev;
info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL); info->battery = devm_power_supply_register(&pdev->dev, &battery_desc, NULL);
if (IS_ERR(info->battery)) { if (IS_ERR(info->battery))
ret = PTR_ERR(info->battery); return PTR_ERR(info->battery);
goto out_unregister_usb;
}
info->battery->dev.parent = &pdev->dev; info->battery->dev.parent = &pdev->dev;
info->batt_detect = pdata->batt_detect; info->batt_detect = pdata->batt_detect;
...@@ -558,24 +551,14 @@ static int max8925_power_probe(struct platform_device *pdev) ...@@ -558,24 +551,14 @@ static int max8925_power_probe(struct platform_device *pdev)
max8925_init_charger(chip, info); max8925_init_charger(chip, info);
return 0; 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) static void max8925_power_remove(struct platform_device *pdev)
{ {
struct max8925_power_info *info = platform_get_drvdata(pdev); struct max8925_power_info *info = platform_get_drvdata(pdev);
if (info) { if (info)
power_supply_unregister(info->ac);
power_supply_unregister(info->usb);
power_supply_unregister(info->battery);
max8925_deinit_charger(info); max8925_deinit_charger(info);
}
} }
static struct platform_driver max8925_power_driver = { static struct platform_driver max8925_power_driver = {
......
...@@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip) ...@@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip)
static enum power_supply_property mm8013_battery_props[] = { static enum power_supply_property mm8013_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_NOW,
...@@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy, ...@@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy,
val->intval = regval; val->intval = regval;
break; 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: case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, &regval); ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, &regval);
if (ret < 0) if (ret < 0)
...@@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy, ...@@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy,
if (regval & MM8013_FLAG_DSG) if (regval & MM8013_FLAG_DSG)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 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) else if (regval & MM8013_FLAG_CHG)
val->intval = POWER_SUPPLY_STATUS_CHARGING; val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (regval & MM8013_FLAG_FC) else if (regval & MM8013_FLAG_FC)
......
...@@ -404,9 +404,9 @@ static int pcf50633_mbc_probe(struct platform_device *pdev) ...@@ -404,9 +404,9 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
psy_cfg.drv_data = mbc; psy_cfg.drv_data = mbc;
/* Create power supplies */ /* Create power supplies */
mbc->adapter = power_supply_register(&pdev->dev, mbc->adapter = devm_power_supply_register(&pdev->dev,
&pcf50633_mbc_adapter_desc, &pcf50633_mbc_adapter_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(mbc->adapter)) { if (IS_ERR(mbc->adapter)) {
dev_err(mbc->pcf->dev, "failed to register adapter\n"); dev_err(mbc->pcf->dev, "failed to register adapter\n");
return PTR_ERR(mbc->adapter); return PTR_ERR(mbc->adapter);
...@@ -415,20 +415,19 @@ static int pcf50633_mbc_probe(struct platform_device *pdev) ...@@ -415,20 +415,19 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
usb_psy_cfg = psy_cfg; usb_psy_cfg = psy_cfg;
usb_psy_cfg.attr_grp = pcf50633_mbc_sysfs_groups; usb_psy_cfg.attr_grp = pcf50633_mbc_sysfs_groups;
mbc->usb = power_supply_register(&pdev->dev, &pcf50633_mbc_usb_desc, mbc->usb = devm_power_supply_register(&pdev->dev,
&usb_psy_cfg); &pcf50633_mbc_usb_desc,
&usb_psy_cfg);
if (IS_ERR(mbc->usb)) { if (IS_ERR(mbc->usb)) {
dev_err(mbc->pcf->dev, "failed to register usb\n"); dev_err(mbc->pcf->dev, "failed to register usb\n");
power_supply_unregister(mbc->adapter);
return PTR_ERR(mbc->usb); return PTR_ERR(mbc->usb);
} }
mbc->ac = power_supply_register(&pdev->dev, &pcf50633_mbc_ac_desc, mbc->ac = devm_power_supply_register(&pdev->dev,
&psy_cfg); &pcf50633_mbc_ac_desc,
&psy_cfg);
if (IS_ERR(mbc->ac)) { if (IS_ERR(mbc->ac)) {
dev_err(mbc->pcf->dev, "failed to register ac\n"); 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); return PTR_ERR(mbc->ac);
} }
...@@ -449,10 +448,6 @@ static void pcf50633_mbc_remove(struct platform_device *pdev) ...@@ -449,10 +448,6 @@ static void pcf50633_mbc_remove(struct platform_device *pdev)
/* Remove IRQ handlers */ /* Remove IRQ handlers */
for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++) for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
pcf50633_free_irq(mbc->pcf, 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 = { static struct platform_driver pcf50633_mbc_driver = {
......
...@@ -15,12 +15,14 @@ struct power_supply; ...@@ -15,12 +15,14 @@ struct power_supply;
#ifdef CONFIG_SYSFS #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 int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env);
extern const struct attribute_group *power_supply_attr_groups[];
#else #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 #define power_supply_uevent NULL
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
......
...@@ -25,13 +25,17 @@ ...@@ -25,13 +25,17 @@
#include "power_supply.h" #include "power_supply.h"
#include "samsung-sdi-battery.h" #include "samsung-sdi-battery.h"
/* exported for the APM Power driver, APM emulation */ static const struct class power_supply_class = {
struct class *power_supply_class; .name = "power_supply",
EXPORT_SYMBOL_GPL(power_supply_class); .dev_uevent = power_supply_uevent,
};
static BLOCKING_NOTIFIER_HEAD(power_supply_notifier); 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) #define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10)
...@@ -93,8 +97,7 @@ static void power_supply_changed_work(struct work_struct *work) ...@@ -93,8 +97,7 @@ static void power_supply_changed_work(struct work_struct *work)
if (likely(psy->changed)) { if (likely(psy->changed)) {
psy->changed = false; psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags); spin_unlock_irqrestore(&psy->changed_lock, flags);
class_for_each_device(power_supply_class, NULL, psy, power_supply_for_each_device(psy, __power_supply_changed_work);
__power_supply_changed_work);
power_supply_update_leds(psy); power_supply_update_leds(psy);
blocking_notifier_call_chain(&power_supply_notifier, blocking_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy); PSY_EVENT_PROP_CHANGED, psy);
...@@ -112,6 +115,12 @@ static void power_supply_changed_work(struct work_struct *work) ...@@ -112,6 +115,12 @@ static void power_supply_changed_work(struct work_struct *work)
spin_unlock_irqrestore(&psy->changed_lock, flags); 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) void power_supply_changed(struct power_supply *psy)
{ {
unsigned long flags; unsigned long flags;
...@@ -187,8 +196,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy) ...@@ -187,8 +196,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
{ {
int error; int error;
error = class_for_each_device(power_supply_class, NULL, psy, error = power_supply_for_each_device(psy, __power_supply_populate_supplied_from);
__power_supply_populate_supplied_from);
dev_dbg(&psy->dev, "%s %d\n", __func__, error); dev_dbg(&psy->dev, "%s %d\n", __func__, error);
...@@ -201,7 +209,7 @@ static int __power_supply_find_supply_from_node(struct device *dev, ...@@ -201,7 +209,7 @@ static int __power_supply_find_supply_from_node(struct device *dev,
struct device_node *np = data; struct device_node *np = data;
struct power_supply *epsy = dev_get_drvdata(dev); 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) if (epsy->of_node == np)
return 1; return 1;
...@@ -213,17 +221,16 @@ static int power_supply_find_supply_from_node(struct device_node *supply_node) ...@@ -213,17 +221,16 @@ static int power_supply_find_supply_from_node(struct device_node *supply_node)
int error; 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(). * returned by __power_supply_find_supply_from_node().
* *
* __power_supply_find_supply_from_node() will return 0 (no match) * __power_supply_find_supply_from_node() will return 0 (no match)
* or 1 (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. * it returned 0, or error as returned by it.
*/ */
error = class_for_each_device(power_supply_class, NULL, supply_node, error = power_supply_for_each_device(supply_node, __power_supply_find_supply_from_node);
__power_supply_find_supply_from_node);
return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER; return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER;
} }
...@@ -329,8 +336,7 @@ int power_supply_am_i_supplied(struct power_supply *psy) ...@@ -329,8 +336,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
struct psy_am_i_supplied_data data = { psy, 0 }; struct psy_am_i_supplied_data data = { psy, 0 };
int error; int error;
error = class_for_each_device(power_supply_class, NULL, &data, error = power_supply_for_each_device(&data, __power_supply_am_i_supplied);
__power_supply_am_i_supplied);
dev_dbg(&psy->dev, "%s count %u err %d\n", __func__, data.count, error); 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) ...@@ -365,8 +371,7 @@ int power_supply_is_system_supplied(void)
int error; int error;
unsigned int count = 0; unsigned int count = 0;
error = class_for_each_device(power_supply_class, NULL, &count, error = power_supply_for_each_device(&count, __power_supply_is_system_supplied);
__power_supply_is_system_supplied);
/* /*
* If no system scope power class device was found at all, most probably we * 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, ...@@ -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 * This function is not intended for use with a supply with multiple
* suppliers, we simply pick the first supply to report the psp. * suppliers, we simply pick the first supply to report the psp.
*/ */
ret = class_for_each_device(power_supply_class, NULL, &data, ret = power_supply_for_each_device(&data, __power_supply_get_supplier_property);
__power_supply_get_supplier_property);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret == 0) if (ret == 0)
...@@ -458,8 +462,8 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat ...@@ -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 *power_supply_get_by_name(const char *name)
{ {
struct power_supply *psy = NULL; struct power_supply *psy = NULL;
struct device *dev = class_find_device(power_supply_class, NULL, name, struct device *dev = class_find_device(&power_supply_class, NULL, name,
power_supply_match_device_by_name); power_supply_match_device_by_name);
if (dev) { if (dev) {
psy = dev_get_drvdata(dev); psy = dev_get_drvdata(dev);
...@@ -515,8 +519,8 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np, ...@@ -515,8 +519,8 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
if (!power_supply_np) if (!power_supply_np)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
dev = class_find_device(power_supply_class, NULL, power_supply_np, dev = class_find_device(&power_supply_class, NULL, power_supply_np,
power_supply_match_device_node); power_supply_match_device_node);
of_node_put(power_supply_np); of_node_put(power_supply_np);
...@@ -1369,7 +1373,7 @@ __power_supply_register(struct device *parent, ...@@ -1369,7 +1373,7 @@ __power_supply_register(struct device *parent,
device_initialize(dev); device_initialize(dev);
dev->class = power_supply_class; dev->class = &power_supply_class;
dev->type = &power_supply_dev_type; dev->type = &power_supply_dev_type;
dev->parent = parent; dev->parent = parent;
dev->release = power_supply_dev_release; dev->release = power_supply_dev_release;
...@@ -1617,20 +1621,13 @@ EXPORT_SYMBOL_GPL(power_supply_get_drvdata); ...@@ -1617,20 +1621,13 @@ EXPORT_SYMBOL_GPL(power_supply_get_drvdata);
static int __init power_supply_class_init(void) static int __init power_supply_class_init(void)
{ {
power_supply_class = class_create("power_supply"); power_supply_init_attrs();
return class_register(&power_supply_class);
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;
} }
static void __exit power_supply_class_exit(void) static void __exit power_supply_class_exit(void)
{ {
class_destroy(power_supply_class); class_unregister(&power_supply_class);
} }
subsys_initcall(power_supply_class_init); subsys_initcall(power_supply_class_init);
......
...@@ -271,6 +271,23 @@ static ssize_t power_supply_show_usb_type(struct device *dev, ...@@ -271,6 +271,23 @@ static ssize_t power_supply_show_usb_type(struct device *dev,
return count; 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, static ssize_t power_supply_show_property(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) { char *buf) {
...@@ -298,21 +315,24 @@ static ssize_t power_supply_show_property(struct device *dev, ...@@ -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) { switch (psp) {
case POWER_SUPPLY_PROP_USB_TYPE: case POWER_SUPPLY_PROP_USB_TYPE:
ret = power_supply_show_usb_type(dev, psy->desc, ret = power_supply_show_usb_type(dev, psy->desc,
&value, buf); &value, buf);
break; 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: case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = sysfs_emit(buf, "%s\n", value.strval); ret = sysfs_emit(buf, "%s\n", value.strval);
break; break;
default: 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; return ret;
...@@ -394,17 +414,15 @@ static const struct attribute_group power_supply_attr_group = { ...@@ -394,17 +414,15 @@ static const struct attribute_group power_supply_attr_group = {
.is_visible = power_supply_attr_is_visible, .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, &power_supply_attr_group,
NULL, NULL
}; };
void power_supply_init_attrs(struct device_type *dev_type) void power_supply_init_attrs(void)
{ {
int i; int i;
dev_type->groups = power_supply_attr_groups;
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) { for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
struct device_attribute *attr; struct device_attribute *attr;
......
...@@ -159,12 +159,12 @@ static int rt5033_battery_probe(struct i2c_client *client) ...@@ -159,12 +159,12 @@ static int rt5033_battery_probe(struct i2c_client *client)
return -EINVAL; return -EINVAL;
} }
i2c_set_clientdata(client, battery);
psy_cfg.of_node = client->dev.of_node; psy_cfg.of_node = client->dev.of_node;
psy_cfg.drv_data = battery; psy_cfg.drv_data = battery;
battery->psy = power_supply_register(&client->dev, battery->psy = devm_power_supply_register(&client->dev,
&rt5033_battery_desc, &psy_cfg); &rt5033_battery_desc,
&psy_cfg);
if (IS_ERR(battery->psy)) if (IS_ERR(battery->psy))
return dev_err_probe(&client->dev, PTR_ERR(battery->psy), return dev_err_probe(&client->dev, PTR_ERR(battery->psy),
"Failed to register power supply\n"); "Failed to register power supply\n");
...@@ -172,13 +172,6 @@ static int rt5033_battery_probe(struct i2c_client *client) ...@@ -172,13 +172,6 @@ static int rt5033_battery_probe(struct i2c_client *client)
return 0; 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[] = { static const struct i2c_device_id rt5033_battery_id[] = {
{ "rt5033-battery", }, { "rt5033-battery", },
{ } { }
...@@ -197,7 +190,6 @@ static struct i2c_driver rt5033_battery_driver = { ...@@ -197,7 +190,6 @@ static struct i2c_driver rt5033_battery_driver = {
.of_match_table = rt5033_battery_of_match, .of_match_table = rt5033_battery_of_match,
}, },
.probe = rt5033_battery_probe, .probe = rt5033_battery_probe,
.remove = rt5033_battery_remove,
.id_table = rt5033_battery_id, .id_table = rt5033_battery_id,
}; };
module_i2c_driver(rt5033_battery_driver); module_i2c_driver(rt5033_battery_driver);
......
...@@ -192,14 +192,11 @@ static int rx51_battery_probe(struct platform_device *pdev) ...@@ -192,14 +192,11 @@ static int rx51_battery_probe(struct platform_device *pdev)
{ {
struct power_supply_config psy_cfg = {}; struct power_supply_config psy_cfg = {};
struct rx51_device_info *di; struct rx51_device_info *di;
int ret;
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) if (!di)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, di);
di->dev = &pdev->dev; di->dev = &pdev->dev;
di->bat_desc.name = "rx51-battery"; di->bat_desc.name = "rx51-battery";
di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
...@@ -209,52 +206,23 @@ static int rx51_battery_probe(struct platform_device *pdev) ...@@ -209,52 +206,23 @@ static int rx51_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = di; psy_cfg.drv_data = di;
di->channel_temp = iio_channel_get(di->dev, "temp"); di->channel_temp = devm_iio_channel_get(di->dev, "temp");
if (IS_ERR(di->channel_temp)) { if (IS_ERR(di->channel_temp))
ret = PTR_ERR(di->channel_temp); return PTR_ERR(di->channel_temp);
goto error;
}
di->channel_bsi = iio_channel_get(di->dev, "bsi"); di->channel_bsi = devm_iio_channel_get(di->dev, "bsi");
if (IS_ERR(di->channel_bsi)) { if (IS_ERR(di->channel_bsi))
ret = PTR_ERR(di->channel_bsi); return PTR_ERR(di->channel_bsi);
goto error_channel_temp;
}
di->channel_vbat = iio_channel_get(di->dev, "vbat"); di->channel_vbat = devm_iio_channel_get(di->dev, "vbat");
if (IS_ERR(di->channel_vbat)) { if (IS_ERR(di->channel_vbat))
ret = PTR_ERR(di->channel_vbat); return PTR_ERR(di->channel_vbat);
goto error_channel_bsi;
}
di->bat = power_supply_register(di->dev, &di->bat_desc, &psy_cfg); di->bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) { if (IS_ERR(di->bat))
ret = PTR_ERR(di->bat); return PTR_ERR(di->bat);
goto error_channel_vbat;
}
return 0; 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 #ifdef CONFIG_OF
...@@ -267,7 +235,6 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match); ...@@ -267,7 +235,6 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match);
static struct platform_driver rx51_battery_driver = { static struct platform_driver rx51_battery_driver = {
.probe = rx51_battery_probe, .probe = rx51_battery_probe,
.remove_new = rx51_battery_remove,
.driver = { .driver = {
.name = "rx51-battery", .name = "rx51-battery",
.of_match_table = of_match_ptr(n900_battery_of_match), .of_match_table = of_match_ptr(n900_battery_of_match),
......
...@@ -262,7 +262,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) ...@@ -262,7 +262,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.of_node; psy_cfg.of_node = pdev->dev.of_node;
psy_cfg.drv_data = cdata; 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); &psy_cfg);
if (IS_ERR(cdata->ac)) { if (IS_ERR(cdata->ac)) {
dev_err(&pdev->dev, "failed: power supply register\n"); dev_err(&pdev->dev, "failed: power supply register\n");
...@@ -277,7 +277,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) ...@@ -277,7 +277,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = tps65090_config_charger(cdata); ret = tps65090_config_charger(cdata);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "charger config failed, err %d\n", ret); dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
goto fail_unregister_supply; return ret;
} }
/* Check for charger presence */ /* Check for charger presence */
...@@ -286,14 +286,14 @@ static int tps65090_charger_probe(struct platform_device *pdev) ...@@ -286,14 +286,14 @@ static int tps65090_charger_probe(struct platform_device *pdev)
if (ret < 0) { if (ret < 0) {
dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__, dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
TPS65090_REG_CG_STATUS1); TPS65090_REG_CG_STATUS1);
goto fail_unregister_supply; return ret;
} }
if (status1 != 0) { if (status1 != 0) {
ret = tps65090_enable_charging(cdata); ret = tps65090_enable_charging(cdata);
if (ret < 0) { if (ret < 0) {
dev_err(cdata->dev, "error enabling charger\n"); dev_err(cdata->dev, "error enabling charger\n");
goto fail_unregister_supply; return ret;
} }
cdata->ac_online = 1; cdata->ac_online = 1;
power_supply_changed(cdata->ac); power_supply_changed(cdata->ac);
...@@ -306,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) ...@@ -306,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
dev_err(cdata->dev, dev_err(cdata->dev,
"Unable to register irq %d err %d\n", irq, "Unable to register irq %d err %d\n", irq,
ret); ret);
goto fail_unregister_supply; return ret;
} }
} else { } else {
cdata->poll_task = kthread_run(tps65090_charger_poll_task, cdata->poll_task = kthread_run(tps65090_charger_poll_task,
...@@ -316,16 +316,11 @@ static int tps65090_charger_probe(struct platform_device *pdev) ...@@ -316,16 +316,11 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = PTR_ERR(cdata->poll_task); ret = PTR_ERR(cdata->poll_task);
dev_err(cdata->dev, dev_err(cdata->dev,
"Unable to run kthread err %d\n", ret); "Unable to run kthread err %d\n", ret);
goto fail_unregister_supply; return ret;
} }
} }
return 0; return 0;
fail_unregister_supply:
power_supply_unregister(cdata->ac);
return ret;
} }
static void tps65090_charger_remove(struct platform_device *pdev) static void tps65090_charger_remove(struct platform_device *pdev)
...@@ -334,7 +329,6 @@ 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) if (cdata->irq == -ENXIO)
kthread_stop(cdata->poll_task); kthread_stop(cdata->poll_task);
power_supply_unregister(cdata->ac);
} }
static const struct of_device_id of_tps65090_charger_match[] = { static const struct of_device_id of_tps65090_charger_match[] = {
......
...@@ -188,30 +188,23 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) ...@@ -188,30 +188,23 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
struct twl4030_madc_battery *twl4030_madc_bat; struct twl4030_madc_battery *twl4030_madc_bat;
struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data; struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {}; struct power_supply_config psy_cfg = {};
int ret = 0;
twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat), twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat),
GFP_KERNEL); GFP_KERNEL);
if (!twl4030_madc_bat) if (!twl4030_madc_bat)
return -ENOMEM; return -ENOMEM;
twl4030_madc_bat->channel_temp = iio_channel_get(&pdev->dev, "temp"); twl4030_madc_bat->channel_temp = devm_iio_channel_get(&pdev->dev, "temp");
if (IS_ERR(twl4030_madc_bat->channel_temp)) { if (IS_ERR(twl4030_madc_bat->channel_temp))
ret = PTR_ERR(twl4030_madc_bat->channel_temp); return PTR_ERR(twl4030_madc_bat->channel_temp);
goto err;
}
twl4030_madc_bat->channel_ichg = iio_channel_get(&pdev->dev, "ichg"); twl4030_madc_bat->channel_ichg = devm_iio_channel_get(&pdev->dev, "ichg");
if (IS_ERR(twl4030_madc_bat->channel_ichg)) { if (IS_ERR(twl4030_madc_bat->channel_ichg))
ret = PTR_ERR(twl4030_madc_bat->channel_ichg); return PTR_ERR(twl4030_madc_bat->channel_ichg);
goto err_temp;
}
twl4030_madc_bat->channel_vbat = iio_channel_get(&pdev->dev, "vbat"); twl4030_madc_bat->channel_vbat = devm_iio_channel_get(&pdev->dev, "vbat");
if (IS_ERR(twl4030_madc_bat->channel_vbat)) { if (IS_ERR(twl4030_madc_bat->channel_vbat))
ret = PTR_ERR(twl4030_madc_bat->channel_vbat); return PTR_ERR(twl4030_madc_bat->channel_vbat);
goto err_ichg;
}
/* sort charging and discharging calibration data */ /* sort charging and discharging calibration data */
sort(pdata->charging, pdata->charging_size, sort(pdata->charging, pdata->charging_size,
...@@ -222,37 +215,14 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) ...@@ -222,37 +215,14 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
twl4030_cmp, NULL); twl4030_cmp, NULL);
twl4030_madc_bat->pdata = pdata; twl4030_madc_bat->pdata = pdata;
platform_set_drvdata(pdev, twl4030_madc_bat);
psy_cfg.drv_data = twl4030_madc_bat; psy_cfg.drv_data = twl4030_madc_bat;
twl4030_madc_bat->psy = power_supply_register(&pdev->dev, twl4030_madc_bat->psy = devm_power_supply_register(&pdev->dev,
&twl4030_madc_bat_desc, &twl4030_madc_bat_desc,
&psy_cfg); &psy_cfg);
if (IS_ERR(twl4030_madc_bat->psy)) { if (IS_ERR(twl4030_madc_bat->psy))
ret = PTR_ERR(twl4030_madc_bat->psy); return PTR_ERR(twl4030_madc_bat->psy);
goto err_vbat;
}
return 0; 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 = { static struct platform_driver twl4030_madc_battery_driver = {
...@@ -260,7 +230,6 @@ static struct platform_driver twl4030_madc_battery_driver = { ...@@ -260,7 +230,6 @@ static struct platform_driver twl4030_madc_battery_driver = {
.name = "twl4030_madc_battery", .name = "twl4030_madc_battery",
}, },
.probe = twl4030_madc_battery_probe, .probe = twl4030_madc_battery_probe,
.remove_new = twl4030_madc_battery_remove,
}; };
module_platform_driver(twl4030_madc_battery_driver); module_platform_driver(twl4030_madc_battery_driver);
......
...@@ -171,7 +171,6 @@ static int wm831x_backup_probe(struct platform_device *pdev) ...@@ -171,7 +171,6 @@ static int wm831x_backup_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
devdata->wm831x = wm831x; devdata->wm831x = wm831x;
platform_set_drvdata(pdev, devdata);
/* We ignore configuration failures since we can still read /* We ignore configuration failures since we can still read
* back the status without enabling the charger (which may * back the status without enabling the charger (which may
...@@ -191,22 +190,14 @@ static int wm831x_backup_probe(struct platform_device *pdev) ...@@ -191,22 +190,14 @@ static int wm831x_backup_probe(struct platform_device *pdev)
devdata->backup_desc.properties = wm831x_backup_props; devdata->backup_desc.properties = wm831x_backup_props;
devdata->backup_desc.num_properties = ARRAY_SIZE(wm831x_backup_props); devdata->backup_desc.num_properties = ARRAY_SIZE(wm831x_backup_props);
devdata->backup_desc.get_property = wm831x_backup_get_prop; devdata->backup_desc.get_property = wm831x_backup_get_prop;
devdata->backup = power_supply_register(&pdev->dev, devdata->backup = devm_power_supply_register(&pdev->dev,
&devdata->backup_desc, NULL); &devdata->backup_desc, NULL);
return PTR_ERR_OR_ZERO(devdata->backup); 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 = { static struct platform_driver wm831x_backup_driver = {
.probe = wm831x_backup_probe, .probe = wm831x_backup_probe,
.remove_new = wm831x_backup_remove,
.driver = { .driver = {
.name = "wm831x-backup", .name = "wm831x-backup",
}, },
......
...@@ -570,8 +570,9 @@ static int wm831x_power_probe(struct platform_device *pdev) ...@@ -570,8 +570,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->wall_desc.properties = wm831x_wall_props; power->wall_desc.properties = wm831x_wall_props;
power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props); power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props);
power->wall_desc.get_property = wm831x_wall_get_prop; power->wall_desc.get_property = wm831x_wall_get_prop;
power->wall = power_supply_register(&pdev->dev, &power->wall_desc, power->wall = devm_power_supply_register(&pdev->dev,
NULL); &power->wall_desc,
NULL);
if (IS_ERR(power->wall)) { if (IS_ERR(power->wall)) {
ret = PTR_ERR(power->wall); ret = PTR_ERR(power->wall);
goto err; goto err;
...@@ -582,7 +583,9 @@ static int wm831x_power_probe(struct platform_device *pdev) ...@@ -582,7 +583,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->usb_desc.properties = wm831x_usb_props; power->usb_desc.properties = wm831x_usb_props;
power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props); power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props);
power->usb_desc.get_property = wm831x_usb_get_prop; 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)) { if (IS_ERR(power->usb)) {
ret = PTR_ERR(power->usb); ret = PTR_ERR(power->usb);
goto err_wall; goto err_wall;
...@@ -599,9 +602,9 @@ static int wm831x_power_probe(struct platform_device *pdev) ...@@ -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.num_properties = ARRAY_SIZE(wm831x_bat_props);
power->battery_desc.get_property = wm831x_bat_get_prop; power->battery_desc.get_property = wm831x_bat_get_prop;
power->battery_desc.use_for_apm = 1; power->battery_desc.use_for_apm = 1;
power->battery = power_supply_register(&pdev->dev, power->battery = devm_power_supply_register(&pdev->dev,
&power->battery_desc, &power->battery_desc,
NULL); NULL);
if (IS_ERR(power->battery)) { if (IS_ERR(power->battery)) {
ret = PTR_ERR(power->battery); ret = PTR_ERR(power->battery);
goto err_usb; goto err_usb;
...@@ -684,12 +687,8 @@ static int wm831x_power_probe(struct platform_device *pdev) ...@@ -684,12 +687,8 @@ static int wm831x_power_probe(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, power); free_irq(irq, power);
err_battery: err_battery:
if (power->have_battery)
power_supply_unregister(power->battery);
err_usb: err_usb:
power_supply_unregister(power->usb);
err_wall: err_wall:
power_supply_unregister(power->wall);
err: err:
return ret; return ret;
} }
...@@ -717,11 +716,6 @@ static void wm831x_power_remove(struct platform_device *pdev) ...@@ -717,11 +716,6 @@ static void wm831x_power_remove(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, wm831x_power); 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 = { static struct platform_driver wm831x_power_driver = {
......
...@@ -540,22 +540,17 @@ static int wm8350_power_probe(struct platform_device *pdev) ...@@ -540,22 +540,17 @@ static int wm8350_power_probe(struct platform_device *pdev)
struct wm8350_charger_policy *policy = power->policy; struct wm8350_charger_policy *policy = power->policy;
int ret; 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)) if (IS_ERR(power->ac))
return PTR_ERR(power->ac); return PTR_ERR(power->ac);
power->battery = power_supply_register(&pdev->dev, &wm8350_battery_desc, power->battery = devm_power_supply_register(&pdev->dev, &wm8350_battery_desc, NULL);
NULL); if (IS_ERR(power->battery))
if (IS_ERR(power->battery)) { return PTR_ERR(power->battery);
ret = PTR_ERR(power->battery);
goto battery_failed;
}
power->usb = power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL); power->usb = devm_power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
if (IS_ERR(power->usb)) { if (IS_ERR(power->usb))
ret = PTR_ERR(power->usb); return PTR_ERR(power->usb);
goto usb_failed;
}
ret = device_create_file(&pdev->dev, &dev_attr_charger_state); ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
if (ret < 0) if (ret < 0)
...@@ -569,26 +564,15 @@ static int wm8350_power_probe(struct platform_device *pdev) ...@@ -569,26 +564,15 @@ static int wm8350_power_probe(struct platform_device *pdev)
wm8350_reg_lock(wm8350); wm8350_reg_lock(wm8350);
} }
return ret;
usb_failed:
power_supply_unregister(power->battery);
battery_failed:
power_supply_unregister(power->ac);
return ret; return ret;
} }
static void wm8350_power_remove(struct platform_device *pdev) static void wm8350_power_remove(struct platform_device *pdev)
{ {
struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350 *wm8350 = platform_get_drvdata(pdev);
struct wm8350_power *power = &wm8350->power;
free_charger_irq(wm8350); free_charger_irq(wm8350);
device_remove_file(&pdev->dev, &dev_attr_charger_state); 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 = { static struct platform_driver wm8350_power_driver = {
......
...@@ -61,7 +61,6 @@ struct bq27xxx_reg_cache { ...@@ -61,7 +61,6 @@ struct bq27xxx_reg_cache {
struct bq27xxx_device_info { struct bq27xxx_device_info {
struct device *dev; struct device *dev;
int id;
enum bq27xxx_chip chip; enum bq27xxx_chip chip;
u32 opts; u32 opts;
const char *name; const char *name;
......
...@@ -242,6 +242,7 @@ struct power_supply_config { ...@@ -242,6 +242,7 @@ struct power_supply_config {
struct power_supply_desc { struct power_supply_desc {
const char *name; const char *name;
enum power_supply_type type; enum power_supply_type type;
u8 charge_behaviours;
const enum power_supply_usb_type *usb_types; const enum power_supply_usb_type *usb_types;
size_t num_usb_types; size_t num_usb_types;
const enum power_supply_property *properties; const enum power_supply_property *properties;
...@@ -894,8 +895,7 @@ extern int power_supply_powers(struct power_supply *psy, struct device *dev); ...@@ -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) #define to_power_supply(device) container_of(device, struct power_supply, dev)
extern void *power_supply_get_drvdata(struct power_supply *psy); extern void *power_supply_get_drvdata(struct power_supply *psy);
/* For APM emulation, think legacy userspace. */ extern int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data));
extern struct class *power_supply_class;
static inline bool power_supply_is_amp_property(enum power_supply_property psp) static inline bool power_supply_is_amp_property(enum power_supply_property psp)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment