/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2004-2021. All rights reserved. * Description:wdg mpi layer api define */ #include #include #include #include #include #include #include #include #include #include "soc_log.h" #include "td_type.h" #include "soc_errno.h" static td_s32 g_wdg_dev_fd = 0; #undef LOG_MODULE_ID #define LOG_MODULE_ID SOC_ID_WDG #define WATCHDOG_TIMEOUT_MAX 179000 #define WATCHDOG_TIMEOUT_MIN 1000 #define EXT_WDG_NUM 1 static pthread_mutex_t g_wdg_mutex = PTHREAD_MUTEX_INITIALIZER; static td_void ext_wdg_lock(td_void) { (void)pthread_mutex_lock(&g_wdg_mutex); } static td_void ext_wdg_unlock(td_void) { (void)pthread_mutex_unlock(&g_wdg_mutex); } /* * Function: ext_mpi_wdg_init * Description: Init WDG devide * Calls: EXT_WDG_Open * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_init(td_void) { td_s32 dev_fd = 0; td_s32 ret = 0; td_s32 option = 0; ext_wdg_lock(); if (g_wdg_dev_fd > 0) { ret = TD_SUCCESS; goto exit; } dev_fd = open("/dev/watchdog", O_RDWR, 0); if (dev_fd < 0) { soc_log_err("open /dev/watchdog faild:%d\n", errno); ret = SOC_ERR_WDG_FAILED_INIT; goto exit; } g_wdg_dev_fd = dev_fd; option = WDIOS_DISABLECARD; ret = ioctl(g_wdg_dev_fd, WDIOC_SETOPTIONS, &option); if (ret != TD_SUCCESS) { soc_log_err("wdg disable failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_DISABLE; close(dev_fd); g_wdg_dev_fd = 0; goto exit; } ret = TD_SUCCESS; exit: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_deinit * Description: Deinit WDG device * Calls: EXT_WDG_Close * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_deinit(td_void) { td_s32 ret; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { ret = TD_SUCCESS; goto exit; } ret = close(g_wdg_dev_fd); if (ret != TD_SUCCESS) { soc_log_fatal("DeInit WDG err:%d\n", ret); ret = SOC_ERR_WDG_FAILED_DEINIT; goto exit; } g_wdg_dev_fd = 0; ret = TD_SUCCESS; exit: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_get_num * Description: get WDG device capability * Calls: EXT_WDG_Enable * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_get_num(td_u32 *wdg_num) { td_s32 ret; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if (wdg_num == TD_NULL) { soc_log_err("para value is null.\n"); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } *wdg_num = EXT_WDG_NUM; ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_enable * Description: enable WDG device * Calls: EXT_WDG_Enable * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_enable(td_u32 wdg_num) { td_s32 ret; td_s32 option; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if (wdg_num >= EXT_WDG_NUM) { soc_log_err("Input parameter(wdg_num) invalid: %d\n", wdg_num); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } option = WDIOS_ENABLECARD; ret = ioctl(g_wdg_dev_fd, WDIOC_SETOPTIONS, &option); if (ret != TD_SUCCESS) { soc_log_err("wdg enable failed:%d, ret:%d\n", errno, ret); ret = SOC_ERR_WDG_FAILED_ENABLE; goto err; } ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_disable * Description: disable WDG device * Calls: EXT_WDG_Disable * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_disable(td_u32 wdg_num) { td_s32 ret; td_s32 option; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if (wdg_num >= EXT_WDG_NUM) { soc_log_err("Input parameter(wdg_num) invalid: %d\n", wdg_num); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } option = WDIOS_DISABLECARD; ret = ioctl(g_wdg_dev_fd, WDIOC_SETOPTIONS, &option); if (ret != TD_SUCCESS) { soc_log_err("wdg disable failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_DISABLE; goto err; } ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_set_timeout * Description: set the time interval of feeding the WDG * Calls: EXT_WDG_SetTimeout * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_set_timeout(td_u32 wdg_num, td_u32 value) { td_s32 ret = 0; td_u32 value_in_sec; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if ((wdg_num >= EXT_WDG_NUM) || (value > WATCHDOG_TIMEOUT_MAX) || (value < WATCHDOG_TIMEOUT_MIN)) { soc_log_err("Input parameter(value) invalid: %d\n", value); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } /* convert ms to s */ value_in_sec = (value + 999) / 1000; /* 999 1000 convert ms to s */ ret = ioctl(g_wdg_dev_fd, WDIOC_SETTIMEOUT, &value_in_sec); if (ret != TD_SUCCESS) { soc_log_err("wdg set timeout failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_SETTIMEOUT; goto err; } ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_get_timeout * Description: get the time interval of feeding the WDG * Calls: EXT_WDG_GetTimeout * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_get_timeout(td_u32 wdg_num, td_u32 *value) { td_s32 ret = 0; td_u32 temp_value = 0; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if ((wdg_num >= EXT_WDG_NUM) || (value == TD_NULL)) { soc_log_err("para value is null.\n"); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } ret = ioctl(g_wdg_dev_fd, WDIOC_GETTIMEOUT, &temp_value); if (ret != TD_SUCCESS) { soc_log_err("wdg get timeout failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_GETTIMEOUT; goto err; } /* convert s to ms */ *value = 1000 * temp_value; /* 1s equal to 1000ms */ ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_clear * Description: clear the WDG * Calls: EXT_WDG_ClearWatchDog * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_clear(td_u32 wdg_num) { td_s32 ret = 0; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if (wdg_num >= EXT_WDG_NUM) { soc_log_err("Input parameter(wdg_num) invalid: %d\n", wdg_num); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } ret = ioctl(g_wdg_dev_fd, WDIOC_KEEPALIVE, NULL); if (ret != TD_SUCCESS) { soc_log_err("clear wdg failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_CLEARWDG; goto err; } ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; } /* * Function: ext_mpi_wdg_reset * Description: reset WDG * Calls: EXT_WDG_Reset * Data Accessed: NA * Data Updated: NA * Input: NA * Output: NA * Return: ErrorCode(reference to document) * Others: NA */ td_s32 ext_mpi_wdg_reset(td_u32 wdg_num) { td_s32 ret = 0; td_s32 option = 0; td_s32 timeout = 0; ext_wdg_lock(); if (g_wdg_dev_fd <= 0) { soc_log_err("file descriptor is illegal\n"); ret = SOC_ERR_WDG_NOT_INIT; goto err; } if (wdg_num >= EXT_WDG_NUM) { soc_log_err("Input parameter(wdg_num) invalid: %d\n", wdg_num); ret = SOC_ERR_WDG_INVALID_PARA; goto err; } option = WDIOS_ENABLECARD; ret = ioctl(g_wdg_dev_fd, WDIOC_SETOPTIONS, &option); if (ret != TD_SUCCESS) { soc_log_err("enable failed:%d\n", errno); ret = SOC_ERR_WDG_FAILED_RESET; goto err; } timeout = 1; ret = ioctl(g_wdg_dev_fd, WDIOC_SETTIMEOUT, &timeout); if (ret != TD_SUCCESS) { soc_log_err("reset failed\n"); ret = SOC_ERR_WDG_FAILED_RESET; goto err; } ret = TD_SUCCESS; err: ext_wdg_unlock(); return ret; }