1 // SPDX-License-Identifier: GPL-2.0-only
3 * Toggles a GPIO pin to power down a device
5 * Jamie Lentin <jm@lentin.co.uk>
6 * Andrew Lunn <andrew@lunn.ch>
8 * Copyright (C) 2012 Jamie Lentin
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/delay.h>
13 #include <linux/platform_device.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/of_platform.h>
16 #include <linux/module.h>
18 #define DEFAULT_TIMEOUT_MS 3000
20 * Hold configuration here, cannot be more than one instance of the driver
21 * since pm_power_off itself is global.
23 static struct gpio_desc
*reset_gpio
;
24 static u32 timeout
= DEFAULT_TIMEOUT_MS
;
25 static u32 active_delay
= 100;
26 static u32 inactive_delay
= 100;
28 static void gpio_poweroff_do_poweroff(void)
32 /* drive it active, also inactive->active edge */
33 gpiod_direction_output(reset_gpio
, 1);
36 /* drive inactive, also active->inactive edge */
37 gpiod_set_value_cansleep(reset_gpio
, 0);
38 mdelay(inactive_delay
);
40 /* drive it active, also inactive->active edge */
41 gpiod_set_value_cansleep(reset_gpio
, 1);
43 /* give it some time */
49 static int gpio_poweroff_probe(struct platform_device
*pdev
)
52 enum gpiod_flags flags
;
54 /* If a pm_power_off function has already been added, leave it alone */
55 if (pm_power_off
!= NULL
) {
57 "%s: pm_power_off function already registered",
62 input
= device_property_read_bool(&pdev
->dev
, "input");
66 flags
= GPIOD_OUT_LOW
;
68 device_property_read_u32(&pdev
->dev
, "active-delay-ms", &active_delay
);
69 device_property_read_u32(&pdev
->dev
, "inactive-delay-ms",
71 device_property_read_u32(&pdev
->dev
, "timeout-ms", &timeout
);
73 reset_gpio
= devm_gpiod_get(&pdev
->dev
, NULL
, flags
);
74 if (IS_ERR(reset_gpio
))
75 return PTR_ERR(reset_gpio
);
77 pm_power_off
= &gpio_poweroff_do_poweroff
;
81 static int gpio_poweroff_remove(struct platform_device
*pdev
)
83 if (pm_power_off
== &gpio_poweroff_do_poweroff
)
89 static const struct of_device_id of_gpio_poweroff_match
[] = {
90 { .compatible
= "gpio-poweroff", },
94 static struct platform_driver gpio_poweroff_driver
= {
95 .probe
= gpio_poweroff_probe
,
96 .remove
= gpio_poweroff_remove
,
98 .name
= "poweroff-gpio",
99 .of_match_table
= of_gpio_poweroff_match
,
103 module_platform_driver(gpio_poweroff_driver
);
105 MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
106 MODULE_DESCRIPTION("GPIO poweroff driver");
107 MODULE_LICENSE("GPL v2");
108 MODULE_ALIAS("platform:poweroff-gpio");