i2c: exynos5: Add bus clock support
In new Exynos SoCs (like Exynos850) where HSI2C is implemented as a part of USIv2 block, there are two clocks provided to HSI2C controller: - PCLK: bus clock (APB), provides access to register interface - IPCLK: operating IP-core clock; SCL is derived from this one Both clocks have to be asserted for HSI2C to be functional in that case. Add code to obtain and enable/disable PCLK in addition to already handled operating clock. Make it optional though, as older Exynos SoC variants only have one HSI2C clock. Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> Reviewed-by: Chanho Park <chanho61.park@samsung.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
parent
3f68910259
commit
697ad2490c
@ -182,7 +182,8 @@ struct exynos5_i2c {
|
||||
unsigned int irq;
|
||||
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct clk *clk; /* operating clock */
|
||||
struct clk *pclk; /* bus clock */
|
||||
struct device *dev;
|
||||
int state;
|
||||
|
||||
@ -757,10 +758,14 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
|
||||
struct exynos5_i2c *i2c = adap->algo_data;
|
||||
int i, ret;
|
||||
|
||||
ret = clk_enable(i2c->clk);
|
||||
ret = clk_enable(i2c->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(i2c->clk);
|
||||
if (ret)
|
||||
goto err_pclk;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);
|
||||
if (ret)
|
||||
@ -768,6 +773,8 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
|
||||
}
|
||||
|
||||
clk_disable(i2c->clk);
|
||||
err_pclk:
|
||||
clk_disable(i2c->pclk);
|
||||
|
||||
return ret ?: num;
|
||||
}
|
||||
@ -807,10 +814,18 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(i2c->clk);
|
||||
i2c->pclk = devm_clk_get(&pdev->dev, "hsi2c_pclk");
|
||||
if (IS_ERR(i2c->pclk))
|
||||
i2c->pclk = NULL; /* pclk is optional */
|
||||
|
||||
ret = clk_prepare_enable(i2c->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(i2c->clk);
|
||||
if (ret)
|
||||
goto err_pclk;
|
||||
|
||||
i2c->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(i2c->regs)) {
|
||||
ret = PTR_ERR(i2c->regs);
|
||||
@ -853,11 +868,15 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
clk_disable(i2c->clk);
|
||||
clk_disable(i2c->pclk);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
|
||||
err_pclk:
|
||||
clk_disable_unprepare(i2c->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -868,6 +887,7 @@ static int exynos5_i2c_remove(struct platform_device *pdev)
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
|
||||
clk_unprepare(i2c->clk);
|
||||
clk_unprepare(i2c->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -879,6 +899,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev)
|
||||
|
||||
i2c_mark_adapter_suspended(&i2c->adap);
|
||||
clk_unprepare(i2c->clk);
|
||||
clk_unprepare(i2c->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -888,21 +909,30 @@ static int exynos5_i2c_resume_noirq(struct device *dev)
|
||||
struct exynos5_i2c *i2c = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_prepare_enable(i2c->clk);
|
||||
ret = clk_prepare_enable(i2c->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(i2c->clk);
|
||||
if (ret)
|
||||
goto err_pclk;
|
||||
|
||||
ret = exynos5_hsi2c_clock_setup(i2c);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
exynos5_i2c_init(i2c);
|
||||
clk_disable(i2c->clk);
|
||||
clk_disable(i2c->pclk);
|
||||
i2c_mark_adapter_resumed(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
err_pclk:
|
||||
clk_disable_unprepare(i2c->pclk);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user