root/drivers/power/reset/gpio-restart.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gpio_restart_notify
  2. gpio_restart_probe
  3. gpio_restart_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Toggles a GPIO pin to restart a device
   4  *
   5  * Copyright (C) 2014 Google, Inc.
   6  *
   7  * Based on the gpio-poweroff driver.
   8  */
   9 #include <linux/reboot.h>
  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 struct gpio_restart {
  19         struct gpio_desc *reset_gpio;
  20         struct notifier_block restart_handler;
  21         u32 active_delay_ms;
  22         u32 inactive_delay_ms;
  23         u32 wait_delay_ms;
  24 };
  25 
  26 static int gpio_restart_notify(struct notifier_block *this,
  27                                 unsigned long mode, void *cmd)
  28 {
  29         struct gpio_restart *gpio_restart =
  30                 container_of(this, struct gpio_restart, restart_handler);
  31 
  32         /* drive it active, also inactive->active edge */
  33         gpiod_direction_output(gpio_restart->reset_gpio, 1);
  34         mdelay(gpio_restart->active_delay_ms);
  35 
  36         /* drive inactive, also active->inactive edge */
  37         gpiod_set_value(gpio_restart->reset_gpio, 0);
  38         mdelay(gpio_restart->inactive_delay_ms);
  39 
  40         /* drive it active, also inactive->active edge */
  41         gpiod_set_value(gpio_restart->reset_gpio, 1);
  42 
  43         /* give it some time */
  44         mdelay(gpio_restart->wait_delay_ms);
  45 
  46         WARN_ON(1);
  47 
  48         return NOTIFY_DONE;
  49 }
  50 
  51 static int gpio_restart_probe(struct platform_device *pdev)
  52 {
  53         struct gpio_restart *gpio_restart;
  54         bool open_source = false;
  55         u32 property;
  56         int ret;
  57 
  58         gpio_restart = devm_kzalloc(&pdev->dev, sizeof(*gpio_restart),
  59                         GFP_KERNEL);
  60         if (!gpio_restart)
  61                 return -ENOMEM;
  62 
  63         open_source = of_property_read_bool(pdev->dev.of_node, "open-source");
  64 
  65         gpio_restart->reset_gpio = devm_gpiod_get(&pdev->dev, NULL,
  66                         open_source ? GPIOD_IN : GPIOD_OUT_LOW);
  67         if (IS_ERR(gpio_restart->reset_gpio)) {
  68                 dev_err(&pdev->dev, "Could not get reset GPIO\n");
  69                 return PTR_ERR(gpio_restart->reset_gpio);
  70         }
  71 
  72         gpio_restart->restart_handler.notifier_call = gpio_restart_notify;
  73         gpio_restart->restart_handler.priority = 129;
  74         gpio_restart->active_delay_ms = 100;
  75         gpio_restart->inactive_delay_ms = 100;
  76         gpio_restart->wait_delay_ms = 3000;
  77 
  78         ret = of_property_read_u32(pdev->dev.of_node, "priority", &property);
  79         if (!ret) {
  80                 if (property > 255)
  81                         dev_err(&pdev->dev, "Invalid priority property: %u\n",
  82                                         property);
  83                 else
  84                         gpio_restart->restart_handler.priority = property;
  85         }
  86 
  87         of_property_read_u32(pdev->dev.of_node, "active-delay",
  88                         &gpio_restart->active_delay_ms);
  89         of_property_read_u32(pdev->dev.of_node, "inactive-delay",
  90                         &gpio_restart->inactive_delay_ms);
  91         of_property_read_u32(pdev->dev.of_node, "wait-delay",
  92                         &gpio_restart->wait_delay_ms);
  93 
  94         platform_set_drvdata(pdev, gpio_restart);
  95 
  96         ret = register_restart_handler(&gpio_restart->restart_handler);
  97         if (ret) {
  98                 dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n",
  99                                 __func__, ret);
 100                 return -ENODEV;
 101         }
 102 
 103         return 0;
 104 }
 105 
 106 static int gpio_restart_remove(struct platform_device *pdev)
 107 {
 108         struct gpio_restart *gpio_restart = platform_get_drvdata(pdev);
 109         int ret;
 110 
 111         ret = unregister_restart_handler(&gpio_restart->restart_handler);
 112         if (ret) {
 113                 dev_err(&pdev->dev,
 114                                 "%s: cannot unregister restart handler, %d\n",
 115                                 __func__, ret);
 116                 return -ENODEV;
 117         }
 118 
 119         return 0;
 120 }
 121 
 122 static const struct of_device_id of_gpio_restart_match[] = {
 123         { .compatible = "gpio-restart", },
 124         {},
 125 };
 126 
 127 static struct platform_driver gpio_restart_driver = {
 128         .probe = gpio_restart_probe,
 129         .remove = gpio_restart_remove,
 130         .driver = {
 131                 .name = "restart-gpio",
 132                 .of_match_table = of_gpio_restart_match,
 133         },
 134 };
 135 
 136 module_platform_driver(gpio_restart_driver);
 137 
 138 MODULE_AUTHOR("David Riley <davidriley@chromium.org>");
 139 MODULE_DESCRIPTION("GPIO restart driver");
 140 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */