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  *
30  * The wdt_ops structure contains a list of low-level operations
31  * that control a watchdog device.
32  */
33 struct wdt_ops {
34 	TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout,
35 			   unsigned long *max_timeout);
36 	void (*start)(struct wdt_chip *chip);
37 	void (*stop)(struct wdt_chip *chip);
38 	void (*ping)(struct wdt_chip *chip);
39 	TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout);
40 };
41 
42 #ifdef CFG_WDT
43 extern struct wdt_chip *wdt_chip;
44 
45 /* Register a watchdog as the system watchdog */
46 TEE_Result watchdog_register(struct wdt_chip *chip);
47 
48 static inline
watchdog_init(unsigned long * min_timeout,unsigned long * max_timeout)49 TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout)
50 {
51 	if (!wdt_chip)
52 		return TEE_ERROR_NOT_SUPPORTED;
53 
54 	if (!wdt_chip->ops->init)
55 		return TEE_SUCCESS;
56 
57 	return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout);
58 }
59 
watchdog_start(void)60 static inline void watchdog_start(void)
61 {
62 	if (wdt_chip)
63 		wdt_chip->ops->start(wdt_chip);
64 }
65 
watchdog_stop(void)66 static inline void watchdog_stop(void)
67 {
68 	if (wdt_chip && wdt_chip->ops->stop)
69 		wdt_chip->ops->stop(wdt_chip);
70 }
71 
watchdog_ping(void)72 static inline void watchdog_ping(void)
73 {
74 	if (wdt_chip)
75 		wdt_chip->ops->ping(wdt_chip);
76 }
77 
watchdog_settimeout(unsigned long timeout)78 static inline void watchdog_settimeout(unsigned long timeout)
79 {
80 	if (wdt_chip)
81 		wdt_chip->ops->set_timeout(wdt_chip, timeout);
82 }
83 #else
watchdog_register(struct wdt_chip * chip __unused)84 static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused)
85 {
86 	return TEE_ERROR_NOT_SUPPORTED;
87 }
88 
watchdog_init(unsigned long * min_timeout __unused,unsigned long * max_timeout __unused)89 static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused,
90 				       unsigned long *max_timeout __unused)
91 {
92 	return TEE_ERROR_NOT_SUPPORTED;
93 }
94 
watchdog_start(void)95 static inline void watchdog_start(void) {}
watchdog_stop(void)96 static inline void watchdog_stop(void) {}
watchdog_ping(void)97 static inline void watchdog_ping(void) {}
watchdog_settimeout(unsigned long timeout __unused)98 static inline void watchdog_settimeout(unsigned long timeout __unused) {}
99 #endif
100 
101 #ifdef CFG_WDT_SM_HANDLER
102 enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args);
103 
104 static inline
wdt_sm_handler(struct thread_smc_args * args)105 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args)
106 {
107 	if (args->a0 != CFG_WDT_SM_HANDLER_ID)
108 		return SM_HANDLER_PENDING_SMC;
109 
110 	return __wdt_sm_handler(args);
111 }
112 #else
113 static inline
wdt_sm_handler(struct thread_smc_args * args __unused)114 enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused)
115 {
116 	return SM_HANDLER_PENDING_SMC;
117 }
118 #endif
119 
120 #endif /* DRIVERS_WDT_H */
121