Re: [PATCH v3] i2c: rk3x: fix bug that cause measured high_ns doesn't meet I2C spec

2014-12-07 Thread addy ke
On 2014/12/8 10:59, Addy Ke wrote:
 high_ns calculated from the low division of CLKDIV register is the sum
 of actual measured high_ns and rise_ns. The rise time which related to
 external pull-up resistor can be up to the maximum rise time in I2C spec.
 
 In my test, if external pull-up resistor is 4.7K, rise_ns is about
 700ns. So the actual measured high_ns is about 3900ns, which is less
 than 4000ns(the minimum high_ns in I2C spec).
 
 To fix this bug, min_low_ns should include fall time and min_high_ns
 should include rise time too.
 
 This patch merged the patch that Doug submitted to chromium, which
 can get the rise and fall times for signals from the device tree.
 This allows us to more accurately calculate timings. see:
 https://chromium-review.googlesource.com/#/c/232774/
 
 Signed-off-by: Addy Ke addy...@rock-chips.com
 ---
 Changes in v2:
 - merged the patch that Doug submitted to chromium
 Changes in v3:
 - merged the patch that Doug submitted to chromium to change bindins
   see: https://chromium-review.googlesource.com/#/c/232775/
Sorry, see https://chromium-review.googlesource.com/#/c/232774/ not 232775
 
  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 11 +
  drivers/i2c/busses/i2c-rk3x.c  | 57 
 +++---
  2 files changed, 50 insertions(+), 18 deletions(-)
 
 diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt 
 b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
 index dde6c22..925d6eb 100644
 --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
 +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
 @@ -21,6 +21,14 @@ Required on RK3066, RK3188 :
  Optional properties :
  
   - clock-frequency : SCL frequency to use (in Hz). If omitted, 100kHz is 
 used.
 + - i2c-scl-rising-time-ns : Number of nanoseconds the signal takes to rise
 + (t(r) in i2c spec). If not specified this is assumed to be the max the
 + spec allows(1000 ns for standard mode, 300 ns for fast mode) which
 + might cause slightly slower communication.
 + - i2c-scl-falling-time-ns : Number of nanoseconds the signal takes to fall
 + (t(f) in the i2c0 spec).  If not specified this is assumed to be the
 + max the spec allows (300 ns) which might cause slightly slower
 + communication.
  
  Example:
  
 @@ -39,4 +47,7 @@ i2c0: i2c@2002d000 {
  
   clock-names = i2c;
   clocks = cru PCLK_I2C0;
 +
 + i2c-scl-rising-time-ns = 800;
 + i2c-scl-falling-time-ns = 100;
  };
 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
 index 0ee5802..50c1678 100644
 --- a/drivers/i2c/busses/i2c-rk3x.c
 +++ b/drivers/i2c/busses/i2c-rk3x.c
 @@ -102,6 +102,8 @@ struct rk3x_i2c {
  
   /* Settings */
   unsigned int scl_frequency;
 + unsigned int rise_ns;
 + unsigned int fall_ns;
  
   /* Synchronization  notification */
   spinlock_t lock;
 @@ -435,6 +437,8 @@ out:
   *
   * @clk_rate: I2C input clock rate
   * @scl_rate: Desired SCL rate
 + * @rise_ns: How many ns it takes for signals to rise.
 + * @fall_ns: How many ns it takes for signals to fall.
   * @div_low: Divider output for low
   * @div_high: Divider output for high
   *
 @@ -443,11 +447,14 @@ out:
   * too high, we silently use the highest possible rate.
   */
  static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
 +   unsigned long rise_ns, unsigned long fall_ns,
 unsigned long *div_low, unsigned long *div_high)
  {
 + unsigned long spec_min_low_ns, spec_min_high_ns;
 + unsigned long spec_max_data_hold_ns;
 + unsigned long spec_data_hold_buffer_ns;
 +
   unsigned long min_low_ns, min_high_ns;
 - unsigned long max_data_hold_ns;
 - unsigned long data_hold_buffer_ns;
   unsigned long max_low_ns, min_total_ns;
  
   unsigned long clk_rate_khz, scl_rate_khz;
 @@ -470,28 +477,30 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate, 
 unsigned long scl_rate,
  
   /*
* min_low_ns:  The minimum number of ns we need to hold low
 -  *  to meet i2c spec
 +  *  to meet i2c spec, should include fall time.
* min_high_ns: The minimum number of ns we need to hold high
 -  *  to meet i2c spec
 +  *  to meet i2c spec, should include rise time.
* max_low_ns:  The maximum number of ns we can hold low
 -  *  to meet i2c spec
 +  *  to meet i2c spec.
*
* Note: max_low_ns should be (max data hold time * 2 - buffer)
*   This is because the i2c host on Rockchip holds the data line
*   for half the low time.
*/
   if (scl_rate = 10) {
 - min_low_ns = 4700;
 - min_high_ns = 4000;
 - max_data_hold_ns = 3450;
 - data_hold_buffer_ns = 50;
 + spec_min_low_ns = 4700;
 + spec_min_high_ns = 4000

[PATCH] i2c: rk3x: fix bug that cause measured high_ns doesn't meet I2C spec

2014-11-06 Thread Addy Ke
high_ns calculated from the low division of CLKDIV register is the sum of
actual measured high_ns and rise_ns. The rise time which related to
external pull-up resistor can be up to the maximum rise time in I2C spec.

In my test, if external pull-up resistor is 4.7K, rise_ns is about 700ns.
So the actual measured high_ns is about 3900ns, which is less than 4000ns
(the minimum high_ns in I2C spec).

Signed-off-by: Addy Ke addy...@rock-chips.com
---
 drivers/i2c/busses/i2c-rk3x.c | 58 +++
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e276ffb..8e1cc2b 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -432,9 +432,12 @@ out:
 static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
   unsigned long *div_low, unsigned long *div_high)
 {
+   unsigned long spec_min_low_ns, spec_min_high_ns;
+   unsigned long spec_max_data_hold_ns;
+   unsigned long spec_data_hold_buffer_ns;
+   unsigned long spec_max_rise_ns;
+
unsigned long min_low_ns, min_high_ns;
-   unsigned long max_data_hold_ns;
-   unsigned long data_hold_buffer_ns;
unsigned long max_low_ns, min_total_ns;
 
unsigned long i2c_rate_khz, scl_rate_khz;
@@ -453,30 +456,43 @@ static int rk3x_i2c_calc_divs(unsigned long i2c_rate, 
unsigned long scl_rate,
if (WARN_ON(scl_rate  1000))
scl_rate = 1000;
 
+   if (scl_rate = 10) {
+   spec_min_low_ns = 4700;
+   spec_min_high_ns = 4000;
+   spec_max_rise_ns = 1000;
+   spec_max_data_hold_ns = 3450;
+   spec_data_hold_buffer_ns = 50;
+   } else {
+   spec_min_low_ns = 1300;
+   spec_min_high_ns = 600;
+   spec_max_rise_ns = 300;
+   spec_max_data_hold_ns = 900;
+   spec_data_hold_buffer_ns = 50;
+   }
+
/*
-* min_low_ns:  The minimum number of ns we need to hold low
-*  to meet i2c spec
-* min_high_ns: The minimum number of ns we need to hold high
-*  to meet i2c spec
-* max_low_ns:  The maximum number of ns we can hold low
-*  to meet i2c spec
+* min_low_ns:  The minimum number of ns we need to hold low.
+*  The fall time in RK3X's I2C controller is approximately
+*  equal to 0. So min_low_ns = spec_min_low_ns.
+* Note: low_ns should be (measured_low_ns + measured_fall_time)
+*   and measured_low_ns must meet I2C spec.
 *
-* Note: max_low_ns should be (max data hold time * 2 - buffer)
+* min_high_ns: The minimum number of ns we need to hold high.
+*  The rise time which related to external pull-up resistor
+*  can be up to spec_max_rise_ns.
+*  So min_high_ns = spec_min_high_ns + spec_max_rise_ns
+* Note: high_ns should be (measured_high_ns + measured_rise_time)
+*   and measured_high_ns must meet I2C spec.
+*
+* max_low_ns:  The maximum number of ns we can hold low.
+* Note: max_low_ns should be (max_data_hold_time * 2 - buffer)
 *   This is because the i2c host on Rockchip holds the data line
 *   for half the low time.
 */
-   if (scl_rate = 10) {
-   min_low_ns = 4700;
-   min_high_ns = 4000;
-   max_data_hold_ns = 3450;
-   data_hold_buffer_ns = 50;
-   } else {
-   min_low_ns = 1300;
-   min_high_ns = 600;
-   max_data_hold_ns = 900;
-   data_hold_buffer_ns = 50;
-   }
-   max_low_ns = max_data_hold_ns * 2 - data_hold_buffer_ns;
+   min_low_ns = spec_min_low_ns;
+   min_high_ns = spec_min_high_ns + spec_max_rise_ns;
+   max_low_ns = spec_max_data_hold_ns * 2 - spec_data_hold_buffer_ns;
+
min_total_ns = min_low_ns + min_high_ns;
 
/* Adjust to avoid overflow */
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-10-14 Thread Addy Ke
As show in I2C specification:
- Standard-mode: the minimum HIGH period of the scl clock is 4.0us
 the minimum LOW period of the scl clock is 4.7us
- Fast-mode: the minimum HIGH period of the scl clock is 0.6us
 the minimum LOW period of the scl clock is 1.3us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

Thanks Doug for the suggestion about division formulas.

Tested-by: Heiko Stuebner he...@sntech.de
Reviewed-by: Doug Anderson diand...@chromium.org
Tested-by: Doug Anderson diand...@chromium.org
Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- remove Fast-mode plus and HS-mode
- use new formulas suggested by Doug
Changes in V3:
- use new formulas (sep 30) suggested by Doug
Changes in V4:
- fix some wrong style
- WARN_ONCE if min_low_div  max_low_div
Changes in V5:
- round up for i2c_rate and round down for scl_rate, suggested by Max
- place a WARN_ON if scl_rate  1000, suggested by Max
- add div_high and div_low overflow protection, suggested by Max
Changes in V6:
- goto to jump to clk_disable if set_scl_rate return error

 drivers/i2c/busses/i2c-rk3x.c | 162 +++---
 1 file changed, 153 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b41d979..47e85dc 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -24,6 +24,7 @@
 #include linux/wait.h
 #include linux/mfd/syscon.h
 #include linux/regmap.h
+#include linux/math64.h
 
 
 /* Register Map */
@@ -428,18 +429,158 @@ out:
return IRQ_HANDLED;
 }
 
-static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
+static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *div_low, unsigned long *div_high)
 {
-   unsigned long i2c_rate = clk_get_rate(i2c-clk);
-   unsigned int div;
+   unsigned long min_low_ns, min_high_ns;
+   unsigned long max_data_hold_ns;
+   unsigned long data_hold_buffer_ns;
+   unsigned long max_low_ns, min_total_ns;
+
+   unsigned long i2c_rate_khz, scl_rate_khz;
+
+   unsigned long min_low_div, min_high_div;
+   unsigned long max_low_div;
+
+   unsigned long min_div_for_hold, min_total_div;
+   unsigned long extra_div, extra_low_div, ideal_low_div;
+
+   /* Only support standard-mode and fast-mode */
+   if (WARN_ON(scl_rate  40))
+   scl_rate = 40;
+
+   /* prevent scl_rate_khz from becoming 0 */
+   if (WARN_ON(scl_rate  1000))
+   scl_rate = 1000;
+
+   /*
+* min_low_ns:  The minimum number of ns we need to hold low
+*  to meet i2c spec
+* min_high_ns: The minimum number of ns we need to hold high
+*  to meet i2c spec
+* max_low_ns:  The maximum number of ns we can hold low
+*  to meet i2c spec
+*
+* Note: max_low_ns should be (max data hold time * 2 - buffer)
+*   This is because the i2c host on Rockchip holds the data line
+*   for half the low time.
+*/
+   if (scl_rate = 10) {
+   min_low_ns = 4700;
+   min_high_ns = 4000;
+   max_data_hold_ns = 3450;
+   data_hold_buffer_ns = 50;
+   } else {
+   min_low_ns = 1300;
+   min_high_ns = 600;
+   max_data_hold_ns = 900;
+   data_hold_buffer_ns = 50;
+   }
+   max_low_ns = max_data_hold_ns * 2 - data_hold_buffer_ns;
+   min_total_ns = min_low_ns + min_high_ns;
+
+   /* Adjust to avoid overflow */
+   i2c_rate_khz = DIV_ROUND_UP(i2c_rate, 1000);
+   scl_rate_khz = scl_rate / 1000;
 
-   /* set DIV = DIVH = DIVL
-* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
-*  = (clk rate) / (16 * (DIV + 1))
+   /*
+* We need the total div to be = this number
+* so we don't clock too fast.
+*/
+   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
+
+   /* These are the min dividers needed for min hold times. */
+   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
+   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
+   min_div_for_hold = (min_low_div + min_high_div);
+
+   /*
+* This is the maximum divider so we don't go over the max.
+* We don't round up here (we round down) since this is a max.
 */
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
+   max_low_div = i2c_rate_khz * max_low_ns / (8 * 100);
+
+   if (min_low_div  max_low_div) {
+   WARN_ONCE(true,
+ Conflicting, min_low_div %lu

[PATCH v5] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-10-12 Thread Addy Ke
As show in I2C specification:
- Standard-mode: the minimum HIGH period of the scl clock is 4.0us
 the minimum LOW period of the scl clock is 4.7us
- Fast-mode: the minimum HIGH period of the scl clock is 0.6us
 the minimum LOW period of the scl clock is 1.3us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

Thanks Doug for the suggestion about division formulas.

Tested-by: Heiko Stuebner he...@sntech.de
Reviewed-by: Doug Anderson diand...@chromium.org
Tested-by: Doug Anderson diand...@chromium.org
Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- remove Fast-mode plus and HS-mode
- use new formulas suggested by Doug
Changes in V3:
- use new formulas (sep 30) suggested by Doug
Changes in V4:
- fix some wrong style
- WARN_ONCE if min_low_div  max_low_div
Changes in V5:
- round up for i2c_rate and round down for scl_rate, suggested by Max
- place a WARN_ON if scl_rate  1000, suggested by Max
- add div_high and div_low overflow protection, suggested by Max

 drivers/i2c/busses/i2c-rk3x.c | 161 +++---
 1 file changed, 152 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b41d979..a30a4fb 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -24,6 +24,7 @@
 #include linux/wait.h
 #include linux/mfd/syscon.h
 #include linux/regmap.h
+#include linux/math64.h
 
 
 /* Register Map */
@@ -428,18 +429,158 @@ out:
return IRQ_HANDLED;
 }
 
-static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
+static int rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *div_low, unsigned long *div_high)
 {
-   unsigned long i2c_rate = clk_get_rate(i2c-clk);
-   unsigned int div;
+   unsigned long min_low_ns, min_high_ns;
+   unsigned long max_data_hold_ns;
+   unsigned long data_hold_buffer_ns;
+   unsigned long max_low_ns, min_total_ns;
+
+   unsigned long i2c_rate_khz, scl_rate_khz;
+
+   unsigned long min_low_div, min_high_div;
+   unsigned long max_low_div;
+
+   unsigned long min_div_for_hold, min_total_div;
+   unsigned long extra_div, extra_low_div, ideal_low_div;
+
+   /* Only support standard-mode and fast-mode */
+   if (WARN_ON(scl_rate  40))
+   scl_rate = 40;
+
+   /* prevent scl_rate_khz from becoming 0 */
+   if (WARN_ON(scl_rate  1000))
+   scl_rate = 1000;
+
+   /*
+* min_low_ns:  The minimum number of ns we need to hold low
+*  to meet i2c spec
+* min_high_ns: The minimum number of ns we need to hold high
+*  to meet i2c spec
+* max_low_ns:  The maximum number of ns we can hold low
+*  to meet i2c spec
+*
+* Note: max_low_ns should be (max data hold time * 2 - buffer)
+*   This is because the i2c host on Rockchip holds the data line
+*   for half the low time.
+*/
+   if (scl_rate = 10) {
+   min_low_ns = 4700;
+   min_high_ns = 4000;
+   max_data_hold_ns = 3450;
+   data_hold_buffer_ns = 50;
+   } else {
+   min_low_ns = 1300;
+   min_high_ns = 600;
+   max_data_hold_ns = 900;
+   data_hold_buffer_ns = 50;
+   }
+   max_low_ns = max_data_hold_ns * 2 - data_hold_buffer_ns;
+   min_total_ns = min_low_ns + min_high_ns;
+
+   /* Adjust to avoid overflow */
+   i2c_rate_khz = DIV_ROUND_UP(i2c_rate, 1000);
+   scl_rate_khz = scl_rate / 1000;
 
-   /* set DIV = DIVH = DIVL
-* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
-*  = (clk rate) / (16 * (DIV + 1))
+   /*
+* We need the total div to be = this number
+* so we don't clock too fast.
+*/
+   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
+
+   /* These are the min dividers needed for min hold times. */
+   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
+   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
+   min_div_for_hold = (min_low_div + min_high_div);
+
+   /*
+* This is the maximum divider so we don't go over the max.
+* We don't round up here (we round down) since this is a max.
 */
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
+   max_low_div = i2c_rate_khz * max_low_ns / (8 * 100);
+
+   if (min_low_div  max_low_div) {
+   WARN_ONCE(true,
+ Conflicting, min_low_div %lu, max_low_div %lu\n,
+ min_low_div, max_low_div

[PATCH v4] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-10-09 Thread Addy Ke
As show in I2C specification:
- Standard-mode: the minimum HIGH period of the scl clock is 4.0us
 the minimum LOW period of the scl clock is 4.7us
- Fast-mode: the minimum HIGH period of the scl clock is 0.6us
 the minimum LOW period of the scl clock is 1.3us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

Thanks Doug for the suggestion about division formulas.

Reviewed-by: Doug Anderson diand...@chromium.org
Tested-by: Doug Anderson diand...@chromium.org
Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- remove Fast-mode plus and HS-mode
- use new formulas suggested by Doug
Changes in V3:
- use new formulas (sep 30) suggested by Doug
Changes in V3:
- fix some wrong style
- WARN_ONCE if min_low_div  max_low_div

 drivers/i2c/busses/i2c-rk3x.c | 140 +++---
 1 file changed, 133 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b41d979..f17f7a2 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -24,6 +24,7 @@
 #include linux/wait.h
 #include linux/mfd/syscon.h
 #include linux/regmap.h
+#include linux/math64.h
 
 
 /* Register Map */
@@ -428,18 +429,143 @@ out:
return IRQ_HANDLED;
 }
 
+static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *div_low, unsigned long *div_high)
+{
+   unsigned long min_low_ns, min_high_ns;
+   unsigned long max_data_hold_ns;
+   unsigned long data_hold_buffer_ns;
+   unsigned long max_low_ns, min_total_ns;
+
+   unsigned long i2c_rate_khz, scl_rate_khz;
+
+   unsigned long min_low_div, min_high_div;
+   unsigned long max_low_div;
+
+   unsigned long min_div_for_hold, min_total_div;
+   unsigned long extra_div, extra_low_div, ideal_low_div;
+
+   /* Only support standard-mode and fast-mode */
+   WARN_ON(scl_rate  40);
+
+   /*
+* min_low_ns:  The minimum number of ns we need to hold low
+*  to meet i2c spec
+* min_high_ns: The minimum number of ns we need to hold high
+*  to meet i2c spec
+* max_low_ns:  The maximum number of ns we can hold low
+*  to meet i2c spec
+*
+* Note: max_low_ns should be (max data hold time * 2 - buffer)
+*   This is because the i2c host on Rockchip holds the data line
+*   for half the low time.
+*/
+   if (scl_rate = 10) {
+   min_low_ns = 4700;
+   min_high_ns = 4000;
+   max_data_hold_ns = 3450;
+   data_hold_buffer_ns = 50;
+   } else {
+   min_low_ns = 1300;
+   min_high_ns = 600;
+   max_data_hold_ns = 900;
+   data_hold_buffer_ns = 50;
+   }
+   max_low_ns = max_data_hold_ns * 2 - data_hold_buffer_ns;
+   min_total_ns = min_low_ns + min_high_ns;
+
+   /* Adjust to avoid overflow */
+   i2c_rate_khz = DIV_ROUND_UP(i2c_rate, 1000);
+   scl_rate_khz = DIV_ROUND_UP(scl_rate, 1000);
+
+   /*
+* We need the total div to be = this number
+* so we don't clock too fast.
+*/
+   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
+
+   /* These are the min dividers needed for min hold times. */
+   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
+   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
+   min_div_for_hold = (min_low_div + min_high_div);
+
+   /*
+* This is the maximum divider so we don't go over the max.
+* We don't round up here (we round down) since this is a max.
+*/
+   max_low_div = i2c_rate_khz * max_low_ns / (8 * 100);
+
+   if (min_low_div  max_low_div) {
+   WARN_ONCE(true,
+ Conflicting, min_low_div %lu, max_low_div %lu\n,
+ min_low_div, max_low_div);
+   max_low_div = min_low_div;
+   }
+
+   if (min_div_for_hold  min_total_div) {
+   /*
+* Time needed to meet hold requirements is important.
+* Just use that.
+*/
+   *div_low = min_low_div;
+   *div_high = min_high_div;
+   } else {
+   /*
+* We've got to distribute some time among the low and high
+* so we don't run too fast.
+*/
+   extra_div = min_total_div - min_div_for_hold;
+
+   /*
+* We'll try to split things up perfectly evenly,
+* biasing slightly towards having a higher div
+* for low (spend more time low

[PATCH v3] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-10-07 Thread Addy Ke
As show in I2C specification:
- Standard-mode: the minimum HIGH period of the scl clock is 4.0us
 the minimum LOW period of the scl clock is 4.7us
- Fast-mode: the minimum HIGH period of the scl clock is 0.6us
 the minimum LOW period of the scl clock is 1.3us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

Thanks Doug for the suggestion about division formulas.

Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- remove Fast-mode plus and HS-mode
- use new formulas suggested by Doug
Changes in V3:
- use new formulas (sep 30) suggested by Doug

 drivers/i2c/busses/i2c-rk3x.c | 135 +++---
 1 file changed, 128 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b41d979..9612eba 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -24,6 +24,7 @@
 #include linux/wait.h
 #include linux/mfd/syscon.h
 #include linux/regmap.h
+#include linux/math64.h
 
 
 /* Register Map */
@@ -428,18 +429,138 @@ out:
return IRQ_HANDLED;
 }
 
+static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *div_low, unsigned long *div_high)
+{
+   unsigned long min_low_ns, min_high_ns;
+   unsigned long max_data_hold_ns;
+   unsigned long data_hold_buffer_ns;
+   unsigned long max_low_ns, min_total_ns;
+
+   unsigned long i2c_rate_khz, scl_rate_khz;
+
+   unsigned long min_low_div, min_high_div;
+   unsigned long max_low_div;
+
+   unsigned long min_div_for_hold, min_total_div;
+   unsigned long extra_div, extra_low_div, ideal_low_div;
+
+   /* Only support standard-mode and fast-mode */
+   WARN_ON(scl_rate  40);
+
+   /*
+* min_low_ns:  The minimum number of ns we need to hold low
+*  to meet i2c spec
+* min_high_ns: The minimum number of ns we need to hold high
+*  to meet i2c spec
+* max_low_ns:  The maximum number of ns we can hold low
+*  to meet i2c spec
+*
+* Note: max_low_ns should be (max data hold time * 2 - buffer)
+*   This is because the i2c host on Rockchip holds the data line
+*   for half the low time.
+*/
+   if (scl_rate = 10) {
+   min_low_ns = 4700;
+   min_high_ns = 4000;
+   max_data_hold_ns = 3450;
+   data_hold_buffer_ns = 50;
+   } else {
+   min_low_ns = 1300;
+   min_high_ns = 600;
+   max_data_hold_ns = 900;
+   data_hold_buffer_ns = 50;
+   }
+   max_low_ns = max_data_hold_ns * 2 - data_hold_buffer_ns;
+   min_total_ns = min_low_ns + min_high_ns;
+
+   /* Adjust to avoid overflow */
+   i2c_rate_khz = DIV_ROUND_UP(i2c_rate, 1000);
+   scl_rate_khz = DIV_ROUND_UP(scl_rate, 1000);
+
+   /*
+* We need the total div to be = this number
+* so we don't clock too fast.
+*/
+   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
+
+   /* These are the min dividers needed for min hold times.*/
+   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
+   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
+   min_div_for_hold = (min_low_div + min_high_div);
+
+   /*
+* This is the maximum divider so we don't go over the max.
+* We don't round up here (we round down) since this is a max.
+*/
+   max_low_div = i2c_rate_khz * max_low_ns / (8 * 100);
+
+   if (min_low_div  max_low_div)
+   max_low_div = min_low_div;
+
+   if (min_div_for_hold  min_total_div) {
+   /*
+* Time needed to meet hold requirements is important.
+* Just use that.
+*/
+   *div_low = min_low_div;
+   *div_high = min_high_div;
+   } else {
+   /*
+* We've got to distribute some time among the low and high
+* so we don't run too fast.
+*/
+   extra_div = min_total_div - min_div_for_hold;
+   /*
+* We'll try to split things up perfectly evenly,
+* biasing slightly towards having a higher div
+* for low (spend more time low).
+*/
+
+   ideal_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns,
+scl_rate_khz * 8 * min_total_ns);
+
+   /* Don't allow it to go over the max */
+   if (ideal_low_div  max_low_div)
+   ideal_low_div = max_low_div

Re: [PATCH v2] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-29 Thread addy ke
Hi Doug

On 2014/9/29 12:39, Doug Anderson wrote:
 Addy,
 
 On Sat, Sep 27, 2014 at 12:11 AM, Addy Ke addy...@rock-chips.com wrote:
 From: Addy addy...@rock-chips.com

 As show in I2C specification:
 - Standard-mode: the minimum HIGH period of the scl clock is 4.0us
  the minimum LOW period of the scl clock is 4.7us
 - Fast-mode: the minimum HIGH period of the scl clock is 0.6us
  the minimum LOW period of the scl clock is 1.3us

 I have measured i2c SCL waveforms in fast-mode by oscilloscope
 on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
 It is so critical that we must adjust LOW division to increase
 the LOW period of the scl clock.

 After put this patch, we can find that min_low_ns is about
 5.4us in Standard-mode and 1.6us in Fast-mode.

 Thanks Doug for the suggestion about division formulas.

 Signed-off-by: Addy addy...@rock-chips.com
 ---
 Changes in v2:
 - remove Fast-mode plus and HS-mode
 - use new formulas suggested by Doug

  drivers/i2c/busses/i2c-rk3x.c | 104 
 +++---
  1 file changed, 97 insertions(+), 7 deletions(-)

 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
 index e637c32..81672a8 100644
 --- a/drivers/i2c/busses/i2c-rk3x.c
 +++ b/drivers/i2c/busses/i2c-rk3x.c
 @@ -428,19 +428,109 @@ out:
 return IRQ_HANDLED;
  }

 +static void rk3x_i2c_get_min_ns(unsigned int scl_rate,
 +   unsigned long *min_low_ns,
 +   unsigned long *min_high_ns)
 +{
 +   WARN_ON(scl_rate  40);
 +
 +   /* As show in I2C specification:
 +* - Standard-mode(100KHz):
 +*   min_low_ns is 4700ns
 +*   min_high_ns is 4000ns
 +* - Fast-mode(400KHz):
 +*   min_low_ns is 1300ns
 +*   min_high_ns is 600ns
 +*
 +* (min_low_ns + min_high_ns) up to 1ns in Standard-mode
 +* and 2500ns in Fast-mode
 +*/
 +   if (scl_rate = 10) {
 +   *min_low_ns = 4700 + 650;
 +   *min_high_ns = 4000 + 650;
 +   } else {
 +   *min_low_ns = 1300 + 300;
 +   *min_high_ns = 600 + 300;
 
 Wait, where did the extra 650 and 300 come from here?  Are you just
 trying to balance things out?  That's not the right way to do things.
 Please explain what you were trying to accomplish and we can figure
 out a better way.
 
 ...maybe this helped make thins nicer in the clock rates you tried,
 but I'd bet that I can find clock rates that this is broken for...
 
 
650 = [(10/100K) ns - min_low_ns_100k - min_high_ns_100k] / 2
300 = [(10/300K) ns - min_low_ns_400k - min_high_ns_400k] / 2

if there is no extra 650 and 300:
extra_div is 3 in fast-mode and 11 in standard-mode.

  1)if all of the extra is asssigned to the high part, the LOW period is too 
close to min_low.
In my test:
400k, scl_low_ns: 1440ns, scl_high_ns: 1120ns
100k, scl_low_ns: 4800ns, scl_high_ns: 5120ns

  2)if not, dato hold time is too close to min_hold_time(400khz, 900ns)
In my test:
400k, scl_low_ns: 1760ns, scl_high_ns: 800ns
100k, scl_low_ns: 5304ns, scl_high_ns: 4368ns

hold_time_ns ~= scl_low_ns / 2 = 880ns

So I think we must decrease min_low_ns:min_high_ns to decrease scl_low in case 2

So I set the extra 650 and 300.

After this, in my test:
   400k, scl_low_ns: 1600ns, scl_high_ns: 960ns
   100k, scl_low_ns: 5200ns, scl_hign_ns: 4576ns

I think this value is more reasonable.

ps:
min_low_ns/min_high_ns   (min_low_ns + extra) / (min_high_ns + extra) (if 
min_low_ns  min_high_ns)

 +   }
 +}
 +
 +static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long 
 scl_rate,
 +  unsigned long *div_low, unsigned long 
 *div_high)
 +{
 +   unsigned long min_low_ns, min_high_ns, min_total_ns;
 +   unsigned long min_low_div, min_high_div;
 +   unsigned long min_total_div, min_div_for_hold;
 +   unsigned long extra_div, extra_low_div, ideal_low_div;
 +   unsigned long i2c_rate_khz, scl_rate_khz;
 +
 +   rk3x_i2c_get_min_ns(scl_rate, min_low_ns, min_high_ns);
 +   min_total_ns = min_low_ns + min_high_ns;
 +
 +   /* To avoid from overflow warning */
 +   i2c_rate_khz = i2c_rate / 1000;
 +   scl_rate_khz = scl_rate / 1000;
 
 DIV_ROUND_UP?
 
 +
 +   /*We need the total div to be = this number
 +* so we don't clock too fast.
 +*/
 
 Please match the commenting style in the rest of the file.  That's:
 
 /*
  * A
  * B
  * C
  */
 
 Not:
 
 /* A
  * B
  * C
  */
 
 +   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
 +
 +   /* These are the min dividers needed for hold times */
 +   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
 +   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
 +   min_div_for_hold = (min_low_div + min_high_div

[PATCH v2] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-27 Thread Addy Ke
From: Addy addy...@rock-chips.com

As show in I2C specification:
- Standard-mode: the minimum HIGH period of the scl clock is 4.0us
 the minimum LOW period of the scl clock is 4.7us
- Fast-mode: the minimum HIGH period of the scl clock is 0.6us
 the minimum LOW period of the scl clock is 1.3us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

After put this patch, we can find that min_low_ns is about
5.4us in Standard-mode and 1.6us in Fast-mode.

Thanks Doug for the suggestion about division formulas.

Signed-off-by: Addy addy...@rock-chips.com
---
Changes in v2:
- remove Fast-mode plus and HS-mode
- use new formulas suggested by Doug

 drivers/i2c/busses/i2c-rk3x.c | 104 +++---
 1 file changed, 97 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e637c32..81672a8 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -428,19 +428,109 @@ out:
return IRQ_HANDLED;
 }
 
+static void rk3x_i2c_get_min_ns(unsigned int scl_rate,
+   unsigned long *min_low_ns,
+   unsigned long *min_high_ns)
+{
+   WARN_ON(scl_rate  40);
+
+   /* As show in I2C specification:
+* - Standard-mode(100KHz):
+*   min_low_ns is 4700ns
+*   min_high_ns is 4000ns
+* - Fast-mode(400KHz):
+*   min_low_ns is 1300ns
+*   min_high_ns is 600ns
+*
+* (min_low_ns + min_high_ns) up to 1ns in Standard-mode
+* and 2500ns in Fast-mode
+*/
+   if (scl_rate = 10) {
+   *min_low_ns = 4700 + 650;
+   *min_high_ns = 4000 + 650;
+   } else {
+   *min_low_ns = 1300 + 300;
+   *min_high_ns = 600 + 300;
+   }
+}
+
+static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *div_low, unsigned long *div_high)
+{
+   unsigned long min_low_ns, min_high_ns, min_total_ns;
+   unsigned long min_low_div, min_high_div;
+   unsigned long min_total_div, min_div_for_hold;
+   unsigned long extra_div, extra_low_div, ideal_low_div;
+   unsigned long i2c_rate_khz, scl_rate_khz;
+
+   rk3x_i2c_get_min_ns(scl_rate, min_low_ns, min_high_ns);
+   min_total_ns = min_low_ns + min_high_ns;
+
+   /* To avoid from overflow warning */
+   i2c_rate_khz = i2c_rate / 1000;
+   scl_rate_khz = scl_rate / 1000;
+
+   /*We need the total div to be = this number
+* so we don't clock too fast.
+*/
+   min_total_div = DIV_ROUND_UP(i2c_rate_khz, scl_rate_khz * 8);
+
+   /* These are the min dividers needed for hold times */
+   min_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns, 8 * 100);
+   min_high_div = DIV_ROUND_UP(i2c_rate_khz * min_high_ns, 8 * 100);
+   min_div_for_hold = (min_low_div + min_high_div);
+
+   if (min_div_for_hold  min_total_div) {
+   /* Time needed to meet hold requirements is important.
+* Just use that
+* */
+   *div_low = min_low_div;
+   *div_high = min_high_div;
+   } else {
+   /* We've got to distribute some time among the low and high
+* so we don't run too fast.
+*/
+   extra_div = min_total_div - min_div_for_hold;
+   /* We'll try to split things up perfectly evenly,
+* biasing slightly towards having a higher div
+* for low (spend more time low).
+*/
+   ideal_low_div = DIV_ROUND_UP(i2c_rate_khz * min_low_ns,
+scl_rate_khz * 8 * min_total_ns);
+   /* Handle when the ideal low div is going to take up
+* more than we have.
+*/
+   if (ideal_low_div  min_low_div + extra_div)
+   ideal_low_div = min_low_div + extra_div;
+   /* Give low the ideal and give high whatever extra is left.*/
+   extra_low_div = ideal_low_div - min_low_div;
+   *div_low = ideal_low_div;
+   *div_high
+   = min_high_div + (extra_div - extra_low_div);
+   }
+
+   /* Adjust to the fact that the hardware has an implicit +1.*/
+   *div_low = *div_low - 1;
+   *div_high = *div_high - 1;
+}
+
 static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
 {
unsigned long i2c_rate = clk_get_rate(i2c-clk);
-   unsigned int div;
+   unsigned long div_low, div_high;
 
-   /* SCL rate = (clk rate) / (8 * DIV) */
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
+   

Re: [PATCH] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-25 Thread addy ke


On 2014/9/26 10:08, Doug Anderson wrote:
 Addy,
 
 On Thu, Sep 25, 2014 at 6:40 PM, addy ke addy...@rock-chips.com wrote:
 Hi, Doug

 On 2014/9/26 5:52, Doug Anderson wrote:
 Addy,

 On Wed, Sep 24, 2014 at 9:36 PM, Doug Anderson diand...@chromium.org 
 wrote:
 Addy,

 On Wed, Sep 24, 2014 at 6:56 PM, addy ke addy...@rock-chips.com wrote:
 In my measurement,all paramter but Data hold time are match the 
 characteristics of SCL bus line.
 the measured value is 0.928us(data hold time on RK3X  ~=  the low 
 period / 2)
 but the maximum value described in table is 0.9us

 About Data hold time, there are described in I2C specification:
 - for CBUS compatible masters for I2C-bus deivices
 - the maximum data hold time has only be met if the device does not 
 stretch the LOW period of the SCL signal.

 I have tested on RK3288-Pinky board, there are no error.
 But I don't known whether this paramter will affect i2c communications.

 I'll have to spend more time tomorrow to really understand this, but
 if changing the code to bias towards slightly longer high times
 instead of low times helps fix it then that's fine with me.

 So what you're saying is that you're seeing a case where the clock
 goes low and the data is not valid until .928us.  Is this data that is
 being driven by the master or data that is being driven by the slave?

 It is driven by the master and will be release at half of LOW period in our 
 IC design.
 
 Ah, I didn't know this.  Is that in the TRM somewhere?
 
No, it was my test and confirmed by IC engineer.
You can find that there is a pulse at half of LOW period of the ninth SCL clock 
each bytes.

 ...so does it work to just replace:
 
 ideal_low_div = DIV_ROUND_UP(clk_rate * min_low_ns,
  scl_rate * 8 * min_total_ns)
 
 ...with:
 
 ideal_low_div = min_low_div
 
 
 That will assign all extra time to the high part.
 
I Think it is more reasonable.
 -Doug
 
 
 

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-24 Thread addy ke


On 2014/9/24 12:10, Doug Anderson wrote:
 Addy,
 
 On Tue, Sep 23, 2014 at 6:55 PM, Addy Ke addy...@rock-chips.com wrote:
 As show in I2C specification:
 - Standard-mode:
   the minimum HIGH period of the scl clock is 4.0us
   the minimum LOW period of the scl clock is 4.7us
 - Fast-mode:
   the minimum HIGH period of the scl clock is 0.6us
   the minimum LOW period of the scl clock is 1.3us
 - Fast-mode plus:
   the minimum HIGH period of the scl clock is 0.26us
   the minimum LOW period of the scl clock is 0.5us
 - HS-mode(1.7MHz):
   the minimum HIGH period of the scl clock is 0.12us
   the minimum LOW period of the scl clock is 0.32us
 - HS-mode(3.4MHz):
   the minimum HIGH period of the scl clock is 0.06us
   the minimum LOW period of the scl clock is 0.16us

 I have measured i2c SCL waveforms in fast-mode by oscilloscope
 on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
 It is so critical that we must adjust LOW division to increase
 the LOW period of the scl clock.

 Thanks Doug for the suggestion about division formula.

 Signed-off-by: Addy Ke addy...@rock-chips.com
 ---
  drivers/i2c/busses/i2c-rk3x.c | 79 
 +++
  1 file changed, 72 insertions(+), 7 deletions(-)

 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
 index 93cfc83..49d67b7 100644
 --- a/drivers/i2c/busses/i2c-rk3x.c
 +++ b/drivers/i2c/busses/i2c-rk3x.c
 @@ -428,18 +428,83 @@ out:
 return IRQ_HANDLED;
  }

 +static void rk3x_i2c_get_ratios(unsigned long scl_rate,
 +   unsigned long *high_ratio,
 +   unsigned long *low_ratio)
 +{
 +   /* As show in I2C specification:
 +* - Standard-mode:
 +*   the minimum HIGH period of the scl clock is 4.0us
 +*   the minimum LOW period of the scl clock is 4.7us
 +* - Fast-mode:
 +*   the minimum HIGH period of the scl clock is 0.6us
 +*   the minimum LOW period of the scl clock is 1.3us
 +* - Fast-mode plus:
 +*   the minimum HIGH period of the scl clock is 0.26us
 +*   the minimum LOW period of the scl clock is 0.5us
 +* - HS-mode(1.7MHz):
 +*   the minimum HIGH period of the scl clock is 0.12us
 +*   the minimum LOW period of the scl clock is 0.32us
 +* - HS-mode(3.4MHz):
 +*   the minimum HIGH period of the scl clock is 0.06us
 +*   the minimum LOW period of the scl clock is 0.16us
 
 Is the rest of the driver ready for Fast-mode plus or HS mode?  If not
 then maybe leave those off?  If nothing else the commit message should
 indicate that this is just being forward thinking.
 
 +*/
 +   if (scl_rate = 10) {
 +   *high_ratio = 40;
 +   *low_ratio = 47;
 +   } else if (scl_rate = 40) {
 +   *high_ratio = 6;
 +   *low_ratio = 13;
 +   } else if (scl_rate = 100) {
 +   *high_ratio = 26;
 +   *low_ratio = 50;
 +   } else if (scl_rate = 170) {
 +   *high_ratio = 12;
 +   *low_ratio = 32;
 +   } else {
 +   *high_ratio = 6;
 +   *low_ratio = 16;
 
 Since it's only the ratio of high to low that matters, you can combine
 the last two.  12 : 32 == 6 : 16
 
 +   }
 +}
 +
 +static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long 
 scl_rate,
 +  unsigned long *divh, unsigned long *divl)
 +{
 +   unsigned long high_ratio, low_ratio;
 +   unsigned long ratio_sum;
 +
 +   rk3x_i2c_get_ratios(scl_rate, high_ratio, low_ratio);
 +   ratio_sum = high_ratio + low_ratio;
 +
 +   /* T_high = T_clk * (divh + 1) * 8
 +* T_low = T_clk * (divl + 1) * 8
 +* T_scl = T_high + T_low
 +* T_scl = 1 / scl_rate
 +* T_clk = 1 / i2c_rate
 +* T_high : T_low = high_ratio : low_ratio
 +* ratio_sum = high_ratio + low_ratio
 +*
 +* so:
 +* divh = (i2c_rate * high_ratio) / (scl_rate * ratio_sum * 8) - 1
 +* divl = (i2c_rate * low_ratio) / (scl_rate * ratio_sum * 8) - 1
 +*/
 +   *divh = DIV_ROUND_UP(i2c_rate * high_ratio, scl_rate * ratio_sum * 
 8);
 +   if (*divh)
 +   *divh = *divh - 1;
 +
 +   *divl = DIV_ROUND_UP(i2c_rate * low_ratio, scl_rate * ratio_sum * 8);
 +   if (*divl)
 +   *divl = *divl - 1;
 
 When I sent you the sample formulas I purposely did it differently
 than this.  Any reason you changed from my formulas?
 
   div_low = DIV_ROUND_UP(clk_rate * low_ratio, scl_rate * 8 * ratio_sum)
   div_high = DIV_ROUND_UP(clk_rate, scl_rate * 8) - div_low
 
   div_low -= 1
   if div_high:
 div_high -= 1
 
 Why did I do it that way?
 
 * Assuming i2c_rate and the ratio is non-zero then you can assume that
 DIV_ROUND_UP gives a value that is = 1.  No need to test the result
 against 0.
 
 * (I think) you'll get

Re: [PATCH] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-24 Thread addy ke
Hi, Doug

On 2014/9/25 1:13, Doug Anderson wrote:
 Addy,
 
 On Wed, Sep 24, 2014 at 1:23 AM, addy ke addy...@rock-chips.com wrote:


 On 2014/9/24 12:10, Doug Anderson wrote:
 Addy,

 On Tue, Sep 23, 2014 at 6:55 PM, Addy Ke addy...@rock-chips.com wrote:
 As show in I2C specification:
 - Standard-mode:
   the minimum HIGH period of the scl clock is 4.0us
   the minimum LOW period of the scl clock is 4.7us
 - Fast-mode:
   the minimum HIGH period of the scl clock is 0.6us
   the minimum LOW period of the scl clock is 1.3us
 - Fast-mode plus:
   the minimum HIGH period of the scl clock is 0.26us
   the minimum LOW period of the scl clock is 0.5us
 - HS-mode(1.7MHz):
   the minimum HIGH period of the scl clock is 0.12us
   the minimum LOW period of the scl clock is 0.32us
 - HS-mode(3.4MHz):
   the minimum HIGH period of the scl clock is 0.06us
   the minimum LOW period of the scl clock is 0.16us

 I have measured i2c SCL waveforms in fast-mode by oscilloscope
 on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
 It is so critical that we must adjust LOW division to increase
 the LOW period of the scl clock.

 Thanks Doug for the suggestion about division formula.

 Signed-off-by: Addy Ke addy...@rock-chips.com
 ---
  drivers/i2c/busses/i2c-rk3x.c | 79 
 +++
  1 file changed, 72 insertions(+), 7 deletions(-)

 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
 index 93cfc83..49d67b7 100644
 --- a/drivers/i2c/busses/i2c-rk3x.c
 +++ b/drivers/i2c/busses/i2c-rk3x.c
 @@ -428,18 +428,83 @@ out:
 return IRQ_HANDLED;
  }

 +static void rk3x_i2c_get_ratios(unsigned long scl_rate,
 +   unsigned long *high_ratio,
 +   unsigned long *low_ratio)
 +{
 +   /* As show in I2C specification:
 +* - Standard-mode:
 +*   the minimum HIGH period of the scl clock is 4.0us
 +*   the minimum LOW period of the scl clock is 4.7us
 +* - Fast-mode:
 +*   the minimum HIGH period of the scl clock is 0.6us
 +*   the minimum LOW period of the scl clock is 1.3us
 +* - Fast-mode plus:
 +*   the minimum HIGH period of the scl clock is 0.26us
 +*   the minimum LOW period of the scl clock is 0.5us
 +* - HS-mode(1.7MHz):
 +*   the minimum HIGH period of the scl clock is 0.12us
 +*   the minimum LOW period of the scl clock is 0.32us
 +* - HS-mode(3.4MHz):
 +*   the minimum HIGH period of the scl clock is 0.06us
 +*   the minimum LOW period of the scl clock is 0.16us

 Is the rest of the driver ready for Fast-mode plus or HS mode?  If not
 then maybe leave those off?  If nothing else the commit message should
 indicate that this is just being forward thinking.

 +*/
 +   if (scl_rate = 10) {
 +   *high_ratio = 40;
 +   *low_ratio = 47;
 +   } else if (scl_rate = 40) {
 +   *high_ratio = 6;
 +   *low_ratio = 13;
 +   } else if (scl_rate = 100) {
 +   *high_ratio = 26;
 +   *low_ratio = 50;
 +   } else if (scl_rate = 170) {
 +   *high_ratio = 12;
 +   *low_ratio = 32;
 +   } else {
 +   *high_ratio = 6;
 +   *low_ratio = 16;

 Since it's only the ratio of high to low that matters, you can combine
 the last two.  12 : 32 == 6 : 16

 +   }
 +}
 +
 +static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long 
 scl_rate,
 +  unsigned long *divh, unsigned long *divl)
 +{
 +   unsigned long high_ratio, low_ratio;
 +   unsigned long ratio_sum;
 +
 +   rk3x_i2c_get_ratios(scl_rate, high_ratio, low_ratio);
 +   ratio_sum = high_ratio + low_ratio;
 +
 +   /* T_high = T_clk * (divh + 1) * 8
 +* T_low = T_clk * (divl + 1) * 8
 +* T_scl = T_high + T_low
 +* T_scl = 1 / scl_rate
 +* T_clk = 1 / i2c_rate
 +* T_high : T_low = high_ratio : low_ratio
 +* ratio_sum = high_ratio + low_ratio
 +*
 +* so:
 +* divh = (i2c_rate * high_ratio) / (scl_rate * ratio_sum * 8) - 1
 +* divl = (i2c_rate * low_ratio) / (scl_rate * ratio_sum * 8) - 1
 +*/
 +   *divh = DIV_ROUND_UP(i2c_rate * high_ratio, scl_rate * ratio_sum * 
 8);
 +   if (*divh)
 +   *divh = *divh - 1;
 +
 +   *divl = DIV_ROUND_UP(i2c_rate * low_ratio, scl_rate * ratio_sum * 
 8);
 +   if (*divl)
 +   *divl = *divl - 1;

 When I sent you the sample formulas I purposely did it differently
 than this.  Any reason you changed from my formulas?

   div_low = DIV_ROUND_UP(clk_rate * low_ratio, scl_rate * 8 * ratio_sum)
   div_high = DIV_ROUND_UP(clk_rate, scl_rate * 8) - div_low

   div_low -= 1
   if div_high:
 div_high -= 1

 Why did I do it that way?

 * Assuming i2c_rate and the ratio is non-zero then you

[PATCH] i2c: rk3x: adjust the LOW divison based on characteristics of SCL

2014-09-23 Thread Addy Ke
As show in I2C specification:
- Standard-mode:
  the minimum HIGH period of the scl clock is 4.0us
  the minimum LOW period of the scl clock is 4.7us
- Fast-mode:
  the minimum HIGH period of the scl clock is 0.6us
  the minimum LOW period of the scl clock is 1.3us
- Fast-mode plus:
  the minimum HIGH period of the scl clock is 0.26us
  the minimum LOW period of the scl clock is 0.5us
- HS-mode(1.7MHz):
  the minimum HIGH period of the scl clock is 0.12us
  the minimum LOW period of the scl clock is 0.32us
- HS-mode(3.4MHz):
  the minimum HIGH period of the scl clock is 0.06us
  the minimum LOW period of the scl clock is 0.16us

I have measured i2c SCL waveforms in fast-mode by oscilloscope
on rk3288-pinky board. the LOW period of the scl clock is 1.3us.
It is so critical that we must adjust LOW division to increase
the LOW period of the scl clock.

Thanks Doug for the suggestion about division formula.

Signed-off-by: Addy Ke addy...@rock-chips.com
---
 drivers/i2c/busses/i2c-rk3x.c | 79 +++
 1 file changed, 72 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 93cfc83..49d67b7 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -428,18 +428,83 @@ out:
return IRQ_HANDLED;
 }
 
+static void rk3x_i2c_get_ratios(unsigned long scl_rate,
+   unsigned long *high_ratio,
+   unsigned long *low_ratio)
+{
+   /* As show in I2C specification:
+* - Standard-mode:
+*   the minimum HIGH period of the scl clock is 4.0us
+*   the minimum LOW period of the scl clock is 4.7us
+* - Fast-mode:
+*   the minimum HIGH period of the scl clock is 0.6us
+*   the minimum LOW period of the scl clock is 1.3us
+* - Fast-mode plus:
+*   the minimum HIGH period of the scl clock is 0.26us
+*   the minimum LOW period of the scl clock is 0.5us
+* - HS-mode(1.7MHz):
+*   the minimum HIGH period of the scl clock is 0.12us
+*   the minimum LOW period of the scl clock is 0.32us
+* - HS-mode(3.4MHz):
+*   the minimum HIGH period of the scl clock is 0.06us
+*   the minimum LOW period of the scl clock is 0.16us
+*/
+   if (scl_rate = 10) {
+   *high_ratio = 40;
+   *low_ratio = 47;
+   } else if (scl_rate = 40) {
+   *high_ratio = 6;
+   *low_ratio = 13;
+   } else if (scl_rate = 100) {
+   *high_ratio = 26;
+   *low_ratio = 50;
+   } else if (scl_rate = 170) {
+   *high_ratio = 12;
+   *low_ratio = 32;
+   } else {
+   *high_ratio = 6;
+   *low_ratio = 16;
+   }
+}
+
+static void rk3x_i2c_calc_divs(unsigned long i2c_rate, unsigned long scl_rate,
+  unsigned long *divh, unsigned long *divl)
+{
+   unsigned long high_ratio, low_ratio;
+   unsigned long ratio_sum;
+
+   rk3x_i2c_get_ratios(scl_rate, high_ratio, low_ratio);
+   ratio_sum = high_ratio + low_ratio;
+
+   /* T_high = T_clk * (divh + 1) * 8
+* T_low = T_clk * (divl + 1) * 8
+* T_scl = T_high + T_low
+* T_scl = 1 / scl_rate
+* T_clk = 1 / i2c_rate
+* T_high : T_low = high_ratio : low_ratio
+* ratio_sum = high_ratio + low_ratio
+*
+* so:
+* divh = (i2c_rate * high_ratio) / (scl_rate * ratio_sum * 8) - 1
+* divl = (i2c_rate * low_ratio) / (scl_rate * ratio_sum * 8) - 1
+*/
+   *divh = DIV_ROUND_UP(i2c_rate * high_ratio, scl_rate * ratio_sum * 8);
+   if (*divh)
+   *divh = *divh - 1;
+
+   *divl = DIV_ROUND_UP(i2c_rate * low_ratio, scl_rate * ratio_sum * 8);
+   if (*divl)
+   *divl = *divl - 1;
+}
+
 static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
 {
unsigned long i2c_rate = clk_get_rate(i2c-clk);
-   unsigned int div;
+   unsigned long divh, divl;
 
-   /* set DIV = DIVH = DIVL
-* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
-*  = (clk rate) / (16 * (DIV + 1))
-*/
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
+   rk3x_i2c_calc_divs(i2c_rate, scl_rate, divh, divl);
 
-   i2c_writel(i2c, (div  16) | (div  0x), REG_CLKDIV);
+   i2c_writel(i2c, (divh  16) | (divl  0x), REG_CLKDIV);
 }
 
 /**
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: About RK3288 i2c scl duty cycle

2014-09-17 Thread addy ke
Add public list

On 2014/9/17 23:17, Doug Anderson wrote:
 Addy,
 
 On Tue, Sep 16, 2014 at 6:30 PM, addy...@rock-chips.com
 addy...@rock-chips.com wrote:
 hi, all
 
 Any reason why you didn't add some public lists?  It seems like this
 is a perfect discussion for linux-i2c.
 
 
 According to i2c-bus specification(version2.1, page 32, Table5, FAST-MODE):
 The minimum LOW period of the scl clock is 1.3us, and the minimum HIGH
 period of the scl clock is 0.6us.
 T(min_low) : T(min_high)  ~= 2 : 1

 If DIVH = DIVL in fast mode(scl rate = 400Khz)
 1)Under ideal conditions, T(scl_low) = T(scl_high) = 1.25us
 2)Our measurement, T(scl_low) = 1.3us, T(scl_high) = 1.25us

 The low period of the scl clock is critical.

 Do we need set DIVL:DIVH = 1 : 2  to increase T(scl_low)?   // T(scl_low )
 : T(scl_High) = 2 : 1
 
 I can't say I've ever looked at that pat of the i2c spec before, but
 what you say seems reasonable to me.  ...well for 400kHz, at least.
 At 100kHz you shouldn't use the same 2:1 ratio.

Yes, in normal-mode(100K) we can be only used 1:1 ratio.
But in FAST-MODE maybe we must use 2:1 ratio.

In Table 5(Characteristics of the SDA and SCL bus lines for F/S-mode I2C-bus 
devices)

1)FAST-MODE(400K):
  The minimum LOW period of the scl clock1.3us
  the minimum HIGH period of the scl clock   0.6us
  T(min_low) : T(min_high)  ~= 2 : 1

  But I can't see any ratio about In FAST-mode(400k) and Normal-mode(100k).
2)Normal-MODE(100K):
  The minimum LOW period of the scl clock4.7us
  the minimum HIGH period of the scl clock   4.0us
  T(min_low) : T(min_high)  ~= 1 : 1

3) HS-mode(3.4M)
  ratio of 1 to 2 is required, decribed as follows:
  Hs-mode master devices generate a serial clock signal with a HIGH to LOW 
ratio of 1 to 2
 
 I'm sure other drivers have solved this problem too, so maybe you can
 copy some code.  In i2c-designware-core.c you can see them doing all
 the calculations you need, I think.
 
 
 -Doug
 
 
 

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] i2c: rk3x: fix divisor calculation for SCL frequency

2014-09-07 Thread Addy Ke
I2C_CLKDIV register descripted in the previous version of
RK3x chip manual is incorrect. Plus 1 is required.

The correct formula:
- T(SCL_HIGH) = T(PCLK) * (CLKDIVH + 1) * 8
- T(SCL_LOW) = T(PCLK) * (CLKDIVL + 1) * 8
- (SCL Divsor) = 8 * ((CLKDIVL + 1) + (CLKDIVH + 1))
- SCL = PCLK / (CLK Divsor)

It will be updated to the latest version of chip manual.

Signed-off-by: Addy Ke addy...@rock-chips.com
---
changes since v1:
- make it more cleaner, suggested by Doug Anderson

 drivers/i2c/busses/i2c-rk3x.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e637c32..93cfc83 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -433,12 +433,11 @@ static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, 
unsigned long scl_rate)
unsigned long i2c_rate = clk_get_rate(i2c-clk);
unsigned int div;
 
-   /* SCL rate = (clk rate) / (8 * DIV) */
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
-
-   /* The lower and upper half of the CLKDIV reg describe the length of
-* SCL low  high periods. */
-   div = DIV_ROUND_UP(div, 2);
+   /* set DIV = DIVH = DIVL
+* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
+*  = (clk rate) / (16 * (DIV + 1))
+*/
+   div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;
 
i2c_writel(i2c, (div  16) | (div  0x), REG_CLKDIV);
 }
-- 
1.8.3.2

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] i2c: rk3x: fix divisor calculation for SCL frequency

2014-09-05 Thread addy ke
 Addy,
 
 On Thu, Sep 4, 2014 at 7:32 PM, Addy Ke addy...@rock-chips.com wrote:
 I2C_CLKDIV register descripted in the previous version of
 RK3x chip manual is incorrect. Plus 1 is required.

 The correct formula:
 - T(SCL_HIGH) = T(PCLK) * (CLKDIVH + 1) * 8
 - T(SCL_LOW) = T(PCLK) * (CLKDIVL + 1) * 8
 - (SCL Divsor) = 8 * ((CLKDIVL + 1) + (CLKDIVH + 1))
 - SCL = PCLK / (CLK Divsor)
 
 I'll trust that you tested this with a scope
 
Yes ,I have tested on RK3188 and RK3288, and confirmed by oscilloscope.
 
 It will be updated to the latest version of chip manual.

 Signed-off-by: Addy Ke addy...@rock-chips.com
 ---
  drivers/i2c/busses/i2c-rk3x.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
 index e637c32..76b6604 100644
 --- a/drivers/i2c/busses/i2c-rk3x.c
 +++ b/drivers/i2c/busses/i2c-rk3x.c
 @@ -433,8 +433,8 @@ static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, 
 unsigned long scl_rate)
 unsigned long i2c_rate = clk_get_rate(i2c-clk);
 unsigned int div;

 -   /* SCL rate = (clk rate) / (8 * DIV) */
 -   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
 +   /* SCL rate = (clk rate) / (8 * (DIV + 2)) */
 +   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8) - 2;
 
 Given the bug I just fixed in the Rockchip SPI driver, I was a little
 worried about div becoming -1 (and thus being a really large positive
 number since div is unsigned).
 
 However, it seems that you get saved by the next statement:
   div = DIV_ROUND_UP(div, 2);
 
 In the testing I did with the Linux macros, that magically transformed
 a div of 0x (-1) to 0, so it's not technically a bug.  ...but
 it's very non-obvious.  Can you do something a little cleaner?

The following modifications is reasonable?

static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
{
unsigned long i2c_rate = clk_get_rate(i2c-clk);
unsigned int div;

/* set DIV = DIVH = DIVL
 * SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
 *  = (clk rate) / (16 * (DIV + 1))
 */
div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;

i2c_writel(i2c, (div  16) | (div  0x), REG_CLKDIV);
}
 
 -Doug
 
 
 

--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c: rk3x: fix divisor calculation for SCL frequency

2014-09-04 Thread Addy Ke
I2C_CLKDIV register descripted in the previous version of
RK3x chip manual is incorrect. Plus 1 is required.

The correct formula:
- T(SCL_HIGH) = T(PCLK) * (CLKDIVH + 1) * 8
- T(SCL_LOW) = T(PCLK) * (CLKDIVL + 1) * 8
- (SCL Divsor) = 8 * ((CLKDIVL + 1) + (CLKDIVH + 1))
- SCL = PCLK / (CLK Divsor)

It will be updated to the latest version of chip manual.

Signed-off-by: Addy Ke addy...@rock-chips.com
---
 drivers/i2c/busses/i2c-rk3x.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e637c32..76b6604 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -433,8 +433,8 @@ static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, 
unsigned long scl_rate)
unsigned long i2c_rate = clk_get_rate(i2c-clk);
unsigned int div;
 
-   /* SCL rate = (clk rate) / (8 * DIV) */
-   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);
+   /* SCL rate = (clk rate) / (8 * (DIV + 2)) */
+   div = DIV_ROUND_UP(i2c_rate, scl_rate * 8) - 2;
 
/* The lower and upper half of the CLKDIV reg describe the length of
 * SCL low  high periods. */
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4] i2c: rk3x: fix bug that cause transfer fails in master receive mode

2014-08-22 Thread Addy Ke
In rk3x SOC, the I2C controller can receive/transmit up to 32 bytes data
in one chunk, so the size of data to be write/read to/from TXDATAx/RXDATAx
must be less than or equal 32 bytes at a time.

Tested on rk3288-pinky board, elan receive 158 bytes data.

Suggested-by: Dmitry Torokhov dmitry.torok...@gmail.com
Signed-off-by: Addy Ke addy...@rock-chips.com
Acked-by: Max Schwarz max.schw...@online.de
---
Changes in v2:
- Use cleaner syntax as suggested by Sergei.
- Update commit message as suggested by Wolfram.

Changes in v3:
- fix typo: maste -- master and double spaces after 'len'
 drivers/i2c/busses/i2c-rk3x.c | 4 

Changes in v4:
- remove unlikely() annotations, suggested by Dmitry Torokhov

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index b8b2b89..31de730 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, 
unsigned int ipd)
/* ack interrupt */
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+   /* Can only handle a maximum of 32 bytes at a time */
+   if (len  32)
+   len = 32;
+
/* read the data from receive buffer */
for (i = 0; i  len; ++i) {
if (i % 4 == 0)
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4] i2c: rk3x: fix bug that cause transfer fails in master receive mode

2014-08-22 Thread addy ke
 Addy,
 
 On Fri, Aug 22, 2014 at 11:00 AM, Addy Ke addy...@rock-chips.com wrote:
 In rk3x SOC, the I2C controller can receive/transmit up to 32 bytes data
 in one chunk, so the size of data to be write/read to/from TXDATAx/RXDATAx
 must be less than or equal 32 bytes at a time.

 Tested on rk3288-pinky board, elan receive 158 bytes data.

 Suggested-by: Dmitry Torokhov dmitry.torok...@gmail.com
 
 You only need a Suggested-by if the entire patch was suggested by
 someone.  If someone provides you review feedback you don't need it.
 
 Said another way: in this case Dmitry didn't suggest that you need to
 fix the i2c controller to transmit 32 byte chunks (he only provided
 review feedback), so you shouldn't say this was Suggested-by him.
 
 You also had my reviewed-by on a previous version so you could keep it.
 
 Reviewed-by: Doug Anderson diand...@chromium.org

so, Do I need repost this patch or post a new one as patch v5?
 
 
 
--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c: rk3x: fix bug that cause transfer fails in master receive mode

2014-08-21 Thread Addy Ke
In rk3x SOC, the I2C controller can receive/transmit up to 32 bytes data
in one transaction, so the size of data to be write/read to/from
TXDATAx/RXDATAx must be less than or equal 32 bytes at a time.

Test on pinky board, elan receive 158 bytes data.

Signed-off-by: Addy Ke addy...@rock-chips.com
---
 drivers/i2c/busses/i2c-rk3x.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 69e1185..dc0aa64 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -323,6 +323,9 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, 
unsigned int ipd)
/* ack interrupt */
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+   /* Can only handle a maximum of 32 bytes at a time */
+   len = (len  32) ? 32 : len;
+
/* read the data from receive buffer */
for (i = 0; i  len; ++i) {
if (i % 4 == 0)
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] i2c: rk3x: fix bug that cause transfer fails in maste receive mode

2014-08-21 Thread Addy Ke
In rk3x SOC, the I2C controller can receive/transmit up to 32 bytes data
in one chunk, so the size of data to be write/read to/from TXDATAx/RXDATAx
must be less than or equal 32 bytes at a time.

Tested on rk3288-pinky board, elan receive 158 bytes data.

Acked-by: Max Schwarz max.schw...@online.de
Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- Use cleaner syntax as suggested by Sergei.
- Update commit message as suggested by Wolfram.

 drivers/i2c/busses/i2c-rk3x.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 69e1185..806724a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, 
unsigned int ipd)
/* ack interrupt */
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+   /* Can only handle a maximum of 32 bytes at a time */
+   if (unlikely(len  32))
+   len  = 32;
+
/* read the data from receive buffer */
for (i = 0; i  len; ++i) {
if (i % 4 == 0)
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] i2c: rk3x: fix bug that cause transfer fails in master receive mode

2014-08-21 Thread Addy Ke
In rk3x SOC, the I2C controller can receive/transmit up to 32 bytes data
in one chunk, so the size of data to be write/read to/from TXDATAx/RXDATAx
must be less than or equal 32 bytes at a time.

Tested on rk3288-pinky board, elan receive 158 bytes data.

Acked-by: Max Schwarz max.schw...@online.de
Signed-off-by: Addy Ke addy...@rock-chips.com
---
Changes in v2:
- Use cleaner syntax as suggested by Sergei.
- Update commit message as suggested by Wolfram.

Changes in v3:
- fix typo: maste -- master and double spaces after 'len'

 drivers/i2c/busses/i2c-rk3x.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 69e1185..806724a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, 
unsigned int ipd)
/* ack interrupt */
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+   /* Can only handle a maximum of 32 bytes at a time */
+   if (unlikely(len  32))
+   len = 32;
+
/* read the data from receive buffer */
for (i = 0; i  len; ++i) {
if (i % 4 == 0)
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] i2c: rk3x: fix interrupt handling issue

2014-08-08 Thread Addy Ke
If slave holds scl, I2C_IPD[7] will be set 1 by controller
for debugging. Driver must ignore it.

[5.752391] rk3x-i2c ff16.i2c: unexpected irq in WRITE: 0x80
[5.939027] rk3x-i2c ff16.i2c: timeout, ipd: 0x80, state: 4

Signed-off-by: Addy Ke addy...@rock-chips.com
---
 drivers/i2c/busses/i2c-rk3x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9e3084c..eab49e6 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -399,7 +399,7 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
}
 
/* is there anything left to handle? */
-   if (unlikely(ipd == 0))
+   if (unlikely((ipd  REG_INT_ALL) == 0))
goto out;
 
switch (i2c-state) {
-- 
1.8.3.2


--
To unsubscribe from this list: send the line unsubscribe linux-i2c in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html