diff options
author | Andrew Lunn <andrew@lunn.ch> | 2013-01-06 05:10:35 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2013-01-06 12:53:00 -0500 |
commit | 5343527bbfab3f71f64d8ba5d51ce12dec8d82d0 (patch) | |
tree | 42e197b8fb215663bbdd5023226acea16c0b55f5 | |
parent | 53dfa8e4aa740cc7a19a39d6d4542f856c6b49ae (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.txt | 20 | ||||
-rw-r--r-- | drivers/power/reset/gpio-poweroff.c | 33 |
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 @@ | |||
1 | GPIO line that should be set high/low to power off a device | 1 | Driver a GPIO line that can be used to turn the power off. |
2 | |||
3 | The driver supports both level triggered and edge triggered power off. | ||
4 | At driver load time, the driver will request the given gpio line and | ||
5 | install a pm_power_off handler. If the optional properties 'input' is | ||
6 | not found, the GPIO line will be driven in the inactive | ||
7 | state. Otherwise its configured as an input. | ||
8 | |||
9 | When the pm_power_off is called, the gpio is configured as an output, | ||
10 | and drive active, so triggering a level triggered power off | ||
11 | condition. This will also cause an inactive->active edge condition, so | ||
12 | triggering positive edge triggered power off. After a delay of 100ms, | ||
13 | the GPIO is set to inactive, thus causing an active->inactive edge, | ||
14 | triggering negative edge triggered power off. After another 100ms | ||
15 | delay the GPIO is driver active again. If the power is still on and | ||
16 | the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted. | ||
2 | 17 | ||
3 | Required properties: | 18 | Required 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 | |||
17 | Examples: | 31 | Examples: |
18 | 32 | ||
19 | gpio-poweroff { | 33 | gpio-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 | ||
30 | static void gpio_poweroff_do_poweroff(void) | 30 | static 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 | ||
99 | static int __devexit gpio_poweroff_remove(struct platform_device *pdev) | 97 | static 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 | ||
124 | module_platform_driver(gpio_poweroff_driver); | 121 | module_platform_driver(gpio_poweroff_driver); |
125 | 122 | ||
126 | MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); | 123 | MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); |
127 | MODULE_DESCRIPTION("GPIO poweroff driver"); | 124 | MODULE_DESCRIPTION("GPIO poweroff driver"); |
128 | MODULE_LICENSE("GPL"); | 125 | MODULE_LICENSE("GPL v2"); |
129 | MODULE_ALIAS("platform:poweroff-gpio"); | 126 | MODULE_ALIAS("platform:poweroff-gpio"); |