661 lines
19 KiB
C
661 lines
19 KiB
C
/**
|
|
* @file sdrv_i2c_drv.c
|
|
* @brief sdrv i2c driver function file.
|
|
*
|
|
* @Copyright (c) 2022 Semidrive Semiconductor.
|
|
* @All rights reserved.
|
|
**/
|
|
|
|
#include <debug.h>
|
|
#include <udelay/udelay.h>
|
|
#include <sdrv_i2c.h>
|
|
|
|
#include "irq.h"
|
|
#include "sdrv_i2c_reg.h"
|
|
|
|
#define i2c_min(a, b) ((a) < (b) ? a : b)
|
|
|
|
/**
|
|
* @brief I2c check error type
|
|
*
|
|
* @param[in] base i2c controller instance pointer
|
|
* @param[in] errcode err code storage variable pointer
|
|
* @param[in] id i2c bus num
|
|
* @param[in] int0_stat int0 register value
|
|
* @param[in] idx local err flag num
|
|
*
|
|
* @return SDRV_I2CDRV_TRANS_NAK/SDRV_I2CDRV_TRANS_ERR
|
|
*/
|
|
static status_t sdrv_i2c_check_err(paddr_t base, uint32_t *errcode,
|
|
uint32_t id, uint32_t int0_stat, uint32_t idx)
|
|
{
|
|
status_t ret;
|
|
uint32_t psr0_stat;
|
|
|
|
psr0_stat = sdrv_i2c_get_psr_stat(base, I2C_PSR0);
|
|
|
|
if ((psr0_stat & 0xff) == 0x27)
|
|
ret = SDRV_I2CDRV_TRANS_NAK;
|
|
else {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u err%u int0=%x, psr0=%x\r\n",
|
|
id, idx, int0_stat, psr0_stat);
|
|
*errcode = psr0_stat;
|
|
sdrv_i2c_reset(base);
|
|
ret = SDRV_I2CDRV_TRANS_ERR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief I2c write data to slave in polling mode
|
|
*
|
|
* @param[in] base i2c controller instance pointer
|
|
* @param[in] id i2c controller instance num
|
|
* @param[in] mctrl i2c controller instance pointer
|
|
* @param[in] timeout timeout in milliseconds to wait (0 = wait forever)
|
|
*
|
|
* @return SDRV_I2CDRV_TRANS_OK
|
|
* SDRV_I2CDRV_TRANS_GO
|
|
* SDRV_I2CDRV_TRANS_ERR
|
|
* SDRV_I2CDRV_TRANS_NAK
|
|
* SDRV_I2CDRV_TRANS_TIMEOUT
|
|
*/
|
|
static status_t sdrv_i2c_pwrite(paddr_t base, uint32_t id,
|
|
sdrv_i2cdrv_mctrl_t *mctrl,
|
|
uint32_t timeout)
|
|
{
|
|
uint8_t len = 0;
|
|
uint8_t flen = 0;
|
|
const uint32_t retry_delay = 10; /* us */
|
|
uint64_t retry_times = (uint64_t)timeout * 1000 / retry_delay;
|
|
uint64_t scnt = 100000UL / retry_delay;
|
|
uint32_t int0_stat = 0;
|
|
uint8_t *wbuf = mctrl->buf;
|
|
uint16_t wlen = mctrl->len;
|
|
|
|
while (wlen) {
|
|
int0_stat = sdrv_i2c_get_int_stat(base, I2C_INTR0);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_ERR_STAT)
|
|
return sdrv_i2c_check_err(base, &mctrl->trans_errcode,
|
|
id, int0_stat, 1);
|
|
|
|
flen = (uint8_t)sdrv_i2c_get_wspace(base);
|
|
if (flen > 0) {
|
|
len = i2c_min(flen, wlen);
|
|
wlen -= len;
|
|
while (len--)
|
|
sdrv_i2c_send_data(base, *wbuf++);
|
|
}
|
|
else if (timeout > 0) {
|
|
if (retry_times--) {
|
|
udelay(retry_delay);
|
|
continue;
|
|
}
|
|
else {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u write retry time runs out\r\n", id);
|
|
return SDRV_I2CDRV_TRANS_TIMEOUT;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (timeout > 0) {
|
|
if (retry_times > 0)
|
|
scnt = retry_times;
|
|
else
|
|
scnt = 1;
|
|
}
|
|
|
|
while (scnt--) {
|
|
int0_stat = sdrv_i2c_get_int_stat(base, I2C_INTR0);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_APBCMDDONE) {
|
|
return SDRV_I2CDRV_TRANS_OK;
|
|
}
|
|
else if (int0_stat & SDRV_I2C_INT0_ERR_STAT) {
|
|
return sdrv_i2c_check_err(base, &mctrl->trans_errcode,
|
|
id, int0_stat, 2);
|
|
}
|
|
else if (scnt <= 1) {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u pwerr may hold by slave\r\n", id);
|
|
return SDRV_I2CDRV_TRANS_TIMEOUT;
|
|
}
|
|
else
|
|
udelay(retry_delay);
|
|
}
|
|
|
|
return SDRV_I2CDRV_TRANS_GO;
|
|
}
|
|
|
|
/**
|
|
* @brief I2c read data from slave in polling mode
|
|
*
|
|
* @param[in] base i2c controller instance pointer
|
|
* @param[in] id i2c controller instance num
|
|
* @param[in] mctrl i2c controller instance pointer
|
|
* @param[in] timeout timeout in milliseconds to wait (0 = wait forever)
|
|
*
|
|
* @return SDRV_I2CDRV_TRANS_OK
|
|
* SDRV_I2CDRV_TRANS_GO
|
|
* SDRV_I2CDRV_TRANS_ERR
|
|
* SDRV_I2CDRV_TRANS_NAK
|
|
* SDRV_I2CDRV_TRANS_TIMEOUT
|
|
*/
|
|
static status_t sdrv_i2c_pread(paddr_t base, uint32_t id,
|
|
sdrv_i2cdrv_mctrl_t *mctrl,
|
|
uint32_t timeout)
|
|
{
|
|
uint8_t len = 0;
|
|
uint8_t flen = 0;
|
|
const uint32_t retry_delay = 10; /* us */
|
|
uint64_t retry_times = (uint64_t)timeout * 1000 / retry_delay;
|
|
uint64_t scnt = 100000UL / retry_delay;
|
|
uint32_t int0_stat = 0;
|
|
uint8_t *rbuf = mctrl->buf;
|
|
uint16_t rlen = mctrl->len;
|
|
|
|
while (rlen) {
|
|
int0_stat = sdrv_i2c_get_int_stat(base, I2C_INTR0);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_ERR_STAT)
|
|
return sdrv_i2c_check_err(base, &mctrl->trans_errcode,
|
|
id, int0_stat, 3);
|
|
|
|
flen = (uint8_t)sdrv_i2c_get_rspace(base);
|
|
if (flen > 0) {
|
|
len = i2c_min(flen, rlen);
|
|
rlen -= len;
|
|
while (len--)
|
|
*rbuf++ = sdrv_i2c_recv_data(base);
|
|
}
|
|
else if (timeout > 0) {
|
|
if (retry_times--) {
|
|
udelay(retry_delay);
|
|
continue;
|
|
}
|
|
else {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u read retry time runs out\r\n", id);
|
|
return SDRV_I2CDRV_TRANS_TIMEOUT;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (timeout > 0) {
|
|
if (retry_times > 0)
|
|
scnt = retry_times;
|
|
else
|
|
scnt = 1;
|
|
}
|
|
|
|
while (scnt--) {
|
|
int0_stat = sdrv_i2c_get_int_stat(base, I2C_INTR0);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_APBCMDDONE) {
|
|
return SDRV_I2CDRV_TRANS_OK;
|
|
}
|
|
else if (int0_stat & SDRV_I2C_INT0_ERR_STAT) {
|
|
return sdrv_i2c_check_err(base, &mctrl->trans_errcode,
|
|
id, int0_stat, 4);
|
|
}
|
|
else if (scnt <= 1) {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u prerr may hold by slave\r\n", id);
|
|
return SDRV_I2CDRV_TRANS_TIMEOUT;
|
|
}
|
|
else
|
|
udelay(retry_delay);
|
|
}
|
|
|
|
return SDRV_I2CDRV_TRANS_GO;
|
|
}
|
|
|
|
/**
|
|
* @brief I2c transfer init
|
|
*
|
|
* @param[in] base i2c controller address
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
static status_t sdrv_i2c_xfer_init(paddr_t base)
|
|
{
|
|
int cnt = 100;
|
|
|
|
sdrv_i2c_set_cmdcsr(base, I2C_CMDCSR0, 0xA5C3);
|
|
sdrv_i2c_clear_fifo(base);
|
|
|
|
do {
|
|
if (sdrv_i2c_get_fifo_empty_stat(base))
|
|
return SDRV_STATUS_OK;
|
|
udelay(10);
|
|
} while (cnt--);
|
|
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
/**
|
|
* @brief I2c driver real transfer function entry
|
|
* init the controller with client configer info(speed/addr/len/need_stop...)
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] timeout timeout in milliseconds to wait (0 = wait forever)
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
static status_t sdrv_i2c_xfer(sdrv_i2c_t *ctrl, uint32_t timeout)
|
|
{
|
|
status_t ret;
|
|
uint32_t int0_mask;
|
|
sdrv_i2c_cfg_t *cfg = ctrl->cfg;
|
|
sdrv_i2cdrv_mctrl_t *mctrl = &ctrl->mctrl;
|
|
mctrl->trans_stat = SDRV_I2CDRV_TRANS_GO;
|
|
mctrl->trans_errcode = 0;
|
|
|
|
if (!ctrl->cfg->inited) {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u not init\r\n", ctrl->cfg->id);
|
|
mctrl->trans_stat = SDRV_I2CDRV_TRANS_ABORT;
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
sdrv_i2c_disable_int(cfg->base);
|
|
|
|
ret = sdrv_i2c_xfer_init(cfg->base);
|
|
if (ret == SDRV_STATUS_FAIL) {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u xfer init fail\r\n", cfg->id);
|
|
mctrl->trans_stat = SDRV_I2CDRV_TRANS_ABORT;
|
|
return ret;
|
|
}
|
|
|
|
sdrv_i2c_clear_int(cfg->base);
|
|
|
|
sdrv_i2c_set_cmdcsr(cfg->base, I2C_CMDCSR2,
|
|
mctrl->slave_addr | (mctrl->read_flag << 11) |
|
|
(mctrl->len << 16));
|
|
|
|
if (mctrl->need_stop)
|
|
sdrv_i2c_set_cmdcsr(cfg->base, I2C_CMDCSR0, 0xA53C | (0x1 << 30));
|
|
else
|
|
sdrv_i2c_set_cmdcsr(cfg->base, I2C_CMDCSR0, 0xA53C | (0x0 << 30));
|
|
|
|
if (cfg->tsmode == SDRV_I2CDRV_POLL) {
|
|
if (mctrl->read_flag)
|
|
mctrl->trans_stat = sdrv_i2c_pread(cfg->base, cfg->id, mctrl, timeout);
|
|
else
|
|
mctrl->trans_stat = sdrv_i2c_pwrite(cfg->base, cfg->id, mctrl, timeout);
|
|
}
|
|
else {
|
|
if (mctrl->read_flag)
|
|
int0_mask = SDRV_I2C_INT0_DEFAULT_MASK | SDRV_I2C_INT0_RXFWF;
|
|
else
|
|
int0_mask = SDRV_I2C_INT0_DEFAULT_MASK | SDRV_I2C_INT0_TXFWE;
|
|
|
|
sdrv_i2c_unmask_int(cfg->base, I2C_INTEN0, int0_mask);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief I2c master mode interrupt handler for data send/receive and
|
|
* transfer status check
|
|
*
|
|
* @param[in] irq i2c controller irq num
|
|
* @param[in] arg i2c ctrl instance get from irq register
|
|
*
|
|
* @return 0
|
|
*/
|
|
static int sdrv_i2c_master_irq_handler(uint32_t irq, void *arg)
|
|
{
|
|
uint16_t len = 0;
|
|
uint16_t flen = 0;
|
|
uint8_t *buf = NULL;
|
|
uint32_t int0_stat = 0;
|
|
sdrv_i2c_t *ctrl = arg;
|
|
sdrv_i2c_cfg_t *cfg = ctrl->cfg;
|
|
sdrv_i2cdrv_mctrl_t *mctrl = &ctrl->mctrl;
|
|
int0_stat = sdrv_i2c_get_int_stat(cfg->base, I2C_INTR0);
|
|
|
|
sdrv_i2c_clear_int_bits(cfg->base, I2C_INTR0, int0_stat);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_APBCMDDONE) {
|
|
mctrl->trans_stat = SDRV_I2CDRV_TRANS_OK;
|
|
|
|
if (mctrl->cb)
|
|
mctrl->cb(ctrl, mctrl->cb_param, mctrl->trans_stat);
|
|
}
|
|
else if (int0_stat & SDRV_I2C_INT0_ERR_STAT) {
|
|
mctrl->trans_stat = sdrv_i2c_check_err(cfg->base, &mctrl->trans_errcode,
|
|
cfg->id, int0_stat, 0);
|
|
|
|
if (mctrl->cb)
|
|
mctrl->cb(ctrl, mctrl->cb_param, mctrl->trans_stat);
|
|
|
|
sdrv_i2c_disable_int(cfg->base);
|
|
return 0;
|
|
}
|
|
|
|
buf = mctrl->buf + mctrl->cur_len;
|
|
|
|
if (mctrl->read_flag) {
|
|
flen = sdrv_i2c_get_rspace(cfg->base);
|
|
len = i2c_min(flen, mctrl->len - mctrl->cur_len);
|
|
mctrl->cur_len += len;
|
|
while (len--)
|
|
*buf++ = sdrv_i2c_recv_data(cfg->base);
|
|
}
|
|
else {
|
|
flen = sdrv_i2c_get_wspace(cfg->base);
|
|
len = i2c_min(flen, mctrl->len - mctrl->cur_len);
|
|
mctrl->cur_len += len;
|
|
while (len--)
|
|
sdrv_i2c_send_data(cfg->base, *buf++);
|
|
}
|
|
|
|
if (mctrl->cur_len >= mctrl->len)
|
|
sdrv_i2c_unmask_int(cfg->base, I2C_INTEN0, SDRV_I2C_INT0_DEFAULT_MASK);
|
|
|
|
if (int0_stat & SDRV_I2C_INT0_APBCMDDONE)
|
|
sdrv_i2c_disable_int(cfg->base);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Set bus stat(only applicable for master).
|
|
* @this api will abandon,please use
|
|
* sdrv_i2c_lock_bus/sdrv_i2c_unlock_bus instead
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] bus_stat bus stat to be set
|
|
*
|
|
* @return SDRV_STATUS_OK
|
|
*/
|
|
status_t sdrv_i2c_set_bus_stat(sdrv_i2c_t *ctrl,
|
|
sdrv_i2cdrv_bus_stat_t bus_stat)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
ctrl->cfg->bus_stat = bus_stat;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get bus stat(only applicable for master).
|
|
* @this api will abandon,please use
|
|
* sdrv_i2c_lock_bus/sdrv_i2c_unlock_bus instead
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
*
|
|
* @return SDRV_I2CDRV_BUS_IDLE/SDRV_I2CDRV_BUS_BUSY
|
|
*/
|
|
sdrv_i2cdrv_bus_stat_t sdrv_i2c_get_bus_stat(sdrv_i2c_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
return ctrl->cfg->bus_stat;
|
|
}
|
|
|
|
/**
|
|
* @brief Lock bus stat(only applicable for master).
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_lock_bus(sdrv_i2c_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
irq_state_t irq_stat;
|
|
status_t ret = SDRV_STATUS_FAIL;
|
|
|
|
irq_stat = arch_irq_save();
|
|
|
|
if (ctrl->cfg->bus_stat == SDRV_I2CDRV_BUS_IDLE) {
|
|
ctrl->cfg->bus_stat = SDRV_I2CDRV_BUS_BUSY;
|
|
ret = SDRV_STATUS_OK;
|
|
}
|
|
|
|
arch_irq_restore(irq_stat);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Unlock bus stat(only applicable for master).
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
*
|
|
* @return SDRV_STATUS_OK
|
|
*/
|
|
status_t sdrv_i2c_unlock_bus(sdrv_i2c_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
irq_state_t irq_stat;
|
|
|
|
irq_stat = arch_irq_save();
|
|
ctrl->cfg->bus_stat = SDRV_I2CDRV_BUS_IDLE;
|
|
arch_irq_restore(irq_stat);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Init the i2c controller.
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_init_ctrl(sdrv_i2c_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
|
|
if (ctrl->cfg->inited == 1)
|
|
return SDRV_STATUS_OK;
|
|
|
|
sdrv_i2c_disable_int(ctrl->cfg->base);
|
|
sdrv_i2c_clear_fifo(ctrl->cfg->base);
|
|
sdrv_i2c_clear_int(ctrl->cfg->base);
|
|
sdrv_i2c_reset(ctrl->cfg->base);
|
|
sdrv_i2c_set_watermark(ctrl->cfg->base, SDRV_I2C_RXTX_WML);
|
|
|
|
if (ctrl->cfg->speed == SDRV_I2CDRV_SSPEED)
|
|
sdrv_i2c_set_timing(ctrl->cfg->base, ctrl->cfg->clk, 0);
|
|
else if (ctrl->cfg->speed == SDRV_I2CDRV_FSPEED)
|
|
sdrv_i2c_set_timing(ctrl->cfg->base, ctrl->cfg->clk, 1);
|
|
else if (ctrl->cfg->speed == SDRV_I2CDRV_PSPEED)
|
|
sdrv_i2c_set_timing(ctrl->cfg->base, ctrl->cfg->clk, 2);
|
|
else if (ctrl->cfg->speed == SDRV_I2CDRV_HSPEED)
|
|
sdrv_i2c_set_timing(ctrl->cfg->base, ctrl->cfg->clk, 3);
|
|
else if (ctrl->cfg->speed == SDRV_I2CDRV_USPEED)
|
|
sdrv_i2c_set_timing(ctrl->cfg->base, ctrl->cfg->clk, 4);
|
|
|
|
if (ctrl->cfg->speed == SDRV_I2CDRV_HSPEED)
|
|
sdrv_i2c_set_speed(ctrl->cfg->base, ctrl->cfg->clk, SDRV_I2C_HSPEED);
|
|
else if (ctrl->cfg->speed == SDRV_I2CDRV_USPEED)
|
|
sdrv_i2c_set_speed(ctrl->cfg->base, ctrl->cfg->clk, SDRV_I2C_USPEED);
|
|
else
|
|
sdrv_i2c_set_speed(ctrl->cfg->base, ctrl->cfg->clk, SDRV_I2C_NSPEED);
|
|
|
|
if (ctrl->cfg->opmode == SDRV_I2CDRV_MASTER) {
|
|
sdrv_i2c_set_opmode(ctrl->cfg->base, SDRV_I2C_MASTER);
|
|
irq_attach(ctrl->cfg->irq, sdrv_i2c_master_irq_handler, ctrl);
|
|
irq_enable(ctrl->cfg->irq);
|
|
}
|
|
else {
|
|
ssdk_printf(SSDK_CRIT, "i2c%u opmode err\r\n", ctrl->cfg->id);
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
ctrl->cfg->inited = 1;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Write data to slave device use poll blocking format
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] addr slave device 7bit addr not include LSB read/write bit
|
|
* @param[in] wbuf point to data buf for send
|
|
* @param[in] wlen data buf len
|
|
* @param[in] timeout timeout in milliseconds to wait (0 = wait forever)
|
|
* @param[in] need_stop whether send stop signal or hold sda after finish write
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_write(sdrv_i2c_t *ctrl, uint16_t addr,
|
|
uint8_t *wbuf, uint16_t wlen,
|
|
uint32_t timeout, bool need_stop)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(wbuf != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
ctrl->mctrl.slave_addr = addr;
|
|
ctrl->mctrl.buf = wbuf;
|
|
ctrl->mctrl.len = wlen;
|
|
ctrl->mctrl.read_flag = 0x0;
|
|
ctrl->mctrl.need_stop = need_stop;
|
|
ctrl->mctrl.cb = NULL;
|
|
ctrl->mctrl.cur_len = 0;
|
|
ctrl->cfg->tsmode = SDRV_I2CDRV_POLL;
|
|
|
|
return sdrv_i2c_xfer(ctrl, timeout);
|
|
}
|
|
|
|
/**
|
|
* @brief Read data from slave device use poll blocking format
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] addr slave device 7bit addr not include LSB read/write bit
|
|
* @param[out] rbuf point to data buf for receive
|
|
* @param[in] rlen data buf len
|
|
* @param[in] timeout timeout in milliseconds to wait (0 = wait forever)
|
|
* @param[in] need_stop whether send stop signal or hold sda after finish read
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_read(sdrv_i2c_t *ctrl, uint16_t addr,
|
|
uint8_t *rbuf, uint16_t rlen,
|
|
uint32_t timeout, bool need_stop)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(rbuf != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
ctrl->mctrl.slave_addr = addr;
|
|
ctrl->mctrl.buf = rbuf;
|
|
ctrl->mctrl.len = rlen;
|
|
ctrl->mctrl.read_flag = 0x1;
|
|
ctrl->mctrl.need_stop = need_stop;
|
|
ctrl->mctrl.cb = NULL;
|
|
ctrl->mctrl.cur_len = 0;
|
|
ctrl->cfg->tsmode = SDRV_I2CDRV_POLL;
|
|
|
|
return sdrv_i2c_xfer(ctrl, timeout);
|
|
}
|
|
|
|
/**
|
|
* @brief Write data to slave device use interrupt non-blocking format
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] addr slave device 7bit addr not include LSB read/write bit
|
|
* @param[in] wbuf point to data buf for send
|
|
* @param[in] wlen data buf len
|
|
* @param[in] need_stop whether send stop signal or hold sda after finish write
|
|
* @param[in] cb callback function pointer
|
|
* @param[in] cb_param callback user parameter
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_write_async(sdrv_i2c_t *ctrl,
|
|
uint16_t addr, uint8_t *wbuf, uint16_t wlen,
|
|
bool need_stop, sdrv_i2c_cb_t cb, void *cb_param)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(wbuf != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
ctrl->mctrl.slave_addr = addr;
|
|
ctrl->mctrl.buf = wbuf;
|
|
ctrl->mctrl.len = wlen;
|
|
ctrl->mctrl.read_flag = 0x0;
|
|
ctrl->mctrl.need_stop = need_stop;
|
|
ctrl->mctrl.cb = cb;
|
|
ctrl->mctrl.cb_param = cb_param;
|
|
ctrl->mctrl.cur_len = 0;
|
|
ctrl->cfg->tsmode = SDRV_I2CDRV_INTP;
|
|
|
|
return sdrv_i2c_xfer(ctrl, 0);
|
|
}
|
|
|
|
/**
|
|
* @brief Read data from slave device use interrupt non-blocking format
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
* @param[in] addr slave device 7bit addr not include LSB read/write bit
|
|
* @param[out] rbuf point to data buf for receive
|
|
* @param[in] rlen data buf len
|
|
* @param[in] need_stop whether send stop signal or hold sda after complete read
|
|
* @param[in] cb callback function pointer
|
|
* @param[in] cb_param callback user parameter
|
|
*
|
|
* @return SDRV_STATUS_OK/SDRV_STATUS_FAIL
|
|
*/
|
|
status_t sdrv_i2c_read_async(sdrv_i2c_t *ctrl,
|
|
uint16_t addr, uint8_t *rbuf, uint16_t rlen,
|
|
bool need_stop, sdrv_i2c_cb_t cb, void *cb_param)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(rbuf != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
ctrl->mctrl.slave_addr = addr;
|
|
ctrl->mctrl.buf = rbuf;
|
|
ctrl->mctrl.len = rlen;
|
|
ctrl->mctrl.read_flag = 0x1;
|
|
ctrl->mctrl.need_stop = need_stop;
|
|
ctrl->mctrl.cb = cb;
|
|
ctrl->mctrl.cb_param = cb_param;
|
|
ctrl->mctrl.cur_len = 0;
|
|
ctrl->cfg->tsmode = SDRV_I2CDRV_INTP;
|
|
|
|
return sdrv_i2c_xfer(ctrl, 0);
|
|
}
|
|
|
|
/**
|
|
* @brief Get transfer stat(only applicable for master).
|
|
*
|
|
* @param[in] ctrl i2c controller instance pointer
|
|
*
|
|
* @return SDRV_I2CDRV_TRANS_OK
|
|
* SDRV_I2CDRV_TRANS_GO
|
|
* SDRV_I2CDRV_TRANS_ERR
|
|
* SDRV_I2CDRV_TRANS_NAK
|
|
* SDRV_I2CDRV_TRANS_ABORT
|
|
* SDRV_I2CDRV_TRANS_TIMEOUT
|
|
*/
|
|
status_t sdrv_i2c_get_trans_stat(sdrv_i2c_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->cfg != NULL);
|
|
ASSERT(ctrl->cfg->opmode == SDRV_I2CDRV_MASTER);
|
|
|
|
return ctrl->mctrl.trans_stat;
|
|
}
|
|
|