i2c: tegra: dynamically control fast clk
Tegra I2C driver enables the fast clock during initialization
and does not disable till driver removed.
Enable this clock before transfer and disable after transfer done.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index ce70147..f981ac4 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -363,12 +363,36 @@
dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
}
+static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
+{
+ int ret;
+ ret = clk_prepare_enable(i2c_dev->fast_clk);
+ if (ret < 0) {
+ dev_err(i2c_dev->dev,
+ "Enabling fast clk failed, err %d\n", ret);
+ return ret;
+ }
+ ret = clk_prepare_enable(i2c_dev->div_clk);
+ if (ret < 0) {
+ dev_err(i2c_dev->dev,
+ "Enabling div clk failed, err %d\n", ret);
+ clk_disable_unprepare(i2c_dev->fast_clk);
+ }
+ return ret;
+}
+
+static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
+{
+ clk_disable_unprepare(i2c_dev->div_clk);
+ clk_disable_unprepare(i2c_dev->fast_clk);
+}
+
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int err = 0;
- clk_prepare_enable(i2c_dev->div_clk);
+ tegra_i2c_clock_enable(i2c_dev);
tegra_periph_reset_assert(i2c_dev->div_clk);
udelay(2);
@@ -399,7 +423,7 @@
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
- clk_disable_unprepare(i2c_dev->div_clk);
+ tegra_i2c_clock_disable(i2c_dev);
if (i2c_dev->irq_disabled) {
i2c_dev->irq_disabled = 0;
@@ -575,7 +599,7 @@
if (i2c_dev->is_suspended)
return -EBUSY;
- clk_prepare_enable(i2c_dev->div_clk);
+ tegra_i2c_clock_enable(i2c_dev);
for (i = 0; i < num; i++) {
enum msg_end_type end_type = MSG_END_STOP;
if (i < (num - 1)) {
@@ -588,7 +612,7 @@
if (ret)
break;
}
- clk_disable_unprepare(i2c_dev->div_clk);
+ tegra_i2c_clock_disable(i2c_dev);
return ret ?: i;
}
@@ -724,8 +748,6 @@
return ret;
}
- clk_prepare_enable(i2c_dev->fast_clk);
-
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
i2c_dev->adapter.owner = THIS_MODULE;
i2c_dev->adapter.class = I2C_CLASS_HWMON;
@@ -739,7 +761,6 @@
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
- clk_disable_unprepare(i2c_dev->fast_clk);
return ret;
}