> -----Original Message----- > From: linux-i2c-owner@xxxxxxxxxxxxxxx <linux-i2c-owner@xxxxxxxxxxxxxxx> On > Behalf Of Marek Vasut > Sent: Saturday, June 13, 2020 8:38 PM > To: linux-i2c@xxxxxxxxxxxxxxx > Cc: Marek Vasut <marex@xxxxxxx>; Michal Simek <michals@xxxxxxxxxx>; > Shubhrajyoti Datta <shubhraj@xxxxxxxxxx>; Wolfram Sang <wsa@xxxxxxxxxx> > Subject: [PATCH 5/5] i2c: xiic: Only ever transfer single message > > Transferring multiple messages via XIIC suffers from strange interaction > between the interrupt status/enable register flags. These flags are being reused > in the hardware to indicate different things for read and write transfer, and > doing multiple transactions becomes horribly complex. Just send a single > transaction and reload the controller with another message once the > transaction is done in the interrupt handler thread. > > Signed-off-by: Marek Vasut <marex@xxxxxxx> > Cc: Michal Simek <michal.simek@xxxxxxxxxx> > Cc: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx> > Cc: Wolfram Sang <wsa@xxxxxxxxxx> > --- > drivers/i2c/busses/i2c-xiic.c | 43 ++++++++--------------------------- > 1 file changed, 10 insertions(+), 33 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index > e4c3427b2f3f5..fad0b84a273d1 100644 > --- a/drivers/i2c/busses/i2c-xiic.c > +++ b/drivers/i2c/busses/i2c-xiic.c > @@ -595,8 +595,6 @@ static void xiic_start_send(struct xiic_i2c *i2c) { > struct i2c_msg *msg = i2c->tx_msg; > > - xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); > - > dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", > __func__, msg, msg->len); > dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", @@ > -614,11 +612,13 @@ static void xiic_start_send(struct xiic_i2c *i2c) > xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); > } > > - xiic_fill_tx_fifo(i2c); > - > /* Clear any pending Tx empty, Tx Error and then enable them. */ > xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | > XIIC_INTR_TX_ERROR_MASK | > - XIIC_INTR_BNB_MASK); > + XIIC_INTR_BNB_MASK | > + ((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ? > + XIIC_INTR_TX_HALF_MASK : 0)); > + > + xiic_fill_tx_fifo(i2c); > } > > static void __xiic_start_xfer(struct xiic_i2c *i2c) @@ -634,35 +634,12 @@ > static void __xiic_start_xfer(struct xiic_i2c *i2c) Can remove the definition of unused variable ("first"). > i2c->rx_pos = 0; > i2c->tx_pos = 0; > i2c->state = STATE_START; > - while ((fifo_space >= 2) && (first || (i2c->nmsgs > 1))) { > - if (!first) { > - i2c->nmsgs--; > - i2c->tx_msg++; > - i2c->tx_pos = 0; > - } else > - first = 0; > - > - if (i2c->tx_msg->flags & I2C_M_RD) { > - /* we dont date putting several reads in the FIFO */ > - xiic_start_recv(i2c); > - return; > - } else { > - xiic_start_send(i2c); > - if (xiic_tx_space(i2c) != 0) { > - /* the message could not be completely sent > */ > - break; > - } > - } > - > - fifo_space = xiic_tx_fifo_space(i2c); > + if (i2c->tx_msg->flags & I2C_M_RD) { > + /* we dont date putting several reads in the FIFO */ > + xiic_start_recv(i2c); > + } else { > + xiic_start_send(i2c); > } > - > - /* there are more messages or the current one could not be completely > - * put into the FIFO, also enable the half empty interrupt > - */ > - if (i2c->nmsgs > 1 || xiic_tx_space(i2c)) > - xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK); > - > } > > static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num) This patch is much needed to simplify the logic. Tested, working fine. Raviteja N