Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347079
b: refs/heads/master
c: 31f313d
h: refs/heads/master
i:
  347077: 257b51b
  347075: 44f99c3
  347071: d2e2e6d
v: v3
  • Loading branch information
Mark Brown authored and Wolfram Sang committed Nov 22, 2012
1 parent 2bd3a31 commit f816fcc
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c5d5474425c4e7e291a98e739ea65f8acd0d8d5c
refs/heads/master: 31f313d9bebfc17e48c787c8c36b38662b4134a1
20 changes: 16 additions & 4 deletions trunk/drivers/i2c/busses/i2c-s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
unsigned long iicstat;
ktime_t start, now;
unsigned long delay;
int spins;

/* ensure the stop has been through the bus */

Expand All @@ -566,12 +567,23 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
* end of a transaction. However, really slow i2c devices can stretch
* the clock, delaying STOP generation.
*
* As a compromise between idle detection latency for the normal, fast
* case, and system load in the slow device case, use an exponential
* back off in the polling loop, up to 1/10th of the total timeout,
* then continue to poll at a constant rate up to the timeout.
* On slower SoCs this typically happens within a very small number of
* instructions so busy wait briefly to avoid scheduling overhead.
*/
spins = 3;
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
while ((iicstat & S3C2410_IICSTAT_START) && --spins) {
cpu_relax();
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
}

/*
* If we do get an appreciable delay as a compromise between idle
* detection latency for the normal, fast case, and system load in the
* slow device case, use an exponential back off in the polling loop,
* up to 1/10th of the total timeout, then continue to poll at a
* constant rate up to the timeout.
*/
delay = 1;
while ((iicstat & S3C2410_IICSTAT_START) &&
ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) {
Expand Down

0 comments on commit f816fcc

Please sign in to comment.