Commit 5343527b authored by Andrew Lunn's avatar Andrew Lunn Committed by Jason Cooper

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: default avatarStephen Warren <swarren@wwwdotorg.org>
Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent 53dfa8e4
GPIO line that should be set high/low to power off a device Driver a GPIO line that can be used to turn the power off.
The driver supports both level triggered and edge triggered power off.
At driver load time, the driver will request the given gpio line and
install a pm_power_off handler. If the optional properties 'input' is
not found, the GPIO line will be driven in the inactive
state. Otherwise its configured as an input.
When the pm_power_off is called, the gpio is configured as an output,
and drive active, so triggering a level triggered power off
condition. This will also cause an inactive->active edge condition, so
triggering positive edge triggered power off. After a delay of 100ms,
the GPIO is set to inactive, thus causing an active->inactive edge,
triggering negative edge triggered power off. After another 100ms
delay the GPIO is driver active again. If the power is still on and
the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
Required properties: Required properties:
- compatible : should be "gpio-poweroff". - compatible : should be "gpio-poweroff".
...@@ -13,10 +28,9 @@ Optional properties: ...@@ -13,10 +28,9 @@ Optional properties:
property is not specified, the GPIO is initialized as an output in its property is not specified, the GPIO is initialized as an output in its
inactive state. inactive state.
Examples: Examples:
gpio-poweroff { gpio-poweroff {
compatible = "gpio-poweroff"; compatible = "gpio-poweroff";
gpios = <&gpio 4 0>; /* GPIO 4 Active Low */ gpios = <&gpio 4 0>;
}; };
...@@ -29,15 +29,16 @@ static int gpio_active_low; ...@@ -29,15 +29,16 @@ static int gpio_active_low;
static void gpio_poweroff_do_poweroff(void) static void gpio_poweroff_do_poweroff(void)
{ {
BUG_ON(gpio_num == -1); BUG_ON(!gpio_is_valid(gpio_num));
/* drive it active */ /* drive it active, also inactive->active edge */
gpio_direction_output(gpio_num, !gpio_active_low); gpio_direction_output(gpio_num, !gpio_active_low);
mdelay(100); mdelay(100);
/* rising edge or drive inactive */ /* drive inactive, also active->inactive edge */
gpio_set_value(gpio_num, gpio_active_low); gpio_set_value(gpio_num, gpio_active_low);
mdelay(100); mdelay(100);
/* falling edge */
/* drive it active, also inactive->active edge */
gpio_set_value(gpio_num, !gpio_active_low); gpio_set_value(gpio_num, !gpio_active_low);
/* give it some time */ /* give it some time */
...@@ -60,15 +61,12 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev) ...@@ -60,15 +61,12 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
} }
gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
if (gpio_num < 0) { if (!gpio_is_valid(gpio_num))
pr_err("%s: Could not get GPIO configuration: %d", return gpio_num;
__func__, gpio_num);
return -ENODEV;
}
gpio_active_low = flags & OF_GPIO_ACTIVE_LOW; gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
if (of_get_property(pdev->dev.of_node, "input", NULL)) input = of_property_read_bool(pdev->dev.of_node, "input");
input = true;
ret = gpio_request(gpio_num, "poweroff-gpio"); ret = gpio_request(gpio_num, "poweroff-gpio");
if (ret) { if (ret) {
...@@ -98,8 +96,7 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev) ...@@ -98,8 +96,7 @@ static int __devinit gpio_poweroff_probe(struct platform_device *pdev)
static int __devexit gpio_poweroff_remove(struct platform_device *pdev) static int __devexit gpio_poweroff_remove(struct platform_device *pdev)
{ {
if (gpio_num != -1) gpio_free(gpio_num);
gpio_free(gpio_num);
if (pm_power_off == &gpio_poweroff_do_poweroff) if (pm_power_off == &gpio_poweroff_do_poweroff)
pm_power_off = NULL; pm_power_off = NULL;
...@@ -115,15 +112,15 @@ static struct platform_driver gpio_poweroff_driver = { ...@@ -115,15 +112,15 @@ static struct platform_driver gpio_poweroff_driver = {
.probe = gpio_poweroff_probe, .probe = gpio_poweroff_probe,
.remove = __devexit_p(gpio_poweroff_remove), .remove = __devexit_p(gpio_poweroff_remove),
.driver = { .driver = {
.name = "poweroff-gpio", .name = "poweroff-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_gpio_poweroff_match, .of_match_table = of_gpio_poweroff_match,
}, },
}; };
module_platform_driver(gpio_poweroff_driver); module_platform_driver(gpio_poweroff_driver);
MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>"); MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
MODULE_DESCRIPTION("GPIO poweroff driver"); MODULE_DESCRIPTION("GPIO poweroff driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:poweroff-gpio"); MODULE_ALIAS("platform:poweroff-gpio");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment