From 6647156c00cc70c1e93161c3cf178071b3381bbb Mon Sep 17 00:00:00 2001 From: René Moll Date: Fri, 8 Aug 2014 13:12:17 +0000 Subject: power: reset: add LTC2952 poweroff driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a driver for the LTC2952, an external power control chip, which signals the OS to shut down. Additionally this driver lets the kernel power down the board. Signed-off-by: René Moll Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/power/reset/Kconfig') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index ca41523bbeb..76156394d68 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -51,6 +51,13 @@ config POWER_RESET_MSM help Power off and restart support for Qualcomm boards. +config POWER_RESET_LTC2952 + bool "LTC2952 PowerPath power-off driver" + depends on OF_GPIO && POWER_RESET + help + This driver supports an external powerdown trigger and board power + down via the LTC2952. Bindings are made in the device tree. + config POWER_RESET_QNAP bool "QNAP power-off driver" depends on OF_GPIO && POWER_RESET && PLAT_ORION -- cgit v1.2.3-70-g09d2 From f0745f3696e88b4055c6229e1306a78fbe503066 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 22 Jul 2014 15:52:28 +0100 Subject: power: reset: Add restart functionality for STiH41x platforms This driver adds the restart functionality for STiH415 and STiH416 platforms from STMicroelectronics. This driver registers an arm_pm_restart function to reset the platform. Signed-off-by: Christophe Kerello Signed-off-by: Lee Jones Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 6 ++ drivers/power/reset/Makefile | 1 + drivers/power/reset/st-poweroff.c | 151 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 drivers/power/reset/st-poweroff.c (limited to 'drivers/power/reset/Kconfig') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 76156394d68..88603b6990e 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -82,6 +82,12 @@ config POWER_RESET_SUN6I help Reboot support for the Allwinner A31 SoCs. +config POWER_RESET_ST + bool "ST restart power-off driver" + depends on POWER_RESET && ARCH_STI + help + Power off and reset support for STMicroelectronics boards. + config POWER_RESET_VEXPRESS bool "ARM Versatile Express power-off and reset driver" depends on ARM || ARM64 diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 5d943528c8f..06f106b6cfc 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o obj-$(CONFIG_POWER_RESET_SUN6I) += sun6i-reboot.o +obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o diff --git a/drivers/power/reset/st-poweroff.c b/drivers/power/reset/st-poweroff.c new file mode 100644 index 00000000000..a0acf25ee2a --- /dev/null +++ b/drivers/power/reset/st-poweroff.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 STMicroelectronics + * + * Power off Restart driver, used in STMicroelectronics devices. + * + * Author: Christophe Kerello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include + +struct reset_syscfg { + struct regmap *regmap; + /* syscfg used for reset */ + unsigned int offset_rst; + unsigned int mask_rst; + /* syscfg used for unmask the reset */ + unsigned int offset_rst_msk; + unsigned int mask_rst_msk; +}; + +/* STiH415 */ +#define STIH415_SYSCFG_11 0x2c +#define STIH415_SYSCFG_15 0x3c + +static struct reset_syscfg stih415_reset = { + .offset_rst = STIH415_SYSCFG_11, + .mask_rst = BIT(0), + .offset_rst_msk = STIH415_SYSCFG_15, + .mask_rst_msk = BIT(0) +}; + +/* STiH416 */ +#define STIH416_SYSCFG_500 0x7d0 +#define STIH416_SYSCFG_504 0x7e0 + +static struct reset_syscfg stih416_reset = { + .offset_rst = STIH416_SYSCFG_500, + .mask_rst = BIT(0), + .offset_rst_msk = STIH416_SYSCFG_504, + .mask_rst_msk = BIT(0) +}; + +/* STiH407 */ +#define STIH407_SYSCFG_4000 0x0 +#define STIH407_SYSCFG_4008 0x20 + +static struct reset_syscfg stih407_reset = { + .offset_rst = STIH407_SYSCFG_4000, + .mask_rst = BIT(0), + .offset_rst_msk = STIH407_SYSCFG_4008, + .mask_rst_msk = BIT(0) +}; + +/* STiD127 */ +#define STID127_SYSCFG_700 0x0 +#define STID127_SYSCFG_773 0x124 + +static struct reset_syscfg stid127_reset = { + .offset_rst = STID127_SYSCFG_773, + .mask_rst = BIT(0), + .offset_rst_msk = STID127_SYSCFG_700, + .mask_rst_msk = BIT(8) +}; + +static struct reset_syscfg *st_restart_syscfg; + +static void st_restart(enum reboot_mode reboot_mode, const char *cmd) +{ + /* reset syscfg updated */ + regmap_update_bits(st_restart_syscfg->regmap, + st_restart_syscfg->offset_rst, + st_restart_syscfg->mask_rst, + 0); + + /* unmask the reset */ + regmap_update_bits(st_restart_syscfg->regmap, + st_restart_syscfg->offset_rst_msk, + st_restart_syscfg->mask_rst_msk, + 0); +} + +static struct of_device_id st_reset_of_match[] = { + { + .compatible = "st,stih415-restart", + .data = (void *)&stih415_reset, + }, { + .compatible = "st,stih416-restart", + .data = (void *)&stih416_reset, + }, { + .compatible = "st,stih407-restart", + .data = (void *)&stih407_reset, + }, { + .compatible = "st,stid127-restart", + .data = (void *)&stid127_reset, + }, + {} +}; + +static int st_reset_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + + match = of_match_device(st_reset_of_match, dev); + if (!match) + return -ENODEV; + + st_restart_syscfg = (struct reset_syscfg *)match->data; + + st_restart_syscfg->regmap = + syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(st_restart_syscfg->regmap)) { + dev_err(dev, "No syscfg phandle specified\n"); + return PTR_ERR(st_restart_syscfg->regmap); + } + + arm_pm_restart = st_restart; + + return 0; +} + +static struct platform_driver st_reset_driver = { + .probe = st_reset_probe, + .driver = { + .name = "st_reset", + .of_match_table = st_reset_of_match, + }, +}; + +static int __init st_reset_init(void) +{ + return platform_driver_register(&st_reset_driver); +} + +device_initcall(st_reset_init); + +MODULE_AUTHOR("Christophe Kerello "); +MODULE_DESCRIPTION("STMicroelectronics Power off Restart driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-70-g09d2 From 371bb20d6927f204ef5a7887ecddb06b2501c0d9 Mon Sep 17 00:00:00 2001 From: David Riley Date: Wed, 27 Aug 2014 12:23:51 -0700 Subject: power: Add simple gpio-restart driver This driver registers a restart handler to set a GPIO line high/low to reset a board based on devicetree bindings. Signed-off-by: David Riley Reviewed-by: Guenter Roeck Signed-off-by: Sebastian Reichel --- .../devicetree/bindings/gpio/gpio-restart.txt | 54 ++++++++ drivers/power/reset/Kconfig | 8 ++ drivers/power/reset/Makefile | 1 + drivers/power/reset/gpio-restart.c | 149 +++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-restart.txt create mode 100644 drivers/power/reset/gpio-restart.c (limited to 'drivers/power/reset/Kconfig') diff --git a/Documentation/devicetree/bindings/gpio/gpio-restart.txt b/Documentation/devicetree/bindings/gpio/gpio-restart.txt new file mode 100644 index 00000000000..af3701bc15c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-restart.txt @@ -0,0 +1,54 @@ +Drive a GPIO line that can be used to restart the system from a restart +handler. + +This binding supports level and edge triggered reset. At driver load +time, the driver will request the given gpio line and install a restart +handler. If the optional properties 'open-source' is not found, the GPIO line +will be driven in the inactive state. Otherwise its not driven until +the restart is initiated. + +When the system is restarted, the restart handler will be invoked in +priority order. The gpio is configured as an output, and driven active, +triggering a level triggered reset condition. This will also cause an +inactive->active edge condition, triggering positive edge triggered +reset. After a delay specified by active-delay, the GPIO is set to +inactive, thus causing an active->inactive edge, triggering negative edge +triggered reset. After a delay specified by inactive-delay, the GPIO +is driven active again. After a delay specified by wait-delay, the +restart handler completes allowing other restart handlers to be attempted. + +Required properties: +- compatible : should be "gpio-restart". +- gpios : The GPIO to set high/low, see "gpios property" in + Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be + low to reset the board set it to "Active Low", otherwise set + gpio to "Active High". + +Optional properties: +- open-source : Treat the GPIO as being open source and defer driving + it to when the restart is initiated. If this optional property is not + specified, the GPIO is initialized as an output in its inactive state. +- priority : A priority ranging from 0 to 255 (default 128) according to + the following guidelines: + 0: Restart handler of last resort, with limited restart + capabilities + 128: Default restart handler; use if no other restart handler is + expected to be available, and/or if restart functionality is + sufficient to restart the entire system + 255: Highest priority restart handler, will preempt all other + restart handlers +- active-delay: Delay (default 100) to wait after driving gpio active [ms] +- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms] +- wait-delay: Delay (default 3000) to wait after completing restart + sequence [ms] + +Examples: + +gpio-restart { + compatible = "gpio-restart"; + gpios = <&gpio 4 0>; + priority = <128>; + active-delay = <100>; + inactive-delay = <100>; + wait-delay = <3000>; +}; diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 88603b6990e..a178e9c50a2 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -39,6 +39,14 @@ config POWER_RESET_GPIO If your board needs a GPIO high/low to power down, say Y and create a binding in your devicetree. +config POWER_RESET_GPIO_RESTART + bool "GPIO restart driver" + depends on OF_GPIO && POWER_RESET + help + This driver supports restarting your board via a GPIO line. + If your board needs a GPIO high/low to restart, say Y and + create a binding in your devicetree. + config POWER_RESET_HISI bool "Hisilicon power-off driver" depends on POWER_RESET && ARCH_HISI diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 06f106b6cfc..ab8cd348a09 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 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_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c new file mode 100644 index 00000000000..a76829b3f1c --- /dev/null +++ b/drivers/power/reset/gpio-restart.c @@ -0,0 +1,149 @@ +/* + * Toggles a GPIO pin to restart a device + * + * Copyright (C) 2014 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + * Based on the gpio-poweroff driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct gpio_restart { + struct gpio_desc *reset_gpio; + struct notifier_block restart_handler; + u32 active_delay_ms; + u32 inactive_delay_ms; + u32 wait_delay_ms; +}; + +static int gpio_restart_notify(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct gpio_restart *gpio_restart = + container_of(this, struct gpio_restart, restart_handler); + + /* drive it active, also inactive->active edge */ + gpiod_direction_output(gpio_restart->reset_gpio, 1); + mdelay(gpio_restart->active_delay_ms); + + /* drive inactive, also active->inactive edge */ + gpiod_set_value(gpio_restart->reset_gpio, 0); + mdelay(gpio_restart->inactive_delay_ms); + + /* drive it active, also inactive->active edge */ + gpiod_set_value(gpio_restart->reset_gpio, 1); + + /* give it some time */ + mdelay(gpio_restart->wait_delay_ms); + + WARN_ON(1); + + return NOTIFY_DONE; +} + +static int gpio_restart_probe(struct platform_device *pdev) +{ + struct gpio_restart *gpio_restart; + bool open_source = false; + u32 property; + int ret; + + gpio_restart = devm_kzalloc(&pdev->dev, sizeof(*gpio_restart), + GFP_KERNEL); + if (!gpio_restart) + return -ENOMEM; + + open_source = of_property_read_bool(pdev->dev.of_node, "open-source"); + + gpio_restart->reset_gpio = devm_gpiod_get(&pdev->dev, NULL, + open_source ? GPIOD_IN : GPIOD_OUT_LOW); + if (IS_ERR(gpio_restart->reset_gpio)) { + dev_err(&pdev->dev, "Could net get reset GPIO\n"); + return PTR_ERR(gpio_restart->reset_gpio); + } + + gpio_restart->restart_handler.notifier_call = gpio_restart_notify; + gpio_restart->restart_handler.priority = 128; + gpio_restart->active_delay_ms = 100; + gpio_restart->inactive_delay_ms = 100; + gpio_restart->wait_delay_ms = 3000; + + ret = of_property_read_u32(pdev->dev.of_node, "priority", &property); + if (!ret) { + if (property > 255) + dev_err(&pdev->dev, "Invalid priority property: %u\n", + property); + else + gpio_restart->restart_handler.priority = property; + } + + of_property_read_u32(pdev->dev.of_node, "active-delay", + &gpio_restart->active_delay_ms); + of_property_read_u32(pdev->dev.of_node, "inactive-delay", + &gpio_restart->inactive_delay_ms); + of_property_read_u32(pdev->dev.of_node, "wait-delay", + &gpio_restart->wait_delay_ms); + + platform_set_drvdata(pdev, gpio_restart); + + ret = register_restart_handler(&gpio_restart->restart_handler); + if (ret) { + dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n", + __func__, ret); + return -ENODEV; + } + + return 0; +} + +static int gpio_restart_remove(struct platform_device *pdev) +{ + struct gpio_restart *gpio_restart = platform_get_drvdata(pdev); + int ret; + + ret = unregister_restart_handler(&gpio_restart->restart_handler); + if (ret) { + dev_err(&pdev->dev, + "%s: cannot unregister restart handler, %d\n", + __func__, ret); + return -ENODEV; + } + + return 0; +} + +static const struct of_device_id of_gpio_restart_match[] = { + { .compatible = "gpio-restart", }, + {}, +}; + +static struct platform_driver gpio_restart_driver = { + .probe = gpio_restart_probe, + .remove = gpio_restart_remove, + .driver = { + .name = "restart-gpio", + .owner = THIS_MODULE, + .of_match_table = of_gpio_restart_match, + }, +}; + +module_platform_driver(gpio_restart_driver); + +MODULE_AUTHOR("David Riley "); +MODULE_DESCRIPTION("GPIO restart driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From 09fb07bcaf529a21612fbebd1297d8c5dd1abf1b Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Tue, 30 Sep 2014 16:25:03 -0700 Subject: power: reset: Add generic SYSCON register mapped reset Add a generic SYSCON register mapped reset mechanism. Signed-off-by: Feng Kan Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 5 ++ drivers/power/reset/Makefile | 1 + drivers/power/reset/syscon-reboot.c | 96 +++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 drivers/power/reset/syscon-reboot.c (limited to 'drivers/power/reset/Kconfig') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index a178e9c50a2..addb26afae5 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -118,3 +118,8 @@ config POWER_RESET_KEYSTONE help Reboot support for the KEYSTONE SoCs. +config POWER_RESET_SYSCON + bool "Generic SYSCON regmap reset driver" + depends on POWER_RESET && MFD_SYSCON && OF + help + Reboot support for generic SYSCON mapped register reset. diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index ab8cd348a09..61ead277333 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o +obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c new file mode 100644 index 00000000000..948e0ee32a4 --- /dev/null +++ b/drivers/power/reset/syscon-reboot.c @@ -0,0 +1,96 @@ +/* + * Generic Syscon Reboot Driver + * + * Copyright (c) 2013, Applied Micro Circuits Corporation + * Author: Feng Kan + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + +struct syscon_reboot_context { + struct regmap *map; + u32 offset; + u32 mask; + struct notifier_block restart_handler; +}; + +static struct syscon_reboot_context *syscon_reboot_ctx; + +static int syscon_restart_handle(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct syscon_reboot_context *ctx = syscon_reboot_ctx; + unsigned long timeout; + + /* Issue the reboot */ + if (ctx->map) + regmap_write(ctx->map, ctx->offset, ctx->mask); + + timeout = jiffies + HZ; + while (time_before(jiffies, timeout)) + cpu_relax(); + + pr_emerg("Unable to restart system\n"); + return NOTIFY_DONE; +} + +static int syscon_reboot_probe(struct platform_device *pdev) +{ + struct syscon_reboot_context *ctx; + struct device *dev = &pdev->dev; + int err; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap"); + if (IS_ERR(ctx->map)) + return PTR_ERR(ctx->map); + + if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset)) + return -EINVAL; + + if (of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask)) + return -EINVAL; + + ctx->restart_handler.notifier_call = syscon_restart_handle; + ctx->restart_handler.priority = 128; + err = register_restart_handler(&ctx->restart_handler); + if (err) + dev_err(dev, "can't register restart notifier (err=%d)\n", err); + + syscon_reboot_ctx = ctx; + + return 0; +} + +static struct of_device_id syscon_reboot_of_match[] = { + { .compatible = "syscon-reboot" }, + {} +}; + +static struct platform_driver syscon_reboot_driver = { + .probe = syscon_reboot_probe, + .driver = { + .name = "syscon-reboot", + .of_match_table = syscon_reboot_of_match, + }, +}; +module_platform_driver(syscon_reboot_driver); -- cgit v1.2.3-70-g09d2 From afaebbdbd48ada5ead707d6a90ce4b604e1d77d4 Mon Sep 17 00:00:00 2001 From: Feng Kan Date: Thu, 2 Oct 2014 11:24:15 -0700 Subject: power: reset: corrections for simple syscon reboot driver This patch is to fix some bugs in reboot driver. Which includes auto selection of the MFD_SYSCON for the driver, use of container to locate restart handler, correction of the count down failure timer and ordering of the header file. Signed-off-by: Feng Kan Reviewed-by: Guenter Roeck [ sre: return err instead of 0 in syscon_reboot_probe() ] Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 3 ++- drivers/power/reset/syscon-reboot.c | 27 +++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers/power/reset/Kconfig') diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index addb26afae5..3b451e162a9 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -120,6 +120,7 @@ config POWER_RESET_KEYSTONE config POWER_RESET_SYSCON bool "Generic SYSCON regmap reset driver" - depends on POWER_RESET && MFD_SYSCON && OF + depends on POWER_RESET && OF + select MFD_SYSCON help Reboot support for generic SYSCON mapped register reset. diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index 948e0ee32a4..815b901822c 100644 --- a/drivers/power/reset/syscon-reboot.c +++ b/drivers/power/reset/syscon-reboot.c @@ -14,14 +14,15 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#include #include -#include -#include -#include #include #include -#include +#include +#include +#include #include +#include struct syscon_reboot_context { struct regmap *map; @@ -30,21 +31,17 @@ struct syscon_reboot_context { struct notifier_block restart_handler; }; -static struct syscon_reboot_context *syscon_reboot_ctx; - static int syscon_restart_handle(struct notifier_block *this, unsigned long mode, void *cmd) { - struct syscon_reboot_context *ctx = syscon_reboot_ctx; - unsigned long timeout; + struct syscon_reboot_context *ctx = + container_of(this, struct syscon_reboot_context, + restart_handler); /* Issue the reboot */ - if (ctx->map) - regmap_write(ctx->map, ctx->offset, ctx->mask); + regmap_write(ctx->map, ctx->offset, ctx->mask); - timeout = jiffies + HZ; - while (time_before(jiffies, timeout)) - cpu_relax(); + mdelay(1000); pr_emerg("Unable to restart system\n"); return NOTIFY_DONE; @@ -76,9 +73,7 @@ static int syscon_reboot_probe(struct platform_device *pdev) if (err) dev_err(dev, "can't register restart notifier (err=%d)\n", err); - syscon_reboot_ctx = ctx; - - return 0; + return err; } static struct of_device_id syscon_reboot_of_match[] = { -- cgit v1.2.3-70-g09d2