[COMMON] i2c: exynos5: Add Standard mode for HSI2C
authorKyungwoo Kang <kwoo.kang@samsung.com>
Wed, 28 Mar 2018 01:03:14 +0000 (10:03 +0900)
committermyung-su.cha <myung-su.cha@samsung.com>
Wed, 9 May 2018 12:14:45 +0000 (21:14 +0900)
Now we support standard mode for HSI2C like below.
[Standard - Fast - Fast plus - High Speed]

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

index 3706a268d39a33428751117cb85312bf3e304375..54c91aadc8dddaa2a804bb072c761fd34bca77e6 100644 (file)
@@ -193,6 +193,9 @@ static LIST_HEAD(drvdata_list);
 #define HSI2C_HS_TX_CLOCK                      2500000
 #define HSI2C_FAST_PLUS_TX_CLOCK       1000000
 #define HSI2C_FS_TX_CLOCK                      400000
+#define HSI2C_STAND_TX_CLOCK           100000
+
+#define HSI2C_STAND_SPD                        3
 #define HSI2C_FAST_PLUS_SPD            2
 #define HSI2C_HIGH_SPD                 1
 #define HSI2C_FAST_SPD                 0
@@ -389,8 +392,8 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
 
        ipclk = (unsigned int)clk_get_rate(i2c->rate_clk);
 
-       if (mode == HSI2C_FAST_PLUS_SPD) {
-               op_clk = i2c->fs_plus_clock;
+       if (mode == HSI2C_STAND_SPD) {
+               op_clk = i2c->stand_clock;
 
                fs_div = ipclk / (op_clk * 16);
                fs_div &= 0xFF;
@@ -407,6 +410,28 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
                utemp = readl(i2c->regs + HSI2C_TIMING_FS1) & ~0x00FF0000;
                writel(utemp | (uTSTART_HD_FS << 16), i2c->regs + HSI2C_TIMING_FS1);
 
+               dev_info(i2c->dev, "%s IPCLK = %d OP_CLK = %d DIV = %d Timing FS1(STAND) = 0x%X "
+                               "TIMING FS2(STAND) = 0x%X TIMING FS3(STAND) = 0x%X\n",__func__, ipclk, op_clk, fs_div,
+                               readl(i2c->regs + HSI2C_TIMING_FS1), readl(i2c->regs + HSI2C_TIMING_FS2),
+                               readl(i2c->regs + HSI2C_TIMING_FS3));
+       } else if (mode == HSI2C_FAST_PLUS_SPD) {
+               op_clk = i2c->fs_plus_clock;
+
+               fs_div = ipclk / (op_clk * 15);
+               fs_div &= 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_FS3) & ~0x00FF0000;
+               writel(utemp | (fs_div << 16), i2c->regs + HSI2C_TIMING_FS3);
+
+               uTSCL_H_FS = (4 * (ipclk / (1000 * 1000))) / ((fs_div + 1) * 10);
+               uTSCL_H_FS = (0xFF << 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 = (4 * (ipclk / (1000 * 1000))) / ((fs_div + 1) * 10) - 1;
+               uTSTART_HD_FS = (0xFF << uTSTART_HD_FS) & 0xFF;
+               utemp = readl(i2c->regs + HSI2C_TIMING_FS1) & ~0x00FF0000;
+               writel(utemp | (uTSTART_HD_FS << 16), i2c->regs + HSI2C_TIMING_FS1);
+
                dev_info(i2c->dev, "%s IPCLK = %d OP_CLK = %d DIV = %d Timing FS1(FS+) = 0x%X "
                                "TIMING FS2(FS+) = 0x%X TIMING FS3(FS+) = 0x%X\n",__func__, ipclk, op_clk, fs_div,
                                readl(i2c->regs + HSI2C_TIMING_FS1), readl(i2c->regs + HSI2C_TIMING_FS2),
@@ -497,6 +522,14 @@ static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
                }
        }
 
+       /* Configure the standard mode timing values */
+       if (i2c->speed_mode == HSI2C_STAND_SPD) {
+               if (exynos5_i2c_set_timing(i2c, HSI2C_STAND_SPD)) {
+                       dev_err(i2c->dev, "HSI2C STAND Clock set up failed\n");
+                       return -EINVAL;
+               }
+       }
+
        return 0;
 }
 
@@ -1052,6 +1085,10 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
                i2c->speed_mode = HSI2C_HIGH_SPD;
                if (of_property_read_u32(np, "clock-frequency", &i2c->hs_clock))
                        i2c->hs_clock = HSI2C_HS_TX_CLOCK;
+       } else if (of_get_property(np, "samsung,stand-mode", NULL)) {
+               i2c->speed_mode = HSI2C_STAND_SPD;
+               if (of_property_read_u32(np, "clock-frequency", &i2c->stand_clock))
+                       i2c->stand_clock = HSI2C_STAND_TX_CLOCK;
        } else {
                i2c->speed_mode = HSI2C_FAST_SPD;
                if (of_property_read_u32(np, "clock-frequency", &i2c->fs_clock))
index 358610d9e5164029e10ece23c3911bd46de0ce9d..d890b91150eb3180a4691e92c0a5fd1156f27fec 100644 (file)
@@ -41,6 +41,7 @@ struct exynos5_i2c {
        unsigned int            fs_clock;
        unsigned int            hs_clock;
        unsigned int            fs_plus_clock;
+       unsigned int            stand_clock;
 
        /* to set the source clock */
        unsigned int            default_clk;