Linux I2C development
 help / color / mirror / Atom feed
From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
To: Manuel Lauss <mano-nEyxjcs6f3Vin2gBucwGBecsttgLyre6@public.gmane.org>
Cc: linuxsh-dev-TtF/mJH4Jtrk1uMJSBkQmQ@public.gmane.org,
	i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Subject: Re: [RFC PATCH] I2C bus driver for SH7760 SoC, #2
Date: Wed, 27 Feb 2008 23:55:06 +0100	[thread overview]
Message-ID: <20080227235506.3e79c27c@hyperion.delvare> (raw)
In-Reply-To: <20080226072330.GB14289-nEyxjcs6f3Vin2gBucwGBecsttgLyre6@public.gmane.org>

Hi Manuel,

On Tue, 26 Feb 2008 08:23:30 +0100, Manuel Lauss wrote:
> > > +	for (cdf = 3; cdf >= 0; cdf--) {
> > > +		iclk = mck / (1 + cdf);
> > > +		/* iclk must not be > 20MHz */
> > > +		if (iclk >= 20000000)
> > 
> > > or >=?
> > 
> > > +			continue;
> > > +		for (scgd = 0; scgd < 63; scgd++) {
> > > +			m1 = iclk / (20 + (scgd << 3));
> > > +			dff = abs(scl_hz - m1);
> > > +			if (dff < odff) {
> > > +				odff = dff;
> > > +				cdfm = cdf;
> > > +				scgdm = scgd;
> > > +			}
> > > +		}
> > > +	}
> > 
> > These imbricated loops don't look exactly optimal. Is there no way to
> > compute the right value right away?
> 
> I'm open to suggestions. I just wanted to support (almost) every conceivable
> scl clock and module clock.

Let me think about it...

In the inner loop, scgd is monotonic (increasing), so m1 is also
monotonic (decreasing). Assuming for simplicity that the first value of
m1 is greater than scl_hz, dff will start big, then shrink until m1 is
almost equal to scl_hz, then grow again. Basically you want scgd such
that

	scl_hz == iclk / (20 + (scgd << 3))

i.e.

	scgd == ((iclk / scl_hz) - 20) >> 3

with the obvious problem that this is integer arithmetic, so the
resolution is limited. The value above is the integer value immediately
below the "correct" value, and scgd + 1 is the integer value
immediately above the correct value. This means that, for each
iteration of the outer loop, there are really only two candidates to
check: ((iclk / scl_hz) - 20) >> 3 and (((iclk / scl_hz) - 20) >> 3) + 1.

This results in the following code:

	/* pclock/CDF = i2c_module clock (iclk)/SCGD = SCL */
	odff = scl_hz;
	scgdm = cdfm = m1 = 0;
	for (cdf = 3; cdf >= 0; cdf--) {
		iclk = mck / (1 + cdf);
		/* iclk must not be > 20MHz */
		if (iclk >= 20000000)
			continue;
		scgd_low = ((iclk / scl_hz) - 20) >> 3;					/* ADDED */
		for (scgd = scgd_low; scgd < 63 && scgd <= scgd_low + 1; scgd++) {	/* CHANGED */
			m1 = iclk / (20 + (scgd << 3));
			dff = abs(scl_hz - m1);
			if (dff < odff) {
				odff = dff;
				cdfm = cdf;
				scgdm = scgd;
			}
		}
	}

This gets you the best combination of settings in a maximum of 8
iterations, instead of 252 with the original code. As an additional
speedup, you could exit the loop as soon as dff == 0, however it's
arguable whether it's worth the additional code now that the number of
iterations is so small.

> I'll resend once I've managed to get zero-byte transfers working without
> ugly hacks.

As I wrote before, you should be able to get everything to work even
without implementing zero-byte transfers, as long as you only use
new-style i2c drivers. With legacy i2c drivers you can use the "force"
module parameters to work around the problem, too.

-- 
Jean Delvare

_______________________________________________
i2c mailing list
i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
http://lists.lm-sensors.org/mailman/listinfo/i2c

      parent reply	other threads:[~2008-02-27 22:55 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20071105172313.GB17951@roarinelk.homelinux.net>
     [not found] ` <20071105172313.GB17951-nEyxjcs6f3Vin2gBucwGBecsttgLyre6@public.gmane.org>
2008-02-23 16:15   ` [RFC PATCH] I2C bus driver for SH7760 SoC, #2 Jean Delvare
2008-02-26  7:23     ` [i2c] " Manuel Lauss
     [not found]       ` <20080226072330.GB14289-nEyxjcs6f3Vin2gBucwGBecsttgLyre6@public.gmane.org>
2008-02-27 22:55         ` Jean Delvare [this message]

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=20080227235506.3e79c27c@hyperion.delvare \
    --to=khali-puyad+kwke1g9huczpvpmw@public.gmane.org \
    --cc=i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org \
    --cc=linuxsh-dev-TtF/mJH4Jtrk1uMJSBkQmQ@public.gmane.org \
    --cc=mano-nEyxjcs6f3Vin2gBucwGBecsttgLyre6@public.gmane.org \
    /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