Re: [PATCH 3/3] i2c: rcar: add FastMode+ support

From: Andi Shyti
Date: Tue Sep 05 2023 - 17:37:18 EST


Hi Wolfram,

[...]

> @@ -217,7 +228,17 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
> rcar_i2c_write(priv, ICMCR, MDBS);
> rcar_i2c_write(priv, ICMSR, 0);
> /* start clock */
> - rcar_i2c_write(priv, ICCCR, priv->icccr);
> + if (priv->flags & ID_P_FMPLUS) {
> + rcar_i2c_write(priv, ICCCR, 0);
> + rcar_i2c_write(priv, ICMPR, priv->clock_val);
> + rcar_i2c_write(priv, ICHPR, 3 * priv->clock_val);
> + rcar_i2c_write(priv, ICLPR, 3 * priv->clock_val);
> + rcar_i2c_write(priv, ICCCR2, FMPE | CDFD | HLSE | SME);
> + } else {
> + rcar_i2c_write(priv, ICCCR, priv->clock_val);
> + if (priv->devtype >= I2C_RCAR_GEN3)
> + rcar_i2c_write(priv, ICCCR2, 0);

is this last bit part of the FM+ enabling or is it part of the
GEN4 support?

> + }

[...]

> + if (priv->flags & ID_P_FMPLUS) {
> + /*
> + * SMD should be smaller than SCLD and SCHD, we arbitrarily set
> + * the ratio 1:3. SCHD:SCLD ratio is 1:1, thus:
> + * SCL = clkp / (8 + SMD * 2 + SCLD + SCHD + F[(ticf + tr + intd) * clkp])
> + * SCL = clkp / (8 + SMD * 2 + SMD * 3 + SMD * 3 + F[...])
> + * SCL = clkp / (8 + SMD * 8 + F[...])
> + */
> + smd = DIV_ROUND_UP(ick / t.bus_freq_hz - 8 - round, 8);
> + scl = ick / (8 + 8 * smd + round);
>
> - if (scgd == 0x40) {
> - dev_err(dev, "it is impossible to calculate best SCL\n");
> - return -EIO;
> - }
> + if (smd > 0xff) {
> + dev_err(dev, "it is impossible to calculate best SCL\n");
> + return -EINVAL;
> + }
>
> - dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
> - scl, t.bus_freq_hz, rate, round, cdf, scgd);
> + dev_dbg(dev, "clk %d/%d(%lu), round %u, SMD:0x%x, SCHD: 0x%x\n",
> + scl, t.bus_freq_hz, rate, round, smd, 3 * smd);

I trust the formula application is right here... I can't say much :)
I don't see anything odd here.

>
> - /* keep icccr value */
> - priv->icccr = scgd << cdf_width | cdf;
> + priv->clock_val = smd;
> + } else {
> + /*
> + * 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
> + */
> + for (scgd = 0; scgd < 0x40; scgd++) {
> + scl = ick / (20 + (scgd * 8) + round);
> + if (scl <= t.bus_freq_hz)
> + break;
> + }
> +
> + if (scgd == 0x40) {

would be nice to give a meaning to this 0x40 constant... either
having it in a define or a comment, at least.

Andi

> + dev_err(dev, "it is impossible to calculate best SCL\n");
> + return -EINVAL;
> + }