aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorVirupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>2011-05-13 06:30:23 -0400
committerBen Dooks <ben-linux@fluff.org>2011-05-24 19:20:43 -0400
commitebd10e0783d9fb92a147e60902e22c2d3f3ad69d (patch)
treea7e6524ae0618638bbff0b74f3abeac1e2d4817a /drivers/i2c
parentb0e751a925260e5998a76dad41d4565ef26870db (diff)
i2c-nomadik: add code to retry on timeout failure
It is seen that i2c-nomadik controller randomly stops generating the interrupts leading to a i2c timeout. As a workaround to this problem, add retries to the on going transfer on failure. Signed-off-by: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c97
1 files changed, 49 insertions, 48 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 234e4a9070b8..b49ff25a2688 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -255,8 +255,6 @@ static int init_hw(struct nmk_i2c_dev *dev)
255{ 255{
256 int stat; 256 int stat;
257 257
258 clk_enable(dev->clk);
259
260 stat = flush_i2c_fifo(dev); 258 stat = flush_i2c_fifo(dev);
261 if (stat) 259 if (stat)
262 goto exit; 260 goto exit;
@@ -271,8 +269,6 @@ static int init_hw(struct nmk_i2c_dev *dev)
271 dev->cli.operation = I2C_NO_OPERATION; 269 dev->cli.operation = I2C_NO_OPERATION;
272 270
273exit: 271exit:
274 /* TODO: Why disable clocks after init hw? */
275 clk_disable(dev->clk);
276 /* 272 /*
277 * TODO: What is this delay for? 273 * TODO: What is this delay for?
278 * Must be pretty pointless since the hw block 274 * Must be pretty pointless since the hw block
@@ -572,6 +568,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
572 u32 cause; 568 u32 cause;
573 struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); 569 struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap);
574 u32 i2c_sr; 570 u32 i2c_sr;
571 int j;
575 572
576 dev->busy = true; 573 dev->busy = true;
577 574
@@ -579,63 +576,67 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
579 regulator_enable(dev->regulator); 576 regulator_enable(dev->regulator);
580 pm_runtime_get_sync(&dev->pdev->dev); 577 pm_runtime_get_sync(&dev->pdev->dev);
581 578
579 clk_enable(dev->clk);
580
582 status = init_hw(dev); 581 status = init_hw(dev);
583 if (status) 582 if (status)
584 goto out2; 583 goto out;
585 584
586 clk_enable(dev->clk); 585 for (j = 0; j < 3; j++) {
587 586 /* setup the i2c controller */
588 /* setup the i2c controller */ 587 setup_i2c_controller(dev);
589 setup_i2c_controller(dev);
590 588
591 for (i = 0; i < num_msgs; i++) { 589 for (i = 0; i < num_msgs; i++) {
592 if (unlikely(msgs[i].flags & I2C_M_TEN)) { 590 if (unlikely(msgs[i].flags & I2C_M_TEN)) {
593 dev_err(&dev->pdev->dev, "10 bit addressing" 591 dev_err(&dev->pdev->dev, "10 bit addressing"
594 "not supported\n"); 592 "not supported\n");
595 593
596 status = -EINVAL; 594 status = -EINVAL;
597 goto out; 595 goto out;
598 } 596 }
599 dev->cli.slave_adr = msgs[i].addr; 597 dev->cli.slave_adr = msgs[i].addr;
600 dev->cli.buffer = msgs[i].buf; 598 dev->cli.buffer = msgs[i].buf;
601 dev->cli.count = msgs[i].len; 599 dev->cli.count = msgs[i].len;
602 dev->stop = (i < (num_msgs - 1)) ? 0 : 1; 600 dev->stop = (i < (num_msgs - 1)) ? 0 : 1;
603 dev->result = 0; 601 dev->result = 0;
604 602
605 if (msgs[i].flags & I2C_M_RD) { 603 if (msgs[i].flags & I2C_M_RD) {
606 /* it is a read operation */ 604 /* it is a read operation */
607 dev->cli.operation = I2C_READ; 605 dev->cli.operation = I2C_READ;
608 status = read_i2c(dev); 606 status = read_i2c(dev);
609 } else { 607 } else {
610 /* write operation */ 608 /* write operation */
611 dev->cli.operation = I2C_WRITE; 609 dev->cli.operation = I2C_WRITE;
612 status = write_i2c(dev); 610 status = write_i2c(dev);
613 } 611 }
614 if (status || (dev->result)) { 612 if (status || (dev->result)) {
615 i2c_sr = readl(dev->virtbase + I2C_SR); 613 i2c_sr = readl(dev->virtbase + I2C_SR);
616 /* 614 /*
617 * Check if the controller I2C operation status is set 615 * Check if the controller I2C operation status
618 * to ABORT(11b). 616 * is set to ABORT(11b).
619 */ 617 */
620 if (((i2c_sr >> 2) & 0x3) == 0x3) { 618 if (((i2c_sr >> 2) & 0x3) == 0x3) {
621 /* get the abort cause */ 619 /* get the abort cause */
622 cause = (i2c_sr >> 4) 620 cause = (i2c_sr >> 4)
623 & 0x7; 621 & 0x7;
624 dev_err(&dev->pdev->dev, "%s\n", cause >= 622 dev_err(&dev->pdev->dev, "%s\n", cause
625 ARRAY_SIZE(abort_causes) ? 623 >= ARRAY_SIZE(abort_causes) ?
626 "unknown reason" : 624 "unknown reason" :
627 abort_causes[cause]); 625 abort_causes[cause]);
628 } 626 }
629 627
630 status = status ? status : dev->result; 628 status = status ? status : dev->result;
631 goto out; 629
630 break;
631 }
632 udelay(I2C_DELAY);
632 } 633 }
633 udelay(I2C_DELAY); 634 if (status == 0)
635 break;
634 } 636 }
635 637
636out: 638out:
637 clk_disable(dev->clk); 639 clk_disable(dev->clk);
638out2:
639 pm_runtime_put_sync(&dev->pdev->dev); 640 pm_runtime_put_sync(&dev->pdev->dev);
640 if (dev->regulator) 641 if (dev->regulator)
641 regulator_disable(dev->regulator); 642 regulator_disable(dev->regulator);