1 /*
2  * Copyright (c) 2017 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_INCLUDE_DRIVERS_WATCHDOG_H_
9 #define ZEPHYR_INCLUDE_DRIVERS_WATCHDOG_H_
10 
11 /**
12  * @brief Watchdog Interface
13  * @defgroup watchdog_interface Watchdog Interface
14  * @ingroup io_interfaces
15  * @{
16  */
17 
18 #include <zephyr/types.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/device.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /**
27  * @name Watchdog options
28  * @anchor WDT_OPT
29  * @{
30  */
31 
32 /** @brief Pause watchdog timer when CPU is in sleep state. */
33 #define WDT_OPT_PAUSE_IN_SLEEP		BIT(0)
34 
35 /** @brief Pause watchdog timer when CPU is halted by the debugger. */
36 #define WDT_OPT_PAUSE_HALTED_BY_DBG	BIT(1)
37 
38 /** @} */
39 
40 /**
41  * @name Watchdog behavior flags
42  * @anchor WDT_FLAGS
43  * @{
44  */
45 
46 /** @cond INTERNAL_HIDDEN */
47 /** @brief Watchdog reset flag bit field mask shift. */
48 #define WDT_FLAG_RESET_SHIFT		(0)
49 /** @brief Watchdog reset flag bit field mask. */
50 #define WDT_FLAG_RESET_MASK		(0x3 << WDT_FLAG_RESET_SHIFT)
51 /** @endcond */
52 
53 /** Reset: none */
54 #define WDT_FLAG_RESET_NONE		(0 << WDT_FLAG_RESET_SHIFT)
55 /** Reset: CPU core */
56 #define WDT_FLAG_RESET_CPU_CORE		(1 << WDT_FLAG_RESET_SHIFT)
57 /** Reset: SoC */
58 #define WDT_FLAG_RESET_SOC		(2 << WDT_FLAG_RESET_SHIFT)
59 
60 /** @} */
61 
62 /**
63  * @brief Watchdog timeout window.
64  *
65  * Each installed timeout needs feeding within the specified time window,
66  * otherwise the watchdog will trigger. If the watchdog instance does not
67  * support window timeouts then min value must be equal to 0.
68  *
69  * @note If specified values can not be precisely set they are always rounded
70  * up.
71  */
72 struct wdt_window {
73 	/** Lower limit of watchdog feed timeout in milliseconds. */
74 	uint32_t min;
75 	/** Upper limit of watchdog feed timeout in milliseconds. */
76 	uint32_t max;
77 };
78 
79 /**
80  * @brief Watchdog callback.
81  *
82  * @param dev Watchdog device instance.
83  * @param channel_id Channel identifier.
84  */
85 typedef void (*wdt_callback_t)(const struct device *dev, int channel_id);
86 
87 /** @brief Watchdog timeout configuration. */
88 struct wdt_timeout_cfg {
89 	/** Timing parameters of watchdog timeout. */
90 	struct wdt_window window;
91 	/** Timeout callback (can be `NULL`). */
92 	wdt_callback_t callback;
93 #if defined(CONFIG_WDT_MULTISTAGE) || defined(__DOXYGEN__)
94 	/**
95 	 * Pointer to the next timeout configuration.
96 	 *
97 	 * This field is only available if @kconfig{CONFIG_WDT_MULTISTAGE} is
98 	 * enabled (watchdogs with staged timeouts functionality). Value must be
99 	 * `NULL` for single stage timeout.
100 	 */
101 	struct wdt_timeout_cfg *next;
102 #endif
103 	/** Flags (see @ref WDT_FLAGS). */
104 	uint8_t flags;
105 };
106 
107 /** @cond INTERNAL_HIDDEN */
108 
109 /**
110  * @brief Callback API for setting up watchdog instance.
111  * @see wdt_setup().
112  */
113 typedef int (*wdt_api_setup)(const struct device *dev, uint8_t options);
114 
115 /**
116  * @brief Callback API for disabling watchdog instance.
117  * @see wdt_disable().
118  */
119 typedef int (*wdt_api_disable)(const struct device *dev);
120 
121 /**
122  * @brief Callback API for installing new timeout.
123  * @see wdt_install_timeout().
124  */
125 typedef int (*wdt_api_install_timeout)(const struct device *dev,
126 				       const struct wdt_timeout_cfg *cfg);
127 
128 /**
129  * @brief Callback API for feeding specified watchdog timeout.
130  * @see wdt_feed().
131  */
132 typedef int (*wdt_api_feed)(const struct device *dev, int channel_id);
133 
134 __subsystem struct wdt_driver_api {
135 	wdt_api_setup setup;
136 	wdt_api_disable disable;
137 	wdt_api_install_timeout install_timeout;
138 	wdt_api_feed feed;
139 };
140 /**
141  * @endcond
142  */
143 
144 /**
145  * @brief Set up watchdog instance.
146  *
147  * This function is used for configuring global watchdog settings that
148  * affect all timeouts. It should be called after installing timeouts.
149  * After successful return, all installed timeouts are valid and must be
150  * serviced periodically by calling wdt_feed().
151  *
152  * @param dev Watchdog device instance.
153  * @param options Configuration options (see @ref WDT_OPT).
154  *
155  * @retval 0 If successful.
156  * @retval -ENOTSUP If any of the set options is not supported.
157  * @retval -EBUSY If watchdog instance has been already setup.
158  * @retval -errno In case of any other failure.
159  */
160 __syscall int wdt_setup(const struct device *dev, uint8_t options);
161 
z_impl_wdt_setup(const struct device * dev,uint8_t options)162 static inline int z_impl_wdt_setup(const struct device *dev, uint8_t options)
163 {
164 	const struct wdt_driver_api *api =
165 		(const struct wdt_driver_api *)dev->api;
166 
167 	return api->setup(dev, options);
168 }
169 
170 /**
171  * @brief Disable watchdog instance.
172  *
173  * This function disables the watchdog instance and automatically uninstalls all
174  * timeouts. To set up a new watchdog, install timeouts and call wdt_setup()
175  * again. Not all watchdogs can be restarted after they are disabled.
176  *
177  * @param dev Watchdog device instance.
178  *
179  * @retval 0 If successful.
180  * @retval -EFAULT If watchdog instance is not enabled.
181  * @retval -EPERM If watchdog can not be disabled directly by application code.
182  * @retval -errno In case of any other failure.
183  */
184 __syscall int wdt_disable(const struct device *dev);
185 
z_impl_wdt_disable(const struct device * dev)186 static inline int z_impl_wdt_disable(const struct device *dev)
187 {
188 	const struct wdt_driver_api *api =
189 		(const struct wdt_driver_api *)dev->api;
190 
191 	return api->disable(dev);
192 }
193 
194 /**
195  * @brief Install a new timeout.
196  *
197  * @note This function must be used before wdt_setup(). Changes applied here
198  * have no effects until wdt_setup() is called.
199  *
200  * @param dev Watchdog device instance.
201  * @param[in] cfg Timeout configuration.
202  *
203  * @retval channel_id If successful, a non-negative value indicating the index
204  * of the channel to which the timeout was assigned. This value is supposed to
205  * be used as the parameter in calls to wdt_feed().
206  * @retval -EBUSY If timeout can not be installed while watchdog has already
207  * been setup.
208  * @retval -ENOMEM If no more timeouts can be installed.
209  * @retval -ENOTSUP If any of the set flags is not supported.
210  * @retval -EINVAL If any of the window timeout value is out of possible range.
211  * This value is also returned if watchdog supports only one timeout value for
212  * all timeouts and the supplied timeout window differs from windows for alarms
213  * installed so far.
214  * @retval -errno In case of any other failure.
215  */
wdt_install_timeout(const struct device * dev,const struct wdt_timeout_cfg * cfg)216 static inline int wdt_install_timeout(const struct device *dev,
217 				      const struct wdt_timeout_cfg *cfg)
218 {
219 	const struct wdt_driver_api *api =
220 		(const struct wdt_driver_api *) dev->api;
221 
222 	return api->install_timeout(dev, cfg);
223 }
224 
225 /**
226  * @brief Feed specified watchdog timeout.
227  *
228  * @param dev Watchdog device instance.
229  * @param channel_id Channel index.
230  *
231  * @retval 0 If successful.
232  * @retval -EAGAIN If completing the feed operation would stall the caller, for
233  * example due to an in-progress watchdog operation such as a previous
234  * wdt_feed() call.
235  * @retval -EINVAL If there is no installed timeout for supplied channel.
236  * @retval -errno In case of any other failure.
237  */
238 __syscall int wdt_feed(const struct device *dev, int channel_id);
239 
z_impl_wdt_feed(const struct device * dev,int channel_id)240 static inline int z_impl_wdt_feed(const struct device *dev, int channel_id)
241 {
242 	const struct wdt_driver_api *api =
243 		(const struct wdt_driver_api *)dev->api;
244 
245 	return api->feed(dev, channel_id);
246 }
247 
248 #ifdef __cplusplus
249 }
250 #endif
251 
252 /** @} */
253 
254 #include <syscalls/watchdog.h>
255 
256 #endif /* ZEPHYR_INCLUDE_DRIVERS_WATCHDOG_H_ */
257