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 u32 active_delay_ms; 21 u32 inactive_delay_ms; 22 u32 wait_delay_ms; 23 }; 24 25 static int gpio_restart_notify(struct sys_off_data *data) 26 { 27 struct gpio_restart *gpio_restart = data->cb_data; 28 29 /* drive it active, also inactive->active edge */ 30 gpiod_direction_output(gpio_restart->reset_gpio, 1); 31 mdelay(gpio_restart->active_delay_ms); 32 33 /* drive inactive, also active->inactive edge */ 34 gpiod_set_value(gpio_restart->reset_gpio, 0); 35 mdelay(gpio_restart->inactive_delay_ms); 36 37 /* drive it active, also inactive->active edge */ 38 gpiod_set_value(gpio_restart->reset_gpio, 1); 39 40 /* give it some time */ 41 mdelay(gpio_restart->wait_delay_ms); 42 43 WARN_ON(1); 44 45 return NOTIFY_DONE; 46 } 47 48 static int gpio_restart_probe(struct platform_device *pdev) 49 { 50 struct gpio_restart *gpio_restart; 51 bool open_source = false; 52 int priority = 129; 53 u32 property; 54 int ret; 55 56 gpio_restart = devm_kzalloc(&pdev->dev, sizeof(*gpio_restart), 57 GFP_KERNEL); 58 if (!gpio_restart) 59 return -ENOMEM; 60 61 open_source = of_property_read_bool(pdev->dev.of_node, "open-source"); 62 63 gpio_restart->reset_gpio = devm_gpiod_get(&pdev->dev, NULL, 64 open_source ? GPIOD_IN : GPIOD_OUT_LOW); 65 ret = PTR_ERR_OR_ZERO(gpio_restart->reset_gpio); 66 if (ret) { 67 if (ret != -EPROBE_DEFER) 68 dev_err(&pdev->dev, "Could not get reset GPIO\n"); 69 return ret; 70 } 71 72 gpio_restart->active_delay_ms = 100; 73 gpio_restart->inactive_delay_ms = 100; 74 gpio_restart->wait_delay_ms = 3000; 75 76 ret = of_property_read_u32(pdev->dev.of_node, "priority", &property); 77 if (!ret) { 78 if (property > 255) 79 dev_err(&pdev->dev, "Invalid priority property: %u\n", 80 property); 81 else 82 priority = property; 83 } 84 85 of_property_read_u32(pdev->dev.of_node, "active-delay", 86 &gpio_restart->active_delay_ms); 87 of_property_read_u32(pdev->dev.of_node, "inactive-delay", 88 &gpio_restart->inactive_delay_ms); 89 of_property_read_u32(pdev->dev.of_node, "wait-delay", 90 &gpio_restart->wait_delay_ms); 91 92 ret = devm_register_sys_off_handler(&pdev->dev, 93 SYS_OFF_MODE_RESTART, 94 priority, 95 gpio_restart_notify, 96 gpio_restart); 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 const struct of_device_id of_gpio_restart_match[] = { 107 { .compatible = "gpio-restart", }, 108 {}, 109 }; 110 111 static struct platform_driver gpio_restart_driver = { 112 .probe = gpio_restart_probe, 113 .driver = { 114 .name = "restart-gpio", 115 .of_match_table = of_gpio_restart_match, 116 }, 117 }; 118 119 module_platform_driver(gpio_restart_driver); 120 121 MODULE_AUTHOR("David Riley <davidriley@chromium.org>"); 122 MODULE_DESCRIPTION("GPIO restart driver"); 123