From 4297397b77d096ad3bcab2cf3551d60a04275422 Mon Sep 17 00:00:00 2001 From: Kyungwoo Kang Date: Mon, 22 Apr 2019 14:01:35 +0900 Subject: [PATCH] [ERD][NEUS7920-226] [COMMON] i2c: exynos: Support multi mode for HSI2C Change-Id: I15809b11225fd0fc017505231c65d2feea53f755 Signed-off-by: Kyungwoo Kang --- drivers/i2c/busses/i2c-exynos5.c | 104 +++++++++++++++++++++---------- drivers/i2c/busses/i2c-exynos5.h | 2 + 2 files changed, 73 insertions(+), 33 deletions(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 5dc5b23d055d..61a153fd017e 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -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 */ diff --git a/drivers/i2c/busses/i2c-exynos5.h b/drivers/i2c/busses/i2c-exynos5.h index d890b91150eb..691aac79f5f6 100644 --- a/drivers/i2c/busses/i2c-exynos5.h +++ b/drivers/i2c/busses/i2c-exynos5.h @@ -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; -- 2.20.1