On Sat, 10 Apr 2021 at 12:37, Ahmad Fatoum <ahmad@xxxxxx> wrote: > > This is a straight port from Linux v5.11. > > Signed-off-by: Ahmad Fatoum <ahmad@xxxxxx> Tested-by: Lars Pedersen <lapeddk@xxxxxxxxx> Tested on imx7-tqma7 platform. > --- > 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 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox