in master/i3c-master-cdns.c [815:873]
static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
const struct i2c_msg *xfers, int nxfers)
{
struct i3c_master_controller *m = i2c_dev_get_master(dev);
struct cdns_i3c_master *master = to_cdns_i3c_master(m);
unsigned int nrxwords = 0, ntxwords = 0;
struct cdns_i3c_xfer *xfer;
int i, ret = 0;
if (nxfers > master->caps.cmdfifodepth)
return -ENOTSUPP;
for (i = 0; i < nxfers; i++) {
if (xfers[i].len > CMD0_FIFO_PL_LEN_MAX)
return -ENOTSUPP;
if (xfers[i].flags & I2C_M_RD)
nrxwords += DIV_ROUND_UP(xfers[i].len, 4);
else
ntxwords += DIV_ROUND_UP(xfers[i].len, 4);
}
if (ntxwords > master->caps.txfifodepth ||
nrxwords > master->caps.rxfifodepth)
return -ENOTSUPP;
xfer = cdns_i3c_master_alloc_xfer(master, nxfers);
if (!xfer)
return -ENOMEM;
for (i = 0; i < nxfers; i++) {
struct cdns_i3c_cmd *ccmd = &xfer->cmds[i];
ccmd->cmd0 = CMD0_FIFO_DEV_ADDR(xfers[i].addr) |
CMD0_FIFO_PL_LEN(xfers[i].len) |
CMD0_FIFO_PRIV_XMIT_MODE(XMIT_BURST_WITHOUT_SUBADDR);
if (xfers[i].flags & I2C_M_TEN)
ccmd->cmd0 |= CMD0_FIFO_IS_10B;
if (xfers[i].flags & I2C_M_RD) {
ccmd->cmd0 |= CMD0_FIFO_RNW;
ccmd->rx_buf = xfers[i].buf;
ccmd->rx_len = xfers[i].len;
} else {
ccmd->tx_buf = xfers[i].buf;
ccmd->tx_len = xfers[i].len;
}
}
cdns_i3c_master_queue_xfer(master, xfer);
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
cdns_i3c_master_unqueue_xfer(master, xfer);
ret = xfer->ret;
cdns_i3c_master_free_xfer(xfer);
return ret;
}