LS1043 i2c dma problem

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

LS1043 i2c dma problem

跳至解决方案
2,996 次查看
thorstenpohlman
Contributor II

Hi,

Custom LS1043 Board

Linux version 5.4.47-2.3 (NXP-SDK 2.2 dunfell)

 

i've got a weird I2C problem:

Everything is working quite fine, reading temperature-sensors, reading/setting rtcs (all transfers < 16 bytes)...

But I need to transmit 4kB of data to a I2C slave, so the drivers/i2c/busses/i2c-imx.c  driver selects DMA ( i2c_imx_xfer line 1171).

The problem: DMA transfer just transmits garbarge over i2c, some unknown part of memory to be precise. I saw parts of the boot-message (klog), different contents on every transfer. I tracked down to the dma_map_single()  (i2c_imx_dma_xfer line 457), everything seems to be correct (msgs->buf contains the correct data).

If i increase the DMA_THRESHOLD so dma isnt used, everything works fine.

 

Its also reproducable with the i2ctransfer tool, e.g. i2ctransfer -y 0 w10@0x12 0+ sends incremental data, i2ctransfer -y 0 w4000@0x12 0+ sends complete nonsense.

(Nonsense sent is validated with a DigiView probe)

Any suggestions?

0 项奖励
回复
1 解答
2,964 次查看
thorstenpohlman
Contributor II

Hi,

obviously the LS1043/1046 don't provide cache/DMA coherency for I2C device DMA?!

So the write buffer stays in cpu cache and is not visible to DMA.

Who is the maintainer for this driver now?

This patch is working for me now (altough i could only test the write-part)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index af352886ef6f..54e2a7b88f0a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -441,6 +441,9 @@ static void i2c_imx_dma_callback(void *arg)
struct imx_i2c_struct *i2c_imx = (struct imx_i2c_struct *)arg;
struct imx_i2c_dma *dma = i2c_imx->dma;

+ if(dma->dma_transfer_dir == DMA_DEV_TO_MEM)
+ dma_sync_single_for_device(&i2c_imx->adapter.dev, dma->dma_buf, dma->dma_len, dma->dma_transfer_dir);
+
dma_unmap_single(dma->chan_using->device->dev, dma->dma_buf,
dma->dma_len, dma->dma_data_dir);
complete(&dma->cmd_complete);
@@ -461,7 +464,8 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
goto err_map;
}

+ if(dma->dma_transfer_dir == DMA_MEM_TO_DEV)
+ dma_sync_single_for_device(dev, dma->dma_buf, dma->dma_len, dma->dma_transfer_dir);

txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
dma->dma_len, dma->dma_transfer_dir,

 

在原帖中查看解决方案

0 项奖励
回复
2 回复数
2,965 次查看
thorstenpohlman
Contributor II

Hi,

obviously the LS1043/1046 don't provide cache/DMA coherency for I2C device DMA?!

So the write buffer stays in cpu cache and is not visible to DMA.

Who is the maintainer for this driver now?

This patch is working for me now (altough i could only test the write-part)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index af352886ef6f..54e2a7b88f0a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -441,6 +441,9 @@ static void i2c_imx_dma_callback(void *arg)
struct imx_i2c_struct *i2c_imx = (struct imx_i2c_struct *)arg;
struct imx_i2c_dma *dma = i2c_imx->dma;

+ if(dma->dma_transfer_dir == DMA_DEV_TO_MEM)
+ dma_sync_single_for_device(&i2c_imx->adapter.dev, dma->dma_buf, dma->dma_len, dma->dma_transfer_dir);
+
dma_unmap_single(dma->chan_using->device->dev, dma->dma_buf,
dma->dma_len, dma->dma_data_dir);
complete(&dma->cmd_complete);
@@ -461,7 +464,8 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
goto err_map;
}

+ if(dma->dma_transfer_dir == DMA_MEM_TO_DEV)
+ dma_sync_single_for_device(dev, dma->dma_buf, dma->dma_len, dma->dma_transfer_dir);

txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
dma->dma_len, dma->dma_transfer_dir,

 

0 项奖励
回复
2,955 次查看
thorstenpohlman
Contributor II

Wow,

 

all reply i got fom NXP was an automatic email if the answer (that i provided myself) "did solve your problem"...

0 项奖励
回复