396 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			396 lines
		
	
	
		
			11 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 "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, | ||
|  | }; |