aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorRomain Baeriswyl <Romain.Baeriswyl@abilis.com>2014-01-20 11:43:43 -0500
committerWolfram Sang <wsa@the-dreams.de>2014-03-09 04:29:08 -0400
commit6468276b22069d4442aafcd8c59e5d8ccae23f5f (patch)
treeed2cc9b10bf940ddc6da148618140b662086f853 /drivers/i2c
parent5029a22a45056603497c82445db9dd203b050e82 (diff)
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 <romainba@abilis.com> Reviewed-by: Christian Ruppert <christian.ruppert@abilis.com> Acked-by: Shinya Kuribayashi <skuribay@pobox.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c27
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h2
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c7
3 files changed, 25 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 14c4b30d4ccc..22e92c3d3d07 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -218,7 +218,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
218 * 218 *
219 * If your hardware is free from tHD;STA issue, try this one. 219 * If your hardware is free from tHD;STA issue, try this one.
220 */ 220 */
221 return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; 221 return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset;
222 else 222 else
223 /* 223 /*
224 * Conditional expression: 224 * Conditional expression:
@@ -234,7 +234,8 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
234 * The reason why we need to take into account "tf" here, 234 * The reason why we need to take into account "tf" here,
235 * is the same as described in i2c_dw_scl_lcnt(). 235 * is the same as described in i2c_dw_scl_lcnt().
236 */ 236 */
237 return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; 237 return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000
238 - 3 + offset;
238} 239}
239 240
240static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) 241static 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)
250 * account the fall time of SCL signal (tf). Default tf value 251 * account the fall time of SCL signal (tf). Default tf value
251 * should be 0.3 us, for safety. 252 * should be 0.3 us, for safety.
252 */ 253 */
253 return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; 254 return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
254} 255}
255 256
256static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) 257static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
@@ -287,6 +288,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
287 u32 input_clock_khz; 288 u32 input_clock_khz;
288 u32 hcnt, lcnt; 289 u32 hcnt, lcnt;
289 u32 reg; 290 u32 reg;
291 u32 sda_falling_time, scl_falling_time;
290 292
291 input_clock_khz = dev->get_clk_rate_khz(dev); 293 input_clock_khz = dev->get_clk_rate_khz(dev);
292 294
@@ -308,15 +310,18 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
308 310
309 /* set standard and fast speed deviders for high/low periods */ 311 /* set standard and fast speed deviders for high/low periods */
310 312
313 sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
314 scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
315
311 /* Standard-mode */ 316 /* Standard-mode */
312 hcnt = i2c_dw_scl_hcnt(input_clock_khz, 317 hcnt = i2c_dw_scl_hcnt(input_clock_khz,
313 40, /* tHD;STA = tHIGH = 4.0 us */ 318 4000, /* tHD;STA = tHIGH = 4.0 us */
314 3, /* tf = 0.3 us */ 319 sda_falling_time,
315 0, /* 0: DW default, 1: Ideal */ 320 0, /* 0: DW default, 1: Ideal */
316 0); /* No offset */ 321 0); /* No offset */
317 lcnt = i2c_dw_scl_lcnt(input_clock_khz, 322 lcnt = i2c_dw_scl_lcnt(input_clock_khz,
318 47, /* tLOW = 4.7 us */ 323 4700, /* tLOW = 4.7 us */
319 3, /* tf = 0.3 us */ 324 scl_falling_time,
320 0); /* No offset */ 325 0); /* No offset */
321 326
322 /* Allow platforms to specify the ideal HCNT and LCNT values */ 327 /* Allow platforms to specify the ideal HCNT and LCNT values */
@@ -330,13 +335,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
330 335
331 /* Fast-mode */ 336 /* Fast-mode */
332 hcnt = i2c_dw_scl_hcnt(input_clock_khz, 337 hcnt = i2c_dw_scl_hcnt(input_clock_khz,
333 6, /* tHD;STA = tHIGH = 0.6 us */ 338 600, /* tHD;STA = tHIGH = 0.6 us */
334 3, /* tf = 0.3 us */ 339 sda_falling_time,
335 0, /* 0: DW default, 1: Ideal */ 340 0, /* 0: DW default, 1: Ideal */
336 0); /* No offset */ 341 0); /* No offset */
337 lcnt = i2c_dw_scl_lcnt(input_clock_khz, 342 lcnt = i2c_dw_scl_lcnt(input_clock_khz,
338 13, /* tLOW = 1.3 us */ 343 1300, /* tLOW = 1.3 us */
339 3, /* tf = 0.3 us */ 344 scl_falling_time,
340 0); /* No offset */ 345 0); /* No offset */
341 346
342 if (dev->fs_hcnt && dev->fs_lcnt) { 347 if (dev->fs_hcnt && dev->fs_lcnt) {
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index e8a756537ed0..d66b6cbc9edc 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -99,6 +99,8 @@ struct dw_i2c_dev {
99 unsigned int rx_fifo_depth; 99 unsigned int rx_fifo_depth;
100 int rx_outstanding; 100 int rx_outstanding;
101 u32 sda_hold_time; 101 u32 sda_hold_time;
102 u32 sda_falling_time;
103 u32 scl_falling_time;
102 u16 ss_hcnt; 104 u16 ss_hcnt;
103 u16 ss_lcnt; 105 u16 ss_lcnt;
104 u16 fs_hcnt; 106 u16 fs_hcnt;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index d0bdac0498ce..fc243992b4b4 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -159,6 +159,13 @@ static int dw_i2c_probe(struct platform_device *pdev)
159 "i2c-sda-hold-time-ns", &ht); 159 "i2c-sda-hold-time-ns", &ht);
160 dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, 160 dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
161 1000000); 161 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);
162 } 169 }
163 170
164 dev->functionality = 171 dev->functionality =