Files
kunlun/driver/extern/ext-io/src/iot_gpio_ex_tca9534a.c

396 lines
11 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
/****************************************************************************
*
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
*
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
* be copied by any method or incorporated into another program without
* the express written consent of Aerospace C.Power. This Information or any portion
* thereof remains the property of Aerospace C.Power. The Information contained herein
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
* liability for its use in any way and conveys no license or title under
* any patent or copyright and makes no representation or warranty that this
* Information is free from patent or copyright infringement.
*
* ****************************************************************************/
#include "iot_errno.h"
#include "iot_i2c_api.h"
#include "iot_config_api.h"
#include "iot_io_api.h"
#include "iot_board_api.h"
#include "os_utils_api.h"
#include "iot_gpio_ex.h"
#include "iot_gpio_api.h"
#include "gpio.h"
/* The iic config of tca9534a. */
#define TCA9534A_SLAVER_ADDR (0x38)
#define TCA9534A_INIT_COMPLETED (1)
#define TCA9534A_INIT_UNCOMPLETED (0)
#define TCA9534A_IIC_DEF_PORT (1) /* Port#0. */
#define TCA9534A_IIC_DEF_SPEED (400) /* 400K. */
#define TCA9534A_IIC_DEF_NACK_NUM (10) /* N-ACK number. */
/* The gpio value addressof tca9534a. */
#define TCA9534A_INPUT_PORT_REG0 (0x00)
#define TCA9534A_OUTPUT_PORT_REG1 (0x01)
#define TCA9534A_POLARITY_INV_REG2 (0x02)
#define TCA9534A_DIRECTION_CONF_REG3 (0x03)
/* tca9534a response time: ms. */
#define TCA9534A_REGISTER_RESPONSE_TM (1)
/* gpio number */
#define TCA9534A_GPIO_NUMBER (8)
#define TCA9534A_GPIO_VALID(gpio) (((gpio) >= 0) && \
((gpio) < TCA9534A_GPIO_NUMBER))
typedef struct _tca9534a_iic_cfg {
uint8_t inited; /* IIC initialization done. 0-not yet, 1-done.*/
uint8_t port; /* IIC port number. */
uint32_t baud; /* IIC baudrate, unit is Kb. */
uint8_t nack_wait_num; /* wait nack number. */
uint16_t gpio_scl; /* SCL gpio pin. */
uint16_t gpio_sda; /* SDA gpio pin. */
} tca9534a_iic_cfg_t;
static tca9534a_iic_cfg_t tca9534a_iic_cfg =
{
TCA9534A_INIT_UNCOMPLETED, /* IIC initialization uncompleted. */
TCA9534A_IIC_DEF_PORT, /* IIC device port number. */
TCA9534A_IIC_DEF_SPEED, /* Baudrate, unit is Kb. */
TCA9534A_IIC_DEF_NACK_NUM, /* Wait nack number. */
0, /* SCL gpio pin. */
0 /* SDA gpio pin. */
};
static os_mutex_h gpio_ext_mutex = NULL;
static uint8_t tca9534a_i2c_write_reg(uint8_t reg_addr, uint8_t val)
{
uint8_t ret = ERR_FAIL;
char buf[2] = {0};
buf[0] = reg_addr;
buf[1] = val;
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d\n", __FUNCTION__, reg_addr,
val);
ret = iot_i2c_write(tca9534a_iic_cfg.port, TCA9534A_SLAVER_ADDR, buf, 2);
os_delay(TCA9534A_REGISTER_RESPONSE_TM);
if (ret != ERR_OK) {
iot_printf("[%s][err] i2c write data error\n", __FUNCTION__);
goto out;
}
out:
return ret;
}
static uint8_t tca9534a_i2c_read_reg(uint8_t reg_addr, uint8_t *data,
uint8_t len)
{
uint8_t ret = ERR_FAIL;
char buf[2] = {0};
buf[0] = reg_addr;
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d, arg3:%d\n", __FUNCTION__,
reg_addr, *data, len);
if ((data == NULL) || (len == 0)) {
return ERR_FAIL;
}
ret = iot_i2c_write(tca9534a_iic_cfg.port, TCA9534A_SLAVER_ADDR, buf, 1);
os_delay(TCA9534A_REGISTER_RESPONSE_TM);
if (ret != ERR_OK) {
iot_printf("[%s][err] i2c write data error\n", __FUNCTION__);
goto out;
}
ret = iot_i2c_read(tca9534a_iic_cfg.port, TCA9534A_SLAVER_ADDR,
(char *)data, len);
os_delay(TCA9534A_REGISTER_RESPONSE_TM);
if (ret != ERR_OK) {
iot_printf("[%s][err] i2c read data error\n", __FUNCTION__);
goto out;
}
out:
return ret;
}
static uint8_t tca9534a_gpio_ex_open_as_in(uint8_t gpio_num)
{
uint8_t ret = ERR_FAIL;
uint8_t data;
uint8_t reg_addr = TCA9534A_DIRECTION_CONF_REG3;
gpio_debug_printf("[%s][info] gpio num:%d\n", __FUNCTION__, gpio_num);
if (!TCA9534A_GPIO_VALID(gpio_num)) {
return ERR_FAIL;
}
os_acquire_mutex(gpio_ext_mutex);
ret = tca9534a_i2c_read_reg(reg_addr, &data, 1);
if (ret != ERR_OK) {
iot_printf("[%s][err] open gpio ext as input mode error!\n", __FUNCTION__);
goto out;
}
data |= 1 << gpio_num;
ret = tca9534a_i2c_write_reg(reg_addr, data);
if (ret != ERR_OK) {
iot_printf("[%s][err] open gpio ext as input mode error!\n", __FUNCTION__);
}
out:
os_release_mutex(gpio_ext_mutex);
return ret;
}
static uint8_t tca9534a_gpio_ex_open_as_out(uint8_t gpio_num)
{
uint8_t ret = ERR_FAIL;
uint8_t data;
uint8_t reg_addr = TCA9534A_DIRECTION_CONF_REG3;
gpio_debug_printf("[%s][info] gpio num:%d\n", __FUNCTION__, gpio_num);
if (!TCA9534A_GPIO_VALID(gpio_num)) {
return ERR_FAIL;
}
os_acquire_mutex(gpio_ext_mutex);
ret = tca9534a_i2c_read_reg(reg_addr, &data, 1);
os_delay(TCA9534A_REGISTER_RESPONSE_TM);
if (ret != ERR_OK) {
iot_printf("[%s][err] open gpio ext as output mode error!\n",
__FUNCTION__);
goto out;
}
data &= ~(1 << gpio_num);
ret = tca9534a_i2c_write_reg(reg_addr, data);
os_delay(TCA9534A_REGISTER_RESPONSE_TM);
if (ret != ERR_OK) {
iot_printf("[%s][err] open gpio ext as output mode error!\n",
__FUNCTION__);
}
out:
os_release_mutex(gpio_ext_mutex);
return ret;
}
int tca9534a_gpio_ex_value_get(int gpio_num)
{
uint8_t reg_addr = TCA9534A_INPUT_PORT_REG0;
uint8_t ret = ERR_FAIL;
uint8_t value;
gpio_debug_printf("[%s][info] gpio_num:%d\n", __FUNCTION__, gpio_num);
if (TCA9534A_INIT_COMPLETED != tca9534a_iic_cfg.inited) {
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
return ERR_FAIL;
}
if (!TCA9534A_GPIO_VALID(gpio_num)) {
return ERR_FAIL;
}
os_acquire_mutex(gpio_ext_mutex);
ret = tca9534a_i2c_read_reg(reg_addr, &value, 1);
if (ERR_OK != ret) {
iot_printf("[%s][err] get gpio ext value error!\n", __FUNCTION__);
goto out;
}
os_release_mutex(gpio_ext_mutex);
return (value >> gpio_num) & 0x01;
out:
os_release_mutex(gpio_ext_mutex);
return ret;
}
int tca9534a_gpio_ex_value_set(int gpio_num, int value)
{
uint8_t ret = ERR_FAIL;
uint8_t data = 0;
uint8_t reg_addr = TCA9534A_OUTPUT_PORT_REG1;
gpio_debug_printf("[%s][info] gpio:%d, value:%d\n",
__FUNCTION__, gpio_num, value);
if (TCA9534A_INIT_COMPLETED != tca9534a_iic_cfg.inited) {
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
return ERR_FAIL;
}
if (!TCA9534A_GPIO_VALID(gpio_num)) {
return ERR_FAIL;
}
os_acquire_mutex(gpio_ext_mutex);
ret = tca9534a_i2c_read_reg(reg_addr, &data, 1);
if (ERR_OK != ret) {
iot_printf("[%s][err] get gpio ext value error!\n", __FUNCTION__);
goto out;
}
if (0 == value) {
data &= ~(1 << gpio_num);
} else {
data |= 1 << gpio_num;
}
ret = tca9534a_i2c_write_reg(reg_addr, data);
if (ret != ERR_OK) {
iot_printf("[%s][err] set gpio ext value error!\n", __FUNCTION__);
}
out:
os_release_mutex(gpio_ext_mutex);
return ret;
}
int tca9534a_gpio_ext_hw_set_mode(int gpio_num, int mode)
{
uint8_t ret = ERR_FAIL;
gpio_debug_printf("[%s][info] gpio:%d,mode:%d\n", __FUNCTION__, gpio, mode);
if (TCA9534A_INIT_COMPLETED != tca9534a_iic_cfg.inited) {
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
return ERR_FAIL;
}
if (!TCA9534A_GPIO_VALID(gpio_num)) {
return ERR_FAIL;
}
os_acquire_mutex(gpio_ext_mutex);
if (GPIO_INPUT == mode) {
ret = tca9534a_gpio_ex_open_as_in(gpio_num);
} else if (GPIO_OUTPUT == mode) {
ret = tca9534a_gpio_ex_open_as_out(gpio_num);
} else {
/* not support */
IOT_ASSERT(0);
}
if (ret != ERR_OK) {
iot_printf("[%s][err] gpio ext set mode error!\n", __FUNCTION__);
}
os_release_mutex(gpio_ext_mutex);
return ret;
}
int tca9534a_gpio_ext_hw_set_interrupt_mode(int gpio, int mode)
{
(void)gpio;
(void)mode;
return 0;
}
int tca9534a_gpio_ext_hw_get_int_status(int gpio)
{
(void)gpio;
return 0;
}
int tca9534a_gpio_ext_hw_clear_int_status(int gpio)
{
(void)gpio;
return 0;
}
int tca9534a_gpio_ext_hw_set_drain_mode(int gpio, int mode)
{
(void)gpio;
(void)mode;
return 0;
}
int tca9534a_gpio_init(void)
{
iot_i2c_module_cfg_t iic_cfg;
uint8_t reg_addr = TCA9534A_DIRECTION_CONF_REG3;
uint8_t data;
if (gpio_ext_mutex == NULL) {
gpio_ext_mutex = os_create_mutex(IOT_DRIVER_MID);
}
if (gpio_ext_mutex == NULL) {
IOT_ASSERT(0);
goto err;
}
if (tca9534a_iic_cfg.inited == TCA9534A_INIT_COMPLETED) {
return ERR_OK;
}
tca9534a_iic_cfg.gpio_scl = iot_board_get_gpio(GPIO_EX_IO_I2C_SCL);
tca9534a_iic_cfg.gpio_sda = iot_board_get_gpio(GPIO_EX_IO_I2C_SDA);
if ((tca9534a_iic_cfg.gpio_scl == GPIO_NO_VALID) ||
(tca9534a_iic_cfg.gpio_sda == GPIO_NO_VALID)) {
iot_printf("[%s] init gpio ext chip tca9534a invalid!\n",
__FUNCTION__);
goto err;
}
iic_cfg.baud = tca9534a_iic_cfg.baud;
iic_cfg.gpio.scl = tca9534a_iic_cfg.gpio_scl;
iic_cfg.gpio.sda = tca9534a_iic_cfg.gpio_sda;
iic_cfg.nack_wait_num = tca9534a_iic_cfg.nack_wait_num;
iic_cfg.port = tca9534a_iic_cfg.port;
if (ERR_OK != iot_i2c_module_init(&iic_cfg)) {
iot_printf("[%s][err] i2c module init err!\n", __FUNCTION__);
goto err;
}
if (ERR_OK != tca9534a_i2c_read_reg(reg_addr, &data, 1)) {
iot_printf("[%s][err] i2c read reg failed!\n", __FUNCTION__);
goto err;
}
iot_printf("[%s][info] init gpio ext chip tca9534a successfully!\n",
__FUNCTION__);
tca9534a_iic_cfg.inited = TCA9534A_INIT_COMPLETED;
return ERR_OK;
err:
os_delete_mutex(gpio_ext_mutex);
return ERR_FAIL;
}
iot_gpio_op_t hw_gpio_api_table_ext_tca9534a = {
.gpio_init = tca9534a_gpio_init,
.set_gpio_mode = tca9534a_gpio_ext_hw_set_mode,
.set_interrupt_mode = tca9534a_gpio_ext_hw_set_interrupt_mode,
.set_value = tca9534a_gpio_ex_value_set,
.get_value = tca9534a_gpio_ex_value_get,
.get_interrupt_status = tca9534a_gpio_ext_hw_get_int_status,
.clear_interrupt_status = tca9534a_gpio_ext_hw_clear_int_status,
.set_gpio_open_drain = tca9534a_gpio_ext_hw_set_drain_mode,
};