Skip to content

Commit 6468276

Browse files
Romain BaeriswylWolfram Sang
authored andcommitted
i2c: designware: make SCL and SDA falling time configurable
This patch allows to set independantly SCL and SDA falling times. The tLOW period is computed by taking into account the SCL falling time. The tHIGH period is computed by taking into account the SDA falling time. For instance in case the margin on tLOW is considered too small, it can be increased by increasing the SCL falling time which is by default set at 300ns. The same applies for tHIGH period with the help of SDA falling time. Signed-off-by: Romain Baeriswyl <[email protected]> Reviewed-by: Christian Ruppert <[email protected]> Acked-by: Shinya Kuribayashi <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 5029a22 commit 6468276

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

Documentation/devicetree/bindings/i2c/i2c-designware.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ Optional properties :
1414
- i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
1515
This option is only supported in hardware blocks version 1.11a or newer.
1616

17+
- i2c-scl-falling-time : should contain the SCL falling time in nanoseconds.
18+
This value which is by default 300ns is used to compute the tLOW period.
19+
20+
- i2c-sda-falling-time : should contain the SDA falling time in nanoseconds.
21+
This value which is by default 300ns is used to compute the tHIGH period.
22+
1723
Example :
1824

1925
i2c@f0000 {
@@ -34,4 +40,6 @@ Example :
3440
interrupts = <12 1>;
3541
clock-frequency = <400000>;
3642
i2c-sda-hold-time-ns = <300>;
43+
i2c-sda-falling-time-ns = <300>;
44+
i2c-scl-falling-time-ns = <300>;
3745
};

drivers/i2c/busses/i2c-designware-core.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
218218
*
219219
* If your hardware is free from tHD;STA issue, try this one.
220220
*/
221-
return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
221+
return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset;
222222
else
223223
/*
224224
* Conditional expression:
@@ -234,7 +234,8 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
234234
* The reason why we need to take into account "tf" here,
235235
* is the same as described in i2c_dw_scl_lcnt().
236236
*/
237-
return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
237+
return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000
238+
- 3 + offset;
238239
}
239240

240241
static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
@@ -250,7 +251,7 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
250251
* account the fall time of SCL signal (tf). Default tf value
251252
* should be 0.3 us, for safety.
252253
*/
253-
return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
254+
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
254255
}
255256

256257
static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
@@ -287,6 +288,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
287288
u32 input_clock_khz;
288289
u32 hcnt, lcnt;
289290
u32 reg;
291+
u32 sda_falling_time, scl_falling_time;
290292

291293
input_clock_khz = dev->get_clk_rate_khz(dev);
292294

@@ -308,15 +310,18 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
308310

309311
/* set standard and fast speed deviders for high/low periods */
310312

313+
sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
314+
scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
315+
311316
/* Standard-mode */
312317
hcnt = i2c_dw_scl_hcnt(input_clock_khz,
313-
40, /* tHD;STA = tHIGH = 4.0 us */
314-
3, /* tf = 0.3 us */
318+
4000, /* tHD;STA = tHIGH = 4.0 us */
319+
sda_falling_time,
315320
0, /* 0: DW default, 1: Ideal */
316321
0); /* No offset */
317322
lcnt = i2c_dw_scl_lcnt(input_clock_khz,
318-
47, /* tLOW = 4.7 us */
319-
3, /* tf = 0.3 us */
323+
4700, /* tLOW = 4.7 us */
324+
scl_falling_time,
320325
0); /* No offset */
321326

322327
/* Allow platforms to specify the ideal HCNT and LCNT values */
@@ -330,13 +335,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
330335

331336
/* Fast-mode */
332337
hcnt = i2c_dw_scl_hcnt(input_clock_khz,
333-
6, /* tHD;STA = tHIGH = 0.6 us */
334-
3, /* tf = 0.3 us */
338+
600, /* tHD;STA = tHIGH = 0.6 us */
339+
sda_falling_time,
335340
0, /* 0: DW default, 1: Ideal */
336341
0); /* No offset */
337342
lcnt = i2c_dw_scl_lcnt(input_clock_khz,
338-
13, /* tLOW = 1.3 us */
339-
3, /* tf = 0.3 us */
343+
1300, /* tLOW = 1.3 us */
344+
scl_falling_time,
340345
0); /* No offset */
341346

342347
if (dev->fs_hcnt && dev->fs_lcnt) {

drivers/i2c/busses/i2c-designware-core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ struct dw_i2c_dev {
9999
unsigned int rx_fifo_depth;
100100
int rx_outstanding;
101101
u32 sda_hold_time;
102+
u32 sda_falling_time;
103+
u32 scl_falling_time;
102104
u16 ss_hcnt;
103105
u16 ss_lcnt;
104106
u16 fs_hcnt;

drivers/i2c/busses/i2c-designware-platdrv.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ static int dw_i2c_probe(struct platform_device *pdev)
159159
"i2c-sda-hold-time-ns", &ht);
160160
dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
161161
1000000);
162+
163+
of_property_read_u32(pdev->dev.of_node,
164+
"i2c-sda-falling-time-ns",
165+
&dev->sda_falling_time);
166+
of_property_read_u32(pdev->dev.of_node,
167+
"i2c-scl-falling-time-ns",
168+
&dev->scl_falling_time);
162169
}
163170

164171
dev->functionality =

0 commit comments

Comments
 (0)