/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2004-2020. All rights reserved. * Description:user space api func */ #include #include #include #include #include #include #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; }