diff options
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index a44e2130d3e0..dd93d3d6510a 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -50,6 +50,9 @@ | |||
50 | #define QUIRK_HDMIPHY (1 << 1) | 50 | #define QUIRK_HDMIPHY (1 << 1) |
51 | #define QUIRK_NO_GPIO (1 << 2) | 51 | #define QUIRK_NO_GPIO (1 << 2) |
52 | 52 | ||
53 | /* Max time to wait for bus to become idle after a xfer (in us) */ | ||
54 | #define S3C2410_IDLE_TIMEOUT 5000 | ||
55 | |||
53 | /* i2c controller state */ | 56 | /* i2c controller state */ |
54 | enum s3c24xx_i2c_state { | 57 | enum s3c24xx_i2c_state { |
55 | STATE_IDLE, | 58 | STATE_IDLE, |
@@ -557,6 +560,48 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) | |||
557 | return -ETIMEDOUT; | 560 | return -ETIMEDOUT; |
558 | } | 561 | } |
559 | 562 | ||
563 | /* s3c24xx_i2c_wait_idle | ||
564 | * | ||
565 | * wait for the i2c bus to become idle. | ||
566 | */ | ||
567 | |||
568 | static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c) | ||
569 | { | ||
570 | unsigned long iicstat; | ||
571 | ktime_t start, now; | ||
572 | unsigned long delay; | ||
573 | |||
574 | /* ensure the stop has been through the bus */ | ||
575 | |||
576 | dev_dbg(i2c->dev, "waiting for bus idle\n"); | ||
577 | |||
578 | start = now = ktime_get(); | ||
579 | |||
580 | /* | ||
581 | * Most of the time, the bus is already idle within a few usec of the | ||
582 | * end of a transaction. However, really slow i2c devices can stretch | ||
583 | * the clock, delaying STOP generation. | ||
584 | * | ||
585 | * As a compromise between idle detection latency for the normal, fast | ||
586 | * case, and system load in the slow device case, use an exponential | ||
587 | * back off in the polling loop, up to 1/10th of the total timeout, | ||
588 | * then continue to poll at a constant rate up to the timeout. | ||
589 | */ | ||
590 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
591 | delay = 1; | ||
592 | while ((iicstat & S3C2410_IICSTAT_START) && | ||
593 | ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) { | ||
594 | usleep_range(delay, 2 * delay); | ||
595 | if (delay < S3C2410_IDLE_TIMEOUT / 10) | ||
596 | delay <<= 1; | ||
597 | now = ktime_get(); | ||
598 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
599 | } | ||
600 | |||
601 | if (iicstat & S3C2410_IICSTAT_START) | ||
602 | dev_warn(i2c->dev, "timeout waiting for bus idle\n"); | ||
603 | } | ||
604 | |||
560 | /* s3c24xx_i2c_doxfer | 605 | /* s3c24xx_i2c_doxfer |
561 | * | 606 | * |
562 | * this starts an i2c transfer | 607 | * this starts an i2c transfer |
@@ -565,8 +610,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) | |||
565 | static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, | 610 | static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, |
566 | struct i2c_msg *msgs, int num) | 611 | struct i2c_msg *msgs, int num) |
567 | { | 612 | { |
568 | unsigned long iicstat, timeout; | 613 | unsigned long timeout; |
569 | int spins = 20; | ||
570 | int ret; | 614 | int ret; |
571 | 615 | ||
572 | if (i2c->suspended) | 616 | if (i2c->suspended) |
@@ -604,24 +648,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, | |||
604 | if (i2c->quirks & QUIRK_HDMIPHY) | 648 | if (i2c->quirks & QUIRK_HDMIPHY) |
605 | goto out; | 649 | goto out; |
606 | 650 | ||
607 | /* ensure the stop has been through the bus */ | 651 | s3c24xx_i2c_wait_idle(i2c); |
608 | |||
609 | dev_dbg(i2c->dev, "waiting for bus idle\n"); | ||
610 | |||
611 | /* first, try busy waiting briefly */ | ||
612 | do { | ||
613 | cpu_relax(); | ||
614 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
615 | } while ((iicstat & S3C2410_IICSTAT_START) && --spins); | ||
616 | |||
617 | /* if that timed out sleep */ | ||
618 | if (!spins) { | ||
619 | msleep(1); | ||
620 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
621 | } | ||
622 | |||
623 | if (iicstat & S3C2410_IICSTAT_START) | ||
624 | dev_warn(i2c->dev, "timeout waiting for bus idle\n"); | ||
625 | 652 | ||
626 | out: | 653 | out: |
627 | return ret; | 654 | return ret; |