diff mbox

[3/3,OMAP:I2C] OMAP3430 Silicon Errata 1.153

Message ID CD8CC2B65FEE304DA95744A5472698F202957C7C3A@dlee06.ent.ti.com (mailing list archive)
State Changes Requested, archived
Headers show

Commit Message

Sonasath, Moiz July 15, 2009, 3:40 p.m. UTC
Hello Nishant,

Comments inlined:

Regards
Moiz Sonasath
Linux Baseport Team, Dallas
214-567-5514


-----Original Message-----
From: Menon, Nishanth 
Sent: Tuesday, July 14, 2009 6:23 PM
To: Sonasath, Moiz
Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley
Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

Sonasath, Moiz wrote:
> 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.
> 
> Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
> if there is NACK | AL, set the appropriate error flags, ack the pending
> interrupts and return from the ISR.
> 
> Signed-off-by: Moiz Sonasath<m-sonasath@ti.com>
> Signed-off-by: Vikram Pandita<vikram.pandita@ti.com>
> ---
>  drivers/i2c/busses/i2c-omap.c |   24 +++++++++++++++++++++++-
>  1 files changed, 23 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index 05b5e4c..8deaf87 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
>  			break;
>  		}
>  
> +		err = 0;
> +complete:
cant we rename this label?
[Moiz]
This path actually completes the IRQ service routine and therefore the name. 

>  		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
>  
> -		err = 0;
>  		if (stat & OMAP_I2C_STAT_NACK) {
>  			err |= OMAP_I2C_STAT_NACK;
>  			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
> @@ -764,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id)
>  							"data to send\n");
>  					break;
>  				}
> +
> +				/*
> +				 * OMAP3430 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.
> +				 */
> +
> +				if (cpu_is_omap34xx()) {
> +						while (!(stat & OMAP_I2C_STAT_XUDF)) {
> +							if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
> +								omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
generic comment - code nesting is getting overwhelming - we may like to 
refactor the isr function at a later date I think..
> +								err |= OMAP_I2C_STAT_XUDF;
why set the err if we wantedly force this to happen?
[Moiz]
The idea here is to let the upper application to know that something went wrong while waiting for the XUDF bit to be set. This is just for debugging purpose.
> +								goto complete;

> +							}
> +							cpu_relax();
> +							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
> +						}
this is an infinite while loop + it tries to handle error cases - 
essentially do another isr routine inside itself.
[Moiz]
Yes, it is a busy wait loop. But AFAIK while we come to this part of the code the only thing that can go wrong in the transfer is either the device would go off suddenly (creating a NACK) or there is an arbitration lost(AL). This loop takes care of these two error conditions. Apart from these, if the hardware is functional, the XUDF bit should be set as soon as the FIFO gets empty. 

Correct me if I am missing something.

How about:
Apply [1] and the following?


Regards,
Nishanth Menon
Ref:
[1] http://patchwork.kernel.org/patch/32332/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Nishanth Menon July 15, 2009, 9:43 p.m. UTC | #1
Sonasath, Moiz had written, on 07/15/2009 10:40 AM, the following:
>> 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.
>>
>> Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
>> if there is NACK | AL, set the appropriate error flags, ack the pending
>> +							}
>> +							cpu_relax();
>> +							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
>> +						}
> this is an infinite while loop + it tries to handle error cases - 
> essentially do another isr routine inside itself.
> [Moiz]
> Yes, it is a busy wait loop. But AFAIK while we come to this part of
 > the code the only thing that can go wrong in the transfer is either
 > the device would go off suddenly (creating a NACK) or there is an
 > arbitration lost(AL). This loop takes care of these two error conditions.
 > Apart from these, if the hardware is functional, the XUDF bit should
 > be set as soon as the FIFO gets empty.
> 
> Correct me if I am missing something.
That is exactly what I was complaining about -> why not use the existing 
logic above in the code to take care of it as I indicated below? do you 
see a problem with the logic I send? it is lesser code and should IMHO 
take care of the same issue without the additional 3rd nested while loop
> 
> How about:
> Apply [1] and the following?
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index ad8d201..e3f21af 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -728,6 +728,12 @@ omap_i2c_isr(int this_irq, void *dev_id)
>                  }
>                  if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
>                          u8 num_bytes = 1;
> +                       if (cpu_is_omap34xx() &&
> +                               !(stat & OMAP_I2C_STAT_XUDF)){
> +                               cpu_relax();
> +                               continue;
> +                       }
> +
>                          if (dev->fifo_size) {
>                                  if (stat & OMAP_I2C_STAT_XRDY)
>                                          num_bytes = dev->fifo_size;
> 
> 
> Regards,
> Nishanth Menon
> Ref:
> [1] http://patchwork.kernel.org/patch/32332/
Sonasath, Moiz July 15, 2009, 10:23 p.m. UTC | #2
Hello Nishant,

Comments inlined,

Regards
Moiz Sonasath


-----Original Message-----
From: Menon, Nishanth 
Sent: Wednesday, July 15, 2009 4:43 PM
To: Sonasath, Moiz
Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley
Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

Sonasath, Moiz had written, on 07/15/2009 10:40 AM, the following:
>> 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.
>>
>> Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
>> if there is NACK | AL, set the appropriate error flags, ack the pending
>> +							}
>> +							cpu_relax();
>> +							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
>> +						}
> this is an infinite while loop + it tries to handle error cases - 
> essentially do another isr routine inside itself.
> [Moiz]
> Yes, it is a busy wait loop. But AFAIK while we come to this part of
 > the code the only thing that can go wrong in the transfer is either
 > the device would go off suddenly (creating a NACK) or there is an
 > arbitration lost(AL). This loop takes care of these two error conditions.
 > Apart from these, if the hardware is functional, the XUDF bit should
 > be set as soon as the FIFO gets empty.
> 
> Correct me if I am missing something.
That is exactly what I was complaining about -> why not use the existing 
logic above in the code to take care of it as I indicated below? do you 
see a problem with the logic I send? it is lesser code and should IMHO 
take care of the same issue without the additional 3rd nested while loop
> 
> How about:
> Apply [1] and the following?
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index ad8d201..e3f21af 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -728,6 +728,12 @@ omap_i2c_isr(int this_irq, void *dev_id)
>                  }
>                  if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
>                          u8 num_bytes = 1;
> +                       if (cpu_is_omap34xx() &&
> +                               !(stat & OMAP_I2C_STAT_XUDF)){
> +                               cpu_relax();
> +                               continue;
> +                       }
> +

[Moiz]

In this alternate implementation if a NACK|AL is produced while waiting on the XUDF, it returns from the ISR (as per my patch [2/3]) without ACKING the XRDY/XDR interrupts which would make it return to the ISR again and again which looks like a problem. To accommodate this implementation, we will have to ACK XRDY/XDR before returning from the ISR.
		

>                          if (dev->fifo_size) {
>                                  if (stat & OMAP_I2C_STAT_XRDY)
>                                          num_bytes = dev->fifo_size;
> 
> 
> Regards,
> Nishanth Menon
> Ref:
> [1] http://patchwork.kernel.org/patch/32332/
Nishanth Menon July 15, 2009, 10:27 p.m. UTC | #3
Sonasath, Moiz had written, on 07/15/2009 05:23 PM, the following:
> Hello Nishant,
> 
> Comments inlined,
> 
> Regards
> Moiz Sonasath
> 
> 
> -----Original Message-----
> From: Menon, Nishanth 
> Sent: Wednesday, July 15, 2009 4:43 PM
> To: Sonasath, Moiz
> Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley
> Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153
> 
> Sonasath, Moiz had written, on 07/15/2009 10:40 AM, the following:
>>> 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.
>>>
>>> Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
>>> if there is NACK | AL, set the appropriate error flags, ack the pending
>>> +							}
>>> +							cpu_relax();
>>> +							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
>>> +						}
>> this is an infinite while loop + it tries to handle error cases - 
>> essentially do another isr routine inside itself.
>> [Moiz]
>> Yes, it is a busy wait loop. But AFAIK while we come to this part of
>  > the code the only thing that can go wrong in the transfer is either
>  > the device would go off suddenly (creating a NACK) or there is an
>  > arbitration lost(AL). This loop takes care of these two error conditions.
>  > Apart from these, if the hardware is functional, the XUDF bit should
>  > be set as soon as the FIFO gets empty.
>> Correct me if I am missing something.
> That is exactly what I was complaining about -> why not use the existing 
> logic above in the code to take care of it as I indicated below? do you 
> see a problem with the logic I send? it is lesser code and should IMHO 
> take care of the same issue without the additional 3rd nested while loop
>> How about:
>> Apply [1] and the following?
>> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
>> index ad8d201..e3f21af 100644
>> --- a/drivers/i2c/busses/i2c-omap.c
>> +++ b/drivers/i2c/busses/i2c-omap.c
>> @@ -728,6 +728,12 @@ omap_i2c_isr(int this_irq, void *dev_id)
>>                  }
>>                  if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
>>                          u8 num_bytes = 1;
>> +                       if (cpu_is_omap34xx() &&
>> +                               !(stat & OMAP_I2C_STAT_XUDF)){
>> +                               cpu_relax();
>> +                               continue;
>> +                       }
>> +
> 
> [Moiz]
> 
> In this alternate implementation if a NACK|AL is produced while waiting
 > on the XUDF, it returns from the ISR (as per my patch [2/3])
 > without ACKING the XRDY/XDR interrupts which would make it return
 > to the ISR again and again which looks like a problem. To accommodate
 >this implementation, we will have to ACK XRDY/XDR before returning 
from the ISR.
ok, this is due to my [1] patch which should have handled this condition 
in the first place. I will rework my original [1] patch and resend it.

Regards,
Nishanth Menon
Ref:
[1] http://patchwork.kernel.org/patch/32332/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sonasath, Moiz July 15, 2009, 10:29 p.m. UTC | #4
Hello Nishant!

I am also not sure, if the count=100; value will be enough time for the XUDF to be set. If not then it will keep running into timeout errors.

Regards
Moiz Sonasath


-----Original Message-----
From: Menon, Nishanth 
Sent: Wednesday, July 15, 2009 5:27 PM
To: Sonasath, Moiz
Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley; Pandita, Vikram
Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

Sonasath, Moiz had written, on 07/15/2009 05:23 PM, the following:
> Hello Nishant,
> 
> Comments inlined,
> 
> Regards
> Moiz Sonasath
> 
> 
> -----Original Message-----
> From: Menon, Nishanth 
> Sent: Wednesday, July 15, 2009 4:43 PM
> To: Sonasath, Moiz
> Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley
> Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153
> 
> Sonasath, Moiz had written, on 07/15/2009 10:40 AM, the following:
>>> 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.
>>>
>>> Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
>>> if there is NACK | AL, set the appropriate error flags, ack the pending
>>> +							}
>>> +							cpu_relax();
>>> +							stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
>>> +						}
>> this is an infinite while loop + it tries to handle error cases - 
>> essentially do another isr routine inside itself.
>> [Moiz]
>> Yes, it is a busy wait loop. But AFAIK while we come to this part of
>  > the code the only thing that can go wrong in the transfer is either
>  > the device would go off suddenly (creating a NACK) or there is an
>  > arbitration lost(AL). This loop takes care of these two error conditions.
>  > Apart from these, if the hardware is functional, the XUDF bit should
>  > be set as soon as the FIFO gets empty.
>> Correct me if I am missing something.
> That is exactly what I was complaining about -> why not use the existing 
> logic above in the code to take care of it as I indicated below? do you 
> see a problem with the logic I send? it is lesser code and should IMHO 
> take care of the same issue without the additional 3rd nested while loop
>> How about:
>> Apply [1] and the following?
>> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
>> index ad8d201..e3f21af 100644
>> --- a/drivers/i2c/busses/i2c-omap.c
>> +++ b/drivers/i2c/busses/i2c-omap.c
>> @@ -728,6 +728,12 @@ omap_i2c_isr(int this_irq, void *dev_id)
>>                  }
>>                  if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
>>                          u8 num_bytes = 1;
>> +                       if (cpu_is_omap34xx() &&
>> +                               !(stat & OMAP_I2C_STAT_XUDF)){
>> +                               cpu_relax();
>> +                               continue;
>> +                       }
>> +
> 
> [Moiz]
> 
> In this alternate implementation if a NACK|AL is produced while waiting
 > on the XUDF, it returns from the ISR (as per my patch [2/3])
 > without ACKING the XRDY/XDR interrupts which would make it return
 > to the ISR again and again which looks like a problem. To accommodate
 >this implementation, we will have to ACK XRDY/XDR before returning 
from the ISR.
ok, this is due to my [1] patch which should have handled this condition 
in the first place. I will rework my original [1] patch and resend it.

Regards,
Nishanth Menon
Ref:
[1] http://patchwork.kernel.org/patch/32332/
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nishanth Menon July 15, 2009, 10:31 p.m. UTC | #5
Sonasath, Moiz had written, on 07/15/2009 05:29 PM, the following:
> 
> I am also not sure, if the count=100; value will be enough time for the XUDF
 > to be set. If not then it will keep running into timeout errors.
> 
Do you mean we need a delay for checking again? that should be easy to 
incorporate - what kind of delay are we speaking of here? do you have a 
count requirement for handling this? it is essentially the time b/w XRDY 
to XUNDF.. this should be deterministic rt?

Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sonasath, Moiz July 15, 2009, 10:37 p.m. UTC | #6
Nishant,

AFAIK, the time between XRDY/XDR and setting of XUDF bit is not deterministic, it depends on the I2C bus speed but I am not sure if we can translate the speed into a fixed count number which we can use as a timeout limit. In that case we need to make a balanced assumption of the count value so that we don't fall in the timeout case under normal operation.

May be someone can give a pointer here.

Regards
Moiz Sonasath


-----Original Message-----
From: Menon, Nishanth 
Sent: Wednesday, July 15, 2009 5:32 PM
To: Sonasath, Moiz
Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley; Pandita, Vikram
Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

Sonasath, Moiz had written, on 07/15/2009 05:29 PM, the following:
> 
> I am also not sure, if the count=100; value will be enough time for the XUDF
 > to be set. If not then it will keep running into timeout errors.
> 
Do you mean we need a delay for checking again? that should be easy to 
incorporate - what kind of delay are we speaking of here? do you have a 
count requirement for handling this? it is essentially the time b/w XRDY 
to XUNDF.. this should be deterministic rt?

Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nishanth Menon July 15, 2009, 11:03 p.m. UTC | #7
Sonasath, Moiz had written, on 07/15/2009 05:37 PM, the following:
 >
 > -----Original Message-----
 > From: Menon, Nishanth
 > Sent: Wednesday, July 15, 2009 5:32 PM

please stop top posting..

 >> Sonasath, Moiz had written, on 07/15/2009 05:29 PM, the following:
 >> I am also not sure, if the count=100; value will be enough time for 
the XUDF
 >>  > to be set. If not then it will keep running into timeout errors.
 >> Do you mean we need a delay for checking again? that should be easy to
 >> incorporate - what kind of delay are we speaking of here? do you 
have a
 >> count requirement for handling this? it is essentially the time b/w 
XRDY
 >> to XUNDF.. this should be deterministic rt?
 >>
 >
 > AFAIK, the time between XRDY/XDR and setting of XUDF bit is not
 >deterministic, it depends on the I2C bus speed but I am not sure if we
 >can translate the speed into a fixed count number which we can use as a
 > timeout limit. In that case we need to make a balanced assumption of
 >the count value so that we don't fall in the timeout case under normal
 >operation.
 >
 > May be someone can give a pointer here.
 >
Here is my attempt at this:
XRDY -> in this case the FIFO is completely empty - fill it up for XTRSH
XDR -> FIFO is not completely empty, fill as per TXSTAT reg.
if you look at the sequences of events that should happen ->
a) no previous data transmitted: XRDY, XUNDF
b) previous data available, XDR, XRDY, XUNDF
The variables are:
i) bus speed
ii) num bytes to empty (if XRDY then 0, else TXSTAT)

Time = (num_bytes+c) * (1/bus_speed)
where c = some constant time interval for XRDY->XUNDF.. I think..

One possible strategy:
a)Worst case is XTRSH, so, Compute time prior to entry into transmit
loop. Set the count as this+ add a constant for additional events
b) Add a constant delay when you decide to continue back - not sure if
cpu_relax is predictable delay..

--
Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sonasath, Moiz July 16, 2009, 3:52 p.m. UTC | #8
Hello Nishant,

Comments inlined,

Regards
Moiz Sonasath


-----Original Message-----
From: Menon, Nishanth 
Sent: Wednesday, July 15, 2009 6:03 PM
To: Sonasath, Moiz
Cc: linux-omap@vger.kernel.org; Kamat, Nishant; Paul Walmsley; Pandita, Vikram
Subject: Re: [PATCH 3/3] [OMAP:I2C]OMAP3430 Silicon Errata 1.153

Sonasath, Moiz had written, on 07/15/2009 05:37 PM, the following:
 >
 > -----Original Message-----
 > From: Menon, Nishanth
 > Sent: Wednesday, July 15, 2009 5:32 PM

please stop top posting..

 >> Sonasath, Moiz had written, on 07/15/2009 05:29 PM, the following:
 >> I am also not sure, if the count=100; value will be enough time for 
the XUDF
 >>  > to be set. If not then it will keep running into timeout errors.
 >> Do you mean we need a delay for checking again? that should be easy to
 >> incorporate - what kind of delay are we speaking of here? do you 
have a
 >> count requirement for handling this? it is essentially the time b/w 
XRDY
 >> to XUNDF.. this should be deterministic rt?
 >>
 >
 > AFAIK, the time between XRDY/XDR and setting of XUDF bit is not
 >deterministic, it depends on the I2C bus speed but I am not sure if we
 >can translate the speed into a fixed count number which we can use as a
 > timeout limit. In that case we need to make a balanced assumption of
 >the count value so that we don't fall in the timeout case under normal
 >operation.
 >
 > May be someone can give a pointer here.
 >
Here is my attempt at this:
XRDY -> in this case the FIFO is completely empty - fill it up for XTRSH
XDR -> FIFO is not completely empty, fill as per TXSTAT reg.
if you look at the sequences of events that should happen ->
a) no previous data transmitted: XRDY, XUNDF
b) previous data available, XDR, XRDY, XUNDF
The variables are:
i) bus speed
ii) num bytes to empty (if XRDY then 0, else TXSTAT)

Time = (num_bytes+c) * (1/bus_speed)
where c = some constant time interval for XRDY->XUNDF.. I think..

One possible strategy:
a)Worst case is XTRSH, so, Compute time prior to entry into transmit
loop. Set the count as this+ add a constant for additional events
b) Add a constant delay when you decide to continue back - not sure if
cpu_relax is predictable delay..


[Moiz]

Let me just rephrase what you said and from what I see in the TRM,

XRDY-> when TX FIFO level is equal/below XTRSH and TXSTAT is equal/greater than XTRSH, LH will write number of data bytes specified by XTRSH
XDR-> when TX FIFO level is equal/below the XTRSH and TXSTAT is less than XTRSH, LH will write number of data bytes specified by TXSTAT
XUDF-> when shift register and the TX FIFO are empty and there are still some bytes to transmit (DCOUNT not 0)

Here we are looking at the wait time between XRDY/XDR and XUDF. Considering worst case scenarios, 

Wait_time = (time to transmit out XTRSH bytes from the FIFO at the slowest bus speed) + (safeguard delay)

The slowest bus speed appears in standard mode (100K bits/sec). Therefore,

Wait_time = [(XTRSH*8)*(1/100K)] seconds + constant;

Does this look correct?

 

--
Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sonasath, Moiz July 20, 2009, 4:54 p.m. UTC | #9
> Sonasath, Moiz wrote:
> > 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.
> >
> > Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
> > if there is NACK | AL, set the appropriate error flags, ack the pending
> > interrupts and return from the ISR.
> >
> > Signed-off-by: Moiz Sonasath<m-sonasath@ti.com>
> > Signed-off-by: Vikram Pandita<vikram.pandita@ti.com>
> > ---
> >  drivers/i2c/busses/i2c-omap.c |   24 +++++++++++++++++++++++-
> >  1 files changed, 23 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-
> omap.c
> > index 05b5e4c..8deaf87 100644
> > --- a/drivers/i2c/busses/i2c-omap.c
> > +++ b/drivers/i2c/busses/i2c-omap.c
> > @@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >  			break;
> >  		}
> >
> > +		err = 0;
> > +complete:
> cant we rename this label?
> [Moiz]
> This path actually completes the IRQ service routine and therefore the
> name.
> 
> >  		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
> >
> > -		err = 0;
> >  		if (stat & OMAP_I2C_STAT_NACK) {
> >  			err |= OMAP_I2C_STAT_NACK;
> >  			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
> > @@ -764,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id)
> >  							"data to send\n");
> >  					break;
> >  				}
> > +
> > +				/*
> > +				 * OMAP3430 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.
> > +				 */
> > +
> > +				if (cpu_is_omap34xx()) {
> > +						while (!(stat & OMAP_I2C_STAT_XUDF)) {
> > +							if (stat & (OMAP_I2C_STAT_NACK |
> OMAP_I2C_STAT_AL)) {
> > +								omap_i2c_ack_stat(dev,
> stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
> generic comment - code nesting is getting overwhelming - we may like to
> refactor the isr function at a later date I think..
> > +								err |= OMAP_I2C_STAT_XUDF;
> why set the err if we wantedly force this to happen?
> [Moiz]
> The idea here is to let the upper application to know that something went
> wrong while waiting for the XUDF bit to be set. This is just for debugging
> purpose.
> > +								goto complete;
> 
> > +							}
> > +							cpu_relax();
> > +							stat = omap_i2c_read_reg(dev,
> OMAP_I2C_STAT_REG);
> > +						}
> this is an infinite while loop + it tries to handle error cases -
> essentially do another isr routine inside itself.
> [Moiz]
> Yes, it is a busy wait loop. But AFAIK while we come to this part of the
> code the only thing that can go wrong in the transfer is either the device
> would go off suddenly (creating a NACK) or there is an arbitration
> lost(AL). This loop takes care of these two error conditions. Apart from
> these, if the hardware is functional, the XUDF bit should be set as soon
> as the FIFO gets empty.
> 
> Correct me if I am missing something.

As of now I am posting my patch without a timeout, later as per the need I will optimize it with a timeout approach.

> 
> How about:
> Apply [1] and the following?
> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
> index ad8d201..e3f21af 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -728,6 +728,12 @@ omap_i2c_isr(int this_irq, void *dev_id)
>                  }
>                  if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
>                          u8 num_bytes = 1;
> +                       if (cpu_is_omap34xx() &&
> +                               !(stat & OMAP_I2C_STAT_XUDF)){
> +                               cpu_relax();
> +                               continue;
> +                       }
> +
>                          if (dev->fifo_size) {
>                                  if (stat & OMAP_I2C_STAT_XRDY)
>                                          num_bytes = dev->fifo_size;
> 
> 
> Regards,
> Nishanth Menon
> Ref:
> [1] http://patchwork.kernel.org/patch/32332/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@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 majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ad8d201..e3f21af 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -728,6 +728,12 @@  omap_i2c_isr(int this_irq, void *dev_id)
                 }
                 if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
                         u8 num_bytes = 1;
+                       if (cpu_is_omap34xx() &&
+                               !(stat & OMAP_I2C_STAT_XUDF)){
+                               cpu_relax();
+                               continue;
+                       }
+
                         if (dev->fifo_size) {
                                 if (stat & OMAP_I2C_STAT_XRDY)
                                         num_bytes = dev->fifo_size;