8b0119640984c944e69ed09beb3918686980fdb9
[openwrt/staging/ldir.git] /
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
5 and dma
6
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.
11
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>
15 ---
16 drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++
17 1 file changed, 26 insertions(+)
18
19 --- a/drivers/i2c/busses/i2c-mt65xx.c
20 +++ b/drivers/i2c/busses/i2c-mt65xx.c
21 @@ -15,6 +15,7 @@
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/io.h>
25 +#include <linux/iopoll.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.h>
28 #include <linux/module.h>
29 @@ -49,6 +50,8 @@
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
35
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
39 u16 restart_flag = 0;
40 u16 dma_sync = 0;
41 u32 reg_4g_mode;
42 + u32 reg_dma_reset;
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
47
48 reinit_completion(&i2c->msg_complete);
49
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);
55 +
56 + ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST,
57 + reg_dma_reset,
58 + !(reg_dma_reset & I2C_DMA_WARM_RST),
59 + 0, 100);
60 + if (ret) {
61 + dev_err(i2c->dev, "DMA warm reset timeout\n");
62 + return -ETIMEDOUT;
63 + }
64 +
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,
69 + OFFSET_DEBUGCTRL);
70 + }
71 +
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))