You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

558 lines
17 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2008-2019. All rights reserved.
* Description:supply the api for userspace application
*/
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#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;
}