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
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;
|
|
}
|