RE: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Paul,

> -----Original Message-----
> From: Paul Walmsley [mailto:paul@xxxxxxxxx]
> Sent: Sunday, August 16, 2009 12:39 PM
> To: Sonasath, Moiz
> Cc: linux-i2c@xxxxxxxxxxxxxxx; linux-omap@xxxxxxxxxxxxxxx; 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-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux