[PATCH 3/5] power: reset: add GPIO poweroff driver

Ahmad Fatoum ahmad at a3f.at
Sat Apr 10 11:35:09 BST 2021


This is a straight port from Linux v5.11.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 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 <jm at lentin.co.uk>
+ * Andrew Lunn <andrew at 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 at lentin.co.uk>");
+MODULE_DESCRIPTION("GPIO poweroff driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:poweroff-gpio");
-- 
2.30.0




More information about the barebox mailing list