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