brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · d1e1771 Raw
123 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Toggles a GPIO pin to restart a device4 *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 18struct 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 25static 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 48static 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		else82			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 106static const struct of_device_id of_gpio_restart_match[] = {107	{ .compatible = "gpio-restart", },108	{},109};110 111static 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 119module_platform_driver(gpio_restart_driver);120 121MODULE_AUTHOR("David Riley <davidriley@chromium.org>");122MODULE_DESCRIPTION("GPIO restart driver");123