public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Wolfgang Denk <wd@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH RFC] ARMV7: OMAP: I2C driver: Reduce excessively long udelay calls
Date: Fri, 15 Oct 2010 21:27:18 +0200	[thread overview]
Message-ID: <20101015192718.6340C1365CF@gemini.denx.de> (raw)
In-Reply-To: <1287158873.7756.66.camel@quadra>

Dear Steve Sakoman,

In message <1287158873.7756.66.camel@quadra> you wrote:
> I've been preparing a patch series for Beagle and Overo that detects expansion
> board configuration information by reading a 128 byte I2C EEPROM on each
> expansion board.
> 
> Using the OMAP I2C driver in its current form takes about 5-6 seconds to read
> this small number of bytes!
> 
> Examining the code I see that there are a large number of fairly long udelay calls
> throughout the driver (10 - 50 milliseconds). I looked through the linux driver
> and did not see equivalent delays in that code.  In fact the longest delay in the
> linux code was one millisecond.

Eventually the long delays are needed to make the code work stable
even under rare conditions, which don't happen to often.  But this may
be caused by the way the code is written, too...


>  	if (readw (&i2c_base->con) & I2C_CON_EN) {
>  		writew (0, &i2c_base->con);
> -		udelay (50000);
> +		udelay (1000);
>  	}

Instead of a simple writew() followed by an eventually long delay it
might make more sense to wait in a (tight) loop for the intended
condition; in this case it looks as if the I2C_CON_EN bit should be
reset (plus some other bits?), so why not wait for it?

For example:

	tout = 1000;
	while ((tout > 0) && (readw (&i2c_base->con) & I2C_CON_EN)) {
		writew(0, &i2c_base->con);
		udelay (50);
	}
	if (!tout)
		error handling;

So if the hardware is really slow to respond you still get the fill 50
ms timeout that you had before, but if it's much faster in the regular
case - and you even get a chance to notify the user in case of errors.

[Not sure if the multiple writew() are ok here, but you get the idea.]

>  	writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */
> @@ -164,7 +164,7 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
>  	if (status & I2C_STAT_XRDY) {
>  		/* Important: have to use byte access */
>  		writeb (regoffset, &i2c_base->data);
> -		udelay (20000);
> +		udelay (1000);
>  		if (readw (&i2c_base->stat) & I2C_STAT_NACK) {
>  			i2c_error = 1;
>  		}

Here the harrdware spec should give an indication how quickly the NAK
can be read reliably.

> @@ -176,7 +176,7 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
>  		writew (I2C_CON_EN, &i2c_base->con);
>  		while (readw(&i2c_base->stat) &
>  			(I2C_STAT_XRDY | I2C_STAT_ARDY)) {
> -			udelay (10000);
> +			udelay (1000);
>  			/* Have to clear pending interrupt to clear I2C_STAT */
>  			writew (0xFFFF, &i2c_base->stat);
>  		}

Here I cannot think of good reasons for such a delay at all.
What does the spec say?


> @@ -206,7 +206,7 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
>  			writew (I2C_CON_EN, &i2c_base->con);
>  			while (readw (&i2c_base->stat) &
>  				(I2C_STAT_RRDY | I2C_STAT_ARDY)) {
> -				udelay (10000);
> +				udelay (1000);
>  				writew (0xFFFF, &i2c_base->stat);
>  			}
>  		}

Here we are in a loop anyway - use a much shrter cycle length combined
with a limit on the max number of cycles.


Etc.

My feeling is that this driver needs a more thorough rework.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Winners never talk about glorious victories. That's  because  they're
the  ones  who  see  what the battlefield looks like afterwards. It's
only the losers who have glorious victories.
                                      - Terry Pratchett, _Small Gods_

  reply	other threads:[~2010-10-15 19:27 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-15 16:07 [U-Boot] [PATCH RFC] ARMV7: OMAP: I2C driver: Reduce excessively long udelay calls Steve Sakoman
2010-10-15 19:27 ` Wolfgang Denk [this message]
2010-10-15 19:48   ` Steve Sakoman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101015192718.6340C1365CF@gemini.denx.de \
    --to=wd@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox