2015-08-04 11:45:10

by Eddie Huang (黃智傑)

[permalink] [raw]
Subject: [PATCH 0/2] Mediatek I2C fixup

This series provide two patches to optimize mediatek i2c driver.
The first patch will reset dma hardware in init function to make sure
hardware work in good state. The second patch fix i2c interrupt handling
for ACK error. All these patches base on v4.2-rc1.

Eddie Huang (2):
i2c: mediatek: Reset DMA engine in hardware init function
i2c: mediatek: Fixup i2c ack error interrupt handling

drivers/i2c/busses/i2c-mt65xx.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)

--
1.7.9.5


2015-08-04 11:45:32

by Eddie Huang (黃智傑)

[permalink] [raw]
Subject: [PATCH 1/2] i2c: mediatek: Reset DMA engine in hardware init function

Reset DMA in hardware init function to avoid unknown hardware state
before do any I2C operation.

Signed-off-by: Liguo Zhang <[email protected]>
Signed-off-by: Eddie Huang <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 9920eef..055159d 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -1,6 +1,8 @@
/*
* Copyright (c) 2014 MediaTek Inc.
- * Author: Xudong Chen <[email protected]>
+ * Author:
+ * Xudong Chen <[email protected]>
+ * Liguo Zhang <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -59,6 +61,7 @@
#define I2C_DMA_START_EN 0x0001
#define I2C_DMA_INT_FLAG_NONE 0x0000
#define I2C_DMA_CLR_FLAG 0x0000
+#define I2C_DMA_HARD_RST 0x0002

#define I2C_DEFAULT_SPEED 100000 /* hz */
#define MAX_FS_MODE_SPEED 400000
@@ -81,6 +84,7 @@ enum DMA_REGS_OFFSET {
OFFSET_INT_FLAG = 0x0,
OFFSET_INT_EN = 0x04,
OFFSET_EN = 0x08,
+ OFFSET_RST = 0x0c,
OFFSET_CON = 0x18,
OFFSET_TX_MEM_ADDR = 0x1c,
OFFSET_RX_MEM_ADDR = 0x20,
@@ -262,6 +266,10 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
writew(control_reg, i2c->base + OFFSET_CONTROL);
writew(I2C_DELAY_LEN, i2c->base + OFFSET_DELAY_LEN);
+
+ writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
+ udelay(50);
+ writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
}

/*
--
1.7.9.5

2015-08-04 11:45:15

by Eddie Huang (黃智傑)

[permalink] [raw]
Subject: [PATCH 2/2] i2c: mediatek: Fixup i2c ack error interrupt handling

When occur i2c ack error, mtk_i2c_irq is called twice,
first is the ack error interrupt, then the complete interrupt.
i2c interrupt handler should keep the two interrupt value, and only
call complete() for the complete interrupt.

Signed-off-by: Liguo Zhang <[email protected]>
Signed-off-by: Eddie Huang <[email protected]>
---
drivers/i2c/busses/i2c-mt65xx.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 055159d..12ce7f8 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -558,16 +558,20 @@ err_exit:
static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
{
struct mtk_i2c *i2c = dev_id;
- u16 restart_flag = 0;
+ u16 intr_stat = 0;

- if (i2c->dev_comp->auto_restart)
- restart_flag = I2C_RS_TRANSFER;
+ intr_stat = readw(i2c->base + OFFSET_INTR_STAT);
+ writew(intr_stat, i2c->base + OFFSET_INTR_STAT);

- i2c->irq_stat = readw(i2c->base + OFFSET_INTR_STAT);
- writew(restart_flag | I2C_HS_NACKERR | I2C_ACKERR
- | I2C_TRANSAC_COMP, i2c->base + OFFSET_INTR_STAT);
+ /*
+ * when occurs i2c ack error, mtk_i2c_irq is called twice,
+ * first is the ack error interrupt, then the complete interrupt,
+ * i2c->irq_stat need keep the two interrupt value.
+ */
+ i2c->irq_stat |= intr_stat;

- complete(&i2c->msg_complete);
+ if (i2c->irq_stat & I2C_TRANSAC_COMP)
+ complete(&i2c->msg_complete);

return IRQ_HANDLED;
}
--
1.7.9.5