474 lines
14 KiB
C
474 lines
14 KiB
C
/****************************************************************************
|
|
*
|
|
* 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 "os_types.h"
|
|
#include "iot_errno.h"
|
|
|
|
#include "iot_i2c_api.h"
|
|
#include "iot_gpio_api.h"
|
|
#include "gpio.h"
|
|
#include "gpio_mtx.h"
|
|
#include "i2c_hw.h"
|
|
#include "os_utils.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "os_lock.h"
|
|
#include "iot_gpio_ex.h"
|
|
|
|
/* The iic config of tpt29555. */
|
|
#define TPT29555_IIC_PHY_ADDR (0x24)
|
|
#define TPT29555_INIT_COMPLETED (1)
|
|
#define TPT29555_INIT_UNCOMPLETED (0)
|
|
#define TPT29555_IIC_DEF_PORT (0) /* Port#0. */
|
|
#define TPT29555_IIC_DEF_SPEED (100) /* 100K. */
|
|
#define TPT29555_IIC_DEF_NACK_NUM (1) /* N-ACK number. */
|
|
|
|
/* TPT29555 reg op cmd. */
|
|
#define TPT29555_INPUT_PORT_REGA (0x00) //read data from gpio.
|
|
#define TPT29555_INPUT_PORT_REGB (0x01)
|
|
#define TPT29555_OUTPUT_PORT_REGA (0x02) //output data to gpio.
|
|
#define TPT29555_OUTPUT_PORT_REGB (0x03)
|
|
#define TPT29555_INVER_PORT_REGA (0x04) //polarity inversion to gpio.
|
|
#define TPT29555_INVER_PORT_REGB (0x05)
|
|
#define TPT29555_CONFIG_PORT_REGA (0x06) //set the directions of gpio.
|
|
#define TPT29555_CONFIG_PORT_REGB (0x07)
|
|
|
|
#define TPT29555_REGISTER_RESPONSE_TM (10) // tpt29555 response time: ms
|
|
|
|
/* each port has 8 gpios, gpio7 ~ gpio0. */
|
|
#define GPIO_EX_PORT_NUMBER (8)
|
|
#define TPT29555_GPIO_EX_PORTA (0x00)
|
|
#define TPT29555_GPIO_EX_PORTB (0x01)
|
|
#define GPIO_EX_GET_GPIO(gpio) ((gpio) % GPIO_EX_PORT_NUMBER)
|
|
#define GPIO_EX_GET_PORT(gpio) ((gpio) / GPIO_EX_PORT_NUMBER)
|
|
#define GPIO_EX_VALID(gpio) (((gpio) >= 0) && \
|
|
((gpio) < GPIO_EX_PORT_NUMBER))
|
|
#define GPIO_PORT_VALID(port) ((port) == TPT29555_GPIO_EX_PORTA || \
|
|
(port) == TPT29555_GPIO_EX_PORTB)
|
|
|
|
typedef struct _tpt29555_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. */
|
|
} tpt29555_iic_cfg_t;
|
|
|
|
static tpt29555_iic_cfg_t tpt29555_iic_cfg =
|
|
{
|
|
TPT29555_INIT_UNCOMPLETED, /* IIC initialization uncompleted. */
|
|
TPT29555_IIC_DEF_PORT, /* IIC device port number. */
|
|
TPT29555_IIC_DEF_SPEED, /* Baudrate, unit is Kb. */
|
|
TPT29555_IIC_DEF_NACK_NUM, /* Wait nack number. */
|
|
0, /* SCL gpio pin. */
|
|
0 /* SDA gpio pin. */
|
|
};
|
|
|
|
static os_mutex_h gpio_ext_mutex = NULL;
|
|
static uint32_t register_opt_tm = 0; /* operate register timestamp: 1ms */
|
|
|
|
static uint8_t tpt29555_i2c_write_reg(uint8_t reg_addr, uint8_t val)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
char buf[2] = {0};
|
|
uint32_t cur_opt_tm = os_boot_time32();
|
|
uint32_t delay_tm;
|
|
buf[0] = reg_addr;
|
|
buf[1] = val;
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d\n", __FUNCTION__, reg_addr,
|
|
val);
|
|
|
|
delay_tm = (uint32_t)(cur_opt_tm - register_opt_tm);
|
|
if (delay_tm < TPT29555_REGISTER_RESPONSE_TM) {
|
|
os_delay(TPT29555_REGISTER_RESPONSE_TM - delay_tm);
|
|
}
|
|
ret = iot_i2c_write(tpt29555_iic_cfg.port, TPT29555_IIC_PHY_ADDR, buf, 2);
|
|
|
|
if (ret != ERR_OK) {
|
|
iot_printf("[%s][err] i2c write data error\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
register_opt_tm = os_boot_time32();
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t tpt29555_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;
|
|
uint32_t cur_opt_tm = os_boot_time32();
|
|
uint32_t delay_tm;
|
|
|
|
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;
|
|
}
|
|
|
|
delay_tm = (uint32_t)(cur_opt_tm - register_opt_tm);
|
|
if (delay_tm < TPT29555_REGISTER_RESPONSE_TM) {
|
|
os_delay(TPT29555_REGISTER_RESPONSE_TM - delay_tm);
|
|
}
|
|
ret = iot_i2c_write(tpt29555_iic_cfg.port, TPT29555_IIC_PHY_ADDR, buf, 1);
|
|
|
|
if (ret != ERR_OK) {
|
|
iot_printf("[%s][err] i2c write data error\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
os_delay(TPT29555_REGISTER_RESPONSE_TM);
|
|
ret = iot_i2c_read(tpt29555_iic_cfg.port, TPT29555_IIC_PHY_ADDR,
|
|
(char *)data, len);
|
|
|
|
if (ret != ERR_OK) {
|
|
iot_printf("[%s][err] i2c read data error\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
register_opt_tm = os_boot_time32();
|
|
return ret;
|
|
}
|
|
|
|
static uint8_t tpt29555_gpio_ex_open_as_out(uint8_t gpio_num, uint8_t gpio_port)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t data;
|
|
uint8_t reg_addr;
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d\n", __FUNCTION__, gpio_num,
|
|
gpio_port);
|
|
|
|
if ((!GPIO_EX_VALID(gpio_num))
|
|
||!GPIO_PORT_VALID(gpio_port)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
os_acquire_mutex(gpio_ext_mutex);
|
|
|
|
if (gpio_port == TPT29555_GPIO_EX_PORTA) {
|
|
reg_addr = TPT29555_CONFIG_PORT_REGA;
|
|
} else if (gpio_port == TPT29555_GPIO_EX_PORTB) {
|
|
reg_addr = TPT29555_CONFIG_PORT_REGB;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
ret = tpt29555_i2c_read_reg(reg_addr, &data, 1);
|
|
|
|
if (ret != ERR_OK) {
|
|
iot_printf("[%s][err] open gpio ext as output mode error!\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
data &= ~(1 << gpio_num);
|
|
|
|
ret = tpt29555_i2c_write_reg(reg_addr, data);
|
|
|
|
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;
|
|
}
|
|
|
|
static uint8_t tpt29555_gpio_ex_open_as_in(uint8_t gpio_num, uint8_t gpio_port)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t data;
|
|
uint8_t reg_addr;
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d\n", __FUNCTION__, gpio_num,
|
|
gpio_port);
|
|
|
|
if ((!GPIO_EX_VALID(gpio_num))
|
|
||!GPIO_PORT_VALID(gpio_port)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
os_acquire_mutex(gpio_ext_mutex);
|
|
|
|
if (gpio_port == TPT29555_GPIO_EX_PORTA) {
|
|
reg_addr = TPT29555_CONFIG_PORT_REGA;
|
|
} else if (gpio_port == TPT29555_GPIO_EX_PORTB) {
|
|
reg_addr = TPT29555_CONFIG_PORT_REGB;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
ret = tpt29555_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 = tpt29555_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 int iot_gpio_ext_hw_set_mode(int gpio, int mode)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t gpio_num = GPIO_EX_GET_GPIO(gpio);
|
|
uint8_t gpio_port = GPIO_EX_GET_PORT(gpio);
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d, arg3:%d\n", __FUNCTION__,
|
|
gpio_num, gpio_port, mode);
|
|
|
|
if (TPT29555_INIT_COMPLETED != tpt29555_iic_cfg.inited) {
|
|
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if ((!GPIO_EX_VALID(gpio_num))
|
|
||!GPIO_PORT_VALID(gpio_port)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
os_acquire_mutex(gpio_ext_mutex);
|
|
|
|
if (GPIO_INPUT == mode) {
|
|
ret = tpt29555_gpio_ex_open_as_in(gpio_num, gpio_port);
|
|
} else if (GPIO_OUTPUT == mode) {
|
|
ret = tpt29555_gpio_ex_open_as_out(gpio_num, gpio_port);
|
|
} 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;
|
|
}
|
|
|
|
static int iot_tpt29555_gpio_ex_value_get(int gpio)
|
|
{
|
|
uint8_t reg_addr, ret = ERR_FAIL;
|
|
uint8_t value;
|
|
|
|
uint8_t gpio_num = GPIO_EX_GET_GPIO(gpio);
|
|
uint8_t gpio_port = GPIO_EX_GET_PORT(gpio);
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d\n", __FUNCTION__, gpio_num,
|
|
gpio_port);
|
|
|
|
if (TPT29555_INIT_COMPLETED != tpt29555_iic_cfg.inited) {
|
|
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if ((!GPIO_EX_VALID(gpio_num))
|
|
||!GPIO_PORT_VALID(gpio_port)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
os_acquire_mutex(gpio_ext_mutex);
|
|
|
|
if (gpio_port == TPT29555_GPIO_EX_PORTA) {
|
|
reg_addr = TPT29555_INPUT_PORT_REGA;
|
|
} else if (gpio_port == TPT29555_GPIO_EX_PORTB) {
|
|
reg_addr = TPT29555_INPUT_PORT_REGB;
|
|
}
|
|
|
|
ret = tpt29555_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;
|
|
}
|
|
|
|
static int iot_tpt29555_gpio_ex_value_set(int gpio, int value)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint8_t data = 0;
|
|
uint8_t reg_addr, gpio_num, gpio_port;
|
|
|
|
gpio_num = GPIO_EX_GET_GPIO(gpio);
|
|
gpio_port = GPIO_EX_GET_PORT(gpio);
|
|
|
|
gpio_debug_printf("[%s][info] arg1:%d, arg2:%d, arg3:%d\n", __FUNCTION__,
|
|
gpio_num, gpio_port, value);
|
|
|
|
if (TPT29555_INIT_COMPLETED != tpt29555_iic_cfg.inited) {
|
|
iot_printf("[%s][err] The chip is not initialized!\n", __FUNCTION__);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
if ((!GPIO_EX_VALID(gpio_num))
|
|
||!GPIO_PORT_VALID(gpio_port)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
os_acquire_mutex(gpio_ext_mutex);
|
|
|
|
if (gpio_port == TPT29555_GPIO_EX_PORTA) {
|
|
reg_addr = TPT29555_OUTPUT_PORT_REGA;
|
|
} else if (gpio_port == TPT29555_GPIO_EX_PORTB) {
|
|
reg_addr = TPT29555_OUTPUT_PORT_REGB;
|
|
}
|
|
|
|
ret = tpt29555_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 = tpt29555_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;
|
|
}
|
|
|
|
static int iot_tpt29555_gpio_ex_init(void)
|
|
{
|
|
iot_i2c_module_cfg_t iic_cfg;
|
|
uint8_t value;
|
|
|
|
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 (tpt29555_iic_cfg.inited == TPT29555_INIT_COMPLETED) {
|
|
return ERR_OK;
|
|
}
|
|
tpt29555_iic_cfg.gpio_scl = iot_board_get_gpio(GPIO_EX_IO_I2C_SCL);
|
|
tpt29555_iic_cfg.gpio_sda = iot_board_get_gpio(GPIO_EX_IO_I2C_SDA);
|
|
if ((tpt29555_iic_cfg.gpio_scl == GPIO_NO_VALID) ||
|
|
(tpt29555_iic_cfg.gpio_sda == GPIO_NO_VALID)) {
|
|
iot_printf("[%s] init gpio ext chip TPT29555 invalid!\n",
|
|
__FUNCTION__);
|
|
goto err;
|
|
}
|
|
iic_cfg.baud = tpt29555_iic_cfg.baud;
|
|
iic_cfg.gpio.scl = tpt29555_iic_cfg.gpio_scl;
|
|
iic_cfg.gpio.sda = tpt29555_iic_cfg.gpio_sda;
|
|
iic_cfg.nack_wait_num = tpt29555_iic_cfg.nack_wait_num;
|
|
iic_cfg.port = tpt29555_iic_cfg.port;
|
|
|
|
if (ERR_OK != iot_i2c_module_init(&iic_cfg)) {
|
|
iot_printf("[%s][err] init err!\n", __FUNCTION__);
|
|
goto err;
|
|
}
|
|
|
|
/* check device ACK or NACK */
|
|
if (ERR_OK != tpt29555_i2c_read_reg(TPT29555_INPUT_PORT_REGA, &value, 1)) {
|
|
iot_printf("[%s][info] read register failed, reg:0x%x, value:0x%x\n",
|
|
__FUNCTION__, TPT29555_INPUT_PORT_REGA, value);
|
|
goto err;
|
|
}
|
|
|
|
iot_printf("[%s][info] init gpio ext chip TPT29555 successfully!\n",
|
|
__FUNCTION__);
|
|
|
|
tpt29555_iic_cfg.inited = TPT29555_INIT_COMPLETED;
|
|
|
|
return ERR_OK;
|
|
|
|
err:
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
static int iot_gpio_ext_hw_set_interrupt_mode(int gpio, int mode)
|
|
{
|
|
(void)gpio;
|
|
(void)mode;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int iot_gpio_ext_hw_get_int_status(int gpio)
|
|
{
|
|
(void)gpio;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int iot_gpio_ext_hw_clear_int_status(int gpio)
|
|
{
|
|
(void)gpio;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int iot_gpio_ext_hw_set_drain_mode(int gpio, int mode)
|
|
{
|
|
(void)gpio;
|
|
(void)mode;
|
|
|
|
return 0;
|
|
}
|
|
|
|
iot_gpio_op_t hw_gpio_api_table_ext_tpt29555 = {
|
|
.gpio_init = iot_tpt29555_gpio_ex_init,
|
|
.set_gpio_mode = iot_gpio_ext_hw_set_mode,
|
|
.set_interrupt_mode = iot_gpio_ext_hw_set_interrupt_mode,
|
|
.set_value = iot_tpt29555_gpio_ex_value_set,
|
|
.get_value = iot_tpt29555_gpio_ex_value_get,
|
|
.get_interrupt_status = iot_gpio_ext_hw_get_int_status,
|
|
.clear_interrupt_status = iot_gpio_ext_hw_clear_int_status,
|
|
.set_gpio_open_drain = iot_gpio_ext_hw_set_drain_mode,
|
|
};
|