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