Skip to content

Commit

Permalink
i2c: tegra: dynamically control fast clk
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laxman Dewangan authored and Stephen Warren committed Sep 13, 2012
1 parent 6ad068e commit fd301cc
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions drivers/i2c/busses/i2c-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,36 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
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);
Expand Down Expand Up @@ -399,7 +423,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
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;
Expand Down Expand Up @@ -575,7 +599,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
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)) {
Expand All @@ -588,7 +612,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
if (ret)
break;
}
clk_disable_unprepare(i2c_dev->div_clk);
tegra_i2c_clock_disable(i2c_dev);
return ret ?: i;
}

Expand Down Expand Up @@ -724,8 +748,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
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;
Expand All @@ -739,7 +761,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
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;
}

Expand Down

0 comments on commit fd301cc

Please sign in to comment.