1 /*
2  * Copyright (c) 2023, Prevas A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_tps382x
8 
9 #include <errno.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/watchdog.h>
12 #include <zephyr/logging/log.h>
13 
14 LOG_MODULE_REGISTER(wdt_ti_tps382x, CONFIG_WDT_LOG_LEVEL);
15 
16 struct ti_tps382x_config {
17 	struct gpio_dt_spec wdi_gpio;
18 	int timeout;
19 };
20 
ti_tps382x_init(const struct device * dev)21 static int ti_tps382x_init(const struct device *dev)
22 {
23 	const struct ti_tps382x_config *config = dev->config;
24 
25 	if (!gpio_is_ready_dt(&config->wdi_gpio)) {
26 		LOG_ERR("WDI gpio not ready");
27 		return -ENODEV;
28 	}
29 
30 	return 0;
31 }
32 
ti_tps382x_setup(const struct device * dev,uint8_t options)33 static int ti_tps382x_setup(const struct device *dev, uint8_t options)
34 {
35 	const struct ti_tps382x_config *config = dev->config;
36 
37 	return gpio_pin_configure_dt(&config->wdi_gpio, GPIO_OUTPUT);
38 }
39 
ti_tps382x_disable(const struct device * dev)40 static int ti_tps382x_disable(const struct device *dev)
41 {
42 	const struct ti_tps382x_config *config = dev->config;
43 
44 	/* The watchdog timer can be disabled by disconnecting the WDI pin from
45 	 * the system. Do this by changing the gpio to an input (tri-state).
46 	 */
47 	return gpio_pin_configure_dt(&config->wdi_gpio, GPIO_INPUT);
48 }
49 
ti_tps382x_install_timeout(const struct device * dev,const struct wdt_timeout_cfg * cfg)50 static int ti_tps382x_install_timeout(const struct device *dev,
51 				      const struct wdt_timeout_cfg *cfg)
52 {
53 	const struct ti_tps382x_config *config = dev->config;
54 
55 	if (cfg->window.max != config->timeout) {
56 		LOG_ERR("Upper limit of watchdog timeout must be %d not %u",
57 			config->timeout, cfg->window.max);
58 		return -EINVAL;
59 	} else if (cfg->window.min != 0) {
60 		LOG_ERR("Window timeouts not supported");
61 		return -EINVAL;
62 	} else if (cfg->callback != NULL) {
63 		LOG_ERR("Callbacks not supported");
64 		return -EINVAL;
65 	}
66 
67 	return 0;
68 }
69 
ti_tps382x_feed(const struct device * dev,int channel_id)70 static int ti_tps382x_feed(const struct device *dev, int channel_id)
71 {
72 	const struct ti_tps382x_config *config = dev->config;
73 
74 	return gpio_pin_toggle_dt(&config->wdi_gpio);
75 }
76 
77 static DEVICE_API(wdt, ti_tps382x_api) = {
78 	.setup = ti_tps382x_setup,
79 	.disable = ti_tps382x_disable,
80 	.install_timeout = ti_tps382x_install_timeout,
81 	.feed = ti_tps382x_feed,
82 };
83 
84 #define WDT_TI_TPS382X_INIT(n)                                                \
85 	static const struct ti_tps382x_config ti_tps382x_##n##config = {      \
86 		.wdi_gpio = GPIO_DT_SPEC_INST_GET(n, wdi_gpios),              \
87 		.timeout = DT_INST_PROP(n, timeout_period),                   \
88 	};                                                                    \
89                                                                               \
90 	DEVICE_DT_INST_DEFINE(                                                \
91 		n, ti_tps382x_init, NULL, NULL, &ti_tps382x_##n##config,      \
92 		POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,              \
93 		&ti_tps382x_api                                               \
94 	);
95 
96 DT_INST_FOREACH_STATUS_OKAY(WDT_TI_TPS382X_INIT);
97