LS1043 i2c dma problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LS1043 i2c dma problem

Jump to solution
1,211 Views
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 Kudos
1 Solution
1,179 Views
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,

 

View solution in original post

0 Kudos
2 Replies
1,180 Views
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 Kudos
1,170 Views
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 Kudos