Skip to content

Commit 54c76ed

Browse files
Wolfram Sangwsakernel
authored andcommitted
i2c: rcar: improve accuracy for R-Car Gen3+
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@sang-engineering.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent 0e864b5 commit 54c76ed

1 file changed

Lines changed: 89 additions & 39 deletions

File tree

drivers/i2c/busses/i2c-rcar.c

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
#define ICSAR 0x1C /* slave address */
4242
#define ICMAR 0x20 /* master address */
4343
#define ICRXTX 0x24 /* data port */
44+
#define ICCCR2 0x28 /* Clock control 2 */
45+
#define ICMPR 0x2C /* SCL mask control */
46+
#define ICHPR 0x30 /* SCL HIGH control */
47+
#define ICLPR 0x34 /* SCL LOW control */
4448
#define ICFBSCR 0x38 /* first bit setup cycle (Gen3) */
4549
#define ICDMAER 0x3c /* DMA enable (Gen3) */
4650

@@ -84,11 +88,25 @@
8488
#define RMDMAE BIT(1) /* DMA Master Received Enable */
8589
#define TMDMAE BIT(0) /* DMA Master Transmitted Enable */
8690

91+
/* ICCCR2 */
92+
#define CDFD BIT(2) /* CDF Disable */
93+
#define HLSE BIT(1) /* HIGH/LOW Separate Control Enable */
94+
#define SME BIT(0) /* SCL Mask Enable */
95+
8796
/* ICFBSCR */
8897
#define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */
8998

9099
#define RCAR_MIN_DMA_LEN 8
91100

101+
/* SCL low/high ratio 5:4 to meet all I2C timing specs (incl safety margin) */
102+
#define RCAR_SCLD_RATIO 5
103+
#define RCAR_SCHD_RATIO 4
104+
/*
105+
* SMD should be smaller than SCLD/SCHD and is always around 20 in the docs.
106+
* Thus, we simply use 20 which works for low and high speeds.
107+
*/
108+
#define RCAR_DEFAULT_SMD 20
109+
92110
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
93111
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
94112
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
@@ -128,6 +146,8 @@ struct rcar_i2c_priv {
128146

129147
int pos;
130148
u32 icccr;
149+
u16 schd;
150+
u16 scld;
131151
u8 recovery_icmcr; /* protected by adapter lock */
132152
enum rcar_i2c_type devtype;
133153
struct i2c_client *slave;
@@ -216,11 +236,16 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
216236
rcar_i2c_write(priv, ICMCR, MDBS);
217237
rcar_i2c_write(priv, ICMSR, 0);
218238
/* start clock */
219-
rcar_i2c_write(priv, ICCCR, priv->icccr);
220-
221-
if (priv->devtype == I2C_RCAR_GEN3)
239+
if (priv->devtype < I2C_RCAR_GEN3) {
240+
rcar_i2c_write(priv, ICCCR, priv->icccr);
241+
} else {
242+
rcar_i2c_write(priv, ICCCR2, CDFD | HLSE | SME);
243+
rcar_i2c_write(priv, ICCCR, priv->icccr);
244+
rcar_i2c_write(priv, ICMPR, RCAR_DEFAULT_SMD);
245+
rcar_i2c_write(priv, ICHPR, priv->schd);
246+
rcar_i2c_write(priv, ICLPR, priv->scld);
222247
rcar_i2c_write(priv, ICFBSCR, TCYC17);
223-
248+
}
224249
}
225250

226251
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
@@ -241,7 +266,7 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
241266

242267
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
243268
{
244-
u32 scgd, cdf, round, ick, sum, scl, cdf_width;
269+
u32 cdf, round, ick, sum, scl, cdf_width;
245270
unsigned long rate;
246271
struct device *dev = rcar_i2c_priv_to_dev(priv);
247272
struct i2c_timings t = {
@@ -254,27 +279,17 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
254279
/* Fall back to previously used values if not supplied */
255280
i2c_parse_fw_timings(dev, &t, false);
256281

257-
switch (priv->devtype) {
258-
case I2C_RCAR_GEN1:
259-
cdf_width = 2;
260-
break;
261-
case I2C_RCAR_GEN2:
262-
case I2C_RCAR_GEN3:
263-
cdf_width = 3;
264-
break;
265-
default:
266-
dev_err(dev, "device type error\n");
267-
return -EIO;
268-
}
269-
270282
/*
271283
* calculate SCL clock
272284
* see
273-
* ICCCR
285+
* ICCCR (and ICCCR2 for Gen3+)
274286
*
275287
* ick = clkp / (1 + CDF)
276288
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
277289
*
290+
* for Gen3+:
291+
* SCL = clkp / (8 + SMD * 2 + SCLD + SCHD +F[(ticf + tr + intd) * clkp])
292+
*
278293
* ick : I2C internal clock < 20 MHz
279294
* ticf : I2C SCL falling time
280295
* tr : I2C SCL rising time
@@ -284,11 +299,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
284299
*/
285300
rate = clk_get_rate(priv->clk);
286301
cdf = rate / 20000000;
287-
if (cdf >= 1U << cdf_width) {
288-
dev_err(dev, "Input clock %lu too high\n", rate);
289-
return -EIO;
290-
}
291-
ick = rate / (cdf + 1);
302+
cdf_width = (priv->devtype == I2C_RCAR_GEN1) ? 2 : 3;
303+
if (cdf >= 1U << cdf_width)
304+
goto err_no_val;
305+
306+
/* On Gen3+, we use cdf only for the filters, not as a SCL divider */
307+
ick = rate / (priv->devtype < I2C_RCAR_GEN3 ? (cdf + 1) : 1);
292308

293309
/*
294310
* It is impossible to calculate a large scale number on u32. Separate it.
@@ -301,24 +317,58 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv)
301317
round = DIV_ROUND_CLOSEST(ick, 1000000);
302318
round = DIV_ROUND_CLOSEST(round * sum, 1000);
303319

304-
/*
305-
* SCL = ick / (20 + 8 * SCGD + F[(ticf + tr + intd) * ick])
306-
* 20 + 8 * SCGD + F[...] = ick / SCL
307-
* SCGD = ((ick / SCL) - 20 - F[...]) / 8
308-
* Result (= SCL) should be less than bus_speed for hardware safety
309-
*/
310-
scgd = DIV_ROUND_UP(ick, t.bus_freq_hz ?: 1);
311-
scgd = DIV_ROUND_UP(scgd - 20 - round, 8);
312-
scl = ick / (20 + 8 * scgd + round);
320+
if (priv->devtype < I2C_RCAR_GEN3) {
321+
u32 scgd;
322+
/*
323+
* SCL = ick / (20 + 8 * SCGD + F[(ticf + tr + intd) * ick])
324+
* 20 + 8 * SCGD + F[...] = ick / SCL
325+
* SCGD = ((ick / SCL) - 20 - F[...]) / 8
326+
* Result (= SCL) should be less than bus_speed for hardware safety
327+
*/
328+
scgd = DIV_ROUND_UP(ick, t.bus_freq_hz ?: 1);
329+
scgd = DIV_ROUND_UP(scgd - 20 - round, 8);
330+
scl = ick / (20 + 8 * scgd + round);
313331

314-
if (scgd > 0x3f)
315-
goto err_no_val;
332+
if (scgd > 0x3f)
333+
goto err_no_val;
316334

317-
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n",
318-
scl, t.bus_freq_hz, rate, round, cdf, scgd);
335+
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n",
336+
scl, t.bus_freq_hz, rate, round, cdf, scgd);
319337

320-
/* keep icccr value */
321-
priv->icccr = scgd << cdf_width | cdf;
338+
priv->icccr = scgd << cdf_width | cdf;
339+
} else {
340+
u32 x, sum_ratio = RCAR_SCHD_RATIO + RCAR_SCLD_RATIO;
341+
/*
342+
* SCLD/SCHD ratio and SMD default value are explained above
343+
* where they are defined. With these definitions, we can compute
344+
* x as a base value for the SCLD/SCHD ratio:
345+
*
346+
* SCL = clkp / (8 + 2 * SMD + SCLD + SCHD + F[(ticf + tr + intd) * clkp])
347+
* SCL = clkp / (8 + 2 * RCAR_DEFAULT_SMD + RCAR_SCLD_RATIO * x
348+
* + RCAR_SCHD_RATIO * x + F[...])
349+
*
350+
* with: sum_ratio = RCAR_SCLD_RATIO + RCAR_SCHD_RATIO
351+
* and: smd = RCAR_DEFAULT_SMD
352+
*
353+
* SCL = clkp / (8 + 2 * smd + sum_ratio * x + F[...])
354+
* 8 + 2 * smd + sum_ratio * x + F[...] = clkp / SCL
355+
* x = ((clkp / SCL) - 8 - 2 * smd - F[...]) / sum_ratio
356+
*/
357+
x = DIV_ROUND_UP(rate, t.bus_freq_hz ?: 1);
358+
x = DIV_ROUND_UP(x - 8 - 2 * RCAR_DEFAULT_SMD - round, sum_ratio);
359+
scl = rate / (8 + 2 * RCAR_DEFAULT_SMD + sum_ratio * x + round);
360+
361+
/* Bail out if values don't fit into 16 bit or SMD became too large */
362+
if (x * RCAR_SCLD_RATIO > 0xffff || RCAR_DEFAULT_SMD > x * RCAR_SCHD_RATIO)
363+
goto err_no_val;
364+
365+
priv->icccr = cdf;
366+
priv->schd = RCAR_SCHD_RATIO * x;
367+
priv->scld = RCAR_SCLD_RATIO * x;
368+
369+
dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u SCHD %u SCLD %u\n",
370+
scl, t.bus_freq_hz, rate, round, cdf, priv->schd, priv->scld);
371+
}
322372

323373
return 0;
324374

0 commit comments

Comments
 (0)