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"); 141