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