Hi Paul,

> -----Original Message-----
> From: Paul Walmsley [mailto:[email protected]]
> Sent: Sunday, August 16, 2009 12:39 PM
> To: Sonasath, Moiz
> Cc: [email protected]; [email protected]; Menon,
> Nishanth; Pandita, Vikram
> Subject: RE: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153
> 
> Hi Moiz,
> 
> On Tue, 11 Aug 2009, Sonasath, Moiz wrote:
> 
> > 1. From the code we have in place now, we are writing
> > num_bytes=dev->fifosize(=XTRSH+1) bytes in case of XRDY OR
> > num_bytes=TXSTAT (last few bytes left) in case of XDR (draining feature)
> >
> > Without the errata we were writing these num_bytes in a while loop one
> > by one into I2C_DATA reg (TXFIFO).
> >
> > With the errata we are writing num_bytes in a while loop, but now we
> > write one byte wait for XUDF bit to get set and then write another byte.
> > Thereby, we write a byte, wait for it to get out of the TXFIFO and only
> > then we write the second byte and so on.
> >
> >     While(num_bytes)
> >     {
> >             Write one byte to I2C_DATA Reg
> >             Wait for XUDF to set
> >     }
> >     Ack the interrupt
> 
> Doesn't your patch do:
> 
>       While(num_bytes)
>       {
>               Wait for XUDF to set
>               Write one byte to I2C_DATA Reg
>       }
>       Ack the interrupt
> 
> ?
> 


Yes I think I just disordered the sequence there, but yes this is exactly what 
the patch does.

> > So irrespective of the XTRSH value, the wait time is actually the same.
> >
> > 2. Now if we see it from the perspective of interrupts, we are
> > generating an interrupt after every chunk of 4 bytes (with XTRSH+1=4)
> > written to the TXFIFO because we ACK the interrupt after writing a chunk
> > of 4 bytes (one byte at a time waiting for the XUDF bit to be set in
> > between each byte).
> >
> > >From the TRM Figure-18-31, in the XRDY path:
> > Write I2Ci.I2C_DATA register for (XTRSH+1) times and then clear XRDY
> interrupt
> >
> > Thus, XTRSH is actually driving how many chunks of data you write before
> > generating a next interrupt. So from this point of view it will be more
> > desirable to make the XTRSH=7 and write chunk of 8 bytes before
> > generating a new interrupt. But we end up staying a longer time in the
> > ISR.
> >
> > Essentially we are looking at a tradeoff between:
> > 1. Lower XTRSH value: More number of interrupts, less time in an ISR
> > 2. Higher XTRSH value: Less number of interrupts, more time in an ISR
> >
> > Please correct me if I am wrong.
> 
> Your analysis looks correct.  I suppose my point is dependent on when the
> XRDY interrupt occurs if XTRSH = 0.
> 
> If it occurs one I2C byte transmission time before the XUDF condition
> occurs, then we should just use your busy-waiting patch.  I don't think we
> can do better than that.
> 
> But if the XRDY interrupt occurs at the same time as the shift register
> empties, or if there is an undocumented XUDF interrupt that we can use,
> then please consider:
> 
> For slower I2C bus speeds, e.g., for a 400KHz I2C bus, emptying a byte out
> of the transmit FIFO should take about 20 microseconds [1].  Another way
> of expressing this is that the duration from when we write a byte to the
> I2C FIFO, to when the controller raises the XRDY/XDR interrupt, should be
> about 20 microseconds when XTRSH = 0.
> 
> We can either spend this time busy-looping in the ISR (the tradeoff #2
> that you mention above), or trying to reach WFI and hopefully entering it
> (the tradeoff #1 above).  If possible, tradeoff #1 seems better.  If the
> MPU can reach WFI, it will waste less active power, but it will also
> trigger the PRCM to shut down any inactive power domains, which might not
> need to wake back up when the next system wakeup event occurs.
> 
> This should improve over time, from a power efficiency perspective,
> as the amount of time the MPU spends trying to reach WFI should decrease
> [2].
> 
> What do you think?
> 

On having a closer look at the code, I realized that there is a struct i2c_msg 
msg[ ] passed to omap_i2c_xfer func in i2c-omap.c driver from the upper 
application and this relates to the following assignments:

dev->buf = msg->buf;
dev->buf_len = msg->len; 

The code returns from the ISR context only in the following conditions:
-after completing the transfer of dev->len amount of data (ARDY interrupt)
-In case of an error (NACK|AL) 
-when the counter is 100 (too much data to send)

So actually, for a given amount of data we spend more or less the same time in 
the ISR irrespective of the XTRSH value. I missed this point in my prior 
analysis.

With the code in place and for the draining feature to work correctly with the 
present code, we want XTRSH=dev->fiffo_size (presently 4). 

Now if we make XTRSH=dev->fiffo_size=8 (use the full FIFO size) we can have 
slightly faster performance. We have the following code in place:

omap_i2c_isr
{
        While(any interrupt)
        {
                If (NACK|AL|ARDY)
                        Complete_cmd and return IRQ_HANDLED
                If (RRDY|RDR)
                        RX implemenetation
                If (XRDY|XDR)
                        If (XRDY)
                                Num_bytes=dev->fifo_size (8 bytes)
                        Else
                                Num_bytes=TXSTAT (amount of data left)
                        While(Num_bytes)
                        {
                                Wait for XUDF to set          
                                Write one byte to I2C_DATA Reg
                        }
                        Ack the interrupt
                        Continue
}       }
        
Interrupts:
XRDY: triggered when TX FIFO level equal/below XTRSH AND TXSTAT is 
equal/greater than XTRSH
XDR: triggered when TX FIFO level equal/below XTRSH AND TXSTAT is less than 
XTRSH

For:
dev->buf_len = 18 bytes and with XTRSH=dev->fiffo_size=8
- XRDY: write 8 bytes in the inner while loop, back to main while loop
- XRDY: write 8 bytes in inner while loop, go back to main while loop
- XDR: write remaining 4 bytes in inner while loop, go back to main while loop
- ARDY: complete command and return IRQ_HANDLED

Opposed to:

dev->buf_len = 18 bytes and with XTRSH=dev->fiffo_size=4
- XRDY: write 4 bytes in inner while loop, go back to main while loop 
- XRDY: write 4 bytes in inner while loop, go back to main while loop
- XRDY: write 4 bytes in inner while loop, go back to main while loop
- XRDY: write 4 bytes in inner while loop, go back to main while loop
- XDR: write remaining 2 bytes in inner while loop, go back to main while loop
- ARDY: complete command and return IRQ_HANDLED

The performance will be worse with XTRSH=dev->fiffo_size=1.

I will try to verify this using oprofile.

Regaards
Moiz
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to