devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Uwe Kleine-König" <u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
To: Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Cc: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	Xudong Chen <xudong.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
	Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>,
	Ian Campbell
	<ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>,
	Liguo Zhang <liguo.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
	Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
	Matthias Brugger
	<matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: Re: [PATCH v8 2/3] I2C: mediatek: Add driver for MediaTek I2C controller
Date: Wed, 20 May 2015 10:57:16 +0200	[thread overview]
Message-ID: <20150520085715.GA17078@pengutronix.de> (raw)
In-Reply-To: <1431967209-5261-3-git-send-email-eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>

Hello,

now that I understood the formula some more comments to the calculation.

On Tue, May 19, 2015 at 12:40:08AM +0800, Eddie Huang wrote:
> +#define I2C_DEFAUT_SPEED		100000	/* hz */
DEFAULT?

> +#define MAX_FS_MODE_SPEED		400000
> +#define MAX_HS_MODE_SPEED		3400000
> +#define MAX_SAMPLE_CNT_DIV		8
> +#define MAX_STEP_CNT_DIV		64
> +#define MAX_HS_STEP_CNT_DIV		8
> [...]
> +/* calculate i2c port speed */
> +static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
> +{
add a comment here, that clk_src_in_hz is the parent clock already
divided by clock-div.

> +	unsigned int khz;
> +	unsigned int step_cnt;
> +	unsigned int sample_cnt;
> +	unsigned int sclk;
> +	unsigned int hclk;
> +	unsigned int max_step_cnt;
> +	unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
> +	unsigned int step_div;
> +	unsigned int min_div;
> +	unsigned int best_mul;
> +	unsigned int cnt_mul;
> +
> +	if (i2c->speed_hz > MAX_HS_MODE_SPEED)
> +		return -EINVAL;
According to the plan to tune for the highest possible rate <=
i2c->speed_hz, you should handle the case (i2c->speed_hz >
MAX_HS_MODE_SPEED) like i2c->speed_hz == MAX_HS_MODE_SPEED.
Well, you might want to prevent an overflow in the calculation below
however.

> +	else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
> +		max_step_cnt = MAX_HS_STEP_CNT_DIV;
> +	else
> +		max_step_cnt = MAX_STEP_CNT_DIV;
So I assume this is the hardware limit on the step_cnt value. For
FS_MODE and below you have 6 bits and writing X corresponds to
step_cnt = X + 1. For HS_MODE there are only 3 bits. right?

> +	step_div = max_step_cnt;
> +	/* Find the best combination */
> +	khz = i2c->speed_hz / 1000;
> +	hclk = clk_src_in_hz / 1000;
Why are you dividing here? There shouldn't be an overflow problem and
you're loosing precision.

> +	min_div = ((hclk >> 1) + khz - 1) / khz;
The shift accounts for the fixed divider 2 in

	i2c_bus_freq = parent_clk / (clock-div * 2 * sample_cnt * step_cnt

? Maybe better call this opt_div instead of min_div? So now we're
searching for the best pair (sample_cnt, step_cnt) with:

	* 0 < sample_cnt < MAX_SAMPLE_CNT_DIV
	* 0 < step_cnt < max_step_cnt
	* sample_cnt * step_cnt >= min_div
	* optimizing for sample_cnt * step_cnt being minimal

Right?

> +	best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
> +
> +	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
> +		step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
DIV_ROUND_UP

> +		cnt_mul = step_cnt * sample_cnt;
> +		if (step_cnt > max_step_cnt)
> +			continue;
I think it can happen that you have step_cnt > max_step_cnt here, but
that (sample_cnt, max_step_cnt) still is a good pair to consider. So:

	step_cnt = DIV_ROUND_UP(min_div, sample_cnt);
	if (step_cnt > max_step_cnt)
		step_cnt = max_step_cnt;

	cnt_mul = step_cnt * sample_cnt;

> +
> +		if (cnt_mul < best_mul) {
> +			best_mul = cnt_mul;
> +			sample_div = sample_cnt;
> +			step_div = step_cnt;
I'd call these best_sample_cnt and best_step_cnt instead of sample_div
and step_div.

> +			if (best_mul == min_div)
> +				break;
> +		}
> +	}
> +
> +	sample_cnt = sample_div;
> +	step_cnt = step_div;
> +	sclk = hclk / (2 * sample_cnt * step_cnt);
> +	if (sclk > khz) {
Can this happen? A better name for "sclk" would be "bus_freq"?

> +		dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
> +			(i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
What is ST/FR? I would have expected FS here.

> +			(long int)khz);
> +		return -EINVAL;
> +	}
> +
> +	step_cnt--;
> +	sample_cnt--;
> +
> +	if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
> +		/* Set the hign speed mode register */
> +		i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
> +		i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
> +			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
> +			(step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
> +	} else {
> +		i2c->timing_reg =
> +			(sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
> +			(step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
> +		/* Disable the high speed transaction */
> +		i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
> +	}
Would it be sensible to write these values directly into hardware here?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

  parent reply	other threads:[~2015-05-20  8:57 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-18 16:40 [PATCH v8 0/3] ARM: mediatek: Add driver for Mediatek I2C Eddie Huang
     [not found] ` <1431967209-5261-1-git-send-email-eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-18 16:40   ` [PATCH v8 1/3] dt-bindings: Add I2C bindings for mt65xx/mt81xx Eddie Huang
     [not found]     ` <1431967209-5261-2-git-send-email-eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-18 18:29       ` Uwe Kleine-König
2015-05-18 16:40 ` [PATCH v8 2/3] I2C: mediatek: Add driver for MediaTek I2C controller Eddie Huang
     [not found]   ` <1431967209-5261-3-git-send-email-eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-18 18:43     ` Uwe Kleine-König
2015-05-19 14:48       ` Matthias Brugger
2015-05-19 19:49         ` Uwe Kleine-König
     [not found]           ` <20150519194917.GI24769-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2015-05-20  5:33             ` Eddie Huang
2015-05-20  3:07         ` Yingjoe Chen
     [not found]       ` <20150518184300.GB28888-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2015-05-20  2:40         ` Eddie Huang
2015-05-20  7:11           ` Uwe Kleine-König
     [not found]             ` <20150520071152.GP24769-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2015-05-20  7:59               ` Eddie Huang
2015-05-20  8:33                 ` Uwe Kleine-König
2015-05-20  8:57     ` Uwe Kleine-König [this message]
     [not found]       ` <20150520085715.GA17078-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2015-05-20 13:03         ` Yingjoe Chen
2015-05-20 15:37           ` Uwe Kleine-König
2015-05-21  7:01       ` Eddie Huang
2015-05-18 16:40 ` [PATCH v8 3/3] I2C: mediatek: Add driver for MediaTek MT8173 " Eddie Huang
2015-05-19 14:45   ` Matthias Brugger
     [not found]     ` <CABuKBeKJ=V6bP9iU9xDN0JecTTFoLDUfsX_QP5rpPj1bn167Vg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-20  2:53       ` Eddie Huang

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=20150520085715.GA17078@pengutronix.de \
    --to=u.kleine-koenig-bicnvbalz9megne8c9+irq@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \
    --cc=ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org \
    --cc=kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    --cc=liguo.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=pawel.moll-5wv7dgnIgG8@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=srv_heupstream-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org \
    --cc=xudong.chen-NuS5LvNUpcJWk0Htik3J/w@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;
as well as URLs for NNTP newsgroup(s).