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.

390 lines
11 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2004-2020. All rights reserved.
* Description:user space api func
*/
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "soc_errno.h"
#include "soc_log.h"
#include "drv_ioctl_i2c.h"
#include "mpi_i2c_ext.h"
#undef LOG_MODULE_ID
#define LOG_MODULE_ID SOC_ID_I2C
#define GPIO_I2C_NUM 10
#define I2C_MAX_NUM (GPIO_I2C_START_POS + GPIO_I2C_NUM)
static td_s32 g_i2c_dev_fd = -1;
static td_s32 g_i2c_open = 0;
static pthread_mutex_t g_i2c_mutex = PTHREAD_MUTEX_INITIALIZER;
#define EXT_I2C_MAX_NUM_USER 15
#define GPIO_GROUP_MAX 31 /* slwd-c group is 31 */
#define check_i2c_open_return_if_fail() do { \
(void)pthread_mutex_lock(&g_i2c_mutex); \
if (g_i2c_dev_fd < 0) { \
soc_log_err("I2C is not open.\n"); \
(void)pthread_mutex_unlock(&g_i2c_mutex); \
return SOC_ERR_I2C_NOT_INIT; \
} \
(void)pthread_mutex_unlock(&g_i2c_mutex); \
} while (0)
/******************************************************
Function: uapi_i2c_init
Description: init i2c device
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
*******************************************************/
#define SOC_DEV_I2C_NAME "soc_i2c"
td_s32 ext_mpi_i2c_init(td_void)
{
(void)pthread_mutex_lock(&g_i2c_mutex);
if (g_i2c_dev_fd < 0) {
g_i2c_dev_fd = open("/dev/" SOC_DEV_I2C_NAME, O_RDWR, 0);
if (g_i2c_dev_fd < 0) {
soc_log_fatal("open I2C err.\n");
(void)pthread_mutex_unlock(&g_i2c_mutex);
return SOC_ERR_I2C_OPEN_ERR;
}
}
g_i2c_open++;
(void)pthread_mutex_unlock(&g_i2c_mutex);
return TD_SUCCESS;
}
/*******************************************************
Function: uapi_i2c_deinit
Description: deinit i2c device
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
********************************************************/
td_s32 ext_mpi_i2c_deinit(td_void)
{
td_s32 ret;
(void)pthread_mutex_lock(&g_i2c_mutex);
if (g_i2c_dev_fd < 0) {
(void)pthread_mutex_unlock(&g_i2c_mutex);
return TD_SUCCESS;
}
g_i2c_open--;
if (g_i2c_open == 0) {
ret = close(g_i2c_dev_fd);
if (ret != TD_SUCCESS) {
soc_log_fatal("Close I2C err.\n");
(void)pthread_mutex_unlock(&g_i2c_mutex);
return SOC_ERR_I2C_CLOSE_ERR;
}
g_i2c_dev_fd = -1;
}
(void)pthread_mutex_unlock(&g_i2c_mutex);
return TD_SUCCESS;
}
/*********************************************************************************************
Function: uapi_i2c_get_total_num
Description: Call this API to get the number of I2C module befor read/write data
Calls: NA
Data Accessed: NA
Data Updated: NA
Input: NA
Output: i2c_num - the number of I2C module
Return: ErrorCode(reference to document)
Others: NA
**********************************************************************************************/
td_s32 ext_mpi_i2c_get_total_num(td_u32 *i2c_num)
{
td_s32 ret;
td_u32 std_i2c_num = 0;
if (i2c_num == TD_NULL) {
soc_log_err("param i2c_num is null!\n");
return TD_FAILURE;
}
check_i2c_open_return_if_fail();
ret = ioctl(g_i2c_dev_fd, CMD_I2C_GETNUM, &std_i2c_num);
if (ret != TD_SUCCESS) {
soc_log_err("ioctl-CMD_I2C_GETNUM failed, ret:%#x\n", ret);
return ret;
}
*i2c_num = std_i2c_num;
return TD_SUCCESS;
}
/******************************************************
Function: uapi_i2c_read
Description: read data via i2c
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
*******************************************************/
td_s32 ext_mpi_i2c_read(td_u32 i2c_id, const ext_i2c_addr_info *i2c_addr_info, td_u8 *buf, td_u32 length)
{
td_s32 ret;
i2c_data data;
check_i2c_open_return_if_fail();
if (i2c_id >= I2C_MAX_NUM) {
soc_log_err("i2c_id is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
if (i2c_addr_info == TD_NULL) {
soc_log_err("i2c_addr_info is null !\n");
return SOC_ERR_I2C_NULL_PTR;
}
if (i2c_addr_info->reg_addr_count > 4) { /* max reg addr count is 4 */
soc_log_err("reg_addr_count is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
if (buf == TD_NULL) {
soc_log_err("penPressStatus is null.\n");
return SOC_ERR_I2C_NULL_PTR;
}
if ((length > EXT_I2C_MAX_LENGTH) || (length == 0)) {
soc_log_err("length is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
data.i2c_num = i2c_id;
data.i2c_dev_addr = i2c_addr_info->dev_address;
data.i2c_reg_addr = i2c_addr_info->reg_addr;
data.i2c_reg_count = i2c_addr_info->reg_addr_count;
data.buf = buf;
data.buf_len = length;
ret = ioctl(g_i2c_dev_fd, CMD_I2C_READ, &data);
if (ret != TD_SUCCESS) {
return ret;
}
return TD_SUCCESS;
}
/*******************************************
Function: uapi_i2c_write
Description: write data via i2c
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
*******************************************/
td_s32 ext_mpi_i2c_write(td_u32 i2c_id, const ext_i2c_addr_info *i2c_addr_info, td_u8 *buf, td_u32 length)
{
td_s32 ret;
i2c_data data;
check_i2c_open_return_if_fail();
if (i2c_id >= I2C_MAX_NUM) {
soc_log_err("para i2c_id is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
if (i2c_addr_info == TD_NULL) {
soc_log_err("para i2c_addr_info is null !\n");
return SOC_ERR_I2C_NULL_PTR;
}
if (i2c_addr_info->reg_addr_count > 4) { /* max reg addr count is 4 */
soc_log_err("para reg_addr_count is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
if (buf == TD_NULL) {
soc_log_err("para penPressStatus is null.\n");
return SOC_ERR_I2C_NULL_PTR;
}
if ((length > EXT_I2C_MAX_LENGTH) || (length == 0)) {
soc_log_err("para length is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
data.i2c_num = i2c_id;
data.i2c_dev_addr = i2c_addr_info->dev_address;
data.i2c_reg_addr = i2c_addr_info->reg_addr;
data.i2c_reg_count = i2c_addr_info->reg_addr_count;
data.buf = buf;
data.buf_len = length;
ret = ioctl(g_i2c_dev_fd, CMD_I2C_WRITE, &data);
if (ret != TD_SUCCESS) {
return ret;
}
return TD_SUCCESS;
}
/*******************************************
Function: uapi_i2c_create_gpio_i2c
Description: config param
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
*******************************************/
td_s32 ext_mpi_i2c_create_gpio_i2c(td_u32 scl_gpio_group, td_u32 scl_gpio_bit,
td_u32 sda_gpio_group, td_u32 sda_gpio_bit, td_u32 *i2c_id)
{
td_s32 ret;
td_u32 scl_gpio_num;
td_u32 sda_gpio_num;
i2c_gpio data;
check_i2c_open_return_if_fail();
if (scl_gpio_group >= GPIO_GROUP_MAX || sda_gpio_group >= GPIO_GROUP_MAX) {
soc_log_err("para scl_sda_gpio_group is invalid.\n");
return SOC_ERR_GPIO_INVALID_PARA;
}
if (scl_gpio_bit >= EXT_GPIO_GROUP_BIT || sda_gpio_bit >= EXT_GPIO_GROUP_BIT) {
soc_log_err("para scl_sda_gpio_bit is invalid\n");
return SOC_ERR_GPIO_INVALID_PARA;
}
scl_gpio_num = scl_gpio_group * EXT_GPIO_GROUP_BIT + scl_gpio_bit;
sda_gpio_num = sda_gpio_group * EXT_GPIO_GROUP_BIT + sda_gpio_bit;
if (i2c_id == TD_NULL) {
soc_log_err("para i2c_id is NULL.\n");
return SOC_ERR_I2C_NULL_PTR;
}
if (scl_gpio_num == sda_gpio_num) {
soc_log_err("scl_gpio_num == sda_gpio_num is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
data.scl_gpio_num = scl_gpio_num;
data.sda_gpio_num = sda_gpio_num;
data.is_used = TD_TRUE;
ret = ioctl(g_i2c_dev_fd, CMD_I2C_CONFIG, &data);
if (ret != TD_SUCCESS) {
soc_log_err(" CreateGpioI2c number failed .\n");
return ret;
}
*i2c_id = data.i2c_num;
return TD_SUCCESS;
}
/*******************************************
Function: uapi_i2c_destroy_gpio_i2c
Description: config param
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
*******************************************/
td_s32 ext_mpi_i2c_destroy_gpio_i2c(td_u32 i2c_id)
{
td_s32 ret;
i2c_gpio data;
check_i2c_open_return_if_fail();
if ((i2c_id < GPIO_I2C_START_POS) || (i2c_id >= I2C_MAX_NUM)) {
soc_log_err("para i2c_id = %d is invalid.\n", i2c_id);
return SOC_ERR_I2C_INVALID_PARA;
}
data.i2c_num = i2c_id;
data.scl_gpio_num = 0;
data.sda_gpio_num = 0;
data.is_used = TD_FALSE;
ret = ioctl(g_i2c_dev_fd, CMD_I2C_DESTROY, &data);
if (ret != TD_SUCCESS) {
return ret;
}
return TD_SUCCESS;
}
/*******************************************************
Function: uapi_i2c_set_rate
Description: set the rate
Data Accessed: NA
Data Updated: NA
Input: NA
Output: NA
Return: ErrorCode(reference to document)
Others: NA
********************************************************/
td_s32 ext_mpi_i2c_set_rate(td_u32 i2c_id, td_u32 rate_kbps)
{
td_s32 ret;
i2c_rate rate;
check_i2c_open_return_if_fail();
if (i2c_id >= GPIO_I2C_START_POS) {
soc_log_err("para i2c_id is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
if (rate_kbps > 400 * 1000) { /* max i2c rate is 400 * 1000 equal to 400K */
soc_log_err("para rate_kbps is invalid.\n");
return SOC_ERR_I2C_INVALID_PARA;
}
rate.i2c_num = i2c_id;
rate.rate_value = rate_kbps;
ret = ioctl(g_i2c_dev_fd, CMD_I2C_SET_RATE, &rate);
if (ret != TD_SUCCESS) {
return ret;
}
return TD_SUCCESS;
}