diff options
author | Ahmad Fatoum <ahmad@a3f.at> | 2021-04-10 12:35:09 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-04-13 07:35:16 +0200 |
commit | f20401261d3ca47cb15d6441f6731c9caec37d67 (patch) | |
tree | 9aaa50077e1082cb0fa9acc309f7f1e9edf026b9 /drivers/power | |
parent | 65da15c116264b6f9dea5738c851ef008fc39449 (diff) | |
download | barebox-f20401261d3ca47cb15d6441f6731c9caec37d67.tar.gz |
power: reset: add GPIO poweroff driver
This is a straight port from Linux v5.11.
Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
Link: https://lore.pengutronix.de/20210410103511.2073504-3-ahmad@a3f.at
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/reset/Kconfig | 8 | ||||
-rw-r--r-- | drivers/power/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/reset/gpio-poweroff.c | 93 |
3 files changed, 102 insertions, 0 deletions
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index e60037a6e6..cadcc0b13f 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -28,3 +28,11 @@ config POWER_RESET_SYSCON_POWEROFF select MFD_SYSCON help Poweroff support for generic SYSCON mapped register poweroff. + +config POWER_RESET_GPIO + bool "GPIO power-off driver" + depends on OF_GPIO + help + 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. diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index a490dce873..438c859700 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o 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 diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c new file mode 100644 index 0000000000..45b0d274e7 --- /dev/null +++ b/drivers/power/reset/gpio-poweroff.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Toggles a GPIO pin to power down a device + * + * Jamie Lentin <jm@lentin.co.uk> + * Andrew Lunn <andrew@lunn.ch> + * + * Copyright (C) 2012 Jamie Lentin + */ +#include <common.h> +#include <driver.h> +#include <poweroff.h> +#include <gpiod.h> + +#define DEFAULT_TIMEOUT_MS 3000 +/* + * Hold configuration here, cannot be more than one instance of the driver + * since pm_power_off itself is global. + */ +static int reset_gpio; +static u32 timeout = DEFAULT_TIMEOUT_MS; +static u32 active_delay = 100; +static u32 inactive_delay = 100; + +static void gpio_poweroff_do_poweroff(struct poweroff_handler *handler) +{ + /* drive it active, also inactive->active edge */ + gpio_direction_active(reset_gpio, true); + mdelay(active_delay); + + /* drive inactive, also active->inactive edge */ + gpio_set_active(reset_gpio, false); + mdelay(inactive_delay); + + /* drive it active, also inactive->active edge */ + gpio_set_active(reset_gpio, true); + + /* give it some time */ + mdelay(timeout); + + WARN_ON(1); +} + +static struct poweroff_handler handler; + +static int gpio_poweroff_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + bool input = false; + enum gpiod_flags flags; + + if (handler.poweroff != NULL) { + dev_err(dev, "%s: pm_power_off function already registered\n", __func__); + return -EBUSY; + } + + input = of_property_read_bool(np, "input"); + if (input) + flags = GPIOD_IN; + else + flags = GPIOD_OUT_LOW; + + of_property_read_u32(np, "active-delay-ms", &active_delay); + of_property_read_u32(np, "inactive-delay-ms", &inactive_delay); + of_property_read_u32(np, "timeout-ms", &timeout); + + reset_gpio = gpiod_get(dev, NULL, flags); + if (reset_gpio < 0) + return reset_gpio; + + handler.name = "gpio-poweroff"; + handler.poweroff = gpio_poweroff_do_poweroff; + handler.priority = 129; + + return poweroff_handler_register(&handler); +} + +static const struct of_device_id of_gpio_poweroff_match[] = { + { .compatible = "gpio-poweroff", }, + {}, +}; + +static struct driver_d gpio_poweroff_driver = { + .name = "poweroff-gpio", + .of_compatible = of_gpio_poweroff_match, + .probe = gpio_poweroff_probe, +}; +device_platform_driver(gpio_poweroff_driver); + +MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); +MODULE_DESCRIPTION("GPIO poweroff driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:poweroff-gpio"); |