static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num)
{
struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
unsigned int temp;
int i, result;
bool is_nostart;
result = lpi2c_imx_master_enable(lpi2c_imx);
if (result)
return result;
for (i = 0; i < num; i++) {
is_nostart = !!(msgs[i].flags & I2C_M_NOSTART);
/*
* Аппаратный СТАРТ генерируем ТОЛЬКО для первого сообщения
* или если флаг I2C_M_NOSTART явно ОТСУТСТВУЕТ.
*/
if (i == 0 || !is_nostart) {
result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
if (result)
goto disable;
} else {
/*
* Если это NOSTART, ПЛИС уже слушает шину.
* Сбрасываем счетчик доставленных байт текущего msg для PIO/DMA логики.
*/
lpi2c_imx->delivered = 0;
}
/* Quick SMBus check */
if (num == 1 && msgs[0].len == 0)
goto stop;
lpi2c_imx->rx_buf = NULL;
lpi2c_imx->tx_buf = NULL;
lpi2c_imx->delivered = 0;
lpi2c_imx->msglen = msgs[i].len;
init_completion(&lpi2c_imx->complete);
/*
* ВНИМАНИЕ: Если это NOSTART-сообщение, принудительно шлем его через PIO.
* Это защищает от микросекундных пауз на переключение eDMA-каналов i.MX95,
* которые вызывают Clock Stretching и BSE Timeout в ПЛИС.
*/
if (is_use_dma(lpi2c_imx, &msgs[i]) && !is_nostart) {
result = lpi2c_imx_dma_xfer(lpi2c_imx, &msgs[i]);
if (result && lpi2c_imx->dma->using_pio_mode)
result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
} else {
result = lpi2c_imx_pio_xfer(lpi2c_imx, &msgs[i]);
}
if (result)
goto stop;
if (!(msgs[i].flags & I2C_M_RD)) {
result = lpi2c_imx_txfifo_empty(lpi2c_imx);
if (result)
goto stop;
}
}
stop:
/*
* Аппаратный СТОП генерируется только один раз в самом конце,
* когда весь массив сообщений (Команда + Куски битстрима) полностью передан.
*/
lpi2c_imx_stop(lpi2c_imx);
temp = readl(lpi2c_imx->base + LPI2C_MSR);
if ((temp & MSR_NDF) && !result)
result = -EIO;
disable:
lpi2c_imx_master_disable(lpi2c_imx);
dev_dbg(&lpi2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
return (result < 0) ? result : num;
}