Skip to content

Commit e3e4949

Browse files
Kewei Xuwsakernel
authored andcommitted
i2c: mediatek: Reset the handshake signal between i2c and dma
Due to changes in the hardware design of the handshaking signal between i2c and dma, it is necessary to reset the handshaking signal before each transfer to ensure that the multi-msgs can be transferred correctly. Signed-off-by: Kewei Xu <[email protected]> Reviewed-by: Qii Wang <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 712d661 commit e3e4949

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

drivers/i2c/busses/i2c-mt65xx.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/init.h>
1616
#include <linux/interrupt.h>
1717
#include <linux/io.h>
18+
#include <linux/iopoll.h>
1819
#include <linux/kernel.h>
1920
#include <linux/mm.h>
2021
#include <linux/module.h>
@@ -49,6 +50,8 @@
4950
#define I2C_RD_TRANAC_VALUE 0x0001
5051
#define I2C_SCL_MIS_COMP_VALUE 0x0000
5152
#define I2C_CHN_CLR_FLAG 0x0000
53+
#define I2C_RELIABILITY 0x0010
54+
#define I2C_DMAACK_ENABLE 0x0008
5255

5356
#define I2C_DMA_CON_TX 0x0000
5457
#define I2C_DMA_CON_RX 0x0001
@@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
851854
u16 restart_flag = 0;
852855
u16 dma_sync = 0;
853856
u32 reg_4g_mode;
857+
u32 reg_dma_reset;
854858
u8 *dma_rd_buf = NULL;
855859
u8 *dma_wr_buf = NULL;
856860
dma_addr_t rpaddr = 0;
@@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
864868

865869
reinit_completion(&i2c->msg_complete);
866870

871+
if (i2c->dev_comp->apdma_sync &&
872+
i2c->op != I2C_MASTER_WRRD && num > 1) {
873+
mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL);
874+
writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
875+
i2c->pdmabase + OFFSET_RST);
876+
877+
ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST,
878+
reg_dma_reset,
879+
!(reg_dma_reset & I2C_DMA_WARM_RST),
880+
0, 100);
881+
if (ret) {
882+
dev_err(i2c->dev, "DMA warm reset timeout\n");
883+
return -ETIMEDOUT;
884+
}
885+
886+
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
887+
mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET);
888+
mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
889+
mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE,
890+
OFFSET_DEBUGCTRL);
891+
}
892+
867893
control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
868894
~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
869895
if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))

0 commit comments

Comments
 (0)