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