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/module.h> 16 #include <linux/of.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 ret = PTR_ERR_OR_ZERO(gpio_restart->reset_gpio); 68 if (ret) { 69 if (ret != -EPROBE_DEFER) 70 dev_err(&pdev->dev, "Could not get reset GPIO\n"); 71 return ret; 72 } 73 74 gpio_restart->restart_handler.notifier_call = gpio_restart_notify; 75 gpio_restart->restart_handler.priority = 129; 76 gpio_restart->active_delay_ms = 100; 77 gpio_restart->inactive_delay_ms = 100; 78 gpio_restart->wait_delay_ms = 3000; 79 80 ret = of_property_read_u32(pdev->dev.of_node, "priority", &property); 81 if (!ret) { 82 if (property > 255) 83 dev_err(&pdev->dev, "Invalid priority property: %u\n", 84 property); 85 else 86 gpio_restart->restart_handler.priority = property; 87 } 88 89 of_property_read_u32(pdev->dev.of_node, "active-delay", 90 &gpio_restart->active_delay_ms); 91 of_property_read_u32(pdev->dev.of_node, "inactive-delay", 92 &gpio_restart->inactive_delay_ms); 93 of_property_read_u32(pdev->dev.of_node, "wait-delay", 94 &gpio_restart->wait_delay_ms); 95 96 platform_set_drvdata(pdev, gpio_restart); 97 98 ret = register_restart_handler(&gpio_restart->restart_handler); 99 if (ret) { 100 dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n", 101 __func__, ret); 102 return -ENODEV; 103 } 104 105 return 0; 106 } 107 108 static void gpio_restart_remove(struct platform_device *pdev) 109 { 110 struct gpio_restart *gpio_restart = platform_get_drvdata(pdev); 111 int ret; 112 113 ret = unregister_restart_handler(&gpio_restart->restart_handler); 114 if (ret) { 115 dev_err(&pdev->dev, 116 "%s: cannot unregister restart handler, %d\n", 117 __func__, ret); 118 } 119 } 120 121 static const struct of_device_id of_gpio_restart_match[] = { 122 { .compatible = "gpio-restart", }, 123 {}, 124 }; 125 126 static struct platform_driver gpio_restart_driver = { 127 .probe = gpio_restart_probe, 128 .remove_new = gpio_restart_remove, 129 .driver = { 130 .name = "restart-gpio", 131 .of_match_table = of_gpio_restart_match, 132 }, 133 }; 134 135 module_platform_driver(gpio_restart_driver); 136 137 MODULE_AUTHOR("David Riley <davidriley@chromium.org>"); 138 MODULE_DESCRIPTION("GPIO restart driver"); 139