From 02720fac73cf7217b6d4ca8c74eb458be512bbfb Mon Sep 17 00:00:00 2001 From: Youngmin Nam Date: Fri, 29 Jul 2016 14:16:45 +0900 Subject: [PATCH] [COMMON] i2c: exynos5: reset i2c master before suspend This patch resets i2c master before suspend to prevent central secquence stuck. If master state is in arbitration lose, I2C master requests clock for operation. So we need to reset i2c master to recover from arbitration lose state. Change-Id: I5f5996b38148868b1fac26d2b81284ae7a9ad1f3 Signed-off-by: Youngmin Nam --- drivers/i2c/busses/Kconfig | 8 ++++++++ drivers/i2c/busses/i2c-exynos5.c | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 45a3f3ca29b3..0f488bd74053 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -590,6 +590,14 @@ config I2C_EXYNOS5 help High-speed I2C controller on Exynos5 based Samsung SoCs. +config I2C_SAMSUNG_HWACG + bool "HWACG(HW Auto Clock Gating) support for Exynos I2C port" + default y + help + If HWACG is enabled on I2C, System power mode will goes into + suspend state only when I2C master is not in busy state. + To support HWACG on I2C, this configuration should be selected. + config I2C_GPIO tristate "GPIO-based bitbanging I2C" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 9e07d783a258..7b1cd37dd9bd 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -1122,9 +1122,25 @@ static int exynos5_i2c_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int exynos5_i2c_suspend_noirq(struct device *dev) { - struct exynos5_i2c *i2c = dev_get_drvdata(dev); + struct platform_device *pdev = to_platform_device(dev); + struct exynos5_i2c *i2c = platform_get_drvdata(pdev); +#ifdef CONFIG_I2C_SAMSUNG_HWACG + int ret = 0; +#endif i2c_lock_adapter(&i2c->adap); +#ifdef CONFIG_I2C_SAMSUNG_HWACG + exynos_update_ip_idle_status(i2c->idle_ip_index, 0); + ret = clk_enable(i2c->clk); + if (ret) { + exynos_update_ip_idle_status(i2c->idle_ip_index, 1); + i2c_unlock_adapter(&i2c->adap); + return ret; + } + exynos5_i2c_reset(i2c); + clk_disable(i2c->clk); + exynos_update_ip_idle_status(i2c->idle_ip_index, 1); +#endif i2c->suspended = 1; i2c_unlock_adapter(&i2c->adap); -- 2.20.1