]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i2c: mediatek: Fix apdma and i2c hand-shake timeout
authorQii Wang <qii.wang@mediatek.com>
Thu, 24 Dec 2020 12:26:07 +0000 (20:26 +0800)
committerWolfram Sang <wsa@kernel.org>
Tue, 5 Jan 2021 09:54:37 +0000 (10:54 +0100)
With the apdma remove hand-shake signal, it requirs special
operation timing to reset i2c manually, otherwise the interrupt
will not be triggered, i2c transmission will be timeout.

Fixes: 8426fe70cfa4("i2c: mediatek: Add apdma sync in i2c driver")
Signed-off-by: Qii Wang <qii.wang@mediatek.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
drivers/i2c/busses/i2c-mt65xx.c

index 33de99b7bc20c0ea215991c43efa1f89529e474e..0818d3e50734771b854b875b78bcc60c37ded121 100644 (file)
@@ -38,6 +38,7 @@
 #define I2C_IO_CONFIG_OPEN_DRAIN       0x0003
 #define I2C_IO_CONFIG_PUSH_PULL                0x0000
 #define I2C_SOFT_RST                   0x0001
+#define I2C_HANDSHAKE_RST              0x0020
 #define I2C_FIFO_ADDR_CLR              0x0001
 #define I2C_DELAY_LEN                  0x0002
 #define I2C_TIME_CLR_VALUE             0x0000
@@ -45,6 +46,7 @@
 #define I2C_WRRD_TRANAC_VALUE          0x0002
 #define I2C_RD_TRANAC_VALUE            0x0001
 #define I2C_SCL_MIS_COMP_VALUE         0x0000
+#define I2C_CHN_CLR_FLAG               0x0000
 
 #define I2C_DMA_CON_TX                 0x0000
 #define I2C_DMA_CON_RX                 0x0001
@@ -54,7 +56,9 @@
 #define I2C_DMA_START_EN               0x0001
 #define I2C_DMA_INT_FLAG_NONE          0x0000
 #define I2C_DMA_CLR_FLAG               0x0000
+#define I2C_DMA_WARM_RST               0x0001
 #define I2C_DMA_HARD_RST               0x0002
+#define I2C_DMA_HANDSHAKE_RST          0x0004
 
 #define MAX_SAMPLE_CNT_DIV             8
 #define MAX_STEP_CNT_DIV               64
@@ -475,11 +479,24 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
        u16 control_reg;
 
-       writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
-       udelay(50);
-       writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
-
-       mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
+       if (i2c->dev_comp->dma_sync) {
+               writel(I2C_DMA_WARM_RST, i2c->pdmabase + OFFSET_RST);
+               udelay(10);
+               writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+               udelay(10);
+               writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_HARD_RST,
+                      i2c->pdmabase + OFFSET_RST);
+               mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST | I2C_SOFT_RST,
+                              OFFSET_SOFTRESET);
+               udelay(10);
+               writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+               mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
+       } else {
+               writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
+               udelay(50);
+               writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+               mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
+       }
 
        /* Set ioconfig */
        if (i2c->use_push_pull)