i2c-qcom-geni: Handle the DMA transfer complete interrupt
Wait for RX_DMA_DONE or TX_DMA_DONE interrupt for transfer
completion in i2c DMA mode.
Change-Id: I9b8a7661363ad2cda67cbfa229fd96a88282ddff
Signed-off-by: Vipin Deep Kaur <vkaur@codeaurora.org>
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index ec37ff0..63dc2ab 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -328,11 +328,12 @@
SE_DMA_RX_IRQ_CLR);
/* Ensure all writes are done before returning from ISR. */
wmb();
+ if ((dm_tx_st & TX_DMA_DONE) || (dm_rx_st & RX_DMA_DONE))
+ complete(&gi2c->xfer);
+
}
/* if this is err with done-bit not set, handle that thr' timeout. */
- if (m_stat & M_CMD_DONE_EN)
- complete(&gi2c->xfer);
- else if ((dm_tx_st & TX_DMA_DONE) || (dm_rx_st & RX_DMA_DONE))
+ else if (m_stat & M_CMD_DONE_EN)
complete(&gi2c->xfer);
return IRQ_HANDLED;
@@ -677,6 +678,7 @@
dma_addr_t tx_dma = 0;
dma_addr_t rx_dma = 0;
enum se_xfer_mode mode = FIFO_MODE;
+ reinit_completion(&gi2c->xfer);
m_param |= (stretch ? STOP_STRETCH : 0);
m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT);
@@ -736,6 +738,7 @@
gi2c->xfer_timeout);
if (!timeout) {
geni_i2c_err(gi2c, GENI_TIMEOUT);
+ reinit_completion(&gi2c->xfer);
gi2c->cur = NULL;
geni_abort_m_cmd(gi2c->base);
timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
@@ -744,6 +747,7 @@
gi2c->cur_rd = 0;
if (mode == SE_DMA) {
if (gi2c->err) {
+ reinit_completion(&gi2c->xfer);
if (msgs[i].flags != I2C_M_RD)
writel_relaxed(1, gi2c->base +
SE_DMA_TX_FSM_RST);
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index 267ed8d..dedcb5f 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -298,6 +298,10 @@
geni_write_reg(0xFFFFFFFF, base, SE_DMA_RX_IRQ_CLR);
geni_write_reg(0xFFFFFFFF, base, SE_IRQ_EN);
+ /* Clearing registers before reading */
+ geni_write_reg(0x00000000, base, SE_GENI_M_IRQ_EN);
+ geni_write_reg(0x00000000, base, SE_GENI_S_IRQ_EN);
+
common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
common_geni_s_irq_en = geni_read_reg(base, SE_GENI_S_IRQ_EN);
geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
@@ -317,9 +321,7 @@
static int geni_se_select_dma_mode(void __iomem *base)
{
- int proto = get_se_proto(base);
unsigned int geni_dma_mode = 0;
- unsigned int common_geni_m_irq_en;
geni_write_reg(0, base, SE_GSI_EVENT_EN);
geni_write_reg(0xFFFFFFFF, base, SE_GENI_M_IRQ_CLEAR);
@@ -327,13 +329,9 @@
geni_write_reg(0xFFFFFFFF, base, SE_DMA_TX_IRQ_CLR);
geni_write_reg(0xFFFFFFFF, base, SE_DMA_RX_IRQ_CLR);
geni_write_reg(0xFFFFFFFF, base, SE_IRQ_EN);
+ geni_write_reg(0x00000000, base, SE_GENI_M_IRQ_EN);
+ geni_write_reg(0x00000000, base, SE_GENI_S_IRQ_EN);
- common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN);
- if (proto != UART)
- common_geni_m_irq_en &=
- ~(M_TX_FIFO_WATERMARK_EN | M_RX_FIFO_WATERMARK_EN);
-
- geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN);
geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
geni_dma_mode |= GENI_DMA_MODE_EN;
geni_write_reg(geni_dma_mode, base, SE_GENI_DMA_MODE_EN);