2023-08-30 16:21:18 +08:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Authors: geo <guojun.dong@artinchip.com>
|
|
|
|
|
*/
|
|
|
|
|
#include <rtconfig.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <hal_i2c.h>
|
|
|
|
|
#include "aic_errno.h"
|
|
|
|
|
|
|
|
|
|
#define gen_reg(val) (volatile void *)(val)
|
|
|
|
|
#define USEC_PER_SEC (1000000)
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_clk_init(aic_i2c_ctrl *i2c_dev)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
int ret = 0;
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_clk_enable_deassertrst(CLK_I2C0 + i2c_dev->index);
|
2023-08-30 16:21:18 +08:00
|
|
|
if (ret < 0)
|
|
|
|
|
pr_err("I2C clock and reset init error\n");
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
void hal_i2c_set_hold(aic_i2c_ctrl *i2c_dev, u32 val)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(val, i2c_dev->reg_base + I2C_SDA_HOLD);
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_set_master_slave_mode(aic_i2c_ctrl *i2c_dev)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
uint32_t reg_val;
|
2024-06-04 19:00:30 +08:00
|
|
|
uint8_t mode;
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
CHECK_PARAM(i2c_dev, -EINVAL);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
mode = i2c_dev->bus_mode;
|
|
|
|
|
reg_val = readl(gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val &= ~I2C_CTL_MASTER_SLAVE_SELECT_MASK;
|
2024-06-04 19:00:30 +08:00
|
|
|
if (!mode)
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val |= I2C_ENABLE_MASTER_DISABLE_SLAVE;
|
|
|
|
|
else
|
|
|
|
|
/* slave mode, and will detect stop signal only if addressed */
|
|
|
|
|
reg_val |= I2C_CTL_STOP_DET_IFADDR;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(reg_val, gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_master_10bit_addr(aic_i2c_ctrl *i2c_dev)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
uint32_t reg_val;
|
2024-06-04 19:00:30 +08:00
|
|
|
uint8_t enable;
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
CHECK_PARAM(i2c_dev, -EINVAL);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
enable = i2c_dev->addr_bit;
|
|
|
|
|
reg_val = readl(gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val &= ~I2C_CTL_10BIT_SELECT_MASTER;
|
|
|
|
|
if (enable)
|
|
|
|
|
reg_val |= I2C_CTL_10BIT_SELECT_MASTER;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(reg_val, gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_slave_10bit_addr(aic_i2c_ctrl *i2c_dev)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
uint32_t reg_val;
|
2024-06-04 19:00:30 +08:00
|
|
|
uint8_t enable;
|
|
|
|
|
CHECK_PARAM(i2c_dev, -EINVAL);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
enable = i2c_dev->addr_bit;
|
|
|
|
|
reg_val = readl(gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val &= ~I2C_CTL_10BIT_SELECT_SLAVE;
|
|
|
|
|
if (enable)
|
|
|
|
|
reg_val |= I2C_CTL_10BIT_SELECT_SLAVE;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(reg_val, gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
static int hal_i2c_scl_cnt(uint32_t clk_freq, uint8_t is_standard_speed,
|
2023-08-30 16:21:18 +08:00
|
|
|
uint16_t *hcnt, uint16_t *lcnt)
|
|
|
|
|
{
|
|
|
|
|
uint16_t hcnt_tmp, lcnt_tmp;
|
|
|
|
|
|
|
|
|
|
CHECK_PARAM(hcnt, -EINVAL);
|
|
|
|
|
CHECK_PARAM(lcnt, -EINVAL);
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
if (is_standard_speed) {
|
2023-08-30 16:21:18 +08:00
|
|
|
/* Minimum value of tHIGH in standard mode is 4000ns
|
|
|
|
|
* Plus 2 is just to increase the time of tHIGH, appropriately.
|
|
|
|
|
* SS_MIN_SCL_HIGH * (clk_freq / 1000) is just to prevent 32bits
|
|
|
|
|
* overflow. SS_MIN_SCL_HIGH * clk_freq will 32bits overflow.
|
|
|
|
|
*/
|
|
|
|
|
hcnt_tmp = SS_MIN_SCL_HIGH * (clk_freq / 1000) / 1000000 + 2;
|
|
|
|
|
lcnt_tmp = SS_MIN_SCL_LOW * (clk_freq / 1000) / 1000000 + 2;
|
|
|
|
|
} else {
|
|
|
|
|
/* If isStandardSpeed is false, set i2c to fast speed
|
|
|
|
|
* Minimum value of tHIGH in fast mode is 600ns
|
|
|
|
|
* Plus 3 is just to increase the time of tHIGH, appropriately.
|
|
|
|
|
* FS_MIN_SCL_HIGH * (clk_freq / 1000)
|
|
|
|
|
*/
|
|
|
|
|
hcnt_tmp = FS_MIN_SCL_HIGH * (clk_freq / 1000) / 1000000 + 2;
|
|
|
|
|
lcnt_tmp = FS_MIN_SCL_LOW * (clk_freq / 1000) / 1000000 + 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*hcnt = hcnt_tmp;
|
|
|
|
|
*lcnt = lcnt_tmp;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_speed_mode_select(aic_i2c_ctrl *i2c_dev, uint32_t clk_freq, uint8_t mode)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
uint32_t reg_val;
|
|
|
|
|
uint16_t hcnt, lcnt;
|
|
|
|
|
int ret;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
CHECK_PARAM(i2c_dev, -EINVAL);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
reg_val = readl(gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val &= ~I2C_CTL_SPEED_MODE_SELECT_MASK;
|
2024-06-04 19:00:30 +08:00
|
|
|
if (!mode) {
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val |= I2C_CTL_SPEED_MODE_FS;
|
|
|
|
|
/* Calculate fast speed HCNT and LCNT */
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_i2c_scl_cnt(clk_freq, false, &hcnt, &lcnt);
|
2023-08-30 16:21:18 +08:00
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(hcnt, gen_reg(i2c_dev->reg_base + I2C_FS_SCL_HCNT));
|
|
|
|
|
writel(lcnt, gen_reg(i2c_dev->reg_base + I2C_FS_SCL_LCNT));
|
2023-08-30 16:21:18 +08:00
|
|
|
} else {
|
|
|
|
|
reg_val |= I2C_CTL_SPEED_MODE_SS;
|
|
|
|
|
/* Calculate standard speed HCNT and LCNT */
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_i2c_scl_cnt(clk_freq, true, &hcnt, &lcnt);
|
2023-08-30 16:21:18 +08:00
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(hcnt, gen_reg(i2c_dev->reg_base + I2C_SS_SCL_HCNT));
|
|
|
|
|
writel(lcnt, gen_reg(i2c_dev->reg_base + I2C_SS_SCL_LCNT));
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(reg_val, gen_reg(i2c_dev->reg_base + I2C_CTL));
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
void hal_i2c_target_addr(aic_i2c_ctrl *i2c_dev, uint32_t addr)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
uint32_t reg_val;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
reg_val = readl(gen_reg(i2c_dev->reg_base + I2C_TAR));
|
2023-08-30 16:21:18 +08:00
|
|
|
reg_val &= ~I2C_TAR_ADDR_MASK;
|
|
|
|
|
reg_val |= addr;
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(reg_val, gen_reg(i2c_dev->reg_base + I2C_TAR));
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_slave_own_addr(aic_i2c_ctrl *i2c_dev, uint32_t addr)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
2024-06-04 19:00:30 +08:00
|
|
|
CHECK_PARAM(i2c_dev, -EINVAL);
|
2023-08-30 16:21:18 +08:00
|
|
|
CHECK_PARAM(!(addr > I2C_TAR_ADDR_MASK), -EINVAL);
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
writel(addr, gen_reg(i2c_dev->reg_base + I2C_SAR));
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int hal_i2c_init(aic_i2c_ctrl *i2c_dev)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
2024-06-04 19:00:30 +08:00
|
|
|
int32_t ret = I2C_OK;
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_i2c_clk_init(i2c_dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
hal_i2c_set_master_slave_mode(i2c_dev);
|
|
|
|
|
hal_i2c_set_hold(i2c_dev, 10);
|
|
|
|
|
hal_i2c_master_10bit_addr(i2c_dev);
|
|
|
|
|
hal_i2c_slave_10bit_addr(i2c_dev);
|
|
|
|
|
#ifdef AIC_I2C_INTERRUPT_MODE
|
|
|
|
|
hal_i2c_disable_all_irq(i2c_dev);
|
|
|
|
|
hal_i2c_set_transmit_fifo_threshold(i2c_dev);
|
|
|
|
|
#else
|
|
|
|
|
hal_i2c_master_enable_irq(i2c_dev);
|
|
|
|
|
#endif
|
|
|
|
|
ret = hal_i2c_speed_mode_select(i2c_dev, I2C_DEFALT_CLOCK, i2c_dev->speed_mode);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
if (i2c_dev->bus_mode) {
|
|
|
|
|
hal_i2c_config_fifo_slave(i2c_dev);
|
|
|
|
|
hal_i2c_clear_all_irq_flags(i2c_dev);
|
|
|
|
|
hal_i2c_slave_enable_irq(i2c_dev);
|
|
|
|
|
hal_i2c_module_disable(i2c_dev);
|
|
|
|
|
hal_i2c_slave_own_addr(i2c_dev, i2c_dev->slave_addr);
|
|
|
|
|
hal_i2c_module_enable(i2c_dev);
|
|
|
|
|
}
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
static int32_t hal_i2c_wait_transmit(aic_i2c_ctrl *i2c_dev, uint32_t timeout)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
int32_t ret = I2C_OK;
|
|
|
|
|
|
|
|
|
|
do {
|
2023-11-30 19:48:02 +08:00
|
|
|
uint64_t timecount = timeout + aic_get_time_ms();
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
while ((hal_i2c_get_transmit_fifo_num(i2c_dev) != 0U) &&
|
2023-08-30 16:21:18 +08:00
|
|
|
(ret == EOK)) {
|
2023-11-09 20:19:51 +08:00
|
|
|
if (aic_get_time_ms() >= timecount) {
|
2023-08-30 16:21:18 +08:00
|
|
|
ret = I2C_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
static int32_t hal_i2c_wait_receive(aic_i2c_ctrl *i2c_dev,
|
2023-08-30 16:21:18 +08:00
|
|
|
uint32_t wait_data_num, uint32_t timeout)
|
|
|
|
|
{
|
|
|
|
|
int32_t ret = I2C_OK;
|
|
|
|
|
|
|
|
|
|
do {
|
2023-11-30 19:48:02 +08:00
|
|
|
uint64_t timecount = timeout + aic_get_time_ms();
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
while ((hal_i2c_get_receive_fifo_num(i2c_dev) < wait_data_num) &&
|
2023-08-30 16:21:18 +08:00
|
|
|
(ret == I2C_OK)) {
|
2023-11-09 20:19:51 +08:00
|
|
|
if (aic_get_time_ms() >= timecount) {
|
2023-08-30 16:21:18 +08:00
|
|
|
ret = I2C_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
int32_t hal_i2c_wait_bus_free(aic_i2c_ctrl *i2c_dev, uint32_t timeout)
|
|
|
|
|
{
|
|
|
|
|
int32_t ret = I2C_OK;
|
|
|
|
|
|
|
|
|
|
uint64_t timecount = timeout + aic_get_time_ms();
|
|
|
|
|
|
|
|
|
|
while (hal_i2c_bus_status(i2c_dev)) {
|
|
|
|
|
if (aic_get_time_ms() >= timecount) {
|
|
|
|
|
ret = I2C_TIMEOUT;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
/**
|
2024-06-04 19:00:30 +08:00
|
|
|
\brief hal_i2c_master_send_msg
|
2023-08-30 16:21:18 +08:00
|
|
|
\param[in] reg_base
|
|
|
|
|
\param[in]
|
|
|
|
|
\return bytes of sent msg
|
|
|
|
|
*/
|
2024-06-04 19:00:30 +08:00
|
|
|
int32_t hal_i2c_master_send_msg(aic_i2c_ctrl *i2c_dev,
|
2024-04-03 16:40:57 +08:00
|
|
|
struct aic_i2c_msg *msg, uint8_t is_last_message)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
CHECK_PARAM(msg, -EINVAL);
|
|
|
|
|
|
|
|
|
|
int32_t ret = I2C_OK;
|
|
|
|
|
uint16_t size = msg->len;
|
|
|
|
|
uint32_t send_count = 0;
|
|
|
|
|
uint32_t stop_time = 0;
|
2024-04-03 16:40:57 +08:00
|
|
|
uint32_t timeout = 10;
|
2023-08-30 16:21:18 +08:00
|
|
|
uint32_t reg_val;
|
2024-01-27 08:47:24 +08:00
|
|
|
uint16_t idx = 0;
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_module_disable(i2c_dev);
|
|
|
|
|
hal_i2c_target_addr(i2c_dev, msg->addr);
|
|
|
|
|
hal_i2c_module_enable(i2c_dev);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
if (!size)
|
|
|
|
|
{
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_transmit_data_with_stop_bit(i2c_dev, 0);
|
2023-08-30 16:21:18 +08:00
|
|
|
while (1)
|
|
|
|
|
{
|
2024-06-04 19:00:30 +08:00
|
|
|
reg_val = readl(i2c_dev->reg_base + I2C_INTR_RAW_STAT);
|
2023-08-30 16:21:18 +08:00
|
|
|
if (reg_val & I2C_INTR_STOP_DET)
|
|
|
|
|
{
|
|
|
|
|
if (reg_val & I2C_INTR_TX_ABRT)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
while (size > 0) {
|
|
|
|
|
uint16_t send_num = size > I2C_FIFO_DEPTH ? I2C_FIFO_DEPTH : size;
|
2024-04-03 16:40:57 +08:00
|
|
|
for (uint16_t i = 0; i < send_num; i++) {
|
|
|
|
|
if (is_last_message && (idx == msg->len -1))
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_transmit_data_with_stop_bit(i2c_dev, msg->buf[idx]);
|
2024-04-03 16:40:57 +08:00
|
|
|
else if (!is_last_message && (idx == 0))
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_set_restart_bit_with_data(i2c_dev, msg->buf[idx]);
|
2024-04-03 16:40:57 +08:00
|
|
|
else
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_transmit_data(i2c_dev, msg->buf[idx]);
|
2024-04-03 16:40:57 +08:00
|
|
|
idx++;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
2024-01-27 08:47:24 +08:00
|
|
|
size -= send_num;
|
|
|
|
|
send_count += send_num;
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_i2c_wait_transmit(i2c_dev, timeout);
|
2024-01-27 08:47:24 +08:00
|
|
|
if (ret != I2C_OK) {
|
|
|
|
|
send_count = ret;
|
|
|
|
|
return I2C_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
while (!(hal_i2c_get_raw_interrupt_state(i2c_dev)
|
2024-04-03 16:40:57 +08:00
|
|
|
& (I2C_INTR_STOP_DET | I2C_INTR_START_DET))) {
|
|
|
|
|
stop_time++;
|
|
|
|
|
if (stop_time > I2C_TIMEOUT_DEF_VAL) {
|
|
|
|
|
return I2C_TIMEOUT;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-03 16:40:57 +08:00
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
return send_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-06-04 19:00:30 +08:00
|
|
|
\brief hal_i2c_master_receive_msg
|
2023-08-30 16:21:18 +08:00
|
|
|
\param[in] reg_base
|
|
|
|
|
\param[in]
|
2024-01-27 08:47:24 +08:00
|
|
|
\return bytes of read msg
|
2023-08-30 16:21:18 +08:00
|
|
|
*/
|
2024-06-04 19:00:30 +08:00
|
|
|
int32_t hal_i2c_master_receive_msg(aic_i2c_ctrl *i2c_dev,
|
2024-04-03 16:40:57 +08:00
|
|
|
struct aic_i2c_msg *msg, uint8_t is_last_message)
|
2023-08-30 16:21:18 +08:00
|
|
|
{
|
|
|
|
|
CHECK_PARAM(msg, -EINVAL);
|
|
|
|
|
|
|
|
|
|
int32_t ret = I2C_OK;
|
|
|
|
|
uint16_t size = msg->len;
|
|
|
|
|
uint32_t read_count = 0;
|
|
|
|
|
uint8_t *receive_data = msg->buf;
|
2024-04-03 16:40:57 +08:00
|
|
|
uint32_t timeout = 10;
|
|
|
|
|
int idx = 0, count = 0;
|
2023-08-30 16:21:18 +08:00
|
|
|
CHECK_PARAM(receive_data, -EINVAL);
|
|
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_module_disable(i2c_dev);
|
|
|
|
|
hal_i2c_target_addr(i2c_dev, msg->addr);
|
|
|
|
|
hal_i2c_module_enable(i2c_dev);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
while (size > 0) {
|
|
|
|
|
int32_t recv_num = size > I2C_FIFO_DEPTH ? I2C_FIFO_DEPTH : size;
|
|
|
|
|
for (uint16_t len = 0; len < recv_num; len++) {
|
2024-04-03 16:40:57 +08:00
|
|
|
if (is_last_message && (count == msg->len - 1))
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_read_data_cmd_with_stop_bit(i2c_dev);
|
2024-04-03 16:40:57 +08:00
|
|
|
else
|
2024-06-04 19:00:30 +08:00
|
|
|
hal_i2c_read_data_cmd(i2c_dev);
|
2024-04-03 16:40:57 +08:00
|
|
|
count++;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
size -= recv_num;
|
|
|
|
|
read_count += recv_num;
|
2024-06-04 19:00:30 +08:00
|
|
|
ret = hal_i2c_wait_receive(i2c_dev, recv_num, timeout);
|
2023-08-30 16:21:18 +08:00
|
|
|
if (ret == I2C_OK) {
|
2024-01-27 08:47:24 +08:00
|
|
|
for (uint16_t i = 0; i < recv_num; i++) {
|
2024-06-04 19:00:30 +08:00
|
|
|
receive_data[idx] = hal_i2c_get_receive_data(i2c_dev);
|
2024-01-27 08:47:24 +08:00
|
|
|
idx++;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
read_count = (int32_t)ret;
|
2024-01-27 08:47:24 +08:00
|
|
|
break;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
2024-01-27 08:47:24 +08:00
|
|
|
}
|
2024-04-03 16:40:57 +08:00
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
uint32_t timecount = timeout + aic_get_time_ms();
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-06-04 19:00:30 +08:00
|
|
|
while (!(hal_i2c_get_raw_interrupt_state(i2c_dev)
|
2024-04-03 16:40:57 +08:00
|
|
|
& (I2C_INTR_STOP_DET | I2C_INTR_START_DET))) {
|
2024-01-27 08:47:24 +08:00
|
|
|
if (aic_get_time_ms() >= timecount) {
|
|
|
|
|
return I2C_TIMEOUT;
|
|
|
|
|
break;
|
2023-08-30 16:21:18 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return read_count;
|
|
|
|
|
}
|
2024-04-03 16:40:57 +08:00
|
|
|
|