/* Copyright 2019 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ #ifndef METAL__WATCHDOG_H #define METAL__WATCHDOG_H /*! * @file watchdog.h * * @brief API for configuring watchdog timers */ #include struct metal_watchdog; /*! * @brief List of watchdog timer count behaviors */ enum metal_watchdog_run_option { METAL_WATCHDOG_STOP = 0, /*!< Stop the watchdog */ METAL_WATCHDOG_RUN_ALWAYS, /*!< Run the watchdog continuously, even during sleep */ METAL_WATCHDOG_RUN_AWAKE, /*!< Run the watchdog only while the CPU is awake */ }; /*! * @brief List of behaviors when a watchdog triggers */ enum metal_watchdog_result { METAL_WATCHDOG_NO_RESULT = 0, /*!< When the watchdog triggers, do nothing */ METAL_WATCHDOG_INTERRUPT, /*!< When the watchdog triggers, fire an interrupt */ METAL_WATCHDOG_FULL_RESET, /*!< When the watchdog triggers, cause a full system reset */ }; struct metal_watchdog_vtable { int (*feed)(const struct metal_watchdog *const wdog); long int (*get_rate)(const struct metal_watchdog *const wdog); long int (*set_rate)(const struct metal_watchdog *const wdog, const long int rate); long int (*get_timeout)(const struct metal_watchdog *const wdog); long int (*set_timeout)(const struct metal_watchdog *const wdog, const long int timeout); int (*set_result)(const struct metal_watchdog *const wdog, const enum metal_watchdog_result result); int (*run)(const struct metal_watchdog *const wdog, const enum metal_watchdog_run_option option); struct metal_interrupt *(*get_interrupt)(const struct metal_watchdog *const wdog); int (*get_interrupt_id)(const struct metal_watchdog *const wdog); int (*clear_interrupt)(const struct metal_watchdog *const wdog); }; /*! * @brief Handle for a Watchdog Timer */ struct metal_watchdog { const struct metal_watchdog_vtable *vtable; }; /*! * @brief Feed the watchdog timer */ inline int metal_watchdog_feed(const struct metal_watchdog *const wdog) { return wdog->vtable->feed(wdog); } /*! * @brief Get the rate of the watchdog timer in Hz * * @return the rate of the watchdog timer */ inline long int metal_watchdog_get_rate(const struct metal_watchdog *const wdog) { return wdog->vtable->get_rate(wdog); } /*! * @brief Set the rate of the watchdog timer in Hz * * There is no guarantee that the new rate will match the requested rate. * * @return the new rate of the watchdog timer */ inline long int metal_watchdog_set_rate(const struct metal_watchdog *const wdog, const long int rate) { return wdog->vtable->set_rate(wdog, rate); } /*! * @brief Get the timeout of the watchdog timer * * @return the watchdog timeout value */ inline long int metal_watchdog_get_timeout(const struct metal_watchdog *const wdog) { return wdog->vtable->get_timeout(wdog); } /*! * @brief Set the timeout of the watchdog timer * * The set rate will be the minimimum of the requested and maximum supported rates. * * @return the new watchdog timeout value */ inline long int metal_watchdog_set_timeout(const struct metal_watchdog *const wdog, const long int timeout) { return wdog->vtable->set_timeout(wdog, timeout); } /*! * @brief Sets the result behavior of a watchdog timer timeout * * @return 0 if the requested result behavior is supported */ inline int metal_watchdog_set_result(const struct metal_watchdog *const wdog, const enum metal_watchdog_result result) { return wdog->vtable->set_result(wdog, result); } /*! * @brief Set the run behavior of the watchdog * * Used to enable/disable the watchdog timer * * @return 0 if the watchdog was successfully started/stopped */ inline int metal_watchdog_run(const struct metal_watchdog *const wdog, const enum metal_watchdog_run_option option) { return wdog->vtable->run(wdog, option); } /*! * @brief Get the interrupt controller for the watchdog interrupt */ inline struct metal_interrupt *metal_watchdog_get_interrupt(const struct metal_watchdog *const wdog) { return wdog->vtable->get_interrupt(wdog); } /*! * @Brief Get the interrupt id for the watchdog interrupt */ inline int metal_watchdog_get_interrupt_id(const struct metal_watchdog *const wdog) { return wdog->vtable->get_interrupt_id(wdog); } /*! * @brief Clear the watchdog interrupt */ inline int metal_watchdog_clear_interrupt(const struct metal_watchdog *const wdog) { return wdog->vtable->clear_interrupt(wdog); } /*! * @brief Get a watchdog handle */ struct metal_watchdog *metal_watchdog_get_device(const int index); #endif /* METAL__WATCHDOG_H */