xref: /optee_os/core/include/drivers/wdt.h (revision cb60bce4e53eb6760bc6e27517a45eb55a09a3a9)
1cbb41c91SAbhishek Shah /* SPDX-License-Identifier: BSD-2-Clause */
2cbb41c91SAbhishek Shah /*
3cbb41c91SAbhishek Shah  * Copyright 2019 Broadcom.
4cbb41c91SAbhishek Shah  */
5cbb41c91SAbhishek Shah 
6cbb41c91SAbhishek Shah #ifndef DRIVERS_WDT_H
7cbb41c91SAbhishek Shah #define DRIVERS_WDT_H
8cbb41c91SAbhishek Shah 
9011a8f96SClément Léger #include <assert.h>
10cbb41c91SAbhishek Shah #include <kernel/interrupt.h>
11*cb60bce4SClément Léger #include <kernel/thread.h>
12*cb60bce4SClément Léger #include <sm/sm.h>
13cbb41c91SAbhishek Shah #include <tee_api_types.h>
14cbb41c91SAbhishek Shah 
15cbb41c91SAbhishek Shah struct wdt_chip {
16cbb41c91SAbhishek Shah 	const struct wdt_ops *ops;
17cbb41c91SAbhishek Shah 	struct itr_handler *wdt_itr;
18cbb41c91SAbhishek Shah };
19cbb41c91SAbhishek Shah 
20cbb41c91SAbhishek Shah /*
21cbb41c91SAbhishek Shah  * struct wdt_ops - The watchdog device operations
22cbb41c91SAbhishek Shah  *
23011a8f96SClément Léger  * @init:	The routine to initialized the watchdog resources.
24cbb41c91SAbhishek Shah  * @start:	The routine for starting the watchdog device.
25cbb41c91SAbhishek Shah  * @stop:	The routine for stopping the watchdog device.
26cbb41c91SAbhishek Shah  * @ping:	The routine that sends a keepalive ping to the watchdog device.
27cbb41c91SAbhishek Shah  * @set_timeout:The routine that finds the load value that will reset system in
28cbb41c91SAbhishek Shah  * required timeout (in seconds).
29cbb41c91SAbhishek Shah  *
30cbb41c91SAbhishek Shah  * The wdt_ops structure contains a list of low-level operations
31cbb41c91SAbhishek Shah  * that control a watchdog device.
32cbb41c91SAbhishek Shah  */
33cbb41c91SAbhishek Shah struct wdt_ops {
34011a8f96SClément Léger 	TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout,
35011a8f96SClément Léger 			   unsigned long *max_timeout);
36cbb41c91SAbhishek Shah 	void (*start)(struct wdt_chip *chip);
37cbb41c91SAbhishek Shah 	void (*stop)(struct wdt_chip *chip);
38cbb41c91SAbhishek Shah 	void (*ping)(struct wdt_chip *chip);
39cbb41c91SAbhishek Shah 	TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout);
40cbb41c91SAbhishek Shah };
41cbb41c91SAbhishek Shah 
42011a8f96SClément Léger #ifdef CFG_WDT
43011a8f96SClément Léger extern struct wdt_chip *wdt_chip;
44011a8f96SClément Léger 
45011a8f96SClément Léger /* Register a watchdog as the system watchdog */
46011a8f96SClément Léger TEE_Result watchdog_register(struct wdt_chip *chip);
47011a8f96SClément Léger 
48011a8f96SClément Léger static inline
49011a8f96SClément Léger TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout)
50011a8f96SClément Léger {
51011a8f96SClément Léger 	if (!wdt_chip)
52011a8f96SClément Léger 		return TEE_ERROR_NOT_SUPPORTED;
53011a8f96SClément Léger 
54011a8f96SClément Léger 	if (!wdt_chip->ops->init)
55011a8f96SClément Léger 		return TEE_SUCCESS;
56011a8f96SClément Léger 
57011a8f96SClément Léger 	return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout);
58011a8f96SClément Léger }
59011a8f96SClément Léger 
60011a8f96SClément Léger static inline void watchdog_start(void)
61011a8f96SClément Léger {
62011a8f96SClément Léger 	if (wdt_chip)
63011a8f96SClément Léger 		wdt_chip->ops->start(wdt_chip);
64011a8f96SClément Léger }
65011a8f96SClément Léger 
66011a8f96SClément Léger static inline void watchdog_stop(void)
67011a8f96SClément Léger {
68011a8f96SClément Léger 	if (wdt_chip && wdt_chip->ops->stop)
69011a8f96SClément Léger 		wdt_chip->ops->stop(wdt_chip);
70011a8f96SClément Léger }
71011a8f96SClément Léger 
72011a8f96SClément Léger static inline void watchdog_ping(void)
73011a8f96SClément Léger {
74011a8f96SClément Léger 	if (wdt_chip)
75011a8f96SClément Léger 		wdt_chip->ops->ping(wdt_chip);
76011a8f96SClément Léger }
77011a8f96SClément Léger 
78011a8f96SClément Léger static inline void watchdog_settimeout(unsigned long timeout)
79011a8f96SClément Léger {
80011a8f96SClément Léger 	if (wdt_chip)
81011a8f96SClément Léger 		wdt_chip->ops->set_timeout(wdt_chip, timeout);
82011a8f96SClément Léger }
83011a8f96SClément Léger #else
84011a8f96SClément Léger static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused)
85011a8f96SClément Léger {
86011a8f96SClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
87011a8f96SClément Léger }
88011a8f96SClément Léger 
89011a8f96SClément Léger static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused,
90011a8f96SClément Léger 				       unsigned long *max_timeout __unused)
91011a8f96SClément Léger {
92011a8f96SClément Léger 	return TEE_ERROR_NOT_SUPPORTED;
93011a8f96SClément Léger }
94011a8f96SClément Léger 
95011a8f96SClément Léger static inline void watchdog_start(void) {}
96011a8f96SClément Léger static inline void watchdog_stop(void) {}
97011a8f96SClément Léger static inline void watchdog_ping(void) {}
98011a8f96SClément Léger static inline void watchdog_settimeout(unsigned long timeout __unused) {}
99011a8f96SClément Léger #endif
100011a8f96SClément Léger 
101*cb60bce4SClément Léger #ifdef CFG_WDT_SM_HANDLER
102*cb60bce4SClément Léger enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args);
103*cb60bce4SClément Léger 
104*cb60bce4SClément Léger static inline
105*cb60bce4SClément Léger enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args)
106*cb60bce4SClément Léger {
107*cb60bce4SClément Léger 	if (args->a0 != CFG_WDT_SM_HANDLER_ID)
108*cb60bce4SClément Léger 		return SM_HANDLER_PENDING_SMC;
109*cb60bce4SClément Léger 
110*cb60bce4SClément Léger 	return __wdt_sm_handler(args);
111*cb60bce4SClément Léger }
112*cb60bce4SClément Léger #else
113*cb60bce4SClément Léger static inline
114*cb60bce4SClément Léger enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused)
115*cb60bce4SClément Léger {
116*cb60bce4SClément Léger 	return SM_HANDLER_PENDING_SMC;
117*cb60bce4SClément Léger }
118*cb60bce4SClément Léger #endif
119*cb60bce4SClément Léger 
120cbb41c91SAbhishek Shah #endif /* DRIVERS_WDT_H */
121