diff options
author | Aaro Koskinen <aaro.koskinen@nokia.com> | 2009-05-27 10:54:45 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-06-13 05:39:25 -0400 |
commit | baf46b4e378d7950dff7ba30cfd50ff585987cb4 (patch) | |
tree | 571bd77cb953d1fc6a206c250b3cf8dd4718546f /drivers/i2c/busses/i2c-omap.c | |
parent | e0cd2dd5dd2b7c6512e46ce0b4f119cd7b0c74a4 (diff) |
i2c: OMAP2/3: Fix scll/sclh calculations
Fix scll/sclh calculations for HS and fast modes. Currently the driver
uses equal (roughly) low/high times which will result in too short
low time.
OMAP3430 TRM gives the following equations:
F/S: tLow = (scll + 7) * internal_clk
tHigh = (sclh + 5) * internal_clk
HS: tLow = (scll + 7) * fclk
tHigh = (sclh + 5) * fclk
Furthermore, the I2C specification sets the following minimum values
for HS tLow/tHigh for capacitive bus loads 100 pF (maximum speed 3400)
and 400 pF (maximum speed 1700):
speed tLow tHigh
3400 160 ns 60 ns
1700 320 ns 120 ns
and for F/S:
speed tLow tHigh
400 1300 ns 600 ns
100 4700 ns 4000 ns
By using duty cycles 33/66 (HS, F) and 50/50 (S) we stay above these
minimum values.
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index ece0125a1ee5..a879e4bf5122 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -343,17 +343,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
343 | 343 | ||
344 | /* If configured for High Speed */ | 344 | /* If configured for High Speed */ |
345 | if (dev->speed > 400) { | 345 | if (dev->speed > 400) { |
346 | unsigned long scl; | ||
347 | |||
346 | /* For first phase of HS mode */ | 348 | /* For first phase of HS mode */ |
347 | fsscll = internal_clk / (400 * 2) - 6; | 349 | scl = internal_clk / 400; |
348 | fssclh = internal_clk / (400 * 2) - 6; | 350 | fsscll = scl - (scl / 3) - 7; |
351 | fssclh = (scl / 3) - 5; | ||
349 | 352 | ||
350 | /* For second phase of HS mode */ | 353 | /* For second phase of HS mode */ |
351 | hsscll = fclk_rate / (dev->speed * 2) - 6; | 354 | scl = fclk_rate / dev->speed; |
352 | hssclh = fclk_rate / (dev->speed * 2) - 6; | 355 | hsscll = scl - (scl / 3) - 7; |
356 | hssclh = (scl / 3) - 5; | ||
357 | } else if (dev->speed > 100) { | ||
358 | unsigned long scl; | ||
359 | |||
360 | /* Fast mode */ | ||
361 | scl = internal_clk / dev->speed; | ||
362 | fsscll = scl - (scl / 3) - 7; | ||
363 | fssclh = (scl / 3) - 5; | ||
353 | } else { | 364 | } else { |
354 | /* To handle F/S modes */ | 365 | /* Standard mode */ |
355 | fsscll = internal_clk / (dev->speed * 2) - 6; | 366 | fsscll = internal_clk / (dev->speed * 2) - 7; |
356 | fssclh = internal_clk / (dev->speed * 2) - 6; | 367 | fssclh = internal_clk / (dev->speed * 2) - 5; |
357 | } | 368 | } |
358 | scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; | 369 | scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; |
359 | sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; | 370 | sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; |