0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/reboot.h>
0010 #include <linux/kernel.h>
0011 #include <linux/init.h>
0012 #include <linux/delay.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/of_platform.h>
0016 #include <linux/module.h>
0017
0018 struct gpio_restart {
0019 struct gpio_desc *reset_gpio;
0020 struct notifier_block restart_handler;
0021 u32 active_delay_ms;
0022 u32 inactive_delay_ms;
0023 u32 wait_delay_ms;
0024 };
0025
0026 static int gpio_restart_notify(struct notifier_block *this,
0027 unsigned long mode, void *cmd)
0028 {
0029 struct gpio_restart *gpio_restart =
0030 container_of(this, struct gpio_restart, restart_handler);
0031
0032
0033 gpiod_direction_output(gpio_restart->reset_gpio, 1);
0034 mdelay(gpio_restart->active_delay_ms);
0035
0036
0037 gpiod_set_value(gpio_restart->reset_gpio, 0);
0038 mdelay(gpio_restart->inactive_delay_ms);
0039
0040
0041 gpiod_set_value(gpio_restart->reset_gpio, 1);
0042
0043
0044 mdelay(gpio_restart->wait_delay_ms);
0045
0046 WARN_ON(1);
0047
0048 return NOTIFY_DONE;
0049 }
0050
0051 static int gpio_restart_probe(struct platform_device *pdev)
0052 {
0053 struct gpio_restart *gpio_restart;
0054 bool open_source = false;
0055 u32 property;
0056 int ret;
0057
0058 gpio_restart = devm_kzalloc(&pdev->dev, sizeof(*gpio_restart),
0059 GFP_KERNEL);
0060 if (!gpio_restart)
0061 return -ENOMEM;
0062
0063 open_source = of_property_read_bool(pdev->dev.of_node, "open-source");
0064
0065 gpio_restart->reset_gpio = devm_gpiod_get(&pdev->dev, NULL,
0066 open_source ? GPIOD_IN : GPIOD_OUT_LOW);
0067 ret = PTR_ERR_OR_ZERO(gpio_restart->reset_gpio);
0068 if (ret) {
0069 if (ret != -EPROBE_DEFER)
0070 dev_err(&pdev->dev, "Could not get reset GPIO\n");
0071 return ret;
0072 }
0073
0074 gpio_restart->restart_handler.notifier_call = gpio_restart_notify;
0075 gpio_restart->restart_handler.priority = 129;
0076 gpio_restart->active_delay_ms = 100;
0077 gpio_restart->inactive_delay_ms = 100;
0078 gpio_restart->wait_delay_ms = 3000;
0079
0080 ret = of_property_read_u32(pdev->dev.of_node, "priority", &property);
0081 if (!ret) {
0082 if (property > 255)
0083 dev_err(&pdev->dev, "Invalid priority property: %u\n",
0084 property);
0085 else
0086 gpio_restart->restart_handler.priority = property;
0087 }
0088
0089 of_property_read_u32(pdev->dev.of_node, "active-delay",
0090 &gpio_restart->active_delay_ms);
0091 of_property_read_u32(pdev->dev.of_node, "inactive-delay",
0092 &gpio_restart->inactive_delay_ms);
0093 of_property_read_u32(pdev->dev.of_node, "wait-delay",
0094 &gpio_restart->wait_delay_ms);
0095
0096 platform_set_drvdata(pdev, gpio_restart);
0097
0098 ret = register_restart_handler(&gpio_restart->restart_handler);
0099 if (ret) {
0100 dev_err(&pdev->dev, "%s: cannot register restart handler, %d\n",
0101 __func__, ret);
0102 return -ENODEV;
0103 }
0104
0105 return 0;
0106 }
0107
0108 static int gpio_restart_remove(struct platform_device *pdev)
0109 {
0110 struct gpio_restart *gpio_restart = platform_get_drvdata(pdev);
0111 int ret;
0112
0113 ret = unregister_restart_handler(&gpio_restart->restart_handler);
0114 if (ret) {
0115 dev_err(&pdev->dev,
0116 "%s: cannot unregister restart handler, %d\n",
0117 __func__, ret);
0118 return -ENODEV;
0119 }
0120
0121 return 0;
0122 }
0123
0124 static const struct of_device_id of_gpio_restart_match[] = {
0125 { .compatible = "gpio-restart", },
0126 {},
0127 };
0128
0129 static struct platform_driver gpio_restart_driver = {
0130 .probe = gpio_restart_probe,
0131 .remove = gpio_restart_remove,
0132 .driver = {
0133 .name = "restart-gpio",
0134 .of_match_table = of_gpio_restart_match,
0135 },
0136 };
0137
0138 module_platform_driver(gpio_restart_driver);
0139
0140 MODULE_AUTHOR("David Riley <davidriley@chromium.org>");
0141 MODULE_DESCRIPTION("GPIO restart driver");
0142 MODULE_LICENSE("GPL");