1 From 95e4dfbf33dc0a0843ba20db811f7ea271235e1e Mon Sep 17 00:00:00 2001
2 From: Kewei Xu <kewei.xu@mediatek.com>
3 Date: Sun, 10 Oct 2021 15:05:12 +0800
4 Subject: [PATCH 01/16] i2c: mediatek: Reset the handshake signal between i2c
7 Due to changes in the hardware design of the handshaking signal
8 between i2c and dma, it is necessary to reset the handshaking
9 signal before each transfer to ensure that the multi-msgs can
10 be transferred correctly.
12 Signed-off-by: Kewei Xu <kewei.xu@mediatek.com>
13 Reviewed-by: Qii Wang <qii.wang@mediatek.com>
14 Signed-off-by: Wolfram Sang <wsa@kernel.org>
16 drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++
17 1 file changed, 26 insertions(+)
19 --- a/drivers/i2c/busses/i2c-mt65xx.c
20 +++ b/drivers/i2c/busses/i2c-mt65xx.c
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
25 +#include <linux/iopoll.h>
26 #include <linux/kernel.h>
28 #include <linux/module.h>
30 #define I2C_RD_TRANAC_VALUE 0x0001
31 #define I2C_SCL_MIS_COMP_VALUE 0x0000
32 #define I2C_CHN_CLR_FLAG 0x0000
33 +#define I2C_RELIABILITY 0x0010
34 +#define I2C_DMAACK_ENABLE 0x0008
36 #define I2C_DMA_CON_TX 0x0000
37 #define I2C_DMA_CON_RX 0x0001
38 @@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mt
43 u8 *dma_rd_buf = NULL;
44 u8 *dma_wr_buf = NULL;
45 dma_addr_t rpaddr = 0;
46 @@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mt
48 reinit_completion(&i2c->msg_complete);
50 + if (i2c->dev_comp->apdma_sync &&
51 + i2c->op != I2C_MASTER_WRRD && num > 1) {
52 + mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL);
53 + writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
54 + i2c->pdmabase + OFFSET_RST);
56 + ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST,
58 + !(reg_dma_reset & I2C_DMA_WARM_RST),
61 + dev_err(i2c->dev, "DMA warm reset timeout\n");
65 + writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
66 + mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET);
67 + mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
68 + mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE,
72 control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
73 ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
74 if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))