Commit 8d049403 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Wolfram Sang

i2c: rcar: get clock rate only once and simplify calculation

There is no need to repeatedly query clock frequency, where it is not
expected to change. The complete loop can also trivially be replaced with
a simple division. A further loop below the one, being simplified, could
also be replaced, but that would get more complicated.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski+renesas@gmail.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 14d32f17
...@@ -231,6 +231,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, ...@@ -231,6 +231,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
u32 round, ick; u32 round, ick;
u32 scl; u32 scl;
u32 cdf_width; u32 cdf_width;
unsigned long rate;
if (!clkp) { if (!clkp) {
dev_err(dev, "there is no peripheral_clk\n"); dev_err(dev, "there is no peripheral_clk\n");
...@@ -264,15 +265,14 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, ...@@ -264,15 +265,14 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* clkp : peripheral_clk * clkp : peripheral_clk
* F[] : integer up-valuation * F[] : integer up-valuation
*/ */
for (cdf = 0; cdf < (1 << cdf_width); cdf++) { rate = clk_get_rate(clkp);
ick = clk_get_rate(clkp) / (1 + cdf); cdf = rate / 20000000;
if (ick < 20000000) if (cdf >= 1 << cdf_width) {
goto ick_find; dev_err(dev, "Input clock %lu too high\n", rate);
return -EIO;
} }
dev_err(dev, "there is no best CDF\n"); ick = rate / (cdf + 1);
return -EIO;
ick_find:
/* /*
* it is impossible to calculate large scale * it is impossible to calculate large scale
* number on u32. separate it * number on u32. separate it
...@@ -290,6 +290,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, ...@@ -290,6 +290,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* *
* Calculation result (= SCL) should be less than * Calculation result (= SCL) should be less than
* bus_speed for hardware safety * bus_speed for hardware safety
*
* We could use something along the lines of
* div = ick / (bus_speed + 1) + 1;
* scgd = (div - 20 - round + 7) / 8;
* scl = ick / (20 + (scgd * 8) + round);
* (not fully verified) but that would get pretty involved
*/ */
for (scgd = 0; scgd < 0x40; scgd++) { for (scgd = 0; scgd < 0x40; scgd++) {
scl = ick / (20 + (scgd * 8) + round); scl = ick / (20 + (scgd * 8) + round);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment