/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2008-2019. All rights reserved. * Description:supply the api for userspace application */ #include #include #include #include #include "mpi_gpio_ext.h" #include "drv_ioctl_gpio.h" #include "soc_errno.h" #include "soc_log.h" #undef LOG_MODULE_ID #define LOG_MODULE_ID SOC_ID_GPIO static td_s32 g_gpio_drv_fd = -1; static td_s32 g_gpio_open = 0; static pthread_mutex_t g_gpio_mutex = PTHREAD_MUTEX_INITIALIZER; #define ext_gpio_lock() (td_void)pthread_mutex_lock(&g_gpio_mutex) #define ext_gpio_unlock() (td_void)pthread_mutex_unlock(&g_gpio_mutex) #define EXT_GPIO_NUMBER_MAX 248 /* slwd-c group is 248 */ #define SOC_DEV_GPIO_NAME "soc_gpio" static gpio_get_gpio_num g_gpio_num; td_s32 ext_mpi_gpio_init(td_void) { td_s32 ret; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { g_gpio_drv_fd = open("/dev/" SOC_DEV_GPIO_NAME, O_RDWR, 0); if (g_gpio_drv_fd < 0) { soc_log_err("open GPIO device failed.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_OPEN_ERR; } ret = ioctl(g_gpio_drv_fd, CMD_GPIO_GET_GPIONUM, &g_gpio_num); if (ret != TD_SUCCESS) { soc_log_err("ioctl CMD_GPIO_GET_CHIPTYPE failed.\n"); close(g_gpio_drv_fd); g_gpio_drv_fd = -1; ext_gpio_unlock(); return TD_FAILURE; } if (g_gpio_num.gpio_group_num == 0) { soc_log_err("gpio_group_num is zero.\n"); close(g_gpio_drv_fd); g_gpio_drv_fd = -1; ext_gpio_unlock(); return TD_FAILURE; } } g_gpio_open++; ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_deinit(td_void) { ext_gpio_lock(); if (g_gpio_drv_fd < 0) { ext_gpio_unlock(); return TD_SUCCESS; } g_gpio_open--; if (g_gpio_open == 0) { close(g_gpio_drv_fd); g_gpio_drv_fd = -1; } ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_set_direction(td_u32 group_number, td_u32 bit_number, td_bool input) { gpio_direction gpio_dir; td_s32 ret; td_u32 gpio_number; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio set direction: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio set direction: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio set direction: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio set direction: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if ((input != TD_TRUE) && (input != TD_FALSE)) { soc_log_err("gpio set direction: para input is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } gpio_number = group_number * group_bit_number + bit_number; gpio_dir.gpio_num = gpio_number; gpio_dir.input = input; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_SET_DIRECTION, &gpio_dir); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETDIRECT; } ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_get_direction(td_u32 group_number, td_u32 bit_number, td_bool *input) { gpio_direction gpio_dir; td_s32 ret; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio get direction: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio get direction: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio get direction: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio get direction: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (input == TD_NULL) { soc_log_err("gpio get direction: para input is null.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NULL_PTR; } gpio_dir.gpio_num = group_number * group_bit_number + bit_number; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_GET_DIRECTION, &gpio_dir); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETDIRECT; } *input = gpio_dir.input; ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_write(td_u32 group_number, td_u32 bit_number, td_bool high_volt) { gpio_value gpio_val; td_s32 ret; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio write: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio write: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio write: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio write: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if ((high_volt != TD_TRUE) && (high_volt != TD_FALSE)) { soc_log_err("gpio write: para high_volt is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } gpio_val.gpio_num = group_number * group_bit_number + bit_number; gpio_val.set = high_volt; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_WRITE_BIT, &gpio_val); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETVALUE; } ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_read(td_u32 group_number, td_u32 bit_number, td_bool *high_volt) { gpio_value gpio_val; td_s32 ret; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio read: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio read: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio read: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio read: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (high_volt == TD_NULL) { soc_log_err("gpio read: para high_volt is null.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NULL_PTR; } gpio_val.gpio_num = group_number * group_bit_number + bit_number; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_READ_BIT, &gpio_val); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETVALUE; } *high_volt = gpio_val.set; ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_set_output_type(td_u32 group_number, td_u32 bit_number, ext_mpi_gpio_output_type output_type) { td_s32 ret; gpio_output_type out_type; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio set output type: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio set output type: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio set output type: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio set output type: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (output_type >= EXT_MPI_GPIO_OUTPUTTYPE_MAX) { soc_log_err("gpio set output type: para output_type is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } out_type.gpio_num = group_number * group_bit_number + bit_number; out_type.output_type = (ext_gpio_outputtype)output_type; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_SET_OUTPUTTYPE, &out_type); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETOUTPUTTYPE; } ext_gpio_unlock(); return ret; } td_s32 ext_mpi_gpio_get_output_type(td_u32 group_number, td_u32 bit_number, ext_mpi_gpio_output_type *output_type) { td_s32 ret; gpio_output_type out_type; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio get output type: GPIO is not open.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio get output type: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio get output type: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio get output type: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (output_type == TD_NULL) { soc_log_err("gpio get output type: para output_type is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } out_type.gpio_num = group_number * group_bit_number + bit_number; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_GET_OUTPUTTYPE, &out_type); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_GETOUTPUTTYPE; } *output_type = (ext_mpi_gpio_output_type)out_type.output_type; ext_gpio_unlock(); return ret; } td_s32 ext_mpi_gpio_set_interrupt_type(td_u32 group_number, td_u32 bit_number, ext_mpi_gpio_interrupt_type interrupt_type) { td_s32 ret; gpio_data gpio_interrupt_type; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio set interrupt type: GPIO dev has not open. fd = %d \n", g_gpio_drv_fd); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio set interrupt type: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio set interrupt type: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio set interrupt type: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (interrupt_type >= EXT_MPI_GPIO_INTTYPE_MAX) { soc_log_err("gpio set interrupt type: para interrupt_type is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } gpio_interrupt_type.gpio_num = group_number * group_bit_number + bit_number; gpio_interrupt_type.interrupt_type = (ext_gpio_interrupt_type)interrupt_type; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_SET_INT_TYPE, &gpio_interrupt_type); if (ret != TD_SUCCESS) { soc_log_err("gpio set interrupt type: set gpio interruput type ioctl failed .ret = %x \n", ret); ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETINT; } ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_set_interrupt_enable(td_u32 group_number, td_u32 bit_number, td_bool enable) { td_s32 ret; gpio_data gpio_interrupt_enable; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio set interrupt enable: GPIO dev has not open. fd = %d \n", g_gpio_drv_fd); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_number * group_bit_number > EXT_GPIO_NUMBER_MAX) { soc_log_err("gpio set interrupt enable: para gpio_num is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number >= g_gpio_num.gpio_group_num) { soc_log_err("gpio set interrupt enable: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number >= group_bit_number) { soc_log_err("gpio set interrupt enable: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if ((enable != TD_TRUE) && (enable != TD_FALSE)) { soc_log_err("gpio set interrupt enable: para enable is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } gpio_interrupt_enable.gpio_num = group_number * group_bit_number + bit_number; gpio_interrupt_enable.enable = enable; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_SET_INT_ENABLE, &gpio_interrupt_enable); if (ret != TD_SUCCESS) { soc_log_err("gpio set interrupt enable: set gpio enabel or disabel ioctl failed .ret = %x \n", ret); ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_SETENABLE; } ext_gpio_unlock(); return TD_SUCCESS; } td_s32 ext_mpi_gpio_query_interrupt(td_u32 *group_number, td_u32 *bit_number, td_u32 timeout_ms) { td_s32 ret; gpio_interrupt gpio_interrupt_value; td_u32 group_bit_number; ext_gpio_lock(); if (g_gpio_drv_fd < 0) { soc_log_err("gpio query interrupt: GPIO dev has not open. fd = %d \n", g_gpio_drv_fd); ext_gpio_unlock(); return SOC_ERR_GPIO_NOT_INIT; } group_bit_number = g_gpio_num.gpio_max_num / g_gpio_num.gpio_group_num; if (group_bit_number == 0) { soc_log_err("gpio query interrupt: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (group_number == NULL) { soc_log_err("gpio query interrupt: para group_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } if (bit_number == NULL) { soc_log_err("gpio query interrupt: para bit_number is invalid.\n"); ext_gpio_unlock(); return SOC_ERR_GPIO_INVALID_PARA; } gpio_interrupt_value.timeout_ms = timeout_ms; ret = ioctl(g_gpio_drv_fd, CMD_GPIO_GET_INT, &gpio_interrupt_value); if (ret != TD_SUCCESS) { ext_gpio_unlock(); return SOC_ERR_GPIO_FAILED_GETINT; } *group_number = gpio_interrupt_value.gpio_num / group_bit_number; *bit_number = gpio_interrupt_value.gpio_num % group_bit_number; ext_gpio_unlock(); return TD_SUCCESS; }