This is a straight port from Linux v5.11. Signed-off-by: Ahmad Fatoum <ahmad@xxxxxx> --- drivers/power/reset/Kconfig | 8 +++ drivers/power/reset/Makefile | 1 + drivers/power/reset/gpio-restart.c | 99 ++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 drivers/power/reset/gpio-restart.c diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index cadcc0b13f2f..dec1482ccd0c 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -36,3 +36,11 @@ config POWER_RESET_GPIO This driver supports turning off your board via a GPIO line. 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 + 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. diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 438c85970028..33d29d2d9546 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o +obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c new file mode 100644 index 000000000000..72c690a3cf4c --- /dev/null +++ b/drivers/power/reset/gpio-restart.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Toggles a GPIO pin to restart a device + * + * Copyright (C) 2014 Google, Inc. + * + * Based on the gpio-poweroff driver. + */ +#include <common.h> +#include <driver.h> +#include <restart.h> +#include <gpiod.h> + +struct gpio_restart { + int reset_gpio; + struct restart_handler restart_handler; + u32 active_delay_ms; + u32 inactive_delay_ms; + u32 wait_delay_ms; +}; + +static void __noreturn gpio_restart_handle(struct restart_handler *this) +{ + struct gpio_restart *gpio_restart = + container_of(this, struct gpio_restart, restart_handler); + + /* drive it active, also inactive->active edge */ + gpio_direction_active(gpio_restart->reset_gpio, true); + mdelay(gpio_restart->active_delay_ms); + + /* drive inactive, also active->inactive edge */ + gpio_set_active(gpio_restart->reset_gpio, false); + mdelay(gpio_restart->inactive_delay_ms); + + /* drive it active, also inactive->active edge */ + gpio_set_active(gpio_restart->reset_gpio, true); + + /* give it some time */ + mdelay(gpio_restart->wait_delay_ms); + + mdelay(1000); + + panic("Unable to restart system\n"); +} + +static int gpio_restart_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + struct gpio_restart *gpio_restart; + bool open_source = false; + u32 property; + int ret; + + gpio_restart = xzalloc(sizeof(*gpio_restart)); + + open_source = of_property_read_bool(np, "open-source"); + + gpio_restart->reset_gpio = gpiod_get(dev, NULL, + open_source ? GPIOD_IN : GPIOD_OUT_LOW); + ret = gpio_restart->reset_gpio; + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Could not get reset GPIO\n"); + return ret; + } + + gpio_restart->restart_handler.restart = gpio_restart_handle; + gpio_restart->restart_handler.name = "gpio-restart"; + gpio_restart->restart_handler.priority = 129; + gpio_restart->active_delay_ms = 100; + gpio_restart->inactive_delay_ms = 100; + gpio_restart->wait_delay_ms = 3000; + + ret = of_property_read_u32(dev->device_node, "priority", &property); + if (!ret) + gpio_restart->restart_handler.priority = property; + + of_property_read_u32(np, "active-delay", &gpio_restart->active_delay_ms); + of_property_read_u32(np, "inactive-delay", &gpio_restart->inactive_delay_ms); + of_property_read_u32(np, "wait-delay", &gpio_restart->wait_delay_ms); + + return restart_handler_register(&gpio_restart->restart_handler); +} + +static const struct of_device_id of_gpio_restart_match[] = { + { .compatible = "gpio-restart", }, + {}, +}; + +static struct driver_d gpio_restart_driver = { + .name = "restart-gpio", + .of_compatible = of_gpio_restart_match, + .probe = gpio_restart_probe, +}; +device_platform_driver(gpio_restart_driver); + +MODULE_AUTHOR("David Riley <davidriley@xxxxxxxxxxxx>"); +MODULE_DESCRIPTION("GPIO restart driver"); +MODULE_LICENSE("GPL"); -- 2.30.0 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox