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 4.2-rc1.
Change in v2:
Fix multi-transfer fail bug - in mtk_i2c_irq(), call complete()
if get I2C_RS_TRANSFER interrupt
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 | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
--
1.7.9.5
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 | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 9920eef..e28ad4c 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -59,6 +59,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 +82,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 +264,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
When occur i2c ack error, i2c controller generate two interrupts,
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 | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e28ad4c..c02e6c0 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -557,15 +557,22 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
{
struct mtk_i2c *i2c = dev_id;
u16 restart_flag = 0;
+ u16 intr_stat;
if (i2c->dev_comp->auto_restart)
restart_flag = I2C_RS_TRANSFER;
- 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);
+ intr_stat = readw(i2c->base + OFFSET_INTR_STAT);
+ writew(intr_stat, i2c->base + OFFSET_INTR_STAT);
- complete(&i2c->msg_complete);
+ /*
+ * when occurs ack error, i2c controller generate two interrupts
+ * first is the ack error interrupt, then the complete interrupt
+ * i2c->irq_stat need keep the two interrupt value.
+ */
+ i2c->irq_stat |= intr_stat;
+ if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
+ complete(&i2c->msg_complete);
return IRQ_HANDLED;
}
--
1.7.9.5
On Thu, Aug 6, 2015 at 3:22 PM, Eddie Huang <[email protected]> wrote:
> 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]>
Reviewed-by: Daniel Kurtz <[email protected]>
> ---
> drivers/i2c/busses/i2c-mt65xx.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 9920eef..e28ad4c 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -59,6 +59,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 +82,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 +264,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
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
On Thu, Aug 6, 2015 at 3:22 PM, Eddie Huang <[email protected]> wrote:
> When occur i2c ack error, i2c controller generate two interrupts,
> 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]>
Reviewed-by: Daniel Kurtz <[email protected]>
> ---
> drivers/i2c/busses/i2c-mt65xx.c | 15 +++++++++++----
> 1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index e28ad4c..c02e6c0 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -557,15 +557,22 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
> {
> struct mtk_i2c *i2c = dev_id;
> u16 restart_flag = 0;
> + u16 intr_stat;
>
> if (i2c->dev_comp->auto_restart)
> restart_flag = I2C_RS_TRANSFER;
>
> - 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);
> + intr_stat = readw(i2c->base + OFFSET_INTR_STAT);
> + writew(intr_stat, i2c->base + OFFSET_INTR_STAT);
>
> - complete(&i2c->msg_complete);
> + /*
> + * when occurs ack error, i2c controller generate two interrupts
> + * first is the ack error interrupt, then the complete interrupt
> + * i2c->irq_stat need keep the two interrupt value.
> + */
> + i2c->irq_stat |= intr_stat;
> + if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
> + complete(&i2c->msg_complete);
>
> return IRQ_HANDLED;
> }
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
On Thu, Aug 06, 2015 at 03:22:10PM +0800, Eddie Huang wrote:
> 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]>
Applied to for-next, thanks!
On Thu, Aug 06, 2015 at 03:22:11PM +0800, Eddie Huang wrote:
> When occur i2c ack error, i2c controller generate two interrupts,
> 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]>
Applied to for-next, thanks!
Hi Wolfram,
On Tue, Aug 11, 2015 at 10:55 PM, Wolfram Sang <[email protected]> wrote:
> On Thu, Aug 06, 2015 at 03:22:11PM +0800, Eddie Huang wrote:
>> When occur i2c ack error, i2c controller generate two interrupts,
>> 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]>
>
> Applied to for-next, thanks!
I don't see them in [0].
[0] https://git.kernel.org/cgit/linux/kernel/git/wsa/linux.git/log/?h=i2c/for-next
Am I not looking in the right place?
Or, did I not wait long enough?
Thanks!
-Dan
> Or, did I not wait long enough?
This.