Files
1CAR/drivers/source/i2c/sdrv_i2c.c
2025-10-25 21:11:06 +08:00

661 lines
20 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;
}