i2c: exynos5: Change HSI2C timing parameter setting routine
authorYoungmin Nam <youngmin.nam@samsung.com>
Sat, 4 Jul 2015 07:33:38 +0000 (16:33 +0900)
committermyung-su.cha <myung-su.cha@samsung.com>
Wed, 9 May 2018 12:14:45 +0000 (21:14 +0900)
This patch modifies HSI2C timing parameter setting routine following
H/W guide.

Change-Id: I10aa37c76dab1237a99ded8a7e8258c98f8a0c58
Signed-off-by: Youngmin Nam <youngmin.nam@samsung.com>
drivers/i2c/busses/i2c-exynos5.c

index 1f22174d47f839cb505581b529446c5887b1cfaf..35ebbecc6a8d3193cd75764ad100758a9f1ccd74 100644 (file)
@@ -404,6 +404,7 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
        u32 i2c_timing_sla;
        unsigned int t_start_su, t_start_hd;
        unsigned int t_stop_su;
+       unsigned int t_sda_su;
        unsigned int t_data_su, t_data_hd;
        unsigned int t_scl_l, t_scl_h;
        unsigned int t_sr_release;
@@ -414,15 +415,21 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
                                i2c->hs_clock : i2c->fs_clock;
 
        /*
-        * FPCLK / FI2C =
-        * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + {(FLT_CYCLE + 3) %
-        * (CLK_DIV + 1)} * 2
+        * FPCLK / FI2C = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) +
+        * {(FLT_CYCLE + 3) - (FLT_CYCLE + 3) % (CLK_DIV + 1)} * 2
         */
        t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
+
+       /*
+        * utemp0 = (FPCLK / FI2C) - (FLT_CYCLE + 3) * 2
+        */
        utemp0 = (clkin / op_clk) - (t_ftl_cycle + 3) * 2;
 
        /* CLK_DIV max is 256 */
        for (div = 0; div < 256; div++) {
+               /*
+                * utemp1 = (TSCLK_L + TSCLK_H + 2)
+                */
                utemp1 = (utemp0 + ((t_ftl_cycle + 3) % (div + 1)) * 2) / (div + 1);
 
                if ((utemp1 < 512) && (utemp1 > 4)) {
@@ -433,19 +440,29 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
                        return -EINVAL;
                }
        }
-       t_scl_l = clk_cycle / 2;
-       t_scl_h = clk_cycle / 2;
+
+       if (mode == HSI2C_HIGH_SPD)
+               t_scl_h = ((clk_cycle + 10) / 3) - 5;
+       else
+               t_scl_h = clk_cycle / 2;
+
+       t_scl_l = clk_cycle - t_scl_h;
        t_start_su = t_scl_l;
        t_start_hd = t_scl_l;
        t_stop_su = t_scl_l;
+       t_sda_su = t_scl_l;
        t_data_su = t_scl_l / 2;
        t_data_hd = t_scl_l / 2;
        t_sr_release = clk_cycle;
 
-       i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8;
-       i2c_timing_s2 = t_data_su << 24 | t_scl_l << 8 | t_scl_h << 0;
-       i2c_timing_s3 = div << 16 | t_sr_release << 0;
-       i2c_timing_sla = t_data_hd << 0;
+       if (mode == HSI2C_HIGH_SPD)
+               i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8 | t_sda_su;
+       else
+               i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8;
+
+       i2c_timing_s2 = (0xF << 16) | t_data_su << 24 | t_scl_l << 8 | t_scl_h;
+       i2c_timing_s3 = (div << 16) | t_sr_release;
+       i2c_timing_sla = t_data_hd;
 
        dev_dbg(i2c->dev, "tSTART_SU: %X, tSTART_HD: %X, tSTOP_SU: %X\n",
                t_start_su, t_start_hd, t_stop_su);