This is a straight port from Linux v5.11.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 drivers/power/reset/Kconfig         |  8 +++
 drivers/power/reset/Makefile        |  1 +
 drivers/power/reset/gpio-poweroff.c | 93 +++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 drivers/power/reset/gpio-poweroff.c

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index e60037a6e637..cadcc0b13f2f 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 a490dce87333..438c85970028 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 000000000000..45b0d274e729
--- /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 <[email protected]>
+ * Andrew Lunn <[email protected]>
+ *
+ * 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 <[email protected]>");
+MODULE_DESCRIPTION("GPIO poweroff driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:poweroff-gpio");
-- 
2.30.0


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to