From c8dd9cce4f3fedf5e333bb8623cb7da6d7e3ea91 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 23 Sep 2014 22:42:15 +0200 Subject: power: gpio-charger: add device tree support Add the ability to parse gpio-charger data from a devicetree node. Signed-off-by: Heiko Stuebner Reviewed-by: Doug Anderson Tested-by: Doug Anderson --- drivers/power/gpio-charger.c | 72 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 7536933..df984ec 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include @@ -69,6 +71,59 @@ static enum power_supply_property gpio_charger_properties[] = { POWER_SUPPLY_PROP_ONLINE, }; +static +struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct gpio_charger_platform_data *pdata; + const char *chargetype; + enum of_gpio_flags flags; + int ret; + + if (!np) + return ERR_PTR(-ENOENT); + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->name = np->name; + + pdata->gpio = of_get_gpio_flags(np, 0, &flags); + if (pdata->gpio < 0) { + if (pdata->gpio != -EPROBE_DEFER) + dev_err(dev, "could not get charger gpio\n"); + return ERR_PTR(pdata->gpio); + } + + pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW); + + pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; + ret = of_property_read_string(np, "charger-type", &chargetype); + if (ret >= 0) { + if (!strncmp("unknown", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; + else if (!strncmp("battery", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_BATTERY; + else if (!strncmp("ups", chargetype, 3)) + pdata->type = POWER_SUPPLY_TYPE_UPS; + else if (!strncmp("mains", chargetype, 5)) + pdata->type = POWER_SUPPLY_TYPE_MAINS; + else if (!strncmp("usb-sdp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB; + else if (!strncmp("usb-dcp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_DCP; + else if (!strncmp("usb-cdp", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_CDP; + else if (!strncmp("usb-aca", chargetype, 7)) + pdata->type = POWER_SUPPLY_TYPE_USB_ACA; + else + dev_warn(dev, "unknown charger type %s\n", chargetype); + } + + return pdata; +} + static int gpio_charger_probe(struct platform_device *pdev) { const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data; @@ -78,8 +133,13 @@ static int gpio_charger_probe(struct platform_device *pdev) int irq; if (!pdata) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; + pdata = gpio_charger_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "No platform data\n"); + return ret; + } } if (!gpio_is_valid(pdata->gpio)) { @@ -103,6 +163,7 @@ static int gpio_charger_probe(struct platform_device *pdev) charger->get_property = gpio_charger_get_property; charger->supplied_to = pdata->supplied_to; charger->num_supplicants = pdata->num_supplicants; + charger->of_node = pdev->dev.of_node; ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); if (ret) { @@ -189,6 +250,12 @@ static int gpio_charger_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, gpio_charger_suspend, gpio_charger_resume); +static const struct of_device_id gpio_charger_match[] = { + { .compatible = "gpio-charger" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpio_charger_match); + static struct platform_driver gpio_charger_driver = { .probe = gpio_charger_probe, .remove = gpio_charger_remove, @@ -196,6 +263,7 @@ static struct platform_driver gpio_charger_driver = { .name = "gpio-charger", .owner = THIS_MODULE, .pm = &gpio_charger_pm_ops, + .of_match_table = gpio_charger_match, }, }; -- cgit v1.1 From b8e64eea41ea71b58e61e35ee347464efd60ca21 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Fri, 26 Sep 2014 11:59:06 +0800 Subject: power: reset: imx-snvs-poweroff: add power off driver for i.mx6 This driver register pm_power_off with snvs power off function. If your boards NOT use PMIC_ON_REQ to turn on/off external pmic, or use other pin to do, please disable the driver in dts, otherwise, your pm_power_off maybe overwrote by this driver. Signed-off-by: Robin Gong Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 9 +++++ drivers/power/reset/Makefile | 1 + drivers/power/reset/imx-snvs-poweroff.c | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 drivers/power/reset/imx-snvs-poweroff.c (limited to 'drivers/power') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index f65ff49..028e765 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -71,6 +71,15 @@ config POWER_RESET_HISI help Reboot support for Hisilicon boards. +config POWER_RESET_IMX + bool "IMX6 power-off driver" + depends on POWER_RESET && SOC_IMX6 + help + This driver support power off external PMIC by PMIC_ON_REQ on i.mx6 + boards.If you want to use other pin to control external power,please + say N here or disable in dts to make sure pm_power_off never be + overwrote wrongly by this driver. + config POWER_RESET_MSM bool "Qualcomm MSM power-off driver" depends on ARCH_QCOM diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 76ce1c5..1d4804d 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o +obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o diff --git a/drivers/power/reset/imx-snvs-poweroff.c b/drivers/power/reset/imx-snvs-poweroff.c new file mode 100644 index 0000000..ad6ce50 --- /dev/null +++ b/drivers/power/reset/imx-snvs-poweroff.c @@ -0,0 +1,66 @@ +/* Power off driver for i.mx6 + * Copyright (c) 2014, FREESCALE CORPORATION. All rights reserved. + * + * based on msm-poweroff.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void __iomem *snvs_base; + +static void do_imx_poweroff(void) +{ + u32 value = readl(snvs_base); + + /* set TOP and DP_EN bit */ + writel(value | 0x60, snvs_base); +} + +static int imx_poweroff_probe(struct platform_device *pdev) +{ + snvs_base = of_iomap(pdev->dev.of_node, 0); + if (!snvs_base) { + dev_err(&pdev->dev, "failed to get memory\n"); + return -ENODEV; + } + + pm_power_off = do_imx_poweroff; + return 0; +} + +static const struct of_device_id of_imx_poweroff_match[] = { + { .compatible = "fsl,sec-v4.0-poweroff", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_imx_poweroff_match); + +static struct platform_driver imx_poweroff_driver = { + .probe = imx_poweroff_probe, + .driver = { + .name = "imx-snvs-poweroff", + .of_match_table = of_match_ptr(of_imx_poweroff_match), + }, +}; + +static int __init imx_poweroff_init(void) +{ + return platform_driver_register(&imx_poweroff_driver); +} +device_initcall(imx_poweroff_init); -- cgit v1.1 From 46c99ac66222aed719f26835eae4946d72880cbe Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:27 -0700 Subject: power/reset: vexpress: Register with kernel restart handler Use the kernel restart handler instead of setting arm_pm_restart directly. This allows for more than one restart handler in the system. Signed-off-by: Guenter Roeck --- drivers/power/reset/vexpress-poweroff.c | 40 ++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 4dc102e2..9dfc9ce 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -12,14 +12,14 @@ */ #include +#include #include #include #include +#include #include #include -#include - static void vexpress_reset_do(struct device *dev, const char *what) { int err = -ENOENT; @@ -43,11 +43,19 @@ static void vexpress_power_off(void) static struct device *vexpress_restart_device; -static void vexpress_restart(enum reboot_mode reboot_mode, const char *cmd) +static int vexpress_restart(struct notifier_block *this, unsigned long mode, + void *cmd) { vexpress_reset_do(vexpress_restart_device, "restart"); + + return NOTIFY_DONE; } +static struct notifier_block vexpress_restart_nb = { + .notifier_call = vexpress_restart, + .priority = 128, +}; + static ssize_t vexpress_reset_active_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -86,12 +94,28 @@ static struct of_device_id vexpress_reset_of_match[] = { {} }; +static int _vexpress_register_restart_handler(struct device *dev) +{ + int err; + + vexpress_restart_device = dev; + err = register_restart_handler(&vexpress_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + return err; + } + device_create_file(dev, &dev_attr_active); + + return 0; +} + static int vexpress_reset_probe(struct platform_device *pdev) { enum vexpress_reset_func func; const struct of_device_id *match = of_match_device(vexpress_reset_of_match, &pdev->dev); struct regmap *regmap; + int ret = 0; if (match) func = (enum vexpress_reset_func)match->data; @@ -110,18 +134,14 @@ static int vexpress_reset_probe(struct platform_device *pdev) break; case FUNC_RESET: if (!vexpress_restart_device) - vexpress_restart_device = &pdev->dev; - arm_pm_restart = vexpress_restart; - device_create_file(&pdev->dev, &dev_attr_active); + ret = _vexpress_register_restart_handler(&pdev->dev); break; case FUNC_REBOOT: - vexpress_restart_device = &pdev->dev; - arm_pm_restart = vexpress_restart; - device_create_file(&pdev->dev, &dev_attr_active); + ret = _vexpress_register_restart_handler(&pdev->dev); break; }; - return 0; + return ret; } static const struct platform_device_id vexpress_reset_id_table[] = { -- cgit v1.1 From ef288f9f656cdf46cb7788b6bb18da1c3b722feb Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:28 -0700 Subject: power/reset: xgene: Return -ENOMEM if out of memory It is customary to return an error code of -ENOMEM if the system is out of memory. Also, in that case, the infrastructure will report an error, so it is unnecessary to report it again. Cc: Loc Ho Signed-off-by: Guenter Roeck --- drivers/power/reset/xgene-reboot.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 6b49be6..6ca4bf9 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -61,10 +61,8 @@ static int xgene_reboot_probe(struct platform_device *pdev) struct xgene_reboot_context *ctx; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - dev_err(&pdev->dev, "out of memory for context\n"); - return -ENODEV; - } + if (!ctx) + return -ENOMEM; ctx->csr = of_iomap(pdev->dev.of_node, 0); if (!ctx->csr) { -- cgit v1.1 From 22ecd65f4067461f0488bc9b1f2c26eb70f69fa5 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:29 -0700 Subject: power/reset: xgene: Drop devm_kfree Calling devm_kfree is unnecessary. Drop it. Cc: Loc Ho Signed-off-by: Guenter Roeck --- drivers/power/reset/xgene-reboot.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 6ca4bf9..c49a3fe 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -66,7 +66,6 @@ static int xgene_reboot_probe(struct platform_device *pdev) ctx->csr = of_iomap(pdev->dev.of_node, 0); if (!ctx->csr) { - devm_kfree(&pdev->dev, ctx); dev_err(&pdev->dev, "can not map resource\n"); return -ENODEV; } -- cgit v1.1 From 43160718d95db9e2336cd787fa8fcad39660b883 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:30 -0700 Subject: power/reset: xgene: Use local variable dev instead of pdev->dev Using a local variable dev to point to the device is simpler then repeatedly dereferencing pdev->dev. Cc: Loc Ho Signed-off-by: Guenter Roeck --- drivers/power/reset/xgene-reboot.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index c49a3fe..94f10ad 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -33,7 +33,7 @@ #include struct xgene_reboot_context { - struct platform_device *pdev; + struct device *dev; void *csr; u32 mask; }; @@ -53,27 +53,28 @@ static void xgene_restart(enum reboot_mode mode, const char *cmd) while (time_before(jiffies, timeout)) cpu_relax(); - dev_emerg(&ctx->pdev->dev, "Unable to restart system\n"); + dev_emerg(ctx->dev, "Unable to restart system\n"); } static int xgene_reboot_probe(struct platform_device *pdev) { struct xgene_reboot_context *ctx; + struct device *dev = &pdev->dev; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; - ctx->csr = of_iomap(pdev->dev.of_node, 0); + ctx->csr = of_iomap(dev->of_node, 0); if (!ctx->csr) { - dev_err(&pdev->dev, "can not map resource\n"); + dev_err(dev, "can not map resource\n"); return -ENODEV; } - if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask)) + if (of_property_read_u32(dev->of_node, "mask", &ctx->mask)) ctx->mask = 0xFFFFFFFF; - ctx->pdev = pdev; + ctx->dev = dev; arm_pm_restart = xgene_restart; xgene_restart_ctx = ctx; -- cgit v1.1 From 745e19764a0cff55a55010cfabe7e9ff77fa72a5 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:31 -0700 Subject: power/reset: xgene: Use mdelay instead of jiffies based timeout jiffies are not running at this stage of system shutdown, meaning an error in the reset function would never be reported. Replace with mdelay(). Cc: Loc Ho Signed-off-by: Guenter Roeck --- drivers/power/reset/xgene-reboot.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 94f10ad..9da341d 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -24,6 +24,7 @@ * For system shutdown, this is board specify. If a board designer * implements GPIO shutdown, use the gpio-poweroff.c driver. */ +#include #include #include #include @@ -43,15 +44,12 @@ static struct xgene_reboot_context *xgene_restart_ctx; static void xgene_restart(enum reboot_mode mode, const char *cmd) { struct xgene_reboot_context *ctx = xgene_restart_ctx; - unsigned long timeout; /* Issue the reboot */ if (ctx) writel(ctx->mask, ctx->csr); - timeout = jiffies + HZ; - while (time_before(jiffies, timeout)) - cpu_relax(); + mdelay(1000); dev_emerg(ctx->dev, "Unable to restart system\n"); } -- cgit v1.1 From 8f57f2310f6b5f787a29e4eb440afd8b3f6b2554 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:32 -0700 Subject: power/reset: xgene: Register with kernel restart handler Register with kernel restart handler instead of setting arm_pm_restart directly. This patch also addresses the following compile warning. drivers/power/reset/xgene-reboot.c: In function 'xgene_reboot_probe': drivers/power/reset/xgene-reboot.c:77:17: warning: assignment from incompatible pointer type [enabled by default] The warning was due to a mismatch between the type of arm_pm_restart and the restart function. Cc: Loc Ho Signed-off-by: Guenter Roeck --- drivers/power/reset/xgene-reboot.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 9da341d..b0e5002 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -26,38 +26,43 @@ */ #include #include +#include #include #include #include +#include #include #include -#include struct xgene_reboot_context { struct device *dev; void *csr; u32 mask; + struct notifier_block restart_handler; }; -static struct xgene_reboot_context *xgene_restart_ctx; - -static void xgene_restart(enum reboot_mode mode, const char *cmd) +static int xgene_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { - struct xgene_reboot_context *ctx = xgene_restart_ctx; + struct xgene_reboot_context *ctx = + container_of(this, struct xgene_reboot_context, + restart_handler); /* Issue the reboot */ - if (ctx) - writel(ctx->mask, ctx->csr); + writel(ctx->mask, ctx->csr); mdelay(1000); dev_emerg(ctx->dev, "Unable to restart system\n"); + + return NOTIFY_DONE; } static int xgene_reboot_probe(struct platform_device *pdev) { struct xgene_reboot_context *ctx; struct device *dev = &pdev->dev; + int err; ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -73,10 +78,13 @@ static int xgene_reboot_probe(struct platform_device *pdev) ctx->mask = 0xFFFFFFFF; ctx->dev = dev; - arm_pm_restart = xgene_restart; - xgene_restart_ctx = ctx; + ctx->restart_handler.notifier_call = xgene_restart_handler; + ctx->restart_handler.priority = 128; + err = register_restart_handler(&ctx->restart_handler); + if (err) + dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return 0; + return err; } static struct of_device_id xgene_reboot_of_match[] = { -- cgit v1.1 From fcf01c51f0f5565a184638b7d055e590aad6c0f8 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:33 -0700 Subject: power/reset: axxia: Register with kernel restart handler Register with kernel restart handler instead of setting arm_pm_restart directly. Cc: Anders Berg Tested-by: Anders Berg Signed-off-by: Guenter Roeck --- drivers/power/reset/axxia-reset.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c index 3b1f8d6..4e4cd1c 100644 --- a/drivers/power/reset/axxia-reset.c +++ b/drivers/power/reset/axxia-reset.c @@ -19,14 +19,12 @@ #include #include #include +#include #include #include #include #include -#include - - #define SC_CRIT_WRITE_KEY 0x1000 #define SC_LATCH_ON_RESET 0x1004 #define SC_RESET_CONTROL 0x1008 @@ -39,7 +37,8 @@ static struct regmap *syscon; -static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) +static int axxia_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { /* Access Key (0xab) */ regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab); @@ -50,11 +49,19 @@ static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) /* Assert chip reset */ regmap_update_bits(syscon, SC_RESET_CONTROL, RSTCTL_RST_CHIP, RSTCTL_RST_CHIP); + + 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; + int err; syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); if (IS_ERR(syscon)) { @@ -62,9 +69,11 @@ static int axxia_reset_probe(struct platform_device *pdev) return PTR_ERR(syscon); } - arm_pm_restart = do_axxia_restart; + err = register_restart_handler(&axxia_restart_nb); + if (err) + dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return 0; + return err; } static const struct of_device_id of_axxia_reset_match[] = { -- cgit v1.1 From f59a42d4e177564b9892112af7a4e73d0c91f9b4 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:34 -0700 Subject: power/reset: keystone: Register with kernel restart handler Register with kernel restart handler instead of setting arm_pm_restart directly. Move notifier registration to the end of the probe function to avoid having to implement error handling. Cc: Ivan Khoronzhuk Cc: Santosh Shilimkar Acked-by: Santosh Shilimkar Tested-by: Ivan Khoronzhuk Signed-off-by: Guenter Roeck --- drivers/power/reset/keystone-reset.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/keystone-reset.c b/drivers/power/reset/keystone-reset.c index 408a18fd..4b6b12e 100644 --- a/drivers/power/reset/keystone-reset.c +++ b/drivers/power/reset/keystone-reset.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include #include @@ -52,7 +52,8 @@ static inline int rsctrl_enable_rspll_write(void) RSCTRL_KEY_MASK, RSCTRL_KEY); } -static void rsctrl_restart(enum reboot_mode mode, const char *cmd) +static int rsctrl_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { /* enable write access to RSTCTRL */ rsctrl_enable_rspll_write(); @@ -60,8 +61,15 @@ static void rsctrl_restart(enum reboot_mode mode, const char *cmd) /* reset the SOC */ regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG, RSCTRL_RESET_MASK, 0); + + return NOTIFY_DONE; } +static struct notifier_block rsctrl_restart_nb = { + .notifier_call = rsctrl_restart_handler, + .priority = 128, +}; + static struct of_device_id rsctrl_of_match[] = { {.compatible = "ti,keystone-reset", }, {}, @@ -114,8 +122,6 @@ static int rsctrl_probe(struct platform_device *pdev) if (ret) return ret; - arm_pm_restart = rsctrl_restart; - /* disable a reset isolation for all module clocks */ ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0); if (ret) @@ -147,7 +153,11 @@ static int rsctrl_probe(struct platform_device *pdev) return ret; } - return 0; + ret = register_restart_handler(&rsctrl_restart_nb); + if (ret) + dev_err(dev, "cannot register restart handler (err=%d)\n", ret); + + return ret; } static struct platform_driver rsctrl_driver = { -- cgit v1.1 From 6724534c79ead70e310616d0e4380bb9fbb67c15 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:35 -0700 Subject: power/reset: hisi: Register with kernel restart handler Register with kernel restart handler instead of setting arm_pm_restart directly. Cc: Haojian Zhuang Signed-off-by: Guenter Roeck --- drivers/power/reset/hisi-reboot.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c index 0c91d02..5385460 100644 --- a/drivers/power/reset/hisi-reboot.c +++ b/drivers/power/reset/hisi-reboot.c @@ -14,27 +14,36 @@ #include #include #include +#include #include #include #include #include -#include static void __iomem *base; static u32 reboot_offset; -static void hisi_restart(enum reboot_mode mode, const char *cmd) +static int hisi_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { writel_relaxed(0xdeadbeef, base + reboot_offset); while (1) cpu_do_idle(); + + return NOTIFY_DONE; } +static struct notifier_block hisi_restart_nb = { + .notifier_call = hisi_restart_handler, + .priority = 128, +}; + static int hisi_reboot_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + int err; base = of_iomap(np, 0); if (!base) { @@ -47,9 +56,12 @@ static int hisi_reboot_probe(struct platform_device *pdev) return -EINVAL; } - arm_pm_restart = hisi_restart; + err = register_restart_handler(&hisi_restart_nb); + if (err) + dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n", + err); - return 0; + return err; } static struct of_device_id hisi_reboot_of_match[] = { -- cgit v1.1 From 6136c41ae9c7af4bd89d845bda5dd84b9c9f3138 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 30 Sep 2014 10:48:36 -0700 Subject: power/reset: brcmstb: Register with kernel restart handler Register with kernel restart handler instead of setting arm_pm_restart directly. Cc: Marc Carino Cc: Brian Norris Signed-off-by: Guenter Roeck --- drivers/power/reset/brcmstb-reboot.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c index 3f23692..1ad5629 100644 --- a/drivers/power/reset/brcmstb-reboot.c +++ b/drivers/power/reset/brcmstb-reboot.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +27,6 @@ #include #include -#include - #define RESET_SOURCE_ENABLE_REG 1 #define SW_MASTER_RESET_REG 2 @@ -35,7 +34,8 @@ static struct regmap *regmap; static u32 rst_src_en; static u32 sw_mstr_rst; -static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) +static int brcmstb_restart_handler(struct notifier_block *this, + unsigned long mode, void *cmd) { int rc; u32 tmp; @@ -43,31 +43,38 @@ static void brcmstb_reboot(enum reboot_mode mode, const char *cmd) rc = regmap_write(regmap, rst_src_en, 1); if (rc) { pr_err("failed to write rst_src_en (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_read(regmap, rst_src_en, &tmp); if (rc) { pr_err("failed to read rst_src_en (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_write(regmap, sw_mstr_rst, 1); if (rc) { pr_err("failed to write sw_mstr_rst (%d)\n", rc); - return; + return NOTIFY_DONE; } rc = regmap_read(regmap, sw_mstr_rst, &tmp); if (rc) { pr_err("failed to read sw_mstr_rst (%d)\n", rc); - return; + return NOTIFY_DONE; } while (1) ; + + return NOTIFY_DONE; } +static struct notifier_block brcmstb_restart_nb = { + .notifier_call = brcmstb_restart_handler, + .priority = 128, +}; + static int brcmstb_reboot_probe(struct platform_device *pdev) { int rc; @@ -93,9 +100,12 @@ static int brcmstb_reboot_probe(struct platform_device *pdev) return -EINVAL; } - arm_pm_restart = brcmstb_reboot; + rc = register_restart_handler(&brcmstb_restart_nb); + if (rc) + dev_err(&pdev->dev, + "cannot register restart handler (err=%d)\n", rc); - return 0; + return rc; } static const struct of_device_id of_match[] = { -- cgit v1.1 From 99a79565e6db676bca8c7aeddd9fec44e730965e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 9 Oct 2014 19:50:26 -0300 Subject: power: ds2782_battery: Simplify the PM hooks The SIMPLE_DEV_PM_OPS() macro already takes care of the CONFIG_PM_SLEEP=n case, so we can simplify the code a little bit. Signed-off-by: Fabio Estevam Signed-off-by: Sebastian Reichel --- drivers/power/ds2782_battery.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 041f9b6..3969488 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -351,13 +351,9 @@ static int ds278x_resume(struct device *dev) schedule_delayed_work(&info->bat_work, DS278x_DELAY); return 0; } +#endif /* CONFIG_PM_SLEEP */ static SIMPLE_DEV_PM_OPS(ds278x_battery_pm_ops, ds278x_suspend, ds278x_resume); -#define DS278X_BATTERY_PM_OPS (&ds278x_battery_pm_ops) - -#else -#define DS278X_BATTERY_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ enum ds278x_num_id { DS2782 = 0, @@ -460,7 +456,7 @@ MODULE_DEVICE_TABLE(i2c, ds278x_id); static struct i2c_driver ds278x_battery_driver = { .driver = { .name = "ds2782-battery", - .pm = DS278X_BATTERY_PM_OPS, + .pm = &ds278x_battery_pm_ops, }, .probe = ds278x_battery_probe, .remove = ds278x_battery_remove, -- cgit v1.1 From b81180b3fd4814af0459a5b6aeb1ee188fea98dc Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 18:11:58 +0100 Subject: power: reset: adjust priority of simple syscon reboot driver Currently, all restart handler use the priority 128, including watchdogs. Probably most SoC have a watchdog, and some of them register it also as a restart handler. But if a SoC specifies a dedicated reboot capability using this syscon driver, this is usually the preferred reboot method. Hence, raise the priority of this driver to 192. Signed-off-by: Stefan Agner Reviewed-by: Guenter Roeck Acked-by: Mark Rutland Signed-off-by: Sebastian Reichel --- drivers/power/reset/syscon-reboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/power') diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index 815b901..c4049f4 100644 --- a/drivers/power/reset/syscon-reboot.c +++ b/drivers/power/reset/syscon-reboot.c @@ -68,7 +68,7 @@ static int syscon_reboot_probe(struct platform_device *pdev) return -EINVAL; ctx->restart_handler.notifier_call = syscon_restart_handle; - ctx->restart_handler.priority = 128; + ctx->restart_handler.priority = 192; err = register_restart_handler(&ctx->restart_handler); if (err) dev_err(dev, "can't register restart notifier (err=%d)\n", err); -- cgit v1.1