#include "../../pinctrl/core.h"
#include "i2c-exynos5.h"
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
#include <soc/samsung/exynos-powermode.h>
+#endif
#ifdef CONFIG_CPU_IDLE
#include <soc/samsung/exynos-pm.h>
#endif
* Returns 0 on success, -EINVAL if the cycle length cannot
* be calculated.
*/
-static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
+static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
{
int ret;
unsigned int ipclk;
static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
{
- /* always set Fast Speed timings */
- int ret = exynos5_i2c_set_timing(i2c, false);
+ /*
+ * 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;
+ }
- if (ret < 0 || i2c->op_clock < HSI2C_HS_TX_CLOCK)
- return ret;
+ /* 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");
+ return -EINVAL;
+ }
+ }
/* Configure the Standard mode timing values */
if (i2c->speed_mode == HSI2C_STAND_SPD) {
#ifdef CONFIG_PM
clk_ret = pm_runtime_get_sync(i2c->dev);
if (clk_ret < 0) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
return ret;
}
}
#else
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
return ret;
}
#endif
#ifdef CONFIG_PM
if (clk_ret < 0) {
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
} else {
pm_runtime_mark_last_busy(i2c->dev);
pm_runtime_put_autosuspend(i2c->dev);
}
#else
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
#endif
return ret;
i2c->nack_restart = 0;
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
i2c->idle_ip_index = exynos_get_idle_ip_index(dev_name(&pdev->dev));
+#endif
strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
#ifdef CONFIG_PM
pm_runtime_get_sync(&pdev->dev);
#else
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
return ret;
}
#endif
pm_runtime_put_autosuspend(&pdev->dev);
#else
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
#endif
+#endif
#if defined(CONFIG_CPU_IDLE)
list_add_tail(&i2c->node, &drvdata_list);
pm_runtime_put_autosuspend(&pdev->dev);
#else
clk_disable_unprepare(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
#endif
err_clk1:
return ret;
struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
i2c->runtime_resumed = 0;
return 0;
struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
int ret = 0;
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
i2c->runtime_resumed = 1;
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
return ret;
}
i2c_lock_adapter(&i2c->adap);
#ifdef CONFIG_I2C_SAMSUNG_HWACG
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
i2c_unlock_adapter(&i2c->adap);
return ret;
}
writel(HSI2C_SW_RST, i2c->regs + HSI2C_CTL);
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
#endif
if (!pm_runtime_status_suspended(dev))
if (!pm_runtime_status_suspended(dev))
exynos5_i2c_runtime_resume(dev);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
+#endif
ret = clk_enable(i2c->clk);
if (ret) {
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
i2c_unlock_adapter(&i2c->adap);
return ret;
}
exynos_usi_init(i2c);
exynos5_i2c_reset(i2c);
clk_disable(i2c->clk);
+#ifdef CONFIG_ARM64_EXYNOS_CPUIDLE
exynos_update_ip_idle_status(i2c->idle_ip_index, 1);
+#endif
i2c->suspended = 0;
i2c_unlock_adapter(&i2c->adap);