power supply and reset changes for the 6.9 series

* 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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmXyI98ACgkQ2O7X88g7
 +prwAQ/+OyQSOwPQYvPe46YFVKwN+cDyEqgqwu3ndHgbx3x/VNbRDzsykQVIKp1/
 H57CzESX6tHA+gdnXBGCHSVBEGuBy3broJi4FBI6DuLmHM0ezIDoYrzScS+yanza
 0cmYDjqUDGfcyAO5xstjXY+yEZ3Dju2pd+uNM66b73FDh1Ch6wj96KTWTSUOO0zb
 O8vbSqfltE6FeqKrtVH3itodiGP5rEcEGypiwl9DG0PCbqKGbgm7TWW7vNcHvMUl
 BYZnJeVmrtHa18uAt6JtO5xB9pb6dst2GZf3cMtLBeAUDvO5mzz4MxEk3FczPnIQ
 sBEBn4GCpgvctIt7I2TPmG+sjNTCv2BX6SWEtmQECMK8w+J9LlEM3Y0dwzP/c87z
 9nrnYDbK/RBtI/C6FEOb5Eb/IYR/2J6l7B1dJOKFgqZI/HnFRn4U+dUJWL/LL9Vg
 QH2hUkiply/7F6ziq7LRFfvDDohZbRnrlBuEjYII5GPyFVBLU2pjtw6wBWsqYUG9
 cm3+BAx+idHjuOP9rxLWBUOBIFhqUkkAjZscTM7FUbEtgXbb7bGQcnjvSBZN/k4O
 4bhW9PFjDa6Isioy3dM+TRmxbn06r8fLa330rcCIhD1kf1zTM8M0sNGM0HixE/+t
 MThYC1dmXl5gQ59OlW3wa192mzim1iTFx1mkXSvlAOzRbGcFY20=
 =II3q
 -----END PGP SIGNATURE-----

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)
  ...
This commit is contained in:
Linus Torvalds 2024-03-14 10:19:48 -07:00
commit 44f89c6d3c
47 changed files with 558 additions and 745 deletions

View File

@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/slab.h>
struct as3722_poweroff {
@ -18,22 +19,18 @@ struct as3722_poweroff {
struct as3722 *as3722;
};
static struct as3722_poweroff *as3722_pm_poweroff;
static void as3722_pm_power_off(void)
static int as3722_pm_power_off(struct sys_off_data *data)
{
struct as3722_poweroff *as3722_pm_poweroff = data->cb_data;
int ret;
if (!as3722_pm_poweroff) {
pr_err("AS3722 poweroff is not initialised\n");
return;
}
ret = as3722_update_bits(as3722_pm_poweroff->as3722,
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
if (ret < 0)
dev_err(as3722_pm_poweroff->dev,
"RESET_CONTROL_REG update failed, %d\n", ret);
return NOTIFY_DONE;
}
static int as3722_poweroff_probe(struct platform_device *pdev)
@ -54,26 +51,21 @@ static int as3722_poweroff_probe(struct platform_device *pdev)
as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
as3722_poweroff->dev = &pdev->dev;
as3722_pm_poweroff = as3722_poweroff;
if (!pm_power_off)
pm_power_off = as3722_pm_power_off;
return devm_register_sys_off_handler(as3722_poweroff->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT,
as3722_pm_power_off,
as3722_poweroff);
return 0;
}
static void as3722_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == as3722_pm_power_off)
pm_power_off = NULL;
as3722_pm_poweroff = NULL;
}
static struct platform_driver as3722_poweroff_driver = {
.driver = {
.name = "as3722-power-off",
},
.probe = as3722_poweroff_probe,
.remove_new = as3722_poweroff_remove,
};
module_platform_driver(as3722_poweroff_driver);

View File

@ -16,13 +16,9 @@
struct atc260x_pwrc {
struct device *dev;
struct regmap *regmap;
struct notifier_block restart_nb;
int (*do_poweroff)(const struct atc260x_pwrc *pwrc, bool restart);
};
/* Global variable needed only for pm_power_off */
static struct atc260x_pwrc *atc260x_pwrc_data;
static int atc2603c_do_poweroff(const struct atc260x_pwrc *pwrc, bool restart)
{
int ret, deep_sleep = 0;
@ -165,18 +161,20 @@ static int atc2609a_init(const struct atc260x_pwrc *pwrc)
return ret;
}
static void atc260x_pwrc_pm_handler(void)
static int atc260x_pwrc_pm_handler(struct sys_off_data *data)
{
atc260x_pwrc_data->do_poweroff(atc260x_pwrc_data, false);
struct atc260x_pwrc *pwrc = data->cb_data;
pwrc->do_poweroff(pwrc, false);
WARN_ONCE(1, "Unable to power off system\n");
return NOTIFY_DONE;
}
static int atc260x_pwrc_restart_handler(struct notifier_block *nb,
unsigned long mode, void *cmd)
static int atc260x_pwrc_restart_handler(struct sys_off_data *data)
{
struct atc260x_pwrc *pwrc = container_of(nb, struct atc260x_pwrc,
restart_nb);
struct atc260x_pwrc *pwrc = data->cb_data;
pwrc->do_poweroff(pwrc, true);
return NOTIFY_DONE;
@ -194,8 +192,6 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
priv->regmap = atc260x->regmap;
priv->restart_nb.notifier_call = atc260x_pwrc_restart_handler;
priv->restart_nb.priority = 192;
switch (atc260x->ic_type) {
case ATC2603C:
@ -216,16 +212,20 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
if (ret)
return ret;
platform_set_drvdata(pdev, priv);
ret = devm_register_sys_off_handler(priv->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT,
atc260x_pwrc_pm_handler,
priv);
if (ret)
dev_err(priv->dev, "failed to register power-off handler: %d\n",
ret);
if (!pm_power_off) {
atc260x_pwrc_data = priv;
pm_power_off = atc260x_pwrc_pm_handler;
} else {
dev_warn(priv->dev, "Poweroff callback already assigned\n");
}
ret = register_restart_handler(&priv->restart_nb);
ret = devm_register_sys_off_handler(priv->dev,
SYS_OFF_MODE_RESTART,
SYS_OFF_PRIO_HIGH,
atc260x_pwrc_restart_handler,
priv);
if (ret)
dev_err(priv->dev, "failed to register restart handler: %d\n",
ret);
@ -233,21 +233,8 @@ static int atc260x_pwrc_probe(struct platform_device *pdev)
return ret;
}
static void atc260x_pwrc_remove(struct platform_device *pdev)
{
struct atc260x_pwrc *priv = platform_get_drvdata(pdev);
if (atc260x_pwrc_data == priv) {
pm_power_off = NULL;
atc260x_pwrc_data = NULL;
}
unregister_restart_handler(&priv->restart_nb);
}
static struct platform_driver atc260x_pwrc_driver = {
.probe = atc260x_pwrc_probe,
.remove_new = atc260x_pwrc_remove,
.driver = {
.name = "atc260x-pwrc",
},

View File

@ -26,11 +26,10 @@
#define SC_EFUSE_INT_STATUS 0x180c
#define EFUSE_READ_DONE (1<<31)
static struct regmap *syscon;
static int axxia_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
static int axxia_restart_handler(struct sys_off_data *data)
{
struct regmap *syscon = data->cb_data;
/* Access Key (0xab) */
regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab);
/* Select internal boot from 0xffff0000 */
@ -44,14 +43,10 @@ static int axxia_restart_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
static struct notifier_block axxia_restart_nb = {
.notifier_call = axxia_restart_handler,
.priority = 128,
};
static int axxia_reset_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *syscon;
int err;
syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
@ -60,7 +55,8 @@ static int axxia_reset_probe(struct platform_device *pdev)
return PTR_ERR(syscon);
}
err = register_restart_handler(&axxia_restart_nb);
err = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
128, axxia_restart_handler, syscon);
if (err)
dev_err(dev, "cannot register restart handler (err=%d)\n", err);

View File

@ -15,8 +15,7 @@
static void __iomem *kona_reset_base;
static int kona_reset_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
static int kona_reset_handler(struct sys_off_data *data)
{
/*
* A soft reset is triggered by writing a 0 to bit 0 of the soft reset
@ -31,18 +30,14 @@ static int kona_reset_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
static struct notifier_block kona_reset_nb = {
.notifier_call = kona_reset_handler,
.priority = 128,
};
static int kona_reset_probe(struct platform_device *pdev)
{
kona_reset_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(kona_reset_base))
return PTR_ERR(kona_reset_base);
return register_restart_handler(&kona_reset_nb);
return devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
128, kona_reset_handler, NULL);
}
static const struct of_device_id of_match[] = {

View File

@ -70,12 +70,9 @@ static irqreturn_t gemini_powerbutton_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
/* This callback needs this static local as it has void as argument */
static struct gemini_powercon *gpw_poweroff;
static void gemini_poweroff(void)
static int gemini_poweroff(struct sys_off_data *data)
{
struct gemini_powercon *gpw = gpw_poweroff;
struct gemini_powercon *gpw = data->cb_data;
u32 val;
dev_crit(gpw->dev, "Gemini power off\n");
@ -86,6 +83,8 @@ static void gemini_poweroff(void)
val &= ~GEMINI_CTRL_ENABLE;
val |= GEMINI_CTRL_SHUTDOWN;
writel(val, gpw->base + GEMINI_PWC_CTRLREG);
return NOTIFY_DONE;
}
static int gemini_poweroff_probe(struct platform_device *pdev)
@ -148,8 +147,11 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
if (ret)
return ret;
pm_power_off = gemini_poweroff;
gpw_poweroff = gpw;
ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT,
gemini_poweroff, gpw);
if (ret)
return ret;
dev_info(dev, "Gemini poweroff driver registered\n");

View File

@ -14,8 +14,8 @@
#include <linux/pm.h>
static void __iomem *msm_ps_hold;
static int deassert_pshold(struct notifier_block *nb, unsigned long action,
void *data)
static int do_msm_poweroff(struct sys_off_data *data)
{
writel(0, msm_ps_hold);
mdelay(10000);
@ -23,25 +23,18 @@ static int deassert_pshold(struct notifier_block *nb, unsigned long action,
return NOTIFY_DONE;
}
static struct notifier_block restart_nb = {
.notifier_call = deassert_pshold,
.priority = 128,
};
static void do_msm_poweroff(void)
{
deassert_pshold(&restart_nb, 0, NULL);
}
static int msm_restart_probe(struct platform_device *pdev)
{
msm_ps_hold = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(msm_ps_hold))
return PTR_ERR(msm_ps_hold);
register_restart_handler(&restart_nb);
devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
128, do_msm_poweroff, NULL);
pm_power_off = do_msm_poweroff;
devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT, do_msm_poweroff,
NULL);
return 0;
}

View File

@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/rtc.h>
#include <linux/reboot.h>
struct mt6323_pwrc {
struct device *dev;
@ -21,11 +22,9 @@ struct mt6323_pwrc {
u32 base;
};
static struct mt6323_pwrc *mt_pwrc;
static void mt6323_do_pwroff(void)
static int mt6323_do_pwroff(struct sys_off_data *data)
{
struct mt6323_pwrc *pwrc = mt_pwrc;
struct mt6323_pwrc *pwrc = data->cb_data;
unsigned int val;
int ret;
@ -44,6 +43,8 @@ static void mt6323_do_pwroff(void)
mdelay(1000);
WARN_ONCE(1, "Unable to power off system\n");
return NOTIFY_DONE;
}
static int mt6323_pwrc_probe(struct platform_device *pdev)
@ -51,6 +52,7 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
struct mt6323_pwrc *pwrc;
struct resource *res;
int ret;
pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
if (!pwrc)
@ -63,19 +65,18 @@ static int mt6323_pwrc_probe(struct platform_device *pdev)
pwrc->base = res->start;
pwrc->regmap = mt6397_chip->regmap;
pwrc->dev = &pdev->dev;
mt_pwrc = pwrc;
pm_power_off = &mt6323_do_pwroff;
ret = devm_register_sys_off_handler(pwrc->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT,
mt6323_do_pwroff,
pwrc);
if (ret)
return dev_err_probe(pwrc->dev, ret, "failed to register power-off handler\n");
return 0;
}
static void mt6323_pwrc_remove(struct platform_device *pdev)
{
if (pm_power_off == &mt6323_do_pwroff)
pm_power_off = NULL;
}
static const struct of_device_id mt6323_pwrc_dt_match[] = {
{ .compatible = "mediatek,mt6323-pwrc" },
{},
@ -84,7 +85,6 @@ MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match);
static struct platform_driver mt6323_pwrc_driver = {
.probe = mt6323_pwrc_probe,
.remove_new = mt6323_pwrc_remove,
.driver = {
.name = "mt6323-pwrc",
.of_match_table = mt6323_pwrc_dt_match,

View File

@ -13,18 +13,15 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/regulator/consumer.h>
#define TIMEOUT_MS 3000
/*
* Hold configuration here, cannot be more than one instance of the driver
* since pm_power_off itself is global.
*/
static struct regulator *cpu_regulator;
static void regulator_poweroff_do_poweroff(void)
static int regulator_poweroff_do_poweroff(struct sys_off_data *data)
{
struct regulator *cpu_regulator = data->cb_data;
if (cpu_regulator && regulator_is_enabled(cpu_regulator))
regulator_force_disable(cpu_regulator);
@ -32,30 +29,24 @@ static void regulator_poweroff_do_poweroff(void)
mdelay(TIMEOUT_MS);
WARN_ON(1);
return NOTIFY_DONE;
}
static int regulator_poweroff_probe(struct platform_device *pdev)
{
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
dev_err(&pdev->dev,
"%s: pm_power_off function already registered\n",
__func__);
return -EBUSY;
}
struct regulator *cpu_regulator;
cpu_regulator = devm_regulator_get(&pdev->dev, "cpu");
if (IS_ERR(cpu_regulator))
return PTR_ERR(cpu_regulator);
pm_power_off = &regulator_poweroff_do_poweroff;
return 0;
}
static void regulator_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == &regulator_poweroff_do_poweroff)
pm_power_off = NULL;
/* Set this handler to low priority to not override an existing handler */
return devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_LOW,
regulator_poweroff_do_poweroff,
cpu_regulator);
}
static const struct of_device_id of_regulator_poweroff_match[] = {
@ -66,7 +57,6 @@ MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);
static struct platform_driver regulator_poweroff_driver = {
.probe = regulator_poweroff_probe,
.remove_new = regulator_poweroff_remove,
.driver = {
.name = "poweroff-regulator",
.of_match_table = of_regulator_poweroff_match,

View File

@ -14,29 +14,21 @@
#include <linux/module.h>
#include <linux/reboot.h>
static void restart_poweroff_do_poweroff(void)
static int restart_poweroff_do_poweroff(struct sys_off_data *data)
{
reboot_mode = REBOOT_HARD;
machine_restart(NULL);
return NOTIFY_DONE;
}
static int restart_poweroff_probe(struct platform_device *pdev)
{
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
dev_err(&pdev->dev,
"pm_power_off function already registered");
return -EBUSY;
}
pm_power_off = &restart_poweroff_do_poweroff;
return 0;
}
static void restart_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == &restart_poweroff_do_poweroff)
pm_power_off = NULL;
/* Set this handler to low priority to not override an existing handler */
return devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_LOW,
restart_poweroff_do_poweroff,
NULL);
}
static const struct of_device_id of_restart_poweroff_match[] = {
@ -47,7 +39,6 @@ MODULE_DEVICE_TABLE(of, of_restart_poweroff_match);
static struct platform_driver restart_poweroff_driver = {
.probe = restart_poweroff_probe,
.remove_new = restart_poweroff_remove,
.driver = {
.name = "poweroff-restart",
.of_match_table = of_restart_poweroff_match,

View File

@ -19,12 +19,9 @@
/* Reset Control Register 2 */
#define RESCNT2_PRES 0x80000000 /* Soft power-on reset */
static void __iomem *sysc_base2;
static int rmobile_reset_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
static int rmobile_reset_handler(struct sys_off_data *data)
{
pr_debug("%s %lu\n", __func__, mode);
void __iomem *sysc_base2 = (void __iomem *)data->cb_data;
/* Let's assume we have acquired the HPB semaphore */
writel(RESCNT2_PRES, sysc_base2 + RESCNT2);
@ -32,37 +29,27 @@ static int rmobile_reset_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
static struct notifier_block rmobile_reset_nb = {
.notifier_call = rmobile_reset_handler,
.priority = 192,
};
static int rmobile_reset_probe(struct platform_device *pdev)
{
void __iomem *sysc_base2;
int error;
sysc_base2 = of_iomap(pdev->dev.of_node, 1);
if (!sysc_base2)
return -ENODEV;
sysc_base2 = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(sysc_base2))
return PTR_ERR(sysc_base2);
error = register_restart_handler(&rmobile_reset_nb);
error = devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_RESTART,
SYS_OFF_PRIO_HIGH,
rmobile_reset_handler,
(__force void *)sysc_base2);
if (error) {
dev_err(&pdev->dev,
"cannot register restart handler (err=%d)\n", error);
goto fail_unmap;
return error;
}
return 0;
fail_unmap:
iounmap(sysc_base2);
return error;
}
static void rmobile_reset_remove(struct platform_device *pdev)
{
unregister_restart_handler(&rmobile_reset_nb);
iounmap(sysc_base2);
}
static const struct of_device_id rmobile_reset_of_match[] = {
@ -73,7 +60,6 @@ MODULE_DEVICE_TABLE(of, rmobile_reset_of_match);
static struct platform_driver rmobile_reset_driver = {
.probe = rmobile_reset_probe,
.remove_new = rmobile_reset_remove,
.driver = {
.name = "rmobile_reset",
.of_match_table = rmobile_reset_of_match,

View File

@ -13,44 +13,56 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
static struct regmap *map;
static u32 offset;
static u32 value;
static u32 mask;
struct syscon_poweroff_data {
struct regmap *map;
u32 offset;
u32 value;
u32 mask;
};
static void syscon_poweroff(void)
static int syscon_poweroff(struct sys_off_data *off_data)
{
struct syscon_poweroff_data *data = off_data->cb_data;
/* Issue the poweroff */
regmap_update_bits(map, offset, mask, value);
regmap_update_bits(data->map, data->offset, data->mask, data->value);
mdelay(1000);
pr_emerg("Unable to poweroff system\n");
return NOTIFY_DONE;
}
static int syscon_poweroff_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct syscon_poweroff_data *data;
int mask_err, value_err;
map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
if (IS_ERR(map)) {
map = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(map)) {
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
if (IS_ERR(data->map)) {
data->map = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(data->map)) {
dev_err(dev, "unable to get syscon");
return PTR_ERR(map);
return PTR_ERR(data->map);
}
}
if (of_property_read_u32(dev->of_node, "offset", &offset)) {
if (of_property_read_u32(dev->of_node, "offset", &data->offset)) {
dev_err(dev, "unable to read 'offset'");
return -EINVAL;
}
value_err = of_property_read_u32(dev->of_node, "value", &value);
mask_err = of_property_read_u32(dev->of_node, "mask", &mask);
value_err = of_property_read_u32(dev->of_node, "value", &data->value);
mask_err = of_property_read_u32(dev->of_node, "mask", &data->mask);
if (value_err && mask_err) {
dev_err(dev, "unable to read 'value' and 'mask'");
return -EINVAL;
@ -58,28 +70,17 @@ static int syscon_poweroff_probe(struct platform_device *pdev)
if (value_err) {
/* support old binding */
value = mask;
mask = 0xFFFFFFFF;
data->value = data->mask;
data->mask = 0xFFFFFFFF;
} else if (mask_err) {
/* support value without mask*/
mask = 0xFFFFFFFF;
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 0;
}
static void syscon_poweroff_remove(struct platform_device *pdev)
{
if (pm_power_off == syscon_poweroff)
pm_power_off = NULL;
return devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_POWER_OFF,
SYS_OFF_PRIO_DEFAULT,
syscon_poweroff, data);
}
static const struct of_device_id syscon_poweroff_of_match[] = {
@ -89,7 +90,6 @@ static const struct of_device_id syscon_poweroff_of_match[] = {
static struct platform_driver syscon_poweroff_driver = {
.probe = syscon_poweroff_probe,
.remove_new = syscon_poweroff_remove,
.driver = {
.name = "syscon-poweroff",
.of_match_table = syscon_poweroff_of_match,

View File

@ -9,22 +9,14 @@
#include <linux/platform_device.h>
#include <linux/reboot.h>
struct tps65086_restart {
struct notifier_block handler;
struct device *dev;
};
static int tps65086_restart_notify(struct notifier_block *this,
unsigned long mode, void *cmd)
static int tps65086_restart_notify(struct sys_off_data *data)
{
struct tps65086_restart *tps65086_restart =
container_of(this, struct tps65086_restart, handler);
struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent);
struct tps65086 *tps65086 = data->cb_data;
int ret;
ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1);
if (ret) {
dev_err(tps65086_restart->dev, "%s: error writing to tps65086 pmic: %d\n",
dev_err(tps65086->dev, "%s: error writing to tps65086 pmic: %d\n",
__func__, ret);
return NOTIFY_DONE;
}
@ -39,44 +31,13 @@ static int tps65086_restart_notify(struct notifier_block *this,
static int tps65086_restart_probe(struct platform_device *pdev)
{
struct tps65086_restart *tps65086_restart;
int ret;
struct tps65086 *tps65086 = dev_get_drvdata(pdev->dev.parent);
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);
if (ret) {
/*
* tps65086_restart_probe() registered the restart handler. So
* unregistering should work fine. Checking the error code
* shouldn't be needed, still doing it for completeness.
*/
dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n",
__func__, ret);
}
return devm_register_sys_off_handler(&pdev->dev,
SYS_OFF_MODE_RESTART,
SYS_OFF_PRIO_HIGH,
tps65086_restart_notify,
tps65086);
}
static const struct platform_device_id tps65086_restart_id_table[] = {
@ -90,7 +51,6 @@ static struct platform_driver tps65086_restart_driver = {
.name = "tps65086-restart",
},
.probe = tps65086_restart_probe,
.remove_new = tps65086_restart_remove,
.id_table = tps65086_restart_id_table,
};
module_platform_driver(tps65086_restart_driver);

View File

@ -22,17 +22,13 @@
struct xgene_reboot_context {
struct device *dev;
void *csr;
void __iomem *csr;
u32 mask;
struct notifier_block restart_handler;
};
static int xgene_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
static int xgene_restart_handler(struct sys_off_data *data)
{
struct xgene_reboot_context *ctx =
container_of(this, struct xgene_reboot_context,
restart_handler);
struct xgene_reboot_context *ctx = data->cb_data;
/* Issue the reboot */
writel(ctx->mask, ctx->csr);
@ -54,23 +50,20 @@ static int xgene_reboot_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
ctx->csr = of_iomap(dev->of_node, 0);
if (!ctx->csr) {
ctx->csr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctx->csr)) {
dev_err(dev, "can not map resource\n");
return -ENODEV;
return PTR_ERR(ctx->csr);
}
if (of_property_read_u32(dev->of_node, "mask", &ctx->mask))
ctx->mask = 0xFFFFFFFF;
ctx->dev = dev;
ctx->restart_handler.notifier_call = xgene_restart_handler;
ctx->restart_handler.priority = 128;
err = register_restart_handler(&ctx->restart_handler);
if (err) {
iounmap(ctx->csr);
err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, 128,
xgene_restart_handler, ctx);
if (err)
dev_err(dev, "cannot register restart handler (err=%d)\n", err);
}
return err;
}

View File

@ -617,8 +617,7 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
*/
static void ab8500_btemp_external_power_changed(struct power_supply *psy)
{
class_for_each_device(power_supply_class, NULL, psy,
ab8500_btemp_get_ext_psy_data);
power_supply_for_each_device(psy, ab8500_btemp_get_ext_psy_data);
}
/* ab8500 btemp driver interrupts and their respective isr */

View File

@ -1231,8 +1231,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
int ret;
/* Collect data from all power_supply class devices */
class_for_each_device(power_supply_class, NULL,
di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
power_supply_for_each_device(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);
ab8500_chargalg_end_of_charge(di);
ab8500_chargalg_check_temp(di);

View File

@ -1949,8 +1949,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
struct ab8500_charger *di = container_of(work,
struct ab8500_charger, check_vbat_work.work);
class_for_each_device(power_supply_class, NULL,
&di->usb_chg, ab8500_charger_get_ext_psy_data);
power_supply_for_each_device(&di->usb_chg, ab8500_charger_get_ext_psy_data);
/* First run old_vbat is 0. */
if (di->old_vbat == 0)

View File

@ -2407,8 +2407,7 @@ out:
*/
static void ab8500_fg_external_power_changed(struct power_supply *psy)
{
class_for_each_device(power_supply_class, NULL, psy,
ab8500_fg_get_ext_psy_data);
power_supply_for_each_device(psy, ab8500_fg_get_ext_psy_data);
}
/**

View File

@ -79,8 +79,7 @@ static void find_main_battery(void)
main_battery = NULL;
bp.main = main_battery;
error = class_for_each_device(power_supply_class, NULL, &bp,
__find_main_battery);
error = power_supply_for_each_device(&bp, __find_main_battery);
if (error) {
main_battery = bp.main;
return;

View File

@ -50,20 +50,24 @@ struct axp_data {
const char * const *irq_names;
unsigned int num_irq_names;
const int *curr_lim_table;
int curr_lim_table_size;
struct reg_field curr_lim_fld;
struct reg_field vbus_valid_bit;
struct reg_field vbus_mon_bit;
struct reg_field usb_bc_en_bit;
struct reg_field usb_bc_det_fld;
struct reg_field vbus_disable_bit;
bool vbus_needs_polling: 1;
};
struct axp20x_usb_power {
struct device *dev;
struct regmap *regmap;
struct regmap_field *curr_lim_fld;
struct regmap_field *vbus_valid_bit;
struct regmap_field *vbus_mon_bit;
struct regmap_field *usb_bc_en_bit;
struct regmap_field *usb_bc_det_fld;
struct regmap_field *vbus_disable_bit;
struct power_supply *supply;
const struct axp_data *axp_data;
@ -115,6 +119,15 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
if (val != power->old_status)
power_supply_changed(power->supply);
if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=
(power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");
ret = regmap_field_write(power->usb_bc_en_bit, 1);
if (ret)
dev_err(power->dev, "failed to enable USB BC: errno %d",
ret);
}
power->old_status = val;
power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
@ -123,6 +136,37 @@ out:
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
}
static int axp20x_get_usb_type(struct axp20x_usb_power *power,
union power_supply_propval *val)
{
unsigned int reg;
int ret;
if (!power->usb_bc_det_fld)
return -EINVAL;
ret = regmap_field_read(power->usb_bc_det_fld, &reg);
if (ret)
return ret;
switch (reg) {
case 1:
val->intval = POWER_SUPPLY_USB_TYPE_SDP;
break;
case 2:
val->intval = POWER_SUPPLY_USB_TYPE_CDP;
break;
case 3:
val->intval = POWER_SUPPLY_USB_TYPE_DCP;
break;
default:
val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
break;
}
return 0;
}
static int axp20x_usb_power_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
@ -160,12 +204,16 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 1700; /* 1 step = 1.7 mV */
return 0;
case POWER_SUPPLY_PROP_CURRENT_MAX:
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
ret = regmap_field_read(power->curr_lim_fld, &v);
if (ret)
return ret;
val->intval = power->axp_data->curr_lim_table[v];
if (v < power->axp_data->curr_lim_table_size)
val->intval = power->axp_data->curr_lim_table[v];
else
val->intval = power->axp_data->curr_lim_table[
power->axp_data->curr_lim_table_size - 1];
return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
@ -189,6 +237,9 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
val->intval = ret * 375; /* 1 step = 0.375 mA */
return 0;
case POWER_SUPPLY_PROP_USB_TYPE:
return axp20x_get_usb_type(power, val);
default:
break;
}
@ -256,19 +307,37 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval)
static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
int intval)
{
const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb,
power->axp_data->curr_lim_fld.lsb);
int ret;
unsigned int reg;
const unsigned int max = power->axp_data->curr_lim_table_size;
if (intval == -1)
return -EINVAL;
for (unsigned int i = 0; i <= max; ++i)
if (power->axp_data->curr_lim_table[i] == intval)
return regmap_field_write(power->curr_lim_fld, i);
/*
* BC1.2 detection can cause a race condition if we try to set a current
* limit while it's in progress. When it finishes it will overwrite the
* current limit we just set.
*/
if (power->usb_bc_en_bit) {
dev_dbg(power->dev,
"disabling BC1.2 detection because current limit was set");
ret = regmap_field_write(power->usb_bc_en_bit, 0);
if (ret)
return ret;
}
return -EINVAL;
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 regmap_field_write(power->curr_lim_fld, reg);
}
static int axp20x_usb_power_set_property(struct power_supply *psy,
@ -287,8 +356,8 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_usb_power_set_voltage_min(power, val->intval);
case POWER_SUPPLY_PROP_CURRENT_MAX:
return axp20x_usb_power_set_current_max(power, val->intval);
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return axp20x_usb_power_set_input_current_limit(power, val->intval);
default:
return -EINVAL;
@ -313,7 +382,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
return power->vbus_disable_bit != NULL;
return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
psp == POWER_SUPPLY_PROP_CURRENT_MAX;
psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
}
static enum power_supply_property axp20x_usb_power_properties[] = {
@ -322,7 +391,7 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_CURRENT_NOW,
};
@ -331,7 +400,23 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
static enum power_supply_property axp813_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_USB_TYPE,
};
static enum power_supply_usb_type axp813_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const struct power_supply_desc axp20x_usb_power_desc = {
@ -354,6 +439,18 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.set_property = axp20x_usb_power_set_property,
};
static const struct power_supply_desc axp813_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
.properties = axp813_usb_power_properties,
.num_properties = ARRAY_SIZE(axp813_usb_power_properties),
.property_is_writeable = axp20x_usb_power_prop_writeable,
.get_property = axp20x_usb_power_get_property,
.set_property = axp20x_usb_power_set_property,
.usb_types = axp813_usb_types,
.num_usb_types = ARRAY_SIZE(axp813_usb_types),
};
static const char * const axp20x_irq_names[] = {
"VBUS_PLUGIN",
"VBUS_REMOVAL",
@ -388,10 +485,15 @@ static int axp221_usb_curr_lim_table[] = {
};
static int axp813_usb_curr_lim_table[] = {
100000,
500000,
900000,
1500000,
2000000,
2500000,
3000000,
3500000,
4000000,
};
static const struct axp_data axp192_data = {
@ -399,6 +501,7 @@ static const struct axp_data axp192_data = {
.irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp192_usb_curr_lim_table,
.curr_lim_table_size = ARRAY_SIZE(axp192_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@ -409,6 +512,7 @@ static const struct axp_data axp202_data = {
.irq_names = axp20x_irq_names,
.num_irq_names = ARRAY_SIZE(axp20x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table,
.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
@ -419,6 +523,7 @@ static const struct axp_data axp221_data = {
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp221_usb_curr_lim_table,
.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
};
@ -428,17 +533,20 @@ static const struct axp_data axp223_data = {
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp20x_usb_curr_lim_table,
.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
};
static const struct axp_data axp813_data = {
.power_desc = &axp22x_usb_power_desc,
.power_desc = &axp813_usb_power_desc,
.irq_names = axp22x_irq_names,
.num_irq_names = ARRAY_SIZE(axp22x_irq_names),
.curr_lim_table = axp813_usb_curr_lim_table,
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7),
.usb_bc_en_bit = REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
.vbus_needs_polling = true,
};
@ -558,6 +666,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, power);
power->dev = &pdev->dev;
power->axp_data = axp_data;
power->regmap = axp20x->regmap;
power->num_irqs = axp_data->num_irq_names;
@ -585,6 +694,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
if (ret)
return ret;
ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->usb_bc_det_fld,
&power->usb_bc_det_fld);
if (ret)
return ret;
ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->vbus_disable_bit,
&power->vbus_disable_bit);

View File

@ -550,18 +550,20 @@ static const struct dmi_system_id axp288_quirks[] = {
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
{
/* Intel Cherry Trail Compute Stick, Windows version */
/* Intel Bay Trail Compute Stick */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"),
/* Partial match for STCK1A32WFC STCK1A32FC, STCK1A8LFC variants */
DMI_MATCH(DMI_PRODUCT_NAME, "STCK1A"),
},
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
{
/* Intel Cherry Trail Compute Stick, version without an OS */
/* Intel Cherry Trail Compute Stick */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"),
/* Partial match for STK1AW32SC and STK1A32SC variants */
DMI_MATCH(DMI_PRODUCT_NAME, "STK1A"),
},
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
@ -599,6 +601,14 @@ static const struct dmi_system_id axp288_quirks[] = {
},
.driver_data = NULL,
},
{
/* Radxa ROCK Pi X Single Board Computer */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "ROCK Pi X"),
DMI_MATCH(DMI_BOARD_VENDOR, "Radxa"),
},
.driver_data = (void *)AXP288_QUIRK_NO_BATTERY,
},
{
/*
* Various Ace PC/Meegopad/MinisForum/Wintel Mini-PCs/HDMI-sticks

View File

@ -991,6 +991,7 @@ static enum power_supply_property bq2415x_power_supply_props[] = {
/* TODO: maybe add more power supply properties */
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_ONLINE,
};
static int bq2415x_power_supply_get_property(struct power_supply *psy,
@ -1017,6 +1018,15 @@ static int bq2415x_power_supply_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = bq->model;
break;
case POWER_SUPPLY_PROP_ONLINE:
/* VBUS is present for all charging and fault states,
* except the 'Ready' state.
*/
ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS);
if (ret < 0)
return ret;
val->intval = ret > 0;
break;
default:
return -EINVAL;
}

View File

@ -1595,17 +1595,24 @@ static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di)
* Return the Design Capacity in µAh
* Or < 0 if something fails.
*/
static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di,
union power_supply_propval *val)
{
int dcap;
/* We only have to read charge design full once */
if (di->charge_design_full > 0) {
val->intval = di->charge_design_full;
return 0;
}
if (di->opts & BQ27XXX_O_ZERO)
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true);
else
dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
if (dcap < 0) {
dev_dbg(di->dev, "error reading initial last measured discharge\n");
dev_dbg(di->dev, "error reading design capacity\n");
return dcap;
}
@ -1614,7 +1621,12 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
else
dcap *= 1000;
return dcap;
/* Save for later reads */
di->charge_design_full = dcap;
val->intval = dcap;
return 0;
}
/*
@ -1816,17 +1828,14 @@ static int bq27xxx_battery_current_and_status(
val_curr->intval = curr;
if (val_status) {
if (curr > 0) {
if (bq27xxx_battery_is_full(di, flags))
val_status->intval = POWER_SUPPLY_STATUS_FULL;
else if (curr > 0)
val_status->intval = POWER_SUPPLY_STATUS_CHARGING;
} else if (curr < 0) {
else if (curr < 0)
val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING;
} else {
if (bq27xxx_battery_is_full(di, flags))
val_status->intval = POWER_SUPPLY_STATUS_FULL;
else
val_status->intval =
POWER_SUPPLY_STATUS_NOT_CHARGING;
}
else
val_status->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
return 0;
@ -1865,10 +1874,6 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
*/
if (!(di->opts & BQ27XXX_O_ZERO))
bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
/* We only have to read charge design full once */
if (di->charge_design_full <= 0)
di->charge_design_full = bq27xxx_battery_read_dcap(di);
}
if ((di->cache.capacity != cache.capacity) ||
@ -2062,7 +2067,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
ret = bq27xxx_simple_value(di->cache.charge_full, val);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = bq27xxx_simple_value(di->charge_design_full, val);
ret = bq27xxx_battery_read_dcap(di, val);
break;
/*
* TODO: Implement these to make registers set from
@ -2101,6 +2106,13 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
mod_delayed_work(system_wq, &di->work, HZ / 2);
}
static void bq27xxx_battery_mutex_destroy(void *data)
{
struct mutex *lock = data;
mutex_destroy(lock);
}
int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{
struct power_supply_desc *psy_desc;
@ -2108,9 +2120,14 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
.of_node = di->dev->of_node,
.drv_data = di,
};
int ret;
INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
mutex_init(&di->lock);
ret = devm_add_action_or_reset(di->dev, bq27xxx_battery_mutex_destroy,
&di->lock);
if (ret)
return ret;
di->regs = bq27xxx_chip_data[di->chip].regs;
di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key;
@ -2128,7 +2145,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
psy_desc->get_property = bq27xxx_battery_get_property;
psy_desc->external_power_changed = bq27xxx_external_power_changed;
di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
di->bat = devm_power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
if (IS_ERR(di->bat))
return dev_err_probe(di->dev, PTR_ERR(di->bat),
"failed to register battery\n");
@ -2156,9 +2173,6 @@ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
mutex_unlock(&di->lock);
cancel_delayed_work_sync(&di->work);
power_supply_unregister(di->bat);
mutex_destroy(&di->lock);
}
EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);

View File

@ -13,8 +13,7 @@
#include <linux/power/bq27xxx_battery.h>
static DEFINE_IDR(battery_id);
static DEFINE_MUTEX(battery_mutex);
static DEFINE_IDA(battery_id);
static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
{
@ -136,30 +135,39 @@ static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
return 0;
}
static void bq27xxx_battery_i2c_devm_ida_free(void *data)
{
int num = (long)data;
ida_free(&battery_id, num);
}
static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct bq27xxx_device_info *di;
int ret;
char *name;
int num;
long num;
/* Get new ID for the new battery device */
mutex_lock(&battery_mutex);
num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
mutex_unlock(&battery_mutex);
num = ida_alloc(&battery_id, GFP_KERNEL);
if (num < 0)
return num;
ret = devm_add_action_or_reset(&client->dev,
bq27xxx_battery_i2c_devm_ida_free,
(void *)num);
if (ret)
return ret;
name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%ld", id->name, num);
if (!name)
goto err_mem;
return -ENOMEM;
di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
if (!di)
goto err_mem;
return -ENOMEM;
di->id = num;
di->dev = &client->dev;
di->chip = id->driver_data;
di->name = name;
@ -171,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
ret = bq27xxx_battery_setup(di);
if (ret)
goto err_failed;
return ret;
/* Schedule a polling after about 1 min */
schedule_delayed_work(&di->work, 60 * HZ);
@ -188,21 +196,11 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
"Unable to register IRQ %d error %d\n",
client->irq, ret);
bq27xxx_battery_teardown(di);
goto err_failed;
return ret;
}
}
return 0;
err_mem:
ret = -ENOMEM;
err_failed:
mutex_lock(&battery_mutex);
idr_remove(&battery_id, num);
mutex_unlock(&battery_mutex);
return ret;
}
static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
@ -213,10 +211,6 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
free_irq(client->irq, di);
bq27xxx_battery_teardown(di);
mutex_lock(&battery_mutex);
idr_remove(&battery_id, di->id);
mutex_unlock(&battery_mutex);
}
static const struct i2c_device_id bq27xxx_i2c_id_table[] = {

View File

@ -530,8 +530,9 @@ static int da9030_battery_probe(struct platform_device *pdev)
da9030_battery_setup_psy(charger);
psy_cfg.drv_data = charger;
charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc,
&psy_cfg);
charger->psy = devm_power_supply_register(&pdev->dev,
&charger->psy_desc,
&psy_cfg);
if (IS_ERR(charger->psy)) {
ret = PTR_ERR(charger->psy);
goto err_ps_register;
@ -563,7 +564,6 @@ static void da9030_battery_remove(struct platform_device *dev)
DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
cancel_delayed_work_sync(&charger->work);
da9030_set_charge(charger, 0);
power_supply_unregister(charger->psy);
}
static struct platform_driver da903x_battery_driver = {

View File

@ -622,7 +622,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
}
}
bat->psy = power_supply_register(&pdev->dev, &psy_desc, &psy_cfg);
bat->psy = devm_power_supply_register(&pdev->dev, &psy_desc, &psy_cfg);
if (IS_ERR(bat->psy)) {
ret = PTR_ERR(bat->psy);
goto err;
@ -644,8 +644,6 @@ static void da9052_bat_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++)
da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
power_supply_unregister(bat->psy);
}
static struct platform_driver da9052_bat_driver = {

View File

@ -521,42 +521,30 @@ static int da9150_charger_probe(struct platform_device *pdev)
charger->dev = dev;
/* Acquire ADC channels */
charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS");
if (IS_ERR(charger->ibus_chan)) {
ret = PTR_ERR(charger->ibus_chan);
goto ibus_chan_fail;
}
charger->ibus_chan = devm_iio_channel_get(dev, "CHAN_IBUS");
if (IS_ERR(charger->ibus_chan))
return PTR_ERR(charger->ibus_chan);
charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS");
if (IS_ERR(charger->vbus_chan)) {
ret = PTR_ERR(charger->vbus_chan);
goto vbus_chan_fail;
}
charger->vbus_chan = devm_iio_channel_get(dev, "CHAN_VBUS");
if (IS_ERR(charger->vbus_chan))
return PTR_ERR(charger->vbus_chan);
charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC");
if (IS_ERR(charger->tjunc_chan)) {
ret = PTR_ERR(charger->tjunc_chan);
goto tjunc_chan_fail;
}
charger->tjunc_chan = devm_iio_channel_get(dev, "CHAN_TJUNC");
if (IS_ERR(charger->tjunc_chan))
return PTR_ERR(charger->tjunc_chan);
charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT");
if (IS_ERR(charger->vbat_chan)) {
ret = PTR_ERR(charger->vbat_chan);
goto vbat_chan_fail;
}
charger->vbat_chan = devm_iio_channel_get(dev, "CHAN_VBAT");
if (IS_ERR(charger->vbat_chan))
return PTR_ERR(charger->vbat_chan);
/* Register power supplies */
charger->usb = power_supply_register(dev, &usb_desc, NULL);
if (IS_ERR(charger->usb)) {
ret = PTR_ERR(charger->usb);
goto usb_fail;
}
charger->usb = devm_power_supply_register(dev, &usb_desc, NULL);
if (IS_ERR(charger->usb))
return PTR_ERR(charger->usb);
charger->battery = power_supply_register(dev, &battery_desc, NULL);
if (IS_ERR(charger->battery)) {
ret = PTR_ERR(charger->battery);
goto battery_fail;
}
charger->battery = devm_power_supply_register(dev, &battery_desc, NULL);
if (IS_ERR(charger->battery))
return PTR_ERR(charger->battery);
/* Get initial online supply */
reg = da9150_reg_read(da9150, DA9150_STATUS_H);
@ -616,22 +604,7 @@ tjunc_irq_fail:
chg_irq_fail:
if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
battery_fail:
power_supply_unregister(charger->usb);
usb_fail:
iio_channel_release(charger->vbat_chan);
vbat_chan_fail:
iio_channel_release(charger->tjunc_chan);
tjunc_chan_fail:
iio_channel_release(charger->vbus_chan);
vbus_chan_fail:
iio_channel_release(charger->ibus_chan);
ibus_chan_fail:
return ret;
}
@ -656,15 +629,6 @@ static void da9150_charger_remove(struct platform_device *pdev)
if (!IS_ERR_OR_NULL(charger->usb_phy))
usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
cancel_work_sync(&charger->otg_work);
power_supply_unregister(charger->battery);
power_supply_unregister(charger->usb);
/* Release ADC channels */
iio_channel_release(charger->ibus_chan);
iio_channel_release(charger->vbus_chan);
iio_channel_release(charger->tjunc_chan);
iio_channel_release(charger->vbat_chan);
}
static struct platform_driver da9150_charger_driver = {

View File

@ -739,7 +739,7 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
if (current_accum)
ds2760_battery_set_current_accum(di, current_accum);
di->bat = power_supply_register(dev, &di->bat_desc, &psy_cfg);
di->bat = devm_power_supply_register(dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n");
retval = PTR_ERR(di->bat);
@ -762,7 +762,6 @@ static int w1_ds2760_add_slave(struct w1_slave *sl)
goto success;
workqueue_failed:
power_supply_unregister(di->bat);
batt_failed:
di_alloc_failed:
success:
@ -777,7 +776,6 @@ static void w1_ds2760_remove_slave(struct w1_slave *sl)
cancel_delayed_work_sync(&di->monitor_work);
cancel_delayed_work_sync(&di->set_charged_work);
destroy_workqueue(di->monitor_wqueue);
power_supply_unregister(di->bat);
}
#ifdef CONFIG_OF

View File

@ -232,31 +232,22 @@ static int goldfish_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = data;
data->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
data->ac = devm_power_supply_register(&pdev->dev,
&ac_desc,
&psy_cfg);
if (IS_ERR(data->ac))
return PTR_ERR(data->ac);
data->battery = power_supply_register(&pdev->dev, &battery_desc,
&psy_cfg);
if (IS_ERR(data->battery)) {
power_supply_unregister(data->ac);
data->battery = devm_power_supply_register(&pdev->dev,
&battery_desc,
&psy_cfg);
if (IS_ERR(data->battery))
return PTR_ERR(data->battery);
}
platform_set_drvdata(pdev, data);
GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
return 0;
}
static void goldfish_battery_remove(struct platform_device *pdev)
{
struct goldfish_battery_data *data = platform_get_drvdata(pdev);
power_supply_unregister(data->battery);
power_supply_unregister(data->ac);
}
static const struct of_device_id goldfish_battery_of_match[] = {
{ .compatible = "google,goldfish-battery", },
{},
@ -273,7 +264,6 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match);
static struct platform_driver goldfish_battery_device = {
.probe = goldfish_battery_probe,
.remove_new = goldfish_battery_remove,
.driver = {
.name = "goldfish-battery",
.of_match_table = goldfish_battery_of_match,

View File

@ -453,39 +453,20 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
psy_cfg.supplied_to = battery_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
psy->ac = power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
psy->ac = devm_power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
if (IS_ERR(psy->ac))
goto err_psy_ac;
return -EPERM;
psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc,
&psy_cfg);
psy->usb = devm_power_supply_register(pchg->dev, &lp8727_usb_desc,
&psy_cfg);
if (IS_ERR(psy->usb))
goto err_psy_usb;
return -EPERM;
psy->batt = power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
psy->batt = devm_power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
if (IS_ERR(psy->batt))
goto err_psy_batt;
return -EPERM;
return 0;
err_psy_batt:
power_supply_unregister(psy->usb);
err_psy_usb:
power_supply_unregister(psy->ac);
err_psy_ac:
return -EPERM;
}
static void lp8727_unregister_psy(struct lp8727_chg *pchg)
{
struct lp8727_psy *psy = pchg->psy;
if (!psy)
return;
power_supply_unregister(psy->ac);
power_supply_unregister(psy->usb);
power_supply_unregister(psy->batt);
}
#ifdef CONFIG_OF
@ -583,7 +564,6 @@ static int lp8727_probe(struct i2c_client *cl)
ret = lp8727_setup_irq(pchg);
if (ret) {
dev_err(pchg->dev, "irq handler err: %d", ret);
lp8727_unregister_psy(pchg);
return ret;
}
@ -595,7 +575,6 @@ static void lp8727_remove(struct i2c_client *cl)
struct lp8727_chg *pchg = i2c_get_clientdata(cl);
lp8727_release_irq(pchg);
lp8727_unregister_psy(pchg);
}
static const struct of_device_id lp8727_dt_ids[] __maybe_unused = {

View File

@ -406,12 +406,6 @@ static const struct power_supply_desc lp8788_psy_battery_desc = {
.get_property = lp8788_battery_get_property,
};
static void lp8788_psy_unregister(struct lp8788_charger *pchg)
{
power_supply_unregister(pchg->battery);
power_supply_unregister(pchg->charger);
}
static void lp8788_charger_event(struct work_struct *work)
{
struct lp8788_charger *pchg =
@ -666,18 +660,16 @@ static int lp8788_psy_register(struct platform_device *pdev,
charger_cfg.supplied_to = battery_supplied_to;
charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
pchg->charger = power_supply_register(&pdev->dev,
&lp8788_psy_charger_desc,
&charger_cfg);
pchg->charger = devm_power_supply_register(&pdev->dev,
&lp8788_psy_charger_desc,
&charger_cfg);
if (IS_ERR(pchg->charger))
return -EPERM;
pchg->battery = power_supply_register(&pdev->dev,
&lp8788_psy_battery_desc, NULL);
if (IS_ERR(pchg->battery)) {
power_supply_unregister(pchg->charger);
pchg->battery = devm_power_supply_register(&pdev->dev,
&lp8788_psy_battery_desc, NULL);
if (IS_ERR(pchg->battery))
return -EPERM;
}
return 0;
}
@ -720,7 +712,6 @@ static void lp8788_charger_remove(struct platform_device *pdev)
flush_work(&pchg->charger_work);
lp8788_irq_unregister(pdev, pchg);
lp8788_psy_unregister(pchg);
}
static struct platform_driver lp8788_charger_driver = {

View File

@ -586,8 +586,9 @@ static int max14577_charger_probe(struct platform_device *pdev)
}
psy_cfg.drv_data = chg;
chg->charger = power_supply_register(&pdev->dev, &max14577_charger_desc,
&psy_cfg);
chg->charger = devm_power_supply_register(&pdev->dev,
&max14577_charger_desc,
&psy_cfg);
if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger);
@ -608,10 +609,7 @@ err:
static void max14577_charger_remove(struct platform_device *pdev)
{
struct max14577_charger *chg = platform_get_drvdata(pdev);
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
power_supply_unregister(chg->charger);
}
static const struct platform_device_id max14577_charger_id[] = {

View File

@ -709,9 +709,9 @@ static int max77693_charger_probe(struct platform_device *pdev)
goto err;
}
chg->charger = power_supply_register(&pdev->dev,
&max77693_charger_desc,
&psy_cfg);
chg->charger = devm_power_supply_register(&pdev->dev,
&max77693_charger_desc,
&psy_cfg);
if (IS_ERR(chg->charger)) {
dev_err(&pdev->dev, "failed: power supply register\n");
ret = PTR_ERR(chg->charger);
@ -730,13 +730,9 @@ err:
static void max77693_charger_remove(struct platform_device *pdev)
{
struct max77693_charger *chg = platform_get_drvdata(pdev);
device_remove_file(&pdev->dev, &dev_attr_top_off_timer);
device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
power_supply_unregister(chg->charger);
}
static const struct platform_device_id max77693_charger_id[] = {

View File

@ -507,7 +507,6 @@ static int max8925_power_probe(struct platform_device *pdev)
struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
struct max8925_power_pdata *pdata = NULL;
struct max8925_power_info *info;
int ret;
pdata = max8925_power_dt_init(pdev);
if (!pdata) {
@ -528,25 +527,19 @@ static int max8925_power_probe(struct platform_device *pdev)
psy_cfg.supplied_to = pdata->supplied_to;
psy_cfg.num_supplicants = pdata->num_supplicants;
info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
if (IS_ERR(info->ac)) {
ret = PTR_ERR(info->ac);
goto out;
}
info->ac = devm_power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
if (IS_ERR(info->ac))
return PTR_ERR(info->ac);
info->ac->dev.parent = &pdev->dev;
info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
if (IS_ERR(info->usb)) {
ret = PTR_ERR(info->usb);
goto out_unregister_ac;
}
info->usb = devm_power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
if (IS_ERR(info->usb))
return PTR_ERR(info->usb);
info->usb->dev.parent = &pdev->dev;
info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL);
if (IS_ERR(info->battery)) {
ret = PTR_ERR(info->battery);
goto out_unregister_usb;
}
info->battery = devm_power_supply_register(&pdev->dev, &battery_desc, NULL);
if (IS_ERR(info->battery))
return PTR_ERR(info->battery);
info->battery->dev.parent = &pdev->dev;
info->batt_detect = pdata->batt_detect;
@ -558,24 +551,14 @@ static int max8925_power_probe(struct platform_device *pdev)
max8925_init_charger(chip, info);
return 0;
out_unregister_usb:
power_supply_unregister(info->usb);
out_unregister_ac:
power_supply_unregister(info->ac);
out:
return ret;
}
static void max8925_power_remove(struct platform_device *pdev)
{
struct max8925_power_info *info = platform_get_drvdata(pdev);
if (info) {
power_supply_unregister(info->ac);
power_supply_unregister(info->usb);
power_supply_unregister(info->battery);
if (info)
max8925_deinit_charger(info);
}
}
static struct platform_driver max8925_power_driver = {

View File

@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip)
static enum power_supply_property mm8013_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_NOW,
@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy,
val->intval = regval;
break;
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
ret = regmap_read(chip->regmap, REG_FLAGS, &regval);
if (ret < 0)
return ret;
if (regval & MM8013_FLAG_CHG_INH)
val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
else
val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, &regval);
if (ret < 0)
@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy,
if (regval & MM8013_FLAG_DSG)
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
else if (regval & MM8013_FLAG_CHG_INH)
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
else if (regval & MM8013_FLAG_CHG)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (regval & MM8013_FLAG_FC)

View File

@ -404,9 +404,9 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
psy_cfg.drv_data = mbc;
/* Create power supplies */
mbc->adapter = power_supply_register(&pdev->dev,
&pcf50633_mbc_adapter_desc,
&psy_cfg);
mbc->adapter = devm_power_supply_register(&pdev->dev,
&pcf50633_mbc_adapter_desc,
&psy_cfg);
if (IS_ERR(mbc->adapter)) {
dev_err(mbc->pcf->dev, "failed to register adapter\n");
return PTR_ERR(mbc->adapter);
@ -415,20 +415,19 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
usb_psy_cfg = psy_cfg;
usb_psy_cfg.attr_grp = pcf50633_mbc_sysfs_groups;
mbc->usb = power_supply_register(&pdev->dev, &pcf50633_mbc_usb_desc,
&usb_psy_cfg);
mbc->usb = devm_power_supply_register(&pdev->dev,
&pcf50633_mbc_usb_desc,
&usb_psy_cfg);
if (IS_ERR(mbc->usb)) {
dev_err(mbc->pcf->dev, "failed to register usb\n");
power_supply_unregister(mbc->adapter);
return PTR_ERR(mbc->usb);
}
mbc->ac = power_supply_register(&pdev->dev, &pcf50633_mbc_ac_desc,
&psy_cfg);
mbc->ac = devm_power_supply_register(&pdev->dev,
&pcf50633_mbc_ac_desc,
&psy_cfg);
if (IS_ERR(mbc->ac)) {
dev_err(mbc->pcf->dev, "failed to register ac\n");
power_supply_unregister(mbc->adapter);
power_supply_unregister(mbc->usb);
return PTR_ERR(mbc->ac);
}
@ -449,10 +448,6 @@ static void pcf50633_mbc_remove(struct platform_device *pdev)
/* Remove IRQ handlers */
for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
power_supply_unregister(mbc->usb);
power_supply_unregister(mbc->adapter);
power_supply_unregister(mbc->ac);
}
static struct platform_driver pcf50633_mbc_driver = {

View File

@ -15,12 +15,14 @@ struct power_supply;
#ifdef CONFIG_SYSFS
extern void power_supply_init_attrs(struct device_type *dev_type);
extern void power_supply_init_attrs(void);
extern int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env);
extern const struct attribute_group *power_supply_attr_groups[];
#else
static inline void power_supply_init_attrs(struct device_type *dev_type) {}
static inline void power_supply_init_attrs(void) {}
#define power_supply_attr_groups NULL
#define power_supply_uevent NULL
#endif /* CONFIG_SYSFS */

View File

@ -25,13 +25,17 @@
#include "power_supply.h"
#include "samsung-sdi-battery.h"
/* exported for the APM Power driver, APM emulation */
struct class *power_supply_class;
EXPORT_SYMBOL_GPL(power_supply_class);
static const struct class power_supply_class = {
.name = "power_supply",
.dev_uevent = power_supply_uevent,
};
static BLOCKING_NOTIFIER_HEAD(power_supply_notifier);
static struct device_type power_supply_dev_type;
static const struct device_type power_supply_dev_type = {
.name = "power_supply",
.groups = power_supply_attr_groups,
};
#define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10)
@ -93,8 +97,7 @@ static void power_supply_changed_work(struct work_struct *work)
if (likely(psy->changed)) {
psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags);
class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);
power_supply_for_each_device(psy, __power_supply_changed_work);
power_supply_update_leds(psy);
blocking_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy);
@ -112,6 +115,12 @@ static void power_supply_changed_work(struct work_struct *work)
spin_unlock_irqrestore(&psy->changed_lock, flags);
}
int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data))
{
return class_for_each_device(&power_supply_class, NULL, data, fn);
}
EXPORT_SYMBOL_GPL(power_supply_for_each_device);
void power_supply_changed(struct power_supply *psy)
{
unsigned long flags;
@ -187,8 +196,7 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
{
int error;
error = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_populate_supplied_from);
error = power_supply_for_each_device(psy, __power_supply_populate_supplied_from);
dev_dbg(&psy->dev, "%s %d\n", __func__, error);
@ -201,7 +209,7 @@ static int __power_supply_find_supply_from_node(struct device *dev,
struct device_node *np = data;
struct power_supply *epsy = dev_get_drvdata(dev);
/* returning non-zero breaks out of class_for_each_device loop */
/* returning non-zero breaks out of power_supply_for_each_device loop */
if (epsy->of_node == np)
return 1;
@ -213,17 +221,16 @@ static int power_supply_find_supply_from_node(struct device_node *supply_node)
int error;
/*
* class_for_each_device() either returns its own errors or values
* power_supply_for_each_device() either returns its own errors or values
* returned by __power_supply_find_supply_from_node().
*
* __power_supply_find_supply_from_node() will return 0 (no match)
* or 1 (match).
*
* We return 0 if class_for_each_device() returned 1, -EPROBE_DEFER if
* We return 0 if power_supply_for_each_device() returned 1, -EPROBE_DEFER if
* it returned 0, or error as returned by it.
*/
error = class_for_each_device(power_supply_class, NULL, supply_node,
__power_supply_find_supply_from_node);
error = power_supply_for_each_device(supply_node, __power_supply_find_supply_from_node);
return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER;
}
@ -329,8 +336,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
struct psy_am_i_supplied_data data = { psy, 0 };
int error;
error = class_for_each_device(power_supply_class, NULL, &data,
__power_supply_am_i_supplied);
error = power_supply_for_each_device(&data, __power_supply_am_i_supplied);
dev_dbg(&psy->dev, "%s count %u err %d\n", __func__, data.count, error);
@ -365,8 +371,7 @@ int power_supply_is_system_supplied(void)
int error;
unsigned int count = 0;
error = class_for_each_device(power_supply_class, NULL, &count,
__power_supply_is_system_supplied);
error = power_supply_for_each_device(&count, __power_supply_is_system_supplied);
/*
* If no system scope power class device was found at all, most probably we
@ -412,8 +417,7 @@ int power_supply_get_property_from_supplier(struct power_supply *psy,
* This function is not intended for use with a supply with multiple
* suppliers, we simply pick the first supply to report the psp.
*/
ret = class_for_each_device(power_supply_class, NULL, &data,
__power_supply_get_supplier_property);
ret = power_supply_for_each_device(&data, __power_supply_get_supplier_property);
if (ret < 0)
return ret;
if (ret == 0)
@ -458,8 +462,8 @@ static int power_supply_match_device_by_name(struct device *dev, const void *dat
struct power_supply *power_supply_get_by_name(const char *name)
{
struct power_supply *psy = NULL;
struct device *dev = class_find_device(power_supply_class, NULL, name,
power_supply_match_device_by_name);
struct device *dev = class_find_device(&power_supply_class, NULL, name,
power_supply_match_device_by_name);
if (dev) {
psy = dev_get_drvdata(dev);
@ -515,8 +519,8 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np,
if (!power_supply_np)
return ERR_PTR(-ENODEV);
dev = class_find_device(power_supply_class, NULL, power_supply_np,
power_supply_match_device_node);
dev = class_find_device(&power_supply_class, NULL, power_supply_np,
power_supply_match_device_node);
of_node_put(power_supply_np);
@ -1369,7 +1373,7 @@ __power_supply_register(struct device *parent,
device_initialize(dev);
dev->class = power_supply_class;
dev->class = &power_supply_class;
dev->type = &power_supply_dev_type;
dev->parent = parent;
dev->release = power_supply_dev_release;
@ -1617,20 +1621,13 @@ EXPORT_SYMBOL_GPL(power_supply_get_drvdata);
static int __init power_supply_class_init(void)
{
power_supply_class = class_create("power_supply");
if (IS_ERR(power_supply_class))
return PTR_ERR(power_supply_class);
power_supply_class->dev_uevent = power_supply_uevent;
power_supply_init_attrs(&power_supply_dev_type);
return 0;
power_supply_init_attrs();
return class_register(&power_supply_class);
}
static void __exit power_supply_class_exit(void)
{
class_destroy(power_supply_class);
class_unregister(&power_supply_class);
}
subsys_initcall(power_supply_class_init);

View File

@ -271,6 +271,23 @@ static ssize_t power_supply_show_usb_type(struct device *dev,
return count;
}
static ssize_t power_supply_show_charge_behaviour(struct device *dev,
struct power_supply *psy,
union power_supply_propval *value,
char *buf)
{
int ret;
ret = power_supply_get_property(psy,
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
value);
if (ret < 0)
return ret;
return power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours,
value->intval, buf);
}
static ssize_t power_supply_show_property(struct device *dev,
struct device_attribute *attr,
char *buf) {
@ -298,21 +315,24 @@ static ssize_t power_supply_show_property(struct device *dev,
}
}
if (ps_attr->text_values_len > 0 &&
value.intval < ps_attr->text_values_len && value.intval >= 0) {
return sysfs_emit(buf, "%s\n", ps_attr->text_values[value.intval]);
}
switch (psp) {
case POWER_SUPPLY_PROP_USB_TYPE:
ret = power_supply_show_usb_type(dev, psy->desc,
&value, buf);
break;
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
ret = power_supply_show_charge_behaviour(dev, psy, &value, buf);
break;
case POWER_SUPPLY_PROP_MODEL_NAME ... POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = sysfs_emit(buf, "%s\n", value.strval);
break;
default:
ret = sysfs_emit(buf, "%d\n", value.intval);
if (ps_attr->text_values_len > 0 &&
value.intval < ps_attr->text_values_len && value.intval >= 0) {
ret = sysfs_emit(buf, "%s\n", ps_attr->text_values[value.intval]);
} else {
ret = sysfs_emit(buf, "%d\n", value.intval);
}
}
return ret;
@ -394,17 +414,15 @@ static const struct attribute_group power_supply_attr_group = {
.is_visible = power_supply_attr_is_visible,
};
static const struct attribute_group *power_supply_attr_groups[] = {
const struct attribute_group *power_supply_attr_groups[] = {
&power_supply_attr_group,
NULL,
NULL
};
void power_supply_init_attrs(struct device_type *dev_type)
void power_supply_init_attrs(void)
{
int i;
dev_type->groups = power_supply_attr_groups;
for (i = 0; i < ARRAY_SIZE(power_supply_attrs); i++) {
struct device_attribute *attr;

View File

@ -159,12 +159,12 @@ static int rt5033_battery_probe(struct i2c_client *client)
return -EINVAL;
}
i2c_set_clientdata(client, battery);
psy_cfg.of_node = client->dev.of_node;
psy_cfg.drv_data = battery;
battery->psy = power_supply_register(&client->dev,
&rt5033_battery_desc, &psy_cfg);
battery->psy = devm_power_supply_register(&client->dev,
&rt5033_battery_desc,
&psy_cfg);
if (IS_ERR(battery->psy))
return dev_err_probe(&client->dev, PTR_ERR(battery->psy),
"Failed to register power supply\n");
@ -172,13 +172,6 @@ static int rt5033_battery_probe(struct i2c_client *client)
return 0;
}
static void rt5033_battery_remove(struct i2c_client *client)
{
struct rt5033_battery *battery = i2c_get_clientdata(client);
power_supply_unregister(battery->psy);
}
static const struct i2c_device_id rt5033_battery_id[] = {
{ "rt5033-battery", },
{ }
@ -197,7 +190,6 @@ static struct i2c_driver rt5033_battery_driver = {
.of_match_table = rt5033_battery_of_match,
},
.probe = rt5033_battery_probe,
.remove = rt5033_battery_remove,
.id_table = rt5033_battery_id,
};
module_i2c_driver(rt5033_battery_driver);

View File

@ -192,14 +192,11 @@ static int rx51_battery_probe(struct platform_device *pdev)
{
struct power_supply_config psy_cfg = {};
struct rx51_device_info *di;
int ret;
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
platform_set_drvdata(pdev, di);
di->dev = &pdev->dev;
di->bat_desc.name = "rx51-battery";
di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
@ -209,52 +206,23 @@ static int rx51_battery_probe(struct platform_device *pdev)
psy_cfg.drv_data = di;
di->channel_temp = iio_channel_get(di->dev, "temp");
if (IS_ERR(di->channel_temp)) {
ret = PTR_ERR(di->channel_temp);
goto error;
}
di->channel_temp = devm_iio_channel_get(di->dev, "temp");
if (IS_ERR(di->channel_temp))
return PTR_ERR(di->channel_temp);
di->channel_bsi = iio_channel_get(di->dev, "bsi");
if (IS_ERR(di->channel_bsi)) {
ret = PTR_ERR(di->channel_bsi);
goto error_channel_temp;
}
di->channel_bsi = devm_iio_channel_get(di->dev, "bsi");
if (IS_ERR(di->channel_bsi))
return PTR_ERR(di->channel_bsi);
di->channel_vbat = iio_channel_get(di->dev, "vbat");
if (IS_ERR(di->channel_vbat)) {
ret = PTR_ERR(di->channel_vbat);
goto error_channel_bsi;
}
di->channel_vbat = devm_iio_channel_get(di->dev, "vbat");
if (IS_ERR(di->channel_vbat))
return PTR_ERR(di->channel_vbat);
di->bat = power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
ret = PTR_ERR(di->bat);
goto error_channel_vbat;
}
di->bat = devm_power_supply_register(di->dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat))
return PTR_ERR(di->bat);
return 0;
error_channel_vbat:
iio_channel_release(di->channel_vbat);
error_channel_bsi:
iio_channel_release(di->channel_bsi);
error_channel_temp:
iio_channel_release(di->channel_temp);
error:
return ret;
}
static void rx51_battery_remove(struct platform_device *pdev)
{
struct rx51_device_info *di = platform_get_drvdata(pdev);
power_supply_unregister(di->bat);
iio_channel_release(di->channel_vbat);
iio_channel_release(di->channel_bsi);
iio_channel_release(di->channel_temp);
}
#ifdef CONFIG_OF
@ -267,7 +235,6 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match);
static struct platform_driver rx51_battery_driver = {
.probe = rx51_battery_probe,
.remove_new = rx51_battery_remove,
.driver = {
.name = "rx51-battery",
.of_match_table = of_match_ptr(n900_battery_of_match),

View File

@ -262,7 +262,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.of_node;
psy_cfg.drv_data = cdata;
cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
cdata->ac = devm_power_supply_register(&pdev->dev, &tps65090_charger_desc,
&psy_cfg);
if (IS_ERR(cdata->ac)) {
dev_err(&pdev->dev, "failed: power supply register\n");
@ -277,7 +277,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = tps65090_config_charger(cdata);
if (ret < 0) {
dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
goto fail_unregister_supply;
return ret;
}
/* Check for charger presence */
@ -286,14 +286,14 @@ static int tps65090_charger_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
TPS65090_REG_CG_STATUS1);
goto fail_unregister_supply;
return ret;
}
if (status1 != 0) {
ret = tps65090_enable_charging(cdata);
if (ret < 0) {
dev_err(cdata->dev, "error enabling charger\n");
goto fail_unregister_supply;
return ret;
}
cdata->ac_online = 1;
power_supply_changed(cdata->ac);
@ -306,7 +306,7 @@ static int tps65090_charger_probe(struct platform_device *pdev)
dev_err(cdata->dev,
"Unable to register irq %d err %d\n", irq,
ret);
goto fail_unregister_supply;
return ret;
}
} else {
cdata->poll_task = kthread_run(tps65090_charger_poll_task,
@ -316,16 +316,11 @@ static int tps65090_charger_probe(struct platform_device *pdev)
ret = PTR_ERR(cdata->poll_task);
dev_err(cdata->dev,
"Unable to run kthread err %d\n", ret);
goto fail_unregister_supply;
return ret;
}
}
return 0;
fail_unregister_supply:
power_supply_unregister(cdata->ac);
return ret;
}
static void tps65090_charger_remove(struct platform_device *pdev)
@ -334,7 +329,6 @@ static void tps65090_charger_remove(struct platform_device *pdev)
if (cdata->irq == -ENXIO)
kthread_stop(cdata->poll_task);
power_supply_unregister(cdata->ac);
}
static const struct of_device_id of_tps65090_charger_match[] = {

View File

@ -188,30 +188,23 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
struct twl4030_madc_battery *twl4030_madc_bat;
struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
struct power_supply_config psy_cfg = {};
int ret = 0;
twl4030_madc_bat = devm_kzalloc(&pdev->dev, sizeof(*twl4030_madc_bat),
GFP_KERNEL);
if (!twl4030_madc_bat)
return -ENOMEM;
twl4030_madc_bat->channel_temp = iio_channel_get(&pdev->dev, "temp");
if (IS_ERR(twl4030_madc_bat->channel_temp)) {
ret = PTR_ERR(twl4030_madc_bat->channel_temp);
goto err;
}
twl4030_madc_bat->channel_temp = devm_iio_channel_get(&pdev->dev, "temp");
if (IS_ERR(twl4030_madc_bat->channel_temp))
return PTR_ERR(twl4030_madc_bat->channel_temp);
twl4030_madc_bat->channel_ichg = iio_channel_get(&pdev->dev, "ichg");
if (IS_ERR(twl4030_madc_bat->channel_ichg)) {
ret = PTR_ERR(twl4030_madc_bat->channel_ichg);
goto err_temp;
}
twl4030_madc_bat->channel_ichg = devm_iio_channel_get(&pdev->dev, "ichg");
if (IS_ERR(twl4030_madc_bat->channel_ichg))
return PTR_ERR(twl4030_madc_bat->channel_ichg);
twl4030_madc_bat->channel_vbat = iio_channel_get(&pdev->dev, "vbat");
if (IS_ERR(twl4030_madc_bat->channel_vbat)) {
ret = PTR_ERR(twl4030_madc_bat->channel_vbat);
goto err_ichg;
}
twl4030_madc_bat->channel_vbat = devm_iio_channel_get(&pdev->dev, "vbat");
if (IS_ERR(twl4030_madc_bat->channel_vbat))
return PTR_ERR(twl4030_madc_bat->channel_vbat);
/* sort charging and discharging calibration data */
sort(pdata->charging, pdata->charging_size,
@ -222,37 +215,14 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
twl4030_cmp, NULL);
twl4030_madc_bat->pdata = pdata;
platform_set_drvdata(pdev, twl4030_madc_bat);
psy_cfg.drv_data = twl4030_madc_bat;
twl4030_madc_bat->psy = power_supply_register(&pdev->dev,
&twl4030_madc_bat_desc,
&psy_cfg);
if (IS_ERR(twl4030_madc_bat->psy)) {
ret = PTR_ERR(twl4030_madc_bat->psy);
goto err_vbat;
}
twl4030_madc_bat->psy = devm_power_supply_register(&pdev->dev,
&twl4030_madc_bat_desc,
&psy_cfg);
if (IS_ERR(twl4030_madc_bat->psy))
return PTR_ERR(twl4030_madc_bat->psy);
return 0;
err_vbat:
iio_channel_release(twl4030_madc_bat->channel_vbat);
err_ichg:
iio_channel_release(twl4030_madc_bat->channel_ichg);
err_temp:
iio_channel_release(twl4030_madc_bat->channel_temp);
err:
return ret;
}
static void twl4030_madc_battery_remove(struct platform_device *pdev)
{
struct twl4030_madc_battery *bat = platform_get_drvdata(pdev);
power_supply_unregister(bat->psy);
iio_channel_release(bat->channel_vbat);
iio_channel_release(bat->channel_ichg);
iio_channel_release(bat->channel_temp);
}
static struct platform_driver twl4030_madc_battery_driver = {
@ -260,7 +230,6 @@ static struct platform_driver twl4030_madc_battery_driver = {
.name = "twl4030_madc_battery",
},
.probe = twl4030_madc_battery_probe,
.remove_new = twl4030_madc_battery_remove,
};
module_platform_driver(twl4030_madc_battery_driver);

View File

@ -171,7 +171,6 @@ static int wm831x_backup_probe(struct platform_device *pdev)
return -ENOMEM;
devdata->wm831x = wm831x;
platform_set_drvdata(pdev, devdata);
/* We ignore configuration failures since we can still read
* back the status without enabling the charger (which may
@ -191,22 +190,14 @@ static int wm831x_backup_probe(struct platform_device *pdev)
devdata->backup_desc.properties = wm831x_backup_props;
devdata->backup_desc.num_properties = ARRAY_SIZE(wm831x_backup_props);
devdata->backup_desc.get_property = wm831x_backup_get_prop;
devdata->backup = power_supply_register(&pdev->dev,
&devdata->backup_desc, NULL);
devdata->backup = devm_power_supply_register(&pdev->dev,
&devdata->backup_desc, NULL);
return PTR_ERR_OR_ZERO(devdata->backup);
}
static void wm831x_backup_remove(struct platform_device *pdev)
{
struct wm831x_backup *devdata = platform_get_drvdata(pdev);
power_supply_unregister(devdata->backup);
}
static struct platform_driver wm831x_backup_driver = {
.probe = wm831x_backup_probe,
.remove_new = wm831x_backup_remove,
.driver = {
.name = "wm831x-backup",
},

View File

@ -570,8 +570,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->wall_desc.properties = wm831x_wall_props;
power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props);
power->wall_desc.get_property = wm831x_wall_get_prop;
power->wall = power_supply_register(&pdev->dev, &power->wall_desc,
NULL);
power->wall = devm_power_supply_register(&pdev->dev,
&power->wall_desc,
NULL);
if (IS_ERR(power->wall)) {
ret = PTR_ERR(power->wall);
goto err;
@ -582,7 +583,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->usb_desc.properties = wm831x_usb_props;
power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props);
power->usb_desc.get_property = wm831x_usb_get_prop;
power->usb = power_supply_register(&pdev->dev, &power->usb_desc, NULL);
power->usb = devm_power_supply_register(&pdev->dev,
&power->usb_desc,
NULL);
if (IS_ERR(power->usb)) {
ret = PTR_ERR(power->usb);
goto err_wall;
@ -599,9 +602,9 @@ static int wm831x_power_probe(struct platform_device *pdev)
power->battery_desc.num_properties = ARRAY_SIZE(wm831x_bat_props);
power->battery_desc.get_property = wm831x_bat_get_prop;
power->battery_desc.use_for_apm = 1;
power->battery = power_supply_register(&pdev->dev,
&power->battery_desc,
NULL);
power->battery = devm_power_supply_register(&pdev->dev,
&power->battery_desc,
NULL);
if (IS_ERR(power->battery)) {
ret = PTR_ERR(power->battery);
goto err_usb;
@ -684,12 +687,8 @@ err_syslo:
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, power);
err_battery:
if (power->have_battery)
power_supply_unregister(power->battery);
err_usb:
power_supply_unregister(power->usb);
err_wall:
power_supply_unregister(power->wall);
err:
return ret;
}
@ -717,11 +716,6 @@ static void wm831x_power_remove(struct platform_device *pdev)
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, wm831x_power);
if (wm831x_power->have_battery)
power_supply_unregister(wm831x_power->battery);
power_supply_unregister(wm831x_power->wall);
power_supply_unregister(wm831x_power->usb);
}
static struct platform_driver wm831x_power_driver = {

View File

@ -540,22 +540,17 @@ static int wm8350_power_probe(struct platform_device *pdev)
struct wm8350_charger_policy *policy = power->policy;
int ret;
power->ac = power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
power->ac = devm_power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
if (IS_ERR(power->ac))
return PTR_ERR(power->ac);
power->battery = power_supply_register(&pdev->dev, &wm8350_battery_desc,
NULL);
if (IS_ERR(power->battery)) {
ret = PTR_ERR(power->battery);
goto battery_failed;
}
power->battery = devm_power_supply_register(&pdev->dev, &wm8350_battery_desc, NULL);
if (IS_ERR(power->battery))
return PTR_ERR(power->battery);
power->usb = power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
if (IS_ERR(power->usb)) {
ret = PTR_ERR(power->usb);
goto usb_failed;
}
power->usb = devm_power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
if (IS_ERR(power->usb))
return PTR_ERR(power->usb);
ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
if (ret < 0)
@ -569,26 +564,15 @@ static int wm8350_power_probe(struct platform_device *pdev)
wm8350_reg_lock(wm8350);
}
return ret;
usb_failed:
power_supply_unregister(power->battery);
battery_failed:
power_supply_unregister(power->ac);
return ret;
}
static void wm8350_power_remove(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
struct wm8350_power *power = &wm8350->power;
free_charger_irq(wm8350);
device_remove_file(&pdev->dev, &dev_attr_charger_state);
power_supply_unregister(power->battery);
power_supply_unregister(power->ac);
power_supply_unregister(power->usb);
}
static struct platform_driver wm8350_power_driver = {

View File

@ -61,7 +61,6 @@ struct bq27xxx_reg_cache {
struct bq27xxx_device_info {
struct device *dev;
int id;
enum bq27xxx_chip chip;
u32 opts;
const char *name;

View File

@ -242,6 +242,7 @@ struct power_supply_config {
struct power_supply_desc {
const char *name;
enum power_supply_type type;
u8 charge_behaviours;
const enum power_supply_usb_type *usb_types;
size_t num_usb_types;
const enum power_supply_property *properties;
@ -894,8 +895,7 @@ extern int power_supply_powers(struct power_supply *psy, struct device *dev);
#define to_power_supply(device) container_of(device, struct power_supply, dev)
extern void *power_supply_get_drvdata(struct power_supply *psy);
/* For APM emulation, think legacy userspace. */
extern struct class *power_supply_class;
extern int power_supply_for_each_device(void *data, int (*fn)(struct device *dev, void *data));
static inline bool power_supply_is_amp_property(enum power_supply_property psp)
{