Hi Wolfram, On Wed, Sep 13, 2023 at 11:38 AM Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx> wrote: > With some new registers, SCL can be calculated to be closer to the > desired rate. Apply the new formula for R-Car Gen3 device types. > > Signed-off-by: Wolfram Sang <wsa+renesas@xxxxxxxxxxxxxxxxxxxx> Thanks for your patch! > --- a/drivers/i2c/busses/i2c-rcar.c > +++ b/drivers/i2c/busses/i2c-rcar.c > @@ -84,11 +88,25 @@ > #define RMDMAE BIT(1) /* DMA Master Received Enable */ > #define TMDMAE BIT(0) /* DMA Master Transmitted Enable */ > > +/* ICCCR2 */ > +#define CDFD BIT(2) /* CDF Disable */ > +#define HLSE BIT(1) /* HIGH/LOW Separate Control Enable */ > +#define SME BIT(0) /* SCL Mask Enable */ > + > /* ICFBSCR */ > #define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */ > > #define RCAR_MIN_DMA_LEN 8 > > +/* SCL low/high ratio 5:4 to meet all I2C timing specs (incl safety margin) */ > +#define RCAR_SCLD_RATIO 5 > +#define RCAR_SCHD_RATIO 4 > +/* > + * SMD should be smaller than SCLD/SCHD and is always around 20 in the docs. > + * Thus, we simply use 20 which works for low and high speeds. > +*/ (checkpatch) WARNING: Block comments should align the * on each line > +#define RCAR_DEFAULT_SMD 20 > + > #define RCAR_BUS_PHASE_START (MDBS | MIE | ESG) > #define RCAR_BUS_PHASE_DATA (MDBS | MIE) > #define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB) > @@ -301,24 +316,57 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) > round = DIV_ROUND_CLOSEST(ick, 1000000); > round = DIV_ROUND_CLOSEST(round * sum, 1000); > > - /* > - * 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 > - */ > - 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 (priv->devtype < I2C_RCAR_GEN3) { > + u32 scgd; > + /* > + * 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 > + */ > + 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 > 0x3f) > - goto err_no_val; > + if (scgd > 0x3f) > + goto err_no_val; > > - dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n", > - scl, t.bus_freq_hz, rate, round, cdf, scgd); > + dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n", > + scl, t.bus_freq_hz, rate, round, cdf, scgd); > > - /* keep icccr value */ > - priv->icccr = scgd << cdf_width | cdf; > + priv->icccr = scgd << cdf_width | cdf; > + } else { > + u32 x, sum_ratio = RCAR_SCHD_RATIO + RCAR_SCLD_RATIO; > + /* > + * SCLD/SCHD ratio and SMD default value are explained above > + * where they are defined. With these definitions, we can compute > + * x as a base value for the SCLD/SCHD ratio: > + * > + * SCL = clkp / (8 + 2 * SMD + SCLD + SCHD + F[(ticf + tr + intd) * clkp]) > + * SCL = clkp / (8 + 2 * RCAR_DEFAULT_SMD + RCAR_SCLD_RATIO * x > + * + RCAR_SCHD_RATIO * x + F[...]) (checkpatch) WARNING: please, no space before tabs I hope to give this a full test-run on my farm soon... Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds