linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Shinya Kuribayashi <skuribay-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
To: christian.ruppert-ux6zf3SgZrrQT0dZR+AlfA@public.gmane.org
Cc: mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH 1/2] i2c-designware: make *CNT values configurable
Date: Wed, 24 Jul 2013 23:31:44 +0900	[thread overview]
Message-ID: <51EFE550.1000507@pobox.com> (raw)
In-Reply-To: <20130722131706.GA24081-7oYq3qWSd+k@public.gmane.org>

On 7/22/13 10:17 PM, Christian Ruppert wrote:> On Wed, Jul 17, 2013 at 11:39:58PM +0900, Shinya Kuribayashi wrote:
>> On 7/16/13 8:16 PM, Christian Ruppert wrote:> On Sat, Jul 13, 2013 at 02:36:43PM +0900, Shinya Kuribayashi wrote:
>>>> Basically, DW I2C core provides a good enough (and quite direct) way
>>>> to control tHIGH and tLOW timing specs, *HCNT and *LCNT registers.
>>>>
>>>> But from my experience (with a slightly old version of DW I2C core
>>>> around 2005, version 1.06a or so), DW I2C core was apparently lacking
>>>> in an appropriate hardware mechanism to meet tHD;STA timing spec.  We
>>>> then found that we could meet tHD;STA by increasing *HCNT values, so
>>>> that's what currently we have in i2c-designware.c  I know with that
>>>> workaround applied, tHIGH is to be configured with a larger value
>>>> than necessary, but we have no choice.  For I2C bus systems, we must
>>>> meet every timing constraint strictly as required.  If DW I2C core
>>>> cannot meet tHD;STA without the sacrifice of tHIGH, and I would call
>>>> it a hardware bug.
>>>
>>> I agree. However, tHD;STA [min] is defined to the same value as tHIGH
>>> [min] for all modes in the I2C specification. Do I understand you
>>> correctly that the SCL_HCNT parameters control at the same time tHIGH
>>> and tHD;STA?
>>
>> *HCNT value does affect both tHIGH and tHD;STA at the same time.
>> But we have to make sure that composition of tHIGH is different
>> from the one of tHD;STA.
>>
>> For tHIGH
>> ----------
>>
>> DW I2C core is aware of the SCL rising transition (tr) and can
>> ignore it.  It starts counting the HIGH period of the SCL signal
>> (tHIGH) after the SCL input voltage increases at VIH.
>>
>> This is described in the data book as an ideal configuration,
>> and the resulting formula would be:
>>
>> 	HCNT + (1+4+3) >= IC_CLK * tHIGH ... (a)
>>
>> please refer to the data book for details about (1+4+3) part.
>>
>> For tLOW
>> --------
>>
>> DW I2C core starts counting the SCL CNTs for the LOW period of
>> the SCL signal (tLOW) as soon as it pulls the SCL line _without_
>> _confirming_ the SCL input voltage decreases at VIL.
>>
>> In order to meet the tLOW timing spec, we need to take into
>> account the fall time of SCL signal (tf), so the resulting
>> formula should be:
>>
>> 	LCNT + 1 >= IC_CLK * (tLOW + tf)
>>
>> please refer to the data book for details about '+1' part.
>>
>> For tHD;STA
>> -----------
>>
>> There is no explanation about tHD;STA in the data book.  We
>> only have (my) experimental result; tHD;STA turned out to be
>> proportional to 'HCNT + 3'.  The formula is:
>>
>> 	HCNT + 3 >= IC_CLK * (tHD;STA + tf) ... (b)
>>
>> DW I2C core seems to start counting the SCL CNTs for the HIGH
>> period of the SCL signel (tHD;STA) as soon as it pulls the _SDA_
>> line without confirming the SDA input voltage decreases at VIL,
>> so we have to take into account the SDA falling transition (tf)
>> here.
>>
>> As can be expected from (a) and (b), if tHD;STA [min] is defined
>> to the same value as tHIGH [min], we need to have larger HCNT
>> value than necessary for tHIGH, to meet tHD;STA constraint.
>>
>> [...]
>
> Hrmmm... This makes my head spin. Do you think the following code
> snippet represents an accurate method to calculate the register values?
> If you agree I'll prepare a patch based on that for the DW I2C. The
> question will be, however, how to obtain the transition times.

Please find my comments below.

> /*
>  *        t_f;SDA
>  *          |-|
>  *     _____              _____ . . .
>  *          \            /
>  * SDA       \          /
>  *            \________/       t_r;SCL    t_f;SCL
>  *                               |-|        |-|
>  *     ______________               ________
>  *                   \             /        \
>  * SCL                \           /          \
>  *                     \_________/            \_______ . . .
>  *            |------| |---------| |--------|
>  *            t_HD;STA    t_LOW      t_HIGH
>  *
>  *          |--------|-----------| |--------|
>  *         (   HCNT       LCNT        HCNT   ) * 1/f_SYS

Composition is:  HCNT+3     LCNT+1      HCNT+(1+4+3)

The offsets for the HCNT are different in the cases of tHD;STA and
t_HIGH.  It's based on my experimental result and we can't know how
DW I2C core actually counts those period, but it can be easily
imagined that for DW I2C core, the way to count t_HD;STA is similar
to the way to count t_LOW; it starts counting CNTs as soon as it
pulls the SCL/SDA line, then waits for given CNTs.

I think your equations and snippet code are based on the assumption
that DW I2C core must be counting the number of CNTs for the HIGH
period of the SCL signal (that's t_HD;STA and t_HIGH) in the same
way, but I don't think so.  From my observation and experimental
results, it must be different.  We couldn't know what actually is,
though.

>  *
>  * HCNT = f_SYS * max(t_HD;STA + t_f;SDA , t_HIGH)
>  *      = f_SYS * (t_HIGH + t_f;SDA)      because T_HD;STA == T_HIGH
>  * LCNT = f_SYS * (t_f;SCL + t_LOW)
>  * HCNT + LCNT + t_r;SCL = 1/f_SCL = t_SCL

As said before, all t_SCL things should go away.  Please forget
about 100kbps, 400kbps, and so on.  Bus/clock speed is totally
pointless concept for the I2C bus systems.  For example, as long
as tr/tf, tHIGH/tLOW, tHD;STA, etc. are met by _all_ devices in a
certain I2C bus, it doesn't matter that the resulting clock speed
is, say 120 kbps with Standard-mode, or even 800 kbps for Fast-mode.
Nobody in the I2C bus doesn't care about actual bus/clock speed.

We don't have to care about the resulting bus speed, or rather
we should/must not check to see if it's within the proper range.

> #define I2C_STD_MODE       (0)
> #define I2C_FAST_MODE      (1)
> #define I2C_FAST_MODE_PLUS (2)
>
> static const struct i2c_timing_params {
> 	unsigned int t_SCL;   /* t_SCL in (ms * 65536) */
> 	unsigned int t_LOW;   /* t_LOW in (ms * 65536) */
> 	unsigned int t_HIGH;  /* t_HIGH = t_HD;STA in (ms * 65536) */
> } i2c_timing_params[] = {
> 	{ /* I2C_STD_MODE */
> 		.t_SCL   = 10.0e-3 * 65536 + 0.5,
> 		.t_LOW   =  4.7e-3 * 65536 + 0.5,
> 		.t_HIGH  =  4.0e-3 * 65536 + 0.5,
> 	},
> 	{ /* I2C_FAST_MODE */
> 		.t_SCL   =  2.5e-3 * 65536 + 0.5,
> 		.t_LOW   =  1.3e-3 * 65536 + 0.5,
> 		.t_HIGH  =  0.6e-3 * 65536 + 0.5,
> 	},
> 	{ /* I2C_FAST_MODE_PLUS */
> 		.t_SCL   =  1.0e-3 * 65536 + 0.5,
> 		.t_LOW   =  0.5e-3 * 65536 + 0.5,
> 		.t_HIGH  =  0.26e-3 * 65536 + 0.5,
> 	},
> };

I just can't take to these 65536s, 0.5s, and {(x + 32768) >> 16},
as it's not intuitive.  Would be nice to come up with another way!

> #define DW_CNT_OFFS    (1)
> #define DW_FILT_OFFS   (2)
> #define DW_SCL_LATENCY (3)
>
> /*
>   * all timings in ns f_SYS in kHz
>   * For worst case scenario assume tf_SCL = tf_SDA = 300ns, tr_SCL = 0ns
>   */
> void calc_timing_params(u16 *HCNT, u16 *LCNT, unsigned int f_SYS
> 			unsigned int tf_SCL, unsigned int tr_SCL,
> 			unsigned int tf_SDA, unsigned int mode,
> 			unsigned int IC_SPKLEN)
> {
> 	unsigned int H, L;
> 	int D;
> 	/*
> 	 * The worst case High count timing includes the SDA falling
> 	 * transition of start condition
> 	 */
> 	H = f_SYS * (tf_SDA + i2c_timing_params[mode].t_HIGH);
>
> 	/* The Low count timing always includes the preceding falling edge. */
> 	L = f_SYS * (tf_SCL + i2c_timing_params[mode].t_LOW);
>
> 	/*
> 	 * The clock timings must not exceed the maximum frequencies
> 	 * from the I2C specification, slow down if required.
> 	 */
> 	D = (f_SYS * i2c_timing_params[mode].t_scl - H - L - tr_SCL) / 2;
> 	if (D > 0) {
> 		H += D;
> 		L += D;
> 	}

These H/L adjustments based on clock timings are not necessary.

> 	/*
> 	 * Round the HIGH count and subtract
> 	 * (DW_CNT_OFFS + DW_FILT_OFFS + DW_SCL_LATENCY + IC_SPKLEN)
> 	 * which are added to the register value inside the DW IP.
> 	 */
> 	H = ((H + 32768) >> 16) - DW_CNT_OFFS - DW_FILT_OFFS
> 				- DW_SCL_LATENCY - IC_SPKLEN;

And this adjustment for HCNT has to be altered to suit t_HIGH or
t_HD;STA.  It can not be processed in a single form like this.

> 	/*
> 	 * Round the LOW count and subtract DW_CNT_OFFS which is added to
> 	 * the register value inside the DW IP.
> 	 */
> 	L = ((L + 32768) >> 16) - DW_CNT_OFFS;

This is Ok.

> 	/* Respect the DW IP minimum timings */
> 	if (H < (IC_SPKLEN + 5))
> 		H = IC_SPKLEN + 5;
> 	if (L < (IC_SPKLEN + 7))
> 		L = IC_SPKLEN + 7;
> 	*HCNT = H;
> 	*LCNT = L;
> }

I'm not familiar with this SPKLEN (spike length?) as it didn't
appear in the data book around 2005, but it's fine to try to make
sure H/L values are within the range supported.

> Would it make sense to add generic I2C device tree properties for those
> parameters? These parameters are independent of the actual bus driver,
> rather a PCB property... And as such the correct place would be device
> tree or ACPI or similar.

If there are other bus drivers that make use of tr/tf transition
times, I think it makes sense.

Hope this helps,

   Shinya

  parent reply	other threads:[~2013-07-24 14:31 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-08 11:45 [PATCH 1/2] i2c-designware: make *CNT values configurable Mika Westerberg
     [not found] ` <1373283927-21677-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2013-07-08 11:45   ` [PATCH 2/2] i2c-designware: configure *CNT values from ACPI Mika Westerberg
     [not found]     ` <1373283927-21677-2-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2013-07-10 13:01       ` Mika Westerberg
2013-07-08 13:42   ` [PATCH 1/2] i2c-designware: make *CNT values configurable Christian Ruppert
     [not found]     ` <20130708134216.GB6402-7oYq3qWSd+k@public.gmane.org>
2013-07-09  8:44       ` Mika Westerberg
     [not found]         ` <20130709084402.GF4898-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-07-09 16:19           ` Christian Ruppert
     [not found]             ` <20130709161927.GC30236-7oYq3qWSd+k@public.gmane.org>
2013-07-10 10:52               ` Mika Westerberg
     [not found]                 ` <20130710105215.GY4898-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-07-10 16:56                   ` Christian Ruppert
     [not found]                     ` <20130710165634.GA30693-7oYq3qWSd+k@public.gmane.org>
2013-07-11  7:36                       ` Mika Westerberg
2013-07-11 10:13                         ` Mika Westerberg
     [not found]                           ` <20130711101330.GP4898-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-07-12  7:56                             ` Shinya Kuribayashi
     [not found]                               ` <51DFB6C1.4040001-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2013-07-12  8:51                                 ` Mika Westerberg
     [not found]                                   ` <20130712085140.GY4898-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-07-13  5:36                                     ` Shinya Kuribayashi
     [not found]                                       ` <51E0E76B.1040304-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2013-07-16 11:16                                         ` Christian Ruppert
     [not found]                                           ` <20130716111616.GA25835-7oYq3qWSd+k@public.gmane.org>
2013-07-17 14:39                                             ` Shinya Kuribayashi
     [not found]                                               ` <51E6ACBE.7000509-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2013-07-22 13:17                                                 ` Christian Ruppert
     [not found]                                                   ` <20130722131706.GA24081-7oYq3qWSd+k@public.gmane.org>
2013-07-24 14:31                                                     ` Shinya Kuribayashi [this message]
     [not found]                                                       ` <51EFE550.1000507-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2013-08-05  9:31                                                         ` Christian Ruppert
     [not found]                                                           ` <20130805093126.GE20936-7oYq3qWSd+k@public.gmane.org>
2013-08-05 10:02                                                             ` Wolfram Sang
2013-08-12  7:48                                                               ` Christian Ruppert
     [not found]                                                                 ` <20130812074800.GA23792-7oYq3qWSd+k@public.gmane.org>
2013-08-12 11:09                                                                   ` Wolfram Sang
2013-08-16  2:15                                                             ` Shinya Kuribayashi
2013-08-19 11:36                                                               ` Mika Westerberg
     [not found]                                                                 ` <20130819113604.GN4898-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-08-19 12:22                                                                   ` Shinya Kuribayashi
2013-08-21 14:39                                                               ` Christian Ruppert
     [not found]                                                                 ` <20130821143915.GA3046-7oYq3qWSd+k@public.gmane.org>
2013-08-24  4:58                                                                   ` Shinya Kuribayashi
     [not found]                                                                     ` <52183D87.40703-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2013-08-28 15:34                                                                       ` Christian Ruppert
2013-10-08 15:00                                                                         ` [PATCH 1/2] i2c designware make SCL and SDA falling time configurable Romain Baeriswyl
2013-10-09  7:55                                                                           ` Mika Westerberg
2013-10-10  0:54                                                                             ` Ryan Mallon
     [not found]                                                                               ` <5255FAB5.7080803-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2013-10-13 11:36                                                                                 ` Shinya Kuribayashi
     [not found]                                                                                   ` <525A85D6.3090608-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>
2014-01-16 19:43                                                                                     ` Wolfram Sang
2014-01-20 16:43                                                                                       ` [PATCH v2 " Romain Baeriswyl
     [not found]                                                                                         ` <1390236223-22584-1-git-send-email-romainba-ux6zf3SgZrrQT0dZR+AlfA@public.gmane.org>
2014-03-09  8:20                                                                                           ` Wolfram Sang
     [not found]                                                                         ` <20130828153429.GB7066-7oYq3qWSd+k@public.gmane.org>
2013-10-08 15:00                                                                           ` [PATCH 2/2] i2c designware add support of I2C standard mode Romain Baeriswyl
2013-10-09  7:56                                                                             ` Mika Westerberg
     [not found]                                                                               ` <20131009075632.GR3521-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-10-13 11:46                                                                                 ` Shinya Kuribayashi
2014-01-16 19:33                                                                             ` Wolfram Sang
2014-01-20 16:45                                                                               ` [PATCH v2 " Romain Baeriswyl
     [not found]                                                                                 ` <1390236338-21407-1-git-send-email-romainba-ux6zf3SgZrrQT0dZR+AlfA@public.gmane.org>
2014-03-09  8:07                                                                                   ` Wolfram Sang
2013-08-19  6:39                                             ` [PATCH 1/2] i2c-designware: make *CNT values configurable Mika Westerberg

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=51EFE550.1000507@pobox.com \
    --to=skuribay-e+axbwqsrlaavxtiumwx3w@public.gmane.org \
    --cc=christian.ruppert-ux6zf3SgZrrQT0dZR+AlfA@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
    --cc=wsa-z923LK4zBo2bacvFa/9K2g@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).