Skip to content

Commit

Permalink
Power: gpio-poweroff: Fix documentation and gpio_is_valid
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andrew Lunn authored and Jason Cooper committed Jan 6, 2013
1 parent 53dfa8e commit 5343527
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 21 deletions.
20 changes: 17 additions & 3 deletions Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
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:
- compatible : should be "gpio-poweroff".
Expand All @@ -13,10 +28,9 @@ Optional properties:
property is not specified, the GPIO is initialized as an output in its
inactive state.


Examples:

gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio 4 0>; /* GPIO 4 Active Low */
gpios = <&gpio 4 0>;
};
33 changes: 15 additions & 18 deletions drivers/power/reset/gpio-poweroff.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ static int gpio_active_low;

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);
mdelay(100);
/* rising edge or drive inactive */
/* drive inactive, also active->inactive edge */
gpio_set_value(gpio_num, gpio_active_low);
mdelay(100);
/* falling edge */

/* drive it active, also inactive->active edge */
gpio_set_value(gpio_num, !gpio_active_low);

/* give it some time */
Expand All @@ -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);
if (gpio_num < 0) {
pr_err("%s: Could not get GPIO configuration: %d",
__func__, gpio_num);
return -ENODEV;
}
if (!gpio_is_valid(gpio_num))
return gpio_num;

gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;

if (of_get_property(pdev->dev.of_node, "input", NULL))
input = true;
input = of_property_read_bool(pdev->dev.of_node, "input");

ret = gpio_request(gpio_num, "poweroff-gpio");
if (ret) {
Expand Down Expand Up @@ -98,8 +96,7 @@ static int __devinit gpio_poweroff_probe(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)
pm_power_off = NULL;

Expand All @@ -115,15 +112,15 @@ static struct platform_driver gpio_poweroff_driver = {
.probe = gpio_poweroff_probe,
.remove = __devexit_p(gpio_poweroff_remove),
.driver = {
.name = "poweroff-gpio",
.owner = THIS_MODULE,
.of_match_table = of_gpio_poweroff_match,
},
.name = "poweroff-gpio",
.owner = THIS_MODULE,
.of_match_table = of_gpio_poweroff_match,
},
};

module_platform_driver(gpio_poweroff_driver);

MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
MODULE_DESCRIPTION("GPIO poweroff driver");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:poweroff-gpio");

0 comments on commit 5343527

Please sign in to comment.