blob: fe06ec8cc90bec7eed1a22d0a11b6e2df4603352 [file] [log] [blame]
Rasmus Villemoes2ac84902021-08-19 11:57:04 +02001// SPDX-License-Identifier: GPL-2.0+
2
3#include <dm.h>
4#include <dm/device_compat.h>
5#include <wdt.h>
6#include <asm/gpio.h>
Paul Doelle1fc45d62022-07-04 09:00:25 +00007#include <linux/delay.h>
8
9enum {
10 HW_ALGO_TOGGLE,
11 HW_ALGO_LEVEL,
12};
Rasmus Villemoes2ac84902021-08-19 11:57:04 +020013
14struct gpio_wdt_priv {
Paul Doelle1fc45d62022-07-04 09:00:25 +000015 struct gpio_desc gpio;
16 unsigned int hw_algo;
17 bool always_running;
18 int state;
Rasmus Villemoes2ac84902021-08-19 11:57:04 +020019};
20
21static int gpio_wdt_reset(struct udevice *dev)
22{
23 struct gpio_wdt_priv *priv = dev_get_priv(dev);
24
Paul Doelle1fc45d62022-07-04 09:00:25 +000025 switch (priv->hw_algo) {
26 case HW_ALGO_TOGGLE:
27 /* Toggle output pin */
28 priv->state = !priv->state;
29 dm_gpio_set_value(&priv->gpio, priv->state);
30 break;
31 case HW_ALGO_LEVEL:
32 /* Pulse */
33 dm_gpio_set_value(&priv->gpio, 1);
34 udelay(1);
35 dm_gpio_set_value(&priv->gpio, 0);
36 break;
37 }
38 return 0;
Rasmus Villemoes2ac84902021-08-19 11:57:04 +020039}
40
41static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
42{
43 struct gpio_wdt_priv *priv = dev_get_priv(dev);
44
45 if (priv->always_running)
46 return 0;
47
48 return -ENOSYS;
49}
50
51static int dm_probe(struct udevice *dev)
52{
53 struct gpio_wdt_priv *priv = dev_get_priv(dev);
54 int ret;
Paul Doelle1fc45d62022-07-04 09:00:25 +000055 const char *algo = dev_read_string(dev, "hw_algo");
56
57 if (!algo)
58 return -EINVAL;
59 if (!strcmp(algo, "toggle"))
60 priv->hw_algo = HW_ALGO_TOGGLE;
61 else if (!strcmp(algo, "level"))
62 priv->hw_algo = HW_ALGO_LEVEL;
63 else
64 return -EINVAL;
Rasmus Villemoes2ac84902021-08-19 11:57:04 +020065
66 priv->always_running = dev_read_bool(dev, "always-running");
67 ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
68 if (ret < 0) {
69 dev_err(dev, "Request for wdt gpio failed: %d\n", ret);
70 return ret;
71 }
72
73 if (priv->always_running)
74 ret = gpio_wdt_reset(dev);
75
76 return ret;
77}
78
79static const struct wdt_ops gpio_wdt_ops = {
80 .start = gpio_wdt_start,
81 .reset = gpio_wdt_reset,
82};
83
84static const struct udevice_id gpio_wdt_ids[] = {
85 { .compatible = "linux,wdt-gpio" },
86 {}
87};
88
89U_BOOT_DRIVER(wdt_gpio) = {
90 .name = "wdt_gpio",
91 .id = UCLASS_WDT,
92 .of_match = gpio_wdt_ids,
93 .ops = &gpio_wdt_ops,
94 .probe = dm_probe,
95 .priv_auto = sizeof(struct gpio_wdt_priv),
96};