[COMMON] i2c: exynos5: I2C Timing cal code changes
authorKyungwoo Kang <kwoo.kang@samsung.com>
Thu, 4 May 2017 04:45:01 +0000 (13:45 +0900)
committermyung-su.cha <myung-su.cha@samsung.com>
Wed, 9 May 2018 12:14:45 +0000 (21:14 +0900)
USIv2 has benn changed timing parameter and IPCLk input.
This patch includes timing calculate code.

Change-Id: I4d3d06a867b56fc50fab73e5064547c0ab9b9a19
Signed-off-by: Kyungwoo Kang <kwoo.kang@samsung.com>
drivers/i2c/busses/i2c-exynos5.c

index c887a08fd6944d07ffdd769b615c3514431d18a2..a97cf79cb23c90c2c08fff2886526ec5b168dd29 100644 (file)
@@ -364,90 +364,63 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
  */
 static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
 {
-       u32 i2c_timing_s1;
-       u32 i2c_timing_s2;
-       u32 i2c_timing_s3;
-       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;
-       unsigned int t_ftl_cycle;
-       unsigned int clkin = clk_get_rate(i2c->rate_clk);
-       unsigned int div, utemp0 = 0, utemp1 = 0, clk_cycle = 0;
-       unsigned int op_clk = (mode == HSI2C_HIGH_SPD) ?
-                               i2c->hs_clock : i2c->fs_clock;
-
-       /*
-        * 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)) {
-                       clk_cycle = utemp1 - 2;
-                       break;
-               } else if (div == 255) {
-                       dev_warn(i2c->dev, "Failed to calculate divisor");
-                       return -EINVAL;
-               }
+       unsigned int nPclk = clk_get_rate(i2c->rate_clk);
+       unsigned int nOpClk = (mode == HSI2C_HIGH_SPD) ?
+               i2c->hs_clock : i2c->fs_clock;
+
+       u32 uCLK_DIV_HS, uTSCL_H_HS, uTSTART_HD_HS;
+       u32 uCLK_DIV_FS, uTSCL_H_FS, uTSTART_HD_FS;
+       u32 utemp;
+
+       if (mode == HSI2C_HIGH_SPD) {
+               /* nPclk's unit is Hz, nOpClk's unit is Hz */
+               uCLK_DIV_HS = nPclk / (nOpClk * 15);
+               uCLK_DIV_HS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_HS3) & ~0x00FF0000;
+               writel(utemp | (uCLK_DIV_HS << 16), i2c->regs + HSI2C_TIMING_HS3);
+
+               uTSCL_H_HS = ((7 * nPclk) / (1000 * 1000)) / ((uCLK_DIV_HS + 1) * 100);
+               /* make to 0 into TSCL_H_HS from LSB */
+               uTSCL_H_HS = (0xFFFFFFFF >> uTSCL_H_HS) << uTSCL_H_HS;
+               uTSCL_H_HS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_HS2) & ~0x000000FF;
+               writel(utemp | (uTSCL_H_HS << 0), i2c->regs + HSI2C_TIMING_HS2);
+
+               uTSTART_HD_HS = (7 * nPclk / (1000 * 1000)) / ((uCLK_DIV_HS + 1) * 100) - 1;
+               /* make to 0 into uTSTART_HD_HS from LSB */
+               uTSTART_HD_HS = (0xFFFFFFFF >> uTSTART_HD_HS) << uTSTART_HD_HS;
+               uTSTART_HD_HS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_HS1) & ~0x00FF0000;
+               writel(utemp | (uTSTART_HD_HS << 16), i2c->regs + HSI2C_TIMING_HS1);
+
+               pr_info("%s nPclk = %d nOpClk = %d Div = %d Timing HS1 = %X TIMING HS2 = %X TIMING HS3 = %X\n",__func__, nPclk, nOpClk, uCLK_DIV_HS,
+                               readl(i2c->regs + HSI2C_TIMING_HS1),  readl(i2c->regs + HSI2C_TIMING_HS2),readl(i2c->regs + HSI2C_TIMING_HS3));
        }
-
-       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;
-
-       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);
-       dev_dbg(i2c->dev, "tDATA_SU: %X, tSCL_L: %X, tSCL_H: %X\n",
-               t_data_su, t_scl_l, t_scl_h);
-       dev_dbg(i2c->dev, "nClkDiv: %X, tSR_RELEASE: %X\n",
-               div, t_sr_release);
-       dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd);
-
-       if (hs_timings) {
-               writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1);
-               writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2);
-               writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
-       } else {
-               writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_FS1);
-               writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_FS2);
-               writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3);
+       else {
+               /* Fast speed mode */
+               /* nPclk's unit is Hz, nOpClk's unit is Hz */
+               uCLK_DIV_FS = nPclk / (nOpClk * 15);
+               uCLK_DIV_FS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_FS3) & ~0x00FF0000;
+               writel(utemp | (uCLK_DIV_FS << 16), i2c->regs + HSI2C_TIMING_FS3);
+
+               uTSCL_H_FS = ((9 * nPclk) / (1000 * 1000)) / ((uCLK_DIV_FS + 1) * 10);
+               /* make to 0 into TSCL_H_FS from LSB */
+               uTSCL_H_FS = (0xFFFFFFFF >> uTSCL_H_FS) << uTSCL_H_FS;
+               uTSCL_H_FS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_FS2) & ~0x000000FF;
+               writel(utemp | (uTSCL_H_FS << 0), i2c->regs + HSI2C_TIMING_FS2);
+
+               uTSTART_HD_FS = (9 * nPclk / (1000 * 1000)) / ((uCLK_DIV_FS + 1) * 10) - 1;
+               /* make to 0 into uTSTART_HD_FS from LSB */
+               uTSTART_HD_FS = (0xFFFFFFFF >> uTSTART_HD_FS) << uTSTART_HD_FS;
+               uTSTART_HD_FS &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_FS1) & ~0x00FF0000;
+               writel(utemp | (uTSTART_HD_FS << 16), i2c->regs + HSI2C_TIMING_FS1);
+
+               pr_info("%s nPclk = %d nOpClk = %d Div = %d Timing FS1 = %X TIMING FS2 = %X TIMING FS3 = %X\n",__func__, nPclk, nOpClk, uCLK_DIV_FS,
+                               readl(i2c->regs + HSI2C_TIMING_FS1),  readl(i2c->regs + HSI2C_TIMING_FS2),readl(i2c->regs + HSI2C_TIMING_FS3));
        }
-       writel(i2c_timing_sla, i2c->regs + HSI2C_TIMING_SLA);
 
        return 0;
 }