diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index b29b110c3e03..d62c3d3b0d3e 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -113,7 +113,10 @@ struct geni_i2c_dev { int err; struct i2c_adapter adap; struct completion done; + struct completion abort_done; struct completion cancel_done; + struct completion tx_reset_done; + struct completion rx_reset_done; struct i2c_msg *cur; int cur_wr; int cur_rd; @@ -127,7 +130,6 @@ struct geni_i2c_dev { struct dma_chan *rx_c; bool no_dma; bool gpi_mode; - bool abort_done; bool is_tx_multi_desc_xfer; u32 num_msgs; struct geni_i2c_gpi_multi_desc_xfer i2c_multi_desc_config; @@ -256,8 +258,6 @@ static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err) switch (err) { case GENI_ABORT_DONE: - gi2c->abort_done = true; - break; case NACK: case GENI_TIMEOUT: dev_dbg(gi2c->se.dev, "%s\n", gi2c_log[err].msg); @@ -359,12 +359,18 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) writel_relaxed(dm_rx_st, base + SE_DMA_RX_IRQ_CLR); /* if this is err with done-bit not set, handle that through timeout. */ - if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN || - dm_tx_st & TX_DMA_DONE || dm_tx_st & TX_RESET_DONE || - dm_rx_st & RX_DMA_DONE || dm_rx_st & RX_RESET_DONE) + if (m_stat & M_CMD_DONE_EN || + dm_tx_st & TX_DMA_DONE || + dm_rx_st & RX_DMA_DONE) complete(&gi2c->done); if (m_stat & M_CMD_CANCEL_EN) complete(&gi2c->cancel_done); + if (m_stat & M_CMD_ABORT_EN) + complete(&gi2c->abort_done); + if (dm_tx_st & TX_RESET_DONE) + complete(&gi2c->tx_reset_done); + if (dm_rx_st & RX_RESET_DONE) + complete(&gi2c->rx_reset_done); spin_unlock(&gi2c->lock); @@ -376,17 +382,13 @@ static void geni_i2c_abort_xfer(struct geni_i2c_dev *gi2c) unsigned long time_left = ABORT_TIMEOUT; unsigned long flags; + reinit_completion(&gi2c->abort_done); + spin_lock_irqsave(&gi2c->lock, flags); - geni_i2c_err(gi2c, GENI_TIMEOUT); - gi2c->cur = NULL; - gi2c->abort_done = false; geni_se_abort_m_cmd(&gi2c->se); spin_unlock_irqrestore(&gi2c->lock, flags); - do { - time_left = wait_for_completion_timeout(&gi2c->done, time_left); - } while (!gi2c->abort_done && time_left); - + time_left = wait_for_completion_timeout(&gi2c->abort_done, time_left); if (!time_left) dev_err(gi2c->se.dev, "Timeout abort_m_cmd\n"); } @@ -414,31 +416,25 @@ static void geni_i2c_cancel_xfer(struct geni_i2c_dev *gi2c) static void geni_i2c_rx_fsm_rst(struct geni_i2c_dev *gi2c) { - u32 val; unsigned long time_left = RST_TIMEOUT; + reinit_completion(&gi2c->rx_reset_done); writel_relaxed(1, gi2c->se.base + SE_DMA_RX_FSM_RST); - do { - time_left = wait_for_completion_timeout(&gi2c->done, time_left); - val = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT); - } while (!(val & RX_RESET_DONE) && time_left); - if (!(val & RX_RESET_DONE)) + time_left = wait_for_completion_timeout(&gi2c->rx_reset_done, time_left); + if (!time_left) dev_err(gi2c->se.dev, "Timeout resetting RX_FSM\n"); } static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c) { - u32 val; unsigned long time_left = RST_TIMEOUT; + reinit_completion(&gi2c->tx_reset_done); writel_relaxed(1, gi2c->se.base + SE_DMA_TX_FSM_RST); - do { - time_left = wait_for_completion_timeout(&gi2c->done, time_left); - val = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT); - } while (!(val & TX_RESET_DONE) && time_left); - if (!(val & TX_RESET_DONE)) + time_left = wait_for_completion_timeout(&gi2c->tx_reset_done, time_left); + if (!time_left) dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n"); } @@ -851,6 +847,7 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i for (i = 0; i < num; i++) { gi2c->cur = &msgs[i]; gi2c->err = 0; + reinit_completion(&gi2c->done); dev_dbg(gi2c->se.dev, "msg[%d].len:%d\n", i, gi2c->cur->len); peripheral.stretch = 0; @@ -920,6 +917,8 @@ static int geni_i2c_fifo_xfer(struct geni_i2c_dev *gi2c, m_param |= ((msgs[i].addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK); gi2c->cur = &msgs[i]; + gi2c->err = 0; + reinit_completion(&gi2c->done); if (msgs[i].flags & I2C_M_RD) ret = geni_i2c_rx_one_msg(gi2c, &msgs[i], m_param); else @@ -939,8 +938,6 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap); int ret; - gi2c->err = 0; - reinit_completion(&gi2c->done); ret = pm_runtime_get_sync(gi2c->se.dev); if (ret < 0) { dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret); @@ -1132,7 +1129,10 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->adap.algo = &geni_i2c_algo; init_completion(&gi2c->done); + init_completion(&gi2c->abort_done); init_completion(&gi2c->cancel_done); + init_completion(&gi2c->tx_reset_done); + init_completion(&gi2c->rx_reset_done); spin_lock_init(&gi2c->lock); platform_set_drvdata(pdev, gi2c);