diff options
Diffstat (limited to 'drivers/power')
23 files changed, 481 insertions, 344 deletions
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index d55b3727e00e..b22c4fdb2561 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -177,6 +177,13 @@ config POWER_RESET_QNAP Say Y if you have a QNAP NAS. +config POWER_RESET_REGULATOR + bool "Regulator subsystem power-off driver" + depends on OF && REGULATOR + help + This driver supports turning off your board by disabling a + power regulator defined in the devicetree. + config POWER_RESET_RESTART bool "Restart power-off driver" help diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index c51eceba9ea3..9dc49d3a57ff 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o +obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o diff --git a/drivers/power/reset/ocelot-reset.c b/drivers/power/reset/ocelot-reset.c index f74e1dbb4ba3..8caa90cb58fc 100644 --- a/drivers/power/reset/ocelot-reset.c +++ b/drivers/power/reset/ocelot-reset.c @@ -29,6 +29,8 @@ struct ocelot_reset_context { struct notifier_block restart_handler; }; +#define BIT_OFF_INVALID 32 + #define SOFT_CHIP_RST BIT(0) #define ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL 0x24 @@ -50,9 +52,11 @@ static int ocelot_restart_handle(struct notifier_block *this, ctx->props->vcore_protect, 0); /* Make the SI back to boot mode */ - regmap_update_bits(ctx->cpu_ctrl, ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, - IF_SI_OWNER_MASK << if_si_owner_bit, - IF_SI_OWNER_SIBM << if_si_owner_bit); + if (if_si_owner_bit != BIT_OFF_INVALID) + regmap_update_bits(ctx->cpu_ctrl, + ICPU_CFG_CPU_SYSTEM_CTRL_GENERAL_CTRL, + IF_SI_OWNER_MASK << if_si_owner_bit, + IF_SI_OWNER_SIBM << if_si_owner_bit); pr_emerg("Resetting SoC\n"); @@ -96,6 +100,20 @@ static int ocelot_reset_probe(struct platform_device *pdev) return err; } +static const struct reset_props reset_props_jaguar2 = { + .syscon = "mscc,ocelot-cpu-syscon", + .protect_reg = 0x20, + .vcore_protect = BIT(2), + .if_si_owner_bit = 6, +}; + +static const struct reset_props reset_props_luton = { + .syscon = "mscc,ocelot-cpu-syscon", + .protect_reg = 0x20, + .vcore_protect = BIT(2), + .if_si_owner_bit = BIT_OFF_INVALID, /* n/a */ +}; + static const struct reset_props reset_props_ocelot = { .syscon = "mscc,ocelot-cpu-syscon", .protect_reg = 0x20, @@ -112,6 +130,12 @@ static const struct reset_props reset_props_sparx5 = { static const struct of_device_id ocelot_reset_of_match[] = { { + .compatible = "mscc,jaguar2-chip-reset", + .data = &reset_props_jaguar2 + }, { + .compatible = "mscc,luton-chip-reset", + .data = &reset_props_luton + }, { .compatible = "mscc,ocelot-chip-reset", .data = &reset_props_ocelot }, { diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c index 52b7dc61d870..0ddf7f25f7b8 100644 --- a/drivers/power/reset/qnap-poweroff.c +++ b/drivers/power/reset/qnap-poweroff.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/serial_reg.h> -#include <linux/kallsyms.h> #include <linux/of.h> #include <linux/io.h> #include <linux/clk.h> @@ -75,7 +74,6 @@ static int qnap_power_off_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct resource *res; struct clk *clk; - char symname[KSYM_NAME_LEN]; const struct of_device_id *match = of_match_node(qnap_power_off_of_match_table, np); @@ -104,10 +102,8 @@ static int qnap_power_off_probe(struct platform_device *pdev) /* Check that nothing else has already setup a handler */ if (pm_power_off) { - lookup_symbol_name((ulong)pm_power_off, symname); - dev_err(&pdev->dev, - "pm_power_off already claimed %p %s", - pm_power_off, symname); + dev_err(&pdev->dev, "pm_power_off already claimed for %ps", + pm_power_off); return -EBUSY; } pm_power_off = qnap_power_off; diff --git a/drivers/power/reset/regulator-poweroff.c b/drivers/power/reset/regulator-poweroff.c new file mode 100644 index 000000000000..f697088e0ad1 --- /dev/null +++ b/drivers/power/reset/regulator-poweroff.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Force-disables a regulator to power down a device + * + * Michael Klein <michael@fossekall.de> + * + * Copyright (C) 2020 Michael Klein + * + * Based on the gpio-poweroff driver. + */ +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm.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) +{ + if (cpu_regulator && regulator_is_enabled(cpu_regulator)) + regulator_force_disable(cpu_regulator); + + /* give it some time */ + mdelay(TIMEOUT_MS); + + WARN_ON(1); +} + +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; + } + + cpu_regulator = devm_regulator_get(&pdev->dev, "cpu"); + if (IS_ERR(cpu_regulator)) + return PTR_ERR(cpu_regulator); + + pm_power_off = ®ulator_poweroff_do_poweroff; + return 0; +} + +static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev) +{ + if (pm_power_off == ®ulator_poweroff_do_poweroff) + pm_power_off = NULL; + + return 0; +} + +static const struct of_device_id of_regulator_poweroff_match[] = { + { .compatible = "regulator-poweroff", }, + {}, +}; + +static struct platform_driver regulator_poweroff_driver = { + .probe = regulator_poweroff_probe, + .remove = regulator_poweroff_remove, + .driver = { + .name = "poweroff-regulator", + .of_match_table = of_regulator_poweroff_match, + }, +}; + +module_platform_driver(regulator_poweroff_driver); + +MODULE_AUTHOR("Michael Klein <michael@fossekall.de>"); +MODULE_DESCRIPTION("Regulator poweroff driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:poweroff-regulator"); diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index 4d6923b102b6..ed58bdf41e27 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -6,7 +6,6 @@ * Author: Moritz Fischer <moritz.fischer@ettus.com> */ -#include <linux/kallsyms.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/notifier.h> @@ -34,7 +33,6 @@ static void syscon_poweroff(void) static int syscon_poweroff_probe(struct platform_device *pdev) { - char symname[KSYM_NAME_LEN]; int mask_err, value_err; map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap"); @@ -65,10 +63,8 @@ static int syscon_poweroff_probe(struct platform_device *pdev) } if (pm_power_off) { - lookup_symbol_name((ulong)pm_power_off, symname); - dev_err(&pdev->dev, - "pm_power_off already claimed %p %s", - pm_power_off, symname); + dev_err(&pdev->dev, "pm_power_off already claimed for %ps", + pm_power_off); return -EBUSY; } diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 909f0242bacb..d20345386b1e 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -936,29 +936,23 @@ static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = { {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler}, }; -#if defined(CONFIG_PM) -static int ab8500_btemp_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_btemp_resume(struct device *dev) { - struct ab8500_btemp *di = platform_get_drvdata(pdev); + struct ab8500_btemp *di = dev_get_drvdata(dev); ab8500_btemp_periodic(di, true); return 0; } -static int ab8500_btemp_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_btemp_suspend(struct device *dev) { - struct ab8500_btemp *di = platform_get_drvdata(pdev); + struct ab8500_btemp *di = dev_get_drvdata(dev); ab8500_btemp_periodic(di, false); return 0; } -#else -#define ab8500_btemp_suspend NULL -#define ab8500_btemp_resume NULL -#endif static int ab8500_btemp_remove(struct platform_device *pdev) { @@ -999,48 +993,45 @@ static int ab8500_btemp_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct abx500_bm_data *plat = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; + struct device *dev = &pdev->dev; struct ab8500_btemp *di; int irq, i, ret = 0; u8 val; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } } /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); /* Get ADC channels */ - di->btemp_ball = devm_iio_channel_get(&pdev->dev, "btemp_ball"); + di->btemp_ball = devm_iio_channel_get(dev, "btemp_ball"); if (IS_ERR(di->btemp_ball)) { - if (PTR_ERR(di->btemp_ball) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get BTEMP BALL ADC channel\n"); - return PTR_ERR(di->btemp_ball); + ret = dev_err_probe(dev, PTR_ERR(di->btemp_ball), + "failed to get BTEMP BALL ADC channel\n"); + return ret; } - di->bat_ctrl = devm_iio_channel_get(&pdev->dev, "bat_ctrl"); + di->bat_ctrl = devm_iio_channel_get(dev, "bat_ctrl"); if (IS_ERR(di->bat_ctrl)) { - if (PTR_ERR(di->bat_ctrl) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get BAT CTRL ADC channel\n"); - return PTR_ERR(di->bat_ctrl); + ret = dev_err_probe(dev, PTR_ERR(di->bat_ctrl), + "failed to get BAT CTRL ADC channel\n"); + return ret; } di->initialized = false; @@ -1053,7 +1044,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) di->btemp_wq = alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); if (di->btemp_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -1065,10 +1056,10 @@ static int ab8500_btemp_probe(struct platform_device *pdev) di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; - ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, + ret = abx500_get_register_interruptible(dev, AB8500_CHARGER, AB8500_BTEMP_HIGH_TH, &val); if (ret < 0) { - dev_err(di->dev, "%s ab8500 read failed\n", __func__); + dev_err(dev, "%s ab8500 read failed\n", __func__); goto free_btemp_wq; } switch (val) { @@ -1088,10 +1079,10 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } /* Register BTEMP power supply class */ - di->btemp_psy = power_supply_register(di->dev, &ab8500_btemp_desc, + di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc, &psy_cfg); if (IS_ERR(di->btemp_psy)) { - dev_err(di->dev, "failed to register BTEMP psy\n"); + dev_err(dev, "failed to register BTEMP psy\n"); ret = PTR_ERR(di->btemp_psy); goto free_btemp_wq; } @@ -1105,15 +1096,15 @@ static int ab8500_btemp_probe(struct platform_device *pdev) } ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_btemp_irq[i].name, di); if (ret) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_btemp_irq[i].name, irq, ret); goto free_irq; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_btemp_irq[i].name, irq, ret); } @@ -1138,6 +1129,8 @@ free_btemp_wq: return ret; } +static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); + static const struct of_device_id ab8500_btemp_match[] = { { .compatible = "stericsson,ab8500-btemp", }, { }, @@ -1146,11 +1139,10 @@ static const struct of_device_id ab8500_btemp_match[] = { static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, .remove = ab8500_btemp_remove, - .suspend = ab8500_btemp_suspend, - .resume = ab8500_btemp_resume, .driver = { .name = "ab8500-btemp", .of_match_table = ab8500_btemp_match, + .pm = &ab8500_btemp_pm_ops, }, }; diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index db65be026920..ac77c8882d17 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3209,11 +3209,10 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, return NOTIFY_OK; } -#if defined(CONFIG_PM) -static int ab8500_charger_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_charger_resume(struct device *dev) { int ret; - struct ab8500_charger *di = platform_get_drvdata(pdev); + struct ab8500_charger *di = dev_get_drvdata(dev); /* * For ABB revision 1.0 and 1.1 there is a bug in the watchdog @@ -3247,10 +3246,9 @@ static int ab8500_charger_resume(struct platform_device *pdev) return 0; } -static int ab8500_charger_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_charger_suspend(struct device *dev) { - struct ab8500_charger *di = platform_get_drvdata(pdev); + struct ab8500_charger *di = dev_get_drvdata(dev); /* Cancel any pending jobs */ cancel_delayed_work(&di->check_hw_failure_work); @@ -3272,10 +3270,6 @@ static int ab8500_charger_suspend(struct platform_device *pdev, return 0; } -#else -#define ab8500_charger_suspend NULL -#define ab8500_charger_resume NULL -#endif static struct notifier_block charger_nb = { .notifier_call = ab8500_external_charger_prepare, @@ -3354,23 +3348,22 @@ static int ab8500_charger_probe(struct platform_device *pdev) struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {}; struct ab8500_charger *di; int irq, i, charger_status, ret = 0, ch_stat; + struct device *dev = &pdev->dev; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); @@ -3378,40 +3371,33 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->autopower_cfg = false; /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); /* Get ADC channels */ - di->adc_main_charger_v = devm_iio_channel_get(&pdev->dev, - "main_charger_v"); + di->adc_main_charger_v = devm_iio_channel_get(dev, "main_charger_v"); if (IS_ERR(di->adc_main_charger_v)) { - if (PTR_ERR(di->adc_main_charger_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC main charger voltage\n"); - return PTR_ERR(di->adc_main_charger_v); + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_v), + "failed to get ADC main charger voltage\n"); + return ret; } - di->adc_main_charger_c = devm_iio_channel_get(&pdev->dev, - "main_charger_c"); + di->adc_main_charger_c = devm_iio_channel_get(dev, "main_charger_c"); if (IS_ERR(di->adc_main_charger_c)) { - if (PTR_ERR(di->adc_main_charger_c) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC main charger current\n"); - return PTR_ERR(di->adc_main_charger_c); + ret = dev_err_probe(dev, PTR_ERR(di->adc_main_charger_c), + "failed to get ADC main charger current\n"); + return ret; } - di->adc_vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v"); + di->adc_vbus_v = devm_iio_channel_get(dev, "vbus_v"); if (IS_ERR(di->adc_vbus_v)) { - if (PTR_ERR(di->adc_vbus_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC USB charger voltage\n"); - return PTR_ERR(di->adc_vbus_v); + ret = dev_err_probe(dev, PTR_ERR(di->adc_vbus_v), + "failed to get ADC USB charger voltage\n"); + return ret; } - di->adc_usb_charger_c = devm_iio_channel_get(&pdev->dev, - "usb_charger_c"); + di->adc_usb_charger_c = devm_iio_channel_get(dev, "usb_charger_c"); if (IS_ERR(di->adc_usb_charger_c)) { - if (PTR_ERR(di->adc_usb_charger_c) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get ADC USB charger current\n"); - return PTR_ERR(di->adc_usb_charger_c); + ret = dev_err_probe(dev, PTR_ERR(di->adc_usb_charger_c), + "failed to get ADC USB charger current\n"); + return ret; } /* initialize lock */ @@ -3467,7 +3453,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq", WQ_MEM_RECLAIM); if (di->charger_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -3526,10 +3512,10 @@ static int ab8500_charger_probe(struct platform_device *pdev) * is a charger connected to avoid erroneous BTEMP_HIGH/LOW * interrupts during charging */ - di->regu = devm_regulator_get(di->dev, "vddadc"); + di->regu = devm_regulator_get(dev, "vddadc"); if (IS_ERR(di->regu)) { ret = PTR_ERR(di->regu); - dev_err(di->dev, "failed to get vddadc regulator\n"); + dev_err(dev, "failed to get vddadc regulator\n"); goto free_charger_wq; } @@ -3537,17 +3523,17 @@ static int ab8500_charger_probe(struct platform_device *pdev) /* Initialize OVV, and other registers */ ret = ab8500_charger_init_hw_registers(di); if (ret) { - dev_err(di->dev, "failed to initialize ABB registers\n"); + dev_err(dev, "failed to initialize ABB registers\n"); goto free_charger_wq; } /* Register AC charger class */ if (di->ac_chg.enabled) { - di->ac_chg.psy = power_supply_register(di->dev, + di->ac_chg.psy = power_supply_register(dev, &ab8500_ac_chg_desc, &ac_psy_cfg); if (IS_ERR(di->ac_chg.psy)) { - dev_err(di->dev, "failed to register AC charger\n"); + dev_err(dev, "failed to register AC charger\n"); ret = PTR_ERR(di->ac_chg.psy); goto free_charger_wq; } @@ -3555,11 +3541,11 @@ static int ab8500_charger_probe(struct platform_device *pdev) /* Register USB charger class */ if (di->usb_chg.enabled) { - di->usb_chg.psy = power_supply_register(di->dev, + di->usb_chg.psy = power_supply_register(dev, &ab8500_usb_chg_desc, &usb_psy_cfg); if (IS_ERR(di->usb_chg.psy)) { - dev_err(di->dev, "failed to register USB charger\n"); + dev_err(dev, "failed to register USB charger\n"); ret = PTR_ERR(di->usb_chg.psy); goto free_ac; } @@ -3567,14 +3553,14 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(di->usb_phy)) { - dev_err(di->dev, "failed to get usb transceiver\n"); + dev_err(dev, "failed to get usb transceiver\n"); ret = -EINVAL; goto free_usb; } di->nb.notifier_call = ab8500_charger_usb_notifier_call; ret = usb_register_notifier(di->usb_phy, &di->nb); if (ret) { - dev_err(di->dev, "failed to register usb notifier\n"); + dev_err(dev, "failed to register usb notifier\n"); goto put_usb_phy; } @@ -3603,15 +3589,15 @@ static int ab8500_charger_probe(struct platform_device *pdev) } ret = request_threaded_irq(irq, NULL, ab8500_charger_irq[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, ab8500_charger_irq[i].name, di); if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n" + dev_err(dev, "failed to request %s IRQ %d: %d\n" , ab8500_charger_irq[i].name, irq, ret); goto free_irq; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", + dev_dbg(dev, "Requested %s IRQ %d: %d\n", ab8500_charger_irq[i].name, irq, ret); } @@ -3659,6 +3645,8 @@ free_charger_wq: return ret; } +static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume); + static const struct of_device_id ab8500_charger_match[] = { { .compatible = "stericsson,ab8500-charger", }, { }, @@ -3667,11 +3655,10 @@ static const struct of_device_id ab8500_charger_match[] = { static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, .remove = ab8500_charger_remove, - .suspend = ab8500_charger_suspend, - .resume = ab8500_charger_resume, .driver = { .name = "ab8500-charger", .of_match_table = ab8500_charger_match, + .pm = &ab8500_charger_pm_ops, }, }; diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 592a73d4dde6..3873e4857e3d 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -2942,10 +2942,9 @@ static void ab8500_fg_sysfs_psy_remove_attrs(struct ab8500_fg *di) /* Exposure to the sysfs interface <<END>> */ -#if defined(CONFIG_PM) -static int ab8500_fg_resume(struct platform_device *pdev) +static int __maybe_unused ab8500_fg_resume(struct device *dev) { - struct ab8500_fg *di = platform_get_drvdata(pdev); + struct ab8500_fg *di = dev_get_drvdata(dev); /* * Change state if we're not charging. If we're charging we will wake @@ -2959,10 +2958,9 @@ static int ab8500_fg_resume(struct platform_device *pdev) return 0; } -static int ab8500_fg_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused ab8500_fg_suspend(struct device *dev) { - struct ab8500_fg *di = platform_get_drvdata(pdev); + struct ab8500_fg *di = dev_get_drvdata(dev); flush_delayed_work(&di->fg_periodic_work); flush_work(&di->fg_work); @@ -2980,10 +2978,6 @@ static int ab8500_fg_suspend(struct platform_device *pdev, return 0; } -#else -#define ab8500_fg_suspend NULL -#define ab8500_fg_resume NULL -#endif static int ab8500_fg_remove(struct platform_device *pdev) { @@ -3007,14 +3001,11 @@ static int ab8500_fg_remove(struct platform_device *pdev) } /* ab8500 fg driver interrupts and their respective isr */ -static struct ab8500_fg_interrupts ab8500_fg_irq_th[] = { +static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"NCONV_ACCU", ab8500_fg_cc_convend_handler}, {"BATT_OVV", ab8500_fg_batt_ovv_handler}, {"LOW_BAT_F", ab8500_fg_lowbatf_handler}, {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler}, -}; - -static struct ab8500_fg_interrupts ab8500_fg_irq_bh[] = { {"CCEOC", ab8500_fg_cc_data_end_handler}, }; @@ -3037,26 +3028,25 @@ static int ab8500_fg_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct abx500_bm_data *plat = pdev->dev.platform_data; struct power_supply_config psy_cfg = {}; + struct device *dev = &pdev->dev; struct ab8500_fg *di; int i, irq; int ret = 0; - di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); - if (!di) { - dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); + di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); + if (!di) return -ENOMEM; - } if (!plat) { - dev_err(&pdev->dev, "no battery management data supplied\n"); + dev_err(dev, "no battery management data supplied\n"); return -EINVAL; } di->bm = plat; if (np) { - ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); + ret = ab8500_bm_of_probe(dev, np, di->bm); if (ret) { - dev_err(&pdev->dev, "failed to get battery information\n"); + dev_err(dev, "failed to get battery information\n"); return ret; } } @@ -3064,15 +3054,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) mutex_init(&di->cc_lock); /* get parent data */ - di->dev = &pdev->dev; + di->dev = dev; di->parent = dev_get_drvdata(pdev->dev.parent); - di->main_bat_v = devm_iio_channel_get(&pdev->dev, "main_bat_v"); + di->main_bat_v = devm_iio_channel_get(dev, "main_bat_v"); if (IS_ERR(di->main_bat_v)) { - if (PTR_ERR(di->main_bat_v) == -ENODEV) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "failed to get main battery ADC channel\n"); - return PTR_ERR(di->main_bat_v); + ret = dev_err_probe(dev, PTR_ERR(di->main_bat_v), + "failed to get main battery ADC channel\n"); + return ret; } psy_cfg.supplied_to = supply_interface; @@ -3094,7 +3083,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Create a work queue for running the FG algorithm */ di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM); if (di->fg_wq == NULL) { - dev_err(di->dev, "failed to create work queue\n"); + dev_err(dev, "failed to create work queue\n"); return -ENOMEM; } @@ -3129,7 +3118,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) /* Initialize OVV, and other registers */ ret = ab8500_fg_init_hw_registers(di); if (ret) { - dev_err(di->dev, "failed to initialize registers\n"); + dev_err(dev, "failed to initialize registers\n"); goto free_inst_curr_wq; } @@ -3138,9 +3127,9 @@ static int ab8500_fg_probe(struct platform_device *pdev) di->flags.batt_id_received = false; /* Register FG power supply class */ - di->fg_psy = power_supply_register(di->dev, &ab8500_fg_desc, &psy_cfg); + di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg); if (IS_ERR(di->fg_psy)) { - dev_err(di->dev, "failed to register FG psy\n"); + dev_err(dev, "failed to register FG psy\n"); ret = PTR_ERR(di->fg_psy); goto free_inst_curr_wq; } @@ -3156,45 +3145,26 @@ static int ab8500_fg_probe(struct platform_device *pdev) init_completion(&di->ab8500_fg_complete); /* Register primary interrupt handlers */ - for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq_th); i++) { - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name); + for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) { + irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name); if (irq < 0) { ret = irq; - goto free_irq_th; + goto free_irq; } - ret = request_irq(irq, ab8500_fg_irq_th[i].isr, - IRQF_SHARED | IRQF_NO_SUSPEND, - ab8500_fg_irq_th[i].name, di); + ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr, + IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, + ab8500_fg_irq[i].name, di); if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n", - ab8500_fg_irq_th[i].name, irq, ret); - goto free_irq_th; + dev_err(dev, "failed to request %s IRQ %d: %d\n", + ab8500_fg_irq[i].name, irq, ret); + goto free_irq; } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", - ab8500_fg_irq_th[i].name, irq, ret); + dev_dbg(dev, "Requested %s IRQ %d: %d\n", + ab8500_fg_irq[i].name, irq, ret); } - /* Register threaded interrupt handler */ - irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name); - if (irq < 0) { - ret = irq; - goto free_irq_th; - } - - ret = request_threaded_irq(irq, NULL, ab8500_fg_irq_bh[0].isr, - IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, - ab8500_fg_irq_bh[0].name, di); - - if (ret != 0) { - dev_err(di->dev, "failed to request %s IRQ %d: %d\n", - ab8500_fg_irq_bh[0].name, irq, ret); - goto free_irq_th; - } - dev_dbg(di->dev, "Requested %s IRQ %d: %d\n", - ab8500_fg_irq_bh[0].name, irq, ret); - di->irq = platform_get_irq_byname(pdev, "CCEOC"); disable_irq(di->irq); di->nbr_cceoc_irq_cnt = 0; @@ -3203,13 +3173,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) ret = ab8500_fg_sysfs_init(di); if (ret) { - dev_err(di->dev, "failed to create sysfs entry\n"); + dev_err(dev, "failed to create sysfs entry\n"); goto free_irq; } ret = ab8500_fg_sysfs_psy_create_attrs(di); if (ret) { - dev_err(di->dev, "failed to create FG psy\n"); + dev_err(dev, "failed to create FG psy\n"); |