Commit 743e227a authored by Marek Vasut's avatar Marek Vasut Committed by Wolfram Sang

i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()

The __xiic_start_xfer() manipulates the interrupt flags, xiic_wakeup()
may result in return from xiic_xfer() early. Defer both to the end of
the xiic_process() interrupt thread, so that they are executed after
all the other interrupt bits handling completed and once it completely
safe to perform changes to the interrupt bits in the hardware.
Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Acked-by: default avatarMichal Simek <michal.simek@xilinx.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent 861dcffe
...@@ -375,6 +375,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -375,6 +375,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
struct xiic_i2c *i2c = dev_id; struct xiic_i2c *i2c = dev_id;
u32 pend, isr, ier; u32 pend, isr, ier;
u32 clr = 0; u32 clr = 0;
int xfer_more = 0;
int wakeup_req = 0;
int wakeup_code = 0;
/* Get the interrupt Status from the IPIF. There is no clearing of /* Get the interrupt Status from the IPIF. There is no clearing of
* interrupts in the IPIF. Interrupts must be cleared at the source. * interrupts in the IPIF. Interrupts must be cleared at the source.
...@@ -411,10 +414,14 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -411,10 +414,14 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
*/ */
xiic_reinit(i2c); xiic_reinit(i2c);
if (i2c->rx_msg) if (i2c->rx_msg) {
xiic_wakeup(i2c, STATE_ERROR); wakeup_req = 1;
if (i2c->tx_msg) wakeup_code = STATE_ERROR;
xiic_wakeup(i2c, STATE_ERROR); }
if (i2c->tx_msg) {
wakeup_req = 1;
wakeup_code = STATE_ERROR;
}
} }
if (pend & XIIC_INTR_RX_FULL_MASK) { if (pend & XIIC_INTR_RX_FULL_MASK) {
/* Receive register/FIFO is full */ /* Receive register/FIFO is full */
...@@ -448,8 +455,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -448,8 +455,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
i2c->tx_msg++; i2c->tx_msg++;
dev_dbg(i2c->adap.dev.parent, dev_dbg(i2c->adap.dev.parent,
"%s will start next...\n", __func__); "%s will start next...\n", __func__);
xfer_more = 1;
__xiic_start_xfer(i2c);
} }
} }
} }
...@@ -463,11 +469,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -463,11 +469,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
if (!i2c->tx_msg) if (!i2c->tx_msg)
goto out; goto out;
if ((i2c->nmsgs == 1) && !i2c->rx_msg && wakeup_req = 1;
if (i2c->nmsgs == 1 && !i2c->rx_msg &&
xiic_tx_space(i2c) == 0) xiic_tx_space(i2c) == 0)
xiic_wakeup(i2c, STATE_DONE); wakeup_code = STATE_DONE;
else else
xiic_wakeup(i2c, STATE_ERROR); wakeup_code = STATE_ERROR;
} }
if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) {
/* Transmit register/FIFO is empty or ½ empty */ /* Transmit register/FIFO is empty or ½ empty */
...@@ -491,7 +499,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -491,7 +499,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
if (i2c->nmsgs > 1) { if (i2c->nmsgs > 1) {
i2c->nmsgs--; i2c->nmsgs--;
i2c->tx_msg++; i2c->tx_msg++;
__xiic_start_xfer(i2c); xfer_more = 1;
} else { } else {
xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
...@@ -509,6 +517,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) ...@@ -509,6 +517,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
if (xfer_more)
__xiic_start_xfer(i2c);
if (wakeup_req)
xiic_wakeup(i2c, wakeup_code);
WARN_ON(xfer_more && wakeup_req);
mutex_unlock(&i2c->lock); mutex_unlock(&i2c->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment