From e6be9bd92ba7f8f133a7d8fd82ebb23dfdf98878 Mon Sep 17 00:00:00 2001 From: Kyungwoo Kang Date: Wed, 28 Mar 2018 10:03:14 +0900 Subject: [PATCH] [COMMON] i2c: exynos5: Add Standard mode for HSI2C Now we support standard mode for HSI2C like below. [Standard - Fast - Fast plus - High Speed] Change-Id: I4c804ed85086b848695a7d21552f7c7cbb6771d9 Signed-off-by: Kyungwoo Kang --- drivers/i2c/busses/i2c-exynos5.c | 41 ++++++++++++++++++++++++++++++-- drivers/i2c/busses/i2c-exynos5.h | 1 + 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 3706a268d39a..54c91aadc8dd 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -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)) diff --git a/drivers/i2c/busses/i2c-exynos5.h b/drivers/i2c/busses/i2c-exynos5.h index 358610d9e516..d890b91150eb 100644 --- a/drivers/i2c/busses/i2c-exynos5.h +++ b/drivers/i2c/busses/i2c-exynos5.h @@ -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; -- 2.20.1