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
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

Some files were not shown because too many files have changed in this diff Show More