xref: /optee_os/core/include/drivers/wdt.h (revision a7f2d4bd86327253733ce88d2160e4d02b8349b7)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright 2019 Broadcom.
4  */
5 
6 #ifndef __DRIVERS_WDT_H
7 #define __DRIVERS_WDT_H
8 
9 #include <assert.h>
10 #include <kernel/interrupt.h>
11 #include <kernel/thread.h>
12 #include <sm/sm.h>
13 #include <tee_api_types.h>
14 
15 struct wdt_chip {
16 	const struct wdt_ops *ops;
17 	struct itr_handler *wdt_itr;
18 };
19 
20 /*
21  * struct wdt_ops - The watchdog device operations
22  *
23  * @init:	The routine to initialized the watchdog resources.
24  * @start:	The routine for starting the watchdog device.
25  * @stop:	The routine for stopping the watchdog device.
26  * @ping:	The routine that sends a keepalive ping to the watchdog device.
27  * @set_timeout:The routine that finds the load value that will reset system in
28  * required timeout (in seconds).
29  * @get_timeleft:The optional routine that finds if the watchdog is already
30  * started and the time left (in seconds) before the watchdog timeouts.
31  *
32  * The wdt_ops structure contains a list of low-level operations
33  * that control a watchdog device.
34  */
35 struct wdt_ops {
36 	TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout,
37 			   unsigned long *max_timeout);
38 	void (*start)(struct wdt_chip *chip);
39 	void (*stop)(struct wdt_chip *chip);
40 	void (*ping)(struct wdt_chip *chip);
41 	TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout);
42 	TEE_Result (*get_timeleft)(struct wdt_chip *chip, bool *is_started,
43 				   unsigned long *timeleft);
44 };
45 
46 #ifdef CFG_WDT
47 extern struct wdt_chip *wdt_chip;
48 
49 /* Register a watchdog as the system watchdog */
50 TEE_Result watchdog_register(struct wdt_chip *chip);
51 
52 static inline
watchdog_init(unsigned long * min_timeout,unsigned long * max_timeout)53 TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout)
54 {
55 	if (!wdt_chip)
56 		return TEE_ERROR_NOT_SUPPORTED;
57 
58 	if (!wdt_chip->ops->init)
59 		return TEE_SUCCESS;
60 
61 	return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout);
62 }
63 
watchdog_start(void)64 static inline void watchdog_start(void)
65 {
66 	if (wdt_chip)
67 		wdt_chip->ops->start(wdt_chip);
68 }
69 
watchdog_stop(void)70 static inline void watchdog_stop(void)
71 {
72 	if (wdt_chip && wdt_chip->ops->stop)
73 		wdt_chip->ops->stop(wdt_chip);
74 }
75 
watchdog_ping(void)76 static inline void watchdog_ping(void)
77 {
78 	if (wdt_chip)
79 		wdt_chip->ops->ping(wdt_chip);
80 }
81 
watchdog_settimeout(unsigned long timeout)82 static inline void watchdog_settimeout(unsigned long timeout)
83 {
84 	if (wdt_chip)
85 		wdt_chip->ops->set_timeout(wdt_chip, timeout);
86 }
87 
88 /*
89  * watchdog_gettimeleft() - Get the time left before the watchdog timeouts
90  * @is_started: [out] true if watchdog has started, false otherwise
91  * @timeleft: [out] time left in seconds before expiration if @is_started==true
92  */
watchdog_gettimeleft(bool * is_started,unsigned long * timeleft)93 static inline TEE_Result watchdog_gettimeleft(bool *is_started,
94 					      unsigned long *timeleft)
95 {
96 	if (!wdt_chip || !wdt_chip->ops->get_timeleft)
97 		return TEE_ERROR_NOT_SUPPORTED;
98 
99 	return wdt_chip->ops->get_timeleft(wdt_chip, is_started, timeleft);
100 }
101 #else
watchdog_register(struct wdt_chip * chip __unused)102 static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused)
103 {
104 	return TEE_ERROR_NOT_SUPPORTED;
105 }
106 
watchdog_init(unsigned long * min_timeout __unused,unsigned long * max_timeout __unused)107 static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused,
108 				       unsigned long *max_timeout __unused)
109 {
110 	return TEE_ERROR_NOT_SUPPORTED;
111 }
112 
watchdog_start(void)113 static inline void watchdog_start(void) {}
watchdog_stop(void)114 static inline void watchdog_stop(void) {}
watchdog_ping(void)115 static inline void watchdog_ping(void) {}
watchdog_settimeout(unsigned long timeout __unused)116 static inline void watchdog_settimeout(unsigned long timeout __unused) {}
watchdog_gettimeleft(bool * is_started __unused,unsigned long * timeleft __unused)117 static inline TEE_Result watchdog_gettimeleft(bool *is_started __unused,
118 					      unsigned long *timeleft __unused)
119 {
120 	return TEE_ERROR_NOT_SUPPORTED;
121 }
122 #endif
123 
124 #ifdef CFG_WDT_SM_HANDLER
125 enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args);
126 
127 static inline
wdt_sm_handler(struct thread_smc_args * args)128 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args)
129 {
130 	if (args->a0 != CFG_WDT_SM_HANDLER_ID)
131 		return SM_HANDLER_PENDING_SMC;
132 
133 	return __wdt_sm_handler(args);
134 }
135 #else
136 static inline
wdt_sm_handler(struct thread_smc_args * args __unused)137 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused)
138 {
139 	return SM_HANDLER_PENDING_SMC;
140 }
141 #endif
142 
143 #endif /* __DRIVERS_WDT_H */
144