[ERD][NEUS7920-226] [COMMON] i2c: exynos: Support multi mode for HSI2C
authorKyungwoo Kang <kwoo.kang@samsung.com>
Mon, 22 Apr 2019 05:01:35 +0000 (14:01 +0900)
committerKim Gunho <gunho.kim@samsung.com>
Fri, 30 Aug 2019 07:58:56 +0000 (16:58 +0900)
Change-Id: I15809b11225fd0fc017505231c65d2feea53f755
Signed-off-by: Kyungwoo Kang <kwoo.kang@samsung.com>
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-exynos5.h

index 5dc5b23d055dde673d605a14dc303878637e2603..61a153fd017e4edfe40a6b0196dc11ceec377ab5 100644 (file)
@@ -195,10 +195,10 @@ static LIST_HEAD(drvdata_list);
 #define HSI2C_FS_TX_CLOCK                      400000
 #define HSI2C_STAND_TX_CLOCK           100000
 
-#define HSI2C_STAND_SPD                        3
+#define HSI2C_STAND_SPD                        0
+#define HSI2C_FAST_SPD                 1
 #define HSI2C_FAST_PLUS_SPD            2
-#define HSI2C_HIGH_SPD                 1
-#define HSI2C_FAST_SPD                 0
+#define HSI2C_HIGH_SPD                 3
 
 #define HSI2C_POLLING 0
 #define HSI2C_INTERRUPT 1
@@ -500,19 +500,21 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
 
 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;
+               }
+       }
+
        /*
         * Configure the Fast speed timing values
         * Even the High Speed mode initially starts with Fast mode
         */
-       if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) {
-               dev_err(i2c->dev, "HSI2C FS Clock set up failed\n");
-               return -EINVAL;
-       }
-
-       /* configure the High speed timing values */
-       if (i2c->speed_mode == HSI2C_HIGH_SPD) {
-               if (exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD)) {
-                       dev_err(i2c->dev, "HSI2C HS Clock set up failed\n");
+       if (i2c->speed_mode == HSI2C_FAST_SPD) {
+               if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) {
+                       dev_err(i2c->dev, "HSI2C FS Clock set up failed\n");
                        return -EINVAL;
                }
        }
@@ -525,14 +527,18 @@ 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");
+       /* configure the High speed timing values */
+       if (i2c->speed_mode == HSI2C_HIGH_SPD) {
+               if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) {
+                       dev_err(i2c->dev, "HSI2C FS Clock set up for HS mode failed\n");
                        return -EINVAL;
                }
-       }
 
+               if (exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD)) {
+                       dev_err(i2c->dev, "HSI2C HS Clock set up failed\n");
+                       return -EINVAL;
+               }
+       }
        return 0;
 }
 
@@ -968,6 +974,34 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
                exynos5_i2c_init(i2c);
        }
 
+       if (i2c->multi_slave_mode) {
+               dev_err(i2c->dev, "HSI2C mode has been changed\n");
+
+               if (!msgs_ptr->freq) {
+                       dev_err(i2c->dev, "No FREQ info Check the slave device driver\n");
+                       goto out;
+               }
+
+               if (msgs_ptr->freq <= HSI2C_STAND_TX_CLOCK) {
+                       i2c->speed_mode = HSI2C_STAND_SPD;
+                       i2c->stand_clock = msgs_ptr->freq;
+               }
+               else if (msgs_ptr->freq <= HSI2C_FS_TX_CLOCK) {
+                       i2c->speed_mode = HSI2C_FAST_SPD;
+                       i2c->fs_clock = msgs_ptr->freq;
+               }
+               else if (msgs_ptr->freq <= HSI2C_FAST_PLUS_TX_CLOCK) {
+                       i2c->speed_mode = HSI2C_FAST_PLUS_SPD;
+                       i2c->fs_plus_clock = msgs_ptr->freq;
+               }
+               else {
+                       i2c->speed_mode = HSI2C_HIGH_SPD;
+                       i2c->hs_clock = msgs_ptr->freq;
+               }
+
+               exynos5_hsi2c_clock_setup(i2c);
+       }
+
        for (retry = 0; retry < adap->retries; retry++) {
                for (i = 0; i < num; i++) {
                        stop = (i == num - 1);
@@ -1075,23 +1109,27 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
        if (of_property_read_u32(np, "default-clk", &i2c->default_clk))
                dev_err(i2c->dev, "Failed to get default clk info\n");
 
-       /* Mode of operation High/Fast/Fast+ Speed mode */
-       if (of_get_property(np, "samsung,fast-plus-mode", NULL)) {
-               i2c->speed_mode = HSI2C_FAST_PLUS_SPD;
-               if (of_property_read_u32(np, "clock-frequency", &i2c->fs_plus_clock))
-                       i2c->fs_plus_clock = HSI2C_FAST_PLUS_TX_CLOCK;
-       } else if (of_get_property(np, "samsung,hs-mode", NULL)) {
-               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;
+       if (of_get_property(np, "samsung,multi-slave-mode", NULL)) {
+               i2c->multi_slave_mode = 1;
        } else {
-               i2c->speed_mode = HSI2C_FAST_SPD;
-               if (of_property_read_u32(np, "clock-frequency", &i2c->fs_clock))
-                       i2c->fs_clock = HSI2C_FS_TX_CLOCK;
+               /* Mode of operation High/Fast/Fast+ Speed mode */
+               if (of_get_property(np, "samsung,fast-plus-mode", NULL)) {
+                       i2c->speed_mode = HSI2C_FAST_PLUS_SPD;
+                       if (of_property_read_u32(np, "clock-frequency", &i2c->fs_plus_clock))
+                               i2c->fs_plus_clock = HSI2C_FAST_PLUS_TX_CLOCK;
+               } else if (of_get_property(np, "samsung,hs-mode", NULL)) {
+                       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))
+                               i2c->fs_clock = HSI2C_FS_TX_CLOCK;
+               }
        }
 
        /* Mode of operation Polling/Interrupt mode */
index d890b91150eb3180a4691e92c0a5fd1156f27fec..691aac79f5f60f2cd9e14c2c74d3f0d58b0af0b0 100644 (file)
@@ -58,6 +58,8 @@ struct exynos5_i2c {
        int                     stop_after_trans;
        unsigned int            transfer_delay;
 
+       unsigned int    multi_slave_mode;
+
        int                     idle_ip_index;
        int                     reset_before_trans;
        unsigned int            runtime_resumed;