aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2013-01-06 05:10:35 -0500
committerJason Cooper <jason@lakedaemon.net>2013-01-06 12:53:00 -0500
commit5343527bbfab3f71f64d8ba5d51ce12dec8d82d0 (patch)
tree42e197b8fb215663bbdd5023226acea16c0b55f5
parent53dfa8e4aa740cc7a19a39d6d4542f856c6b49ae (diff)
Power: gpio-poweroff: Fix documentation and gpio_is_valid
Improve the documentation to clarify level vs edge triggered power off. Improve the comments for level vs edge triggered power off. Make use of gpio_is_valid(). Reported-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-poweroff.txt20
-rw-r--r--drivers/power/reset/gpio-poweroff.c33
2 files changed, 32 insertions, 21 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
index 558cdf3c9ab..d4eab9227ea 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
@@ -1,4 +1,19 @@
1GPIO line that should be set high/low to power off a device 1Driver a GPIO line that can be used to turn the power off.
2
3The driver supports both level triggered and edge triggered power off.
4At driver load time, the driver will request the given gpio line and
5install a pm_power_off handler. If the optional properties 'input' is
6not found, the GPIO line will be driven in the inactive
7state. Otherwise its configured as an input.
8
9When the pm_power_off is called, the gpio is configured as an output,
10and drive active, so triggering a level triggered power off
11condition. This will also cause an inactive->active edge condition, so
12triggering positive edge triggered power off. After a delay of 100ms,
13the GPIO is set to inactive, thus causing an active->inactive edge,
14triggering negative edge triggered power off. After another 100ms
15delay the GPIO is driver active again. If the power is still on and
16the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
2 17
3Required properties: 18Required properties:
4- compatible : should be "gpio-poweroff". 19- compatible : should be "gpio-poweroff".
@@ -13,10 +28,9 @@ Optional properties:
13 property is not specified, the GPIO is initialized as an output in its 28 property is not specified, the GPIO is initialized as an output in its
14 inactive state. 29 inactive state.
15 30
16
17Examples: 31Examples:
18 32
19gpio-poweroff { 33gpio-poweroff {
20 compatible = "gpio-poweroff"; 34 compatible = "gpio-poweroff";
21 gpios = <&gpio 4 0>; /* GPIO 4 Active Low */ 35 gpios = <&gpio 4 0>;
22}; 36};
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index 0491e5335d0..adc943b3fc3 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -29,15 +29,16 @@ static int gpio_active_low;
29 29
30static void gpio_poweroff_do_poweroff(void) 30static void gpio_poweroff_do_poweroff(void)
31{ 31{
32 BUG_ON(gpio_num == -1); 32 BUG_ON(!gpio_is_valid(gpio_num));
33 33
34 /* drive it active */ 34 /* drive it active, also inactive->active edge */
35 gpio_direction_output(gpio_num, !gpio_active_low); 35 gpio_direction_output(gpio_num, !gpio_active_low);
36 mdelay(100); 36 mdelay(100);
37 /* rising edge or drive inactive */ 37 /* drive inactive, also active->inactive edge */
38 gpio_set_value(gpio_num, gpio_active_low); 38 gpio_set_value(gpio_num, gpio_active_low);
39 mdelay(100); 39 mdelay(100);
40 /* falling edge */ 40
41 /* drive it active, also inactive->active edge */
41 gpio_set_value(gpio_num, !gpio_active_low); 42 gpio_set_value(gpio_num, !gpio_active_low);
42 43
43 /* give it some time */ 44 /* give it some time */
@@ -60,15 +61,12 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
60 } 61 }
61 62
62 gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); 63 gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
63 if (gpio_num < 0) { 64 if (!gpio_is_valid(gpio_num))
64 pr_err("%s: Could not get GPIO configuration: %d", 65 return gpio_num;
65 __func__, gpio_num); 66
66 return -ENODEV;
67 }
68 gpio_active_low = flags & OF_GPIO_ACTIVE_LOW; 67 gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
69 68
70 if (of_get_property(pdev->dev.of_node, "input", NULL)) 69 input = of_property_read_bool(pdev->dev.of_node, "input");
71 input = true;
72 70
73 ret = gpio_request(gpio_num, "poweroff-gpio"); 71 ret = gpio_request(gpio_num, "poweroff-gpio");
74 if (ret) { 72 if (ret) {
@@ -98,8 +96,7 @@ err:
98 96
99static int __devexit gpio_poweroff_remove(struct platform_device *pdev) 97static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
100{ 98{
101 if (gpio_num != -1) 99 gpio_free(gpio_num);
102 gpio_free(gpio_num);
103 if (pm_power_off == &gpio_poweroff_do_poweroff) 100 if (pm_power_off == &gpio_poweroff_do_poweroff)
104 pm_power_off = NULL; 101 pm_power_off = NULL;
105 102
@@ -115,15 +112,15 @@ static struct platform_driver gpio_poweroff_driver = {
115 .probe = gpio_poweroff_probe, 112 .probe = gpio_poweroff_probe,
116 .remove = __devexit_p(gpio_poweroff_remove), 113 .remove = __devexit_p(gpio_poweroff_remove),
117 .driver = { 114 .driver = {
118 .name = "poweroff-gpio", 115 .name = "poweroff-gpio",
119 .owner = THIS_MODULE, 116 .owner = THIS_MODULE,
120 .of_match_table = of_gpio_poweroff_match, 117 .of_match_table = of_gpio_poweroff_match,
121 }, 118 },
122}; 119};
123 120
124module_platform_driver(gpio_poweroff_driver); 121module_platform_driver(gpio_poweroff_driver);
125 122
126MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); 123MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
127MODULE_DESCRIPTION("GPIO poweroff driver"); 124MODULE_DESCRIPTION("GPIO poweroff driver");
128MODULE_LICENSE("GPL"); 125MODULE_LICENSE("GPL v2");
129MODULE_ALIAS("platform:poweroff-gpio"); 126MODULE_ALIAS("platform:poweroff-gpio");