Commit 47280af8 authored by Wolfram Sang's avatar Wolfram Sang Committed by Wolfram Sang

i2c: rcar: calculate divider instead of brute-forcing it

Instead of trying all values, we can actually compute it as the comment
suggests. It is unclear what the comment means with "involved", it works
nicely.
Signed-off-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent d7285790
......@@ -303,24 +303,16 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
round = (round + 500) / 1000;
/*
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
*
* Calculation result (= SCL) should be less than
* 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
* SCL = ick / (20 + 8 * SCGD + F[(ticf + tr + intd) * ick])
* 20 + 8 * SCGD + F[...] = ick / SCL
* SCGD = ((ick / SCL) - 20 - F[...]) / 8
* Result (= SCL) should be less than bus_speed for hardware safety
*/
for (scgd = 0; scgd < 0x40; scgd++) {
scl = ick / (20 + (scgd * 8) + round);
if (scl <= t.bus_freq_hz)
break;
}
scgd = DIV_ROUND_UP(ick, t.bus_freq_hz ?: 1);
scgd = DIV_ROUND_UP(scgd - 20 - round, 8);
scl = ick / (20 + 8 * scgd + round);
if (scgd == 0x40)
if (scgd > 0x3f)
goto err_no_val;
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n",
......
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