Skip to content

Commit 697ad24

Browse files
Sam Protsenkowsakernel
authored andcommitted
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>
1 parent 3f68910 commit 697ad24

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

drivers/i2c/busses/i2c-exynos5.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ struct exynos5_i2c {
182182
unsigned int irq;
183183

184184
void __iomem *regs;
185-
struct clk *clk;
185+
struct clk *clk; /* operating clock */
186+
struct clk *pclk; /* bus clock */
186187
struct device *dev;
187188
int state;
188189

@@ -757,17 +758,23 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
757758
struct exynos5_i2c *i2c = adap->algo_data;
758759
int i, ret;
759760

760-
ret = clk_enable(i2c->clk);
761+
ret = clk_enable(i2c->pclk);
761762
if (ret)
762763
return ret;
763764

765+
ret = clk_enable(i2c->clk);
766+
if (ret)
767+
goto err_pclk;
768+
764769
for (i = 0; i < num; ++i) {
765770
ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);
766771
if (ret)
767772
break;
768773
}
769774

770775
clk_disable(i2c->clk);
776+
err_pclk:
777+
clk_disable(i2c->pclk);
771778

772779
return ret ?: num;
773780
}
@@ -807,10 +814,18 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
807814
return -ENOENT;
808815
}
809816

810-
ret = clk_prepare_enable(i2c->clk);
817+
i2c->pclk = devm_clk_get(&pdev->dev, "hsi2c_pclk");
818+
if (IS_ERR(i2c->pclk))
819+
i2c->pclk = NULL; /* pclk is optional */
820+
821+
ret = clk_prepare_enable(i2c->pclk);
811822
if (ret)
812823
return ret;
813824

825+
ret = clk_prepare_enable(i2c->clk);
826+
if (ret)
827+
goto err_pclk;
828+
814829
i2c->regs = devm_platform_ioremap_resource(pdev, 0);
815830
if (IS_ERR(i2c->regs)) {
816831
ret = PTR_ERR(i2c->regs);
@@ -853,11 +868,15 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
853868
platform_set_drvdata(pdev, i2c);
854869

855870
clk_disable(i2c->clk);
871+
clk_disable(i2c->pclk);
856872

857873
return 0;
858874

859875
err_clk:
860876
clk_disable_unprepare(i2c->clk);
877+
878+
err_pclk:
879+
clk_disable_unprepare(i2c->pclk);
861880
return ret;
862881
}
863882

@@ -868,6 +887,7 @@ static int exynos5_i2c_remove(struct platform_device *pdev)
868887
i2c_del_adapter(&i2c->adap);
869888

870889
clk_unprepare(i2c->clk);
890+
clk_unprepare(i2c->pclk);
871891

872892
return 0;
873893
}
@@ -879,6 +899,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev)
879899

880900
i2c_mark_adapter_suspended(&i2c->adap);
881901
clk_unprepare(i2c->clk);
902+
clk_unprepare(i2c->pclk);
882903

883904
return 0;
884905
}
@@ -888,21 +909,30 @@ static int exynos5_i2c_resume_noirq(struct device *dev)
888909
struct exynos5_i2c *i2c = dev_get_drvdata(dev);
889910
int ret = 0;
890911

891-
ret = clk_prepare_enable(i2c->clk);
912+
ret = clk_prepare_enable(i2c->pclk);
892913
if (ret)
893914
return ret;
894915

916+
ret = clk_prepare_enable(i2c->clk);
917+
if (ret)
918+
goto err_pclk;
919+
895920
ret = exynos5_hsi2c_clock_setup(i2c);
896-
if (ret) {
897-
clk_disable_unprepare(i2c->clk);
898-
return ret;
899-
}
921+
if (ret)
922+
goto err_clk;
900923

901924
exynos5_i2c_init(i2c);
902925
clk_disable(i2c->clk);
926+
clk_disable(i2c->pclk);
903927
i2c_mark_adapter_resumed(&i2c->adap);
904928

905929
return 0;
930+
931+
err_clk:
932+
clk_disable_unprepare(i2c->clk);
933+
err_pclk:
934+
clk_disable_unprepare(i2c->pclk);
935+
return ret;
906936
}
907937
#endif
908938

0 commit comments

Comments
 (0)