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

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
Loading
Loading
Loading
Loading
+8 −16
Original line number Diff line number Diff line
@@ -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",