Hello Moiz, Nishant, Jagadeesh,

Any plans to respond to these comments?  

- Paul

On Mon, 22 Jun 2009, Paul Walmsley wrote:

> Moiz, Nishant, Jagadeesh,
> 
> Looks like this patch has some serious problems.
> 
> On Mon, 22 Jun 2009, Sonasath, Moiz wrote:
> 
> > This patch includes the workarround for I2C Errata 1.153: When an 
> > XRDY/XDR is hit, wait for XUDF before writing data to DATA_REG
> > 
> > Signed-off-by: Jagadeesh Bhaskar Pakaravoor <j-pakarav...@ti.com>
> > Signed-off by: Nishant Kamat <nska...@ti.com>
> > Signed-off-by: Moiz Sonasath<m-sonas...@ti.com>
> > ---
> >  drivers/i2c/busses/i2c-omap.c |   54 
> > +++++++++++++++++++++++++++++++++++++---
> >  1 files changed, 50 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> > index ece0125..e84836b 100644
> > --- a/drivers/i2c/busses/i2c-omap.c
> > +++ b/drivers/i2c/busses/i2c-omap.c
> > @@ -632,6 +632,37 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
> >  #define omap_i2c_rev1_isr          NULL
> >  #endif
> >  
> > +/* I2C Errata 1.153:
> > + * When an XRDY/XDR is hit, wait for XUDF before writing data to DATA_REG.
> > + * Otherwise some data bytes can be lost while transferring them from the
> > + * memory to the I2C interface.
> > + */
> > +
> > +static int omap_i2c_wait_for_xudf(struct omap_i2c_dev *dev)
> > +{
> > +   u16 xudf;
> > +   int counter = 500;
> 
> Shouldn't the timeout threshold depend on the I2C bus speed and transmit 
> FIFO threshold?
> 
> > +
> > +   /* We are in interrupt context. Wait for XUDF for max 7 msec */
> 
> There's no way an interrupt service routine should loop for up to 7 
> milliseconds.  Why does it need to wait this long?  Shouldn't this patch 
> zero the transmit FIFO threshold to minimize the amount of time between 
> XRDY/XDR and XUDF?
> 
> > +   xudf = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
> > +   while (!(xudf & OMAP_I2C_STAT_XUDF) && counter--) {
> 
> Why is a separate I2C_STAT loop used here?  Shouldn't this patch just use 
> the existing I2C_STAT loop in the ISR and use a state variable to indicate 
> the current state of the ISR?
> 
> > +           if (xudf & (OMAP_I2C_STAT_ROVR | OMAP_I2C_STAT_NACK |
> > +                       OMAP_I2C_STAT_AL))
> > +                   return -EINVAL;
> > +           udelay(10);
> 
> udelay() in an ISR is a big red flag.  Why is this needed?
> 
> > +           xudf = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
> > +   }
> > +
> > +   if (!counter) {
> > +           /* Clear Tx FIFO */
> > +           omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
> > +                           OMAP_I2C_BUF_TXFIF_CLR);
> > +           return -ETIMEDOUT;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >  static irqreturn_t
> >  omap_i2c_isr(int this_irq, void *dev_id)
> >  {
> > @@ -639,6 +670,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >     u16 bits;
> >     u16 stat, w;
> >     int err, count = 0;
> > +   int error;
> >  
> >     if (dev->idle)
> >             return IRQ_NONE;
> > @@ -647,7 +679,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >     while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
> >             dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
> >             if (count++ == 100) {
> > -                   dev_warn(dev->dev, "Too much work in one IRQ\n");
> > +                   dev_dbg(dev->dev, "Too much work in one IRQ\n");
> >                     break;
> >             }
> >  
> > @@ -715,11 +747,22 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >                                                     OMAP_I2C_BUFSTAT_REG);
> >                     }
> >                     while (num_bytes) {
> > -                           num_bytes--;
> >                             w = 0;
> >                             if (dev->buf_len) {
> > +                                   if (cpu_is_omap34xx()) {
> > +                                           /* OMAP3430 Errata 1.153 */
> 
> What about this I2C IP block on previous chip versions?  Is this problem 
> also present on 2430, which also has FIFO transmit capability?
> 
> > +                                           error = 
> > omap_i2c_wait_for_xudf(dev);
> > +                                           if (error) {
> > +                                                   omap_i2c_ack_stat(dev, 
> > stat &
> > +                                                           
> > (OMAP_I2C_STAT_XRDY |
> > +                                                            
> > OMAP_I2C_STAT_XDR));
> > +                                                   dev_err(dev->dev, 
> > "Transmit error\n");
> > +                                                   
> > omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_XUDF);
> > +
> > +                                                   return IRQ_HANDLED;
> > +                                           }
> > +                                   }
> >                                     w = *dev->buf++;
> > -                                   dev->buf_len--;
> >                                     /* Data reg from  2430 is 8 bit wide */
> >                                     if (!cpu_is_omap2430() &&
> >                                                     !cpu_is_omap34xx()) {
> > @@ -728,6 +771,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >                                                     dev->buf_len--;
> >                                             }
> >                                     }
> > +                                   omap_i2c_write_reg(dev,
> > +                                           OMAP_I2C_DATA_REG, w);
> > +                                   num_bytes--;
> > +                                   dev->buf_len--;
> >                             } else {
> >                                     if (stat & OMAP_I2C_STAT_XRDY)
> >                                             dev_err(dev->dev,
> > @@ -739,7 +786,6 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >                                                     "data to send\n");
> >                                     break;
> >                             }
> > -                           omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
> >                     }
> >                     omap_i2c_ack_stat(dev,
> >                             stat & (OMAP_I2C_STAT_XRDY | 
> > OMAP_I2C_STAT_XDR));
> 
> 
> - Paul
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to