Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/power/reset/gpio-poweroff.c

  1 /*
  2  * Toggles a GPIO pin to power down a device
  3  *
  4  * Jamie Lentin <jm@lentin.co.uk>
  5  * Andrew Lunn <andrew@lunn.ch>
  6  *
  7  * Copyright (C) 2012 Jamie Lentin
  8  *
  9  * This program is free software; you can redistribute it and/or modify
 10  * it under the terms of the GNU General Public License version 2 as
 11  * published by the Free Software Foundation.
 12  *
 13  */
 14 #include <linux/kernel.h>
 15 #include <linux/init.h>
 16 #include <linux/delay.h>
 17 #include <linux/platform_device.h>
 18 #include <linux/gpio.h>
 19 #include <linux/of_platform.h>
 20 #include <linux/of_gpio.h>
 21 #include <linux/module.h>
 22 
 23 /*
 24  * Hold configuration here, cannot be more than one instance of the driver
 25  * since pm_power_off itself is global.
 26  */
 27 static int gpio_num = -1;
 28 static int gpio_active_low;
 29 
 30 static void gpio_poweroff_do_poweroff(void)
 31 {
 32         BUG_ON(!gpio_is_valid(gpio_num));
 33 
 34         /* drive it active, also inactive->active edge */
 35         gpio_direction_output(gpio_num, !gpio_active_low);
 36         mdelay(100);
 37         /* drive inactive, also active->inactive edge */
 38         gpio_set_value(gpio_num, gpio_active_low);
 39         mdelay(100);
 40 
 41         /* drive it active, also inactive->active edge */
 42         gpio_set_value(gpio_num, !gpio_active_low);
 43 
 44         /* give it some time */
 45         mdelay(3000);
 46 
 47         WARN_ON(1);
 48 }
 49 
 50 static int gpio_poweroff_probe(struct platform_device *pdev)
 51 {
 52         enum of_gpio_flags flags;
 53         bool input = false;
 54         int ret;
 55 
 56         /* If a pm_power_off function has already been added, leave it alone */
 57         if (pm_power_off != NULL) {
 58                 pr_err("%s: pm_power_off function already registered",
 59                        __func__);
 60                 return -EBUSY;
 61         }
 62 
 63         gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
 64         if (!gpio_is_valid(gpio_num))
 65                 return gpio_num;
 66 
 67         gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
 68 
 69         input = of_property_read_bool(pdev->dev.of_node, "input");
 70 
 71         ret = gpio_request(gpio_num, "poweroff-gpio");
 72         if (ret) {
 73                 pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
 74                 return ret;
 75         }
 76         if (input) {
 77                 if (gpio_direction_input(gpio_num)) {
 78                         pr_err("Could not set direction of GPIO %d to input",
 79                                gpio_num);
 80                         goto err;
 81                 }
 82         } else {
 83                 if (gpio_direction_output(gpio_num, gpio_active_low)) {
 84                         pr_err("Could not set direction of GPIO %d", gpio_num);
 85                         goto err;
 86                 }
 87         }
 88 
 89         pm_power_off = &gpio_poweroff_do_poweroff;
 90         return 0;
 91 
 92 err:
 93         gpio_free(gpio_num);
 94         return -ENODEV;
 95 }
 96 
 97 static int gpio_poweroff_remove(struct platform_device *pdev)
 98 {
 99         gpio_free(gpio_num);
100         if (pm_power_off == &gpio_poweroff_do_poweroff)
101                 pm_power_off = NULL;
102 
103         return 0;
104 }
105 
106 static const struct of_device_id of_gpio_poweroff_match[] = {
107         { .compatible = "gpio-poweroff", },
108         {},
109 };
110 
111 static struct platform_driver gpio_poweroff_driver = {
112         .probe = gpio_poweroff_probe,
113         .remove = gpio_poweroff_remove,
114         .driver = {
115                 .name = "poweroff-gpio",
116                 .owner = THIS_MODULE,
117                 .of_match_table = of_gpio_poweroff_match,
118         },
119 };
120 
121 module_platform_driver(gpio_poweroff_driver);
122 
123 MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
124 MODULE_DESCRIPTION("GPIO poweroff driver");
125 MODULE_LICENSE("GPL v2");
126 MODULE_ALIAS("platform:poweroff-gpio");
127 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us