LCOV - code coverage report
Current view: top level - drivers/power/reset - gpio-poweroff.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 1 32 3.1 %
Date: 2020-09-30 20:25:40 Functions: 1 5 20.0 %
Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Toggles a GPIO pin to power down a device
       4                 :            :  *
       5                 :            :  * Jamie Lentin <jm@lentin.co.uk>
       6                 :            :  * Andrew Lunn <andrew@lunn.ch>
       7                 :            :  *
       8                 :            :  * Copyright (C) 2012 Jamie Lentin
       9                 :            :  */
      10                 :            : #include <linux/kernel.h>
      11                 :            : #include <linux/init.h>
      12                 :            : #include <linux/delay.h>
      13                 :            : #include <linux/platform_device.h>
      14                 :            : #include <linux/gpio/consumer.h>
      15                 :            : #include <linux/of_platform.h>
      16                 :            : #include <linux/module.h>
      17                 :            : 
      18                 :            : #define DEFAULT_TIMEOUT_MS 3000
      19                 :            : /*
      20                 :            :  * Hold configuration here, cannot be more than one instance of the driver
      21                 :            :  * since pm_power_off itself is global.
      22                 :            :  */
      23                 :            : static struct gpio_desc *reset_gpio;
      24                 :            : static u32 timeout = DEFAULT_TIMEOUT_MS;
      25                 :            : static u32 active_delay = 100;
      26                 :            : static u32 inactive_delay = 100;
      27                 :            : 
      28                 :          0 : static void gpio_poweroff_do_poweroff(void)
      29                 :            : {
      30         [ #  # ]:          0 :         BUG_ON(!reset_gpio);
      31                 :            : 
      32                 :            :         /* drive it active, also inactive->active edge */
      33                 :          0 :         gpiod_direction_output(reset_gpio, 1);
      34   [ #  #  #  #  :          0 :         mdelay(active_delay);
          #  #  #  #  #  
                      # ]
      35                 :            : 
      36                 :            :         /* drive inactive, also active->inactive edge */
      37                 :          0 :         gpiod_set_value_cansleep(reset_gpio, 0);
      38   [ #  #  #  #  :          0 :         mdelay(inactive_delay);
          #  #  #  #  #  
                      # ]
      39                 :            : 
      40                 :            :         /* drive it active, also inactive->active edge */
      41                 :          0 :         gpiod_set_value_cansleep(reset_gpio, 1);
      42                 :            : 
      43                 :            :         /* give it some time */
      44   [ #  #  #  #  :          0 :         mdelay(timeout);
          #  #  #  #  #  
                      # ]
      45                 :            : 
      46                 :          0 :         WARN_ON(1);
      47                 :          0 : }
      48                 :            : 
      49                 :          0 : static int gpio_poweroff_probe(struct platform_device *pdev)
      50                 :            : {
      51                 :            :         bool input = false;
      52                 :            :         enum gpiod_flags flags;
      53                 :            :         bool force = false;
      54                 :            :         bool export = false;
      55                 :            : 
      56                 :            :         /* If a pm_power_off function has already been added, leave it alone */
      57                 :          0 :         force = of_property_read_bool(pdev->dev.of_node, "force");
      58   [ #  #  #  # ]:          0 :         if (!force && (pm_power_off != NULL)) {
      59                 :          0 :                 dev_err(&pdev->dev,
      60                 :            :                         "%s: pm_power_off function already registered",
      61                 :            :                        __func__);
      62                 :          0 :                 return -EBUSY;
      63                 :            :         }
      64                 :            : 
      65                 :          0 :         input = device_property_read_bool(&pdev->dev, "input");
      66         [ #  # ]:          0 :         if (input)
      67                 :            :                 flags = GPIOD_IN;
      68                 :            :         else
      69                 :            :                 flags = GPIOD_OUT_LOW;
      70                 :            : 
      71                 :            :         device_property_read_u32(&pdev->dev, "active-delay-ms", &active_delay);
      72                 :            :         device_property_read_u32(&pdev->dev, "inactive-delay-ms",
      73                 :            :                                  &inactive_delay);
      74                 :            :         device_property_read_u32(&pdev->dev, "timeout-ms", &timeout);
      75                 :            : 
      76                 :          0 :         reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags);
      77         [ #  # ]:          0 :         if (IS_ERR(reset_gpio))
      78                 :          0 :                 return PTR_ERR(reset_gpio);
      79                 :            : 
      80                 :          0 :         export = of_property_read_bool(pdev->dev.of_node, "export");
      81         [ #  # ]:          0 :         if (export) {
      82                 :          0 :                 gpiod_export(reset_gpio, false);
      83                 :          0 :                 gpiod_export_link(&pdev->dev, "poweroff-gpio", reset_gpio);
      84                 :            :         }
      85                 :            : 
      86                 :          0 :         pm_power_off = &gpio_poweroff_do_poweroff;
      87                 :          0 :         return 0;
      88                 :            : }
      89                 :            : 
      90                 :          0 : static int gpio_poweroff_remove(struct platform_device *pdev)
      91                 :            : {
      92         [ #  # ]:          0 :         if (pm_power_off == &gpio_poweroff_do_poweroff)
      93                 :          0 :                 pm_power_off = NULL;
      94                 :            : 
      95                 :          0 :         gpiod_unexport(reset_gpio);
      96                 :            : 
      97                 :          0 :         return 0;
      98                 :            : }
      99                 :            : 
     100                 :            : static const struct of_device_id of_gpio_poweroff_match[] = {
     101                 :            :         { .compatible = "gpio-poweroff", },
     102                 :            :         {},
     103                 :            : };
     104                 :            : 
     105                 :            : static struct platform_driver gpio_poweroff_driver = {
     106                 :            :         .probe = gpio_poweroff_probe,
     107                 :            :         .remove = gpio_poweroff_remove,
     108                 :            :         .driver = {
     109                 :            :                 .name = "poweroff-gpio",
     110                 :            :                 .of_match_table = of_gpio_poweroff_match,
     111                 :            :         },
     112                 :            : };
     113                 :            : 
     114                 :        207 : module_platform_driver(gpio_poweroff_driver);
     115                 :            : 
     116                 :            : MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
     117                 :            : MODULE_DESCRIPTION("GPIO poweroff driver");
     118                 :            : MODULE_LICENSE("GPL v2");
     119                 :            : MODULE_ALIAS("platform:poweroff-gpio");

Generated by: LCOV version 1.14