aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-eg20t.c
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-10-12 00:13:03 -0400
committerBen Dooks <ben-linux@fluff.org>2011-10-29 06:09:33 -0400
commit12bd3146518ab984c1eb234a0f81756ddc5e3683 (patch)
tree569803f477950373973f510aa70831af163335d7 /drivers/i2c/busses/i2c-eg20t.c
parentc249ac207f2cedb49f2c9442afbaac35bfcfcd25 (diff)
i2c-eg20t: Separate error processing
Error processing for NACK or wait-event must be precessed separately. So divide wait-event error processing into NACK-receiving and timeout. Add arbitration lost processing. Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.lapis-semi.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-eg20t.c')
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c173
1 files changed, 115 insertions, 58 deletions
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 38e44d959f0..cb296862ae0 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -391,6 +391,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
391 u32 addr_2_msb; 391 u32 addr_2_msb;
392 u32 addr_8_lsb; 392 u32 addr_8_lsb;
393 s32 wrcount; 393 s32 wrcount;
394 s32 rtn;
394 void __iomem *p = adap->pch_base_address; 395 void __iomem *p = adap->pch_base_address;
395 396
396 length = msgs->len; 397 length = msgs->len;
@@ -413,11 +414,25 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
413 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); 414 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
414 if (first) 415 if (first)
415 pch_i2c_start(adap); 416 pch_i2c_start(adap);
416 if (pch_i2c_wait_for_xfer_complete(adap) == 0 && 417
417 pch_i2c_getack(adap) == 0) { 418 rtn = pch_i2c_wait_for_xfer_complete(adap);
419 if (rtn == 0) {
420 if (pch_i2c_getack(adap)) {
421 pch_dbg(adap, "Receive NACK for slave address"
422 "setting\n");
423 return -EIO;
424 }
418 addr_8_lsb = (addr & I2C_ADDR_MSK); 425 addr_8_lsb = (addr & I2C_ADDR_MSK);
419 iowrite32(addr_8_lsb, p + PCH_I2CDR); 426 iowrite32(addr_8_lsb, p + PCH_I2CDR);
420 } else { 427 } else if (rtn == -EIO) { /* Arbitration Lost */
428 pch_err(adap, "Lost Arbitration\n");
429 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
430 I2CMAL_BIT);
431 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
432 I2CMIF_BIT);
433 pch_i2c_init(adap);
434 return -EAGAIN;
435 } else { /* wait-event timeout */
421 pch_i2c_stop(adap); 436 pch_i2c_stop(adap);
422 return -ETIME; 437 return -ETIME;
423 } 438 }
@@ -428,30 +443,48 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
428 pch_i2c_start(adap); 443 pch_i2c_start(adap);
429 } 444 }
430 445
431 if ((pch_i2c_wait_for_xfer_complete(adap) == 0) && 446 rtn = pch_i2c_wait_for_xfer_complete(adap);
432 (pch_i2c_getack(adap) == 0)) { 447 if (rtn == 0) {
433 for (wrcount = 0; wrcount < length; ++wrcount) { 448 if (pch_i2c_getack(adap)) {
434 /* write buffer value to I2C data register */ 449 pch_dbg(adap, "Receive NACK for slave address"
435 iowrite32(buf[wrcount], p + PCH_I2CDR); 450 "setting\n");
436 pch_dbg(adap, "writing %x to Data register\n", 451 return -EIO;
437 buf[wrcount]); 452 }
453 } else if (rtn == -EIO) { /* Arbitration Lost */
454 pch_err(adap, "Lost Arbitration\n");
455 pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
456 pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
457 return -EAGAIN;
458 } else { /* wait-event timeout */
459 return -ETIME;
460 }
438 461
439 if (pch_i2c_wait_for_xfer_complete(adap) != 0) 462 for (wrcount = 0; wrcount < length; ++wrcount) {
440 return -ETIME; 463 /* write buffer value to I2C data register */
464 iowrite32(buf[wrcount], p + PCH_I2CDR);
465 pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
441 466
442 if (pch_i2c_getack(adap)) 467 rtn = pch_i2c_wait_for_xfer_complete(adap);
468 if (rtn == 0) {
469 if (pch_i2c_getack(adap)) {
470 pch_dbg(adap, "Receive NACK for slave address"
471 "setting\n");
443 return -EIO; 472 return -EIO;
473 }
474 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
475 I2CMCF_BIT);
476 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
477 I2CMIF_BIT);
478 } else { /* wait-event timeout */
479 return -ETIME;
444 } 480 }
481 }
445 482
446 /* check if this is the last message */ 483 /* check if this is the last message */
447 if (last) 484 if (last)
448 pch_i2c_stop(adap);
449 else
450 pch_i2c_repstart(adap);
451 } else {
452 pch_i2c_stop(adap); 485 pch_i2c_stop(adap);
453 return -EIO; 486 else
454 } 487 pch_i2c_repstart(adap);
455 488
456 pch_dbg(adap, "return=%d\n", wrcount); 489 pch_dbg(adap, "return=%d\n", wrcount);
457 490
@@ -512,6 +545,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
512 u32 addr_2_msb; 545 u32 addr_2_msb;
513 u32 addr_8_lsb; 546 u32 addr_8_lsb;
514 void __iomem *p = adap->pch_base_address; 547 void __iomem *p = adap->pch_base_address;
548 s32 rtn;
515 549
516 length = msgs->len; 550 length = msgs->len;
517 buf = msgs->buf; 551 buf = msgs->buf;
@@ -585,56 +619,79 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
585 if (first) 619 if (first)
586 pch_i2c_start(adap); 620 pch_i2c_start(adap);
587 621
588 if ((pch_i2c_wait_for_xfer_complete(adap) == 0) && 622 rtn = pch_i2c_wait_for_xfer_complete(adap);
589 (pch_i2c_getack(adap) == 0)) { 623 if (rtn == 0) {
590 pch_dbg(adap, "return %d\n", 0); 624 if (pch_i2c_getack(adap)) {
625 pch_dbg(adap, "Receive NACK for slave address"
626 "setting\n");
627 return -EIO;
628 }
629 } else if (rtn == -EIO) { /* Arbitration Lost */
630 pch_err(adap, "Lost Arbitration\n");
631 pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
632 pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
633 return -EAGAIN;
634 } else { /* wait-event timeout */
635 return -ETIME;
636 }
591 637
592 if (length == 0) { 638 if (length == 0) {
593 pch_i2c_stop(adap); 639 pch_i2c_stop(adap);
594 ioread32(p + PCH_I2CDR); /* Dummy read needs */ 640 ioread32(p + PCH_I2CDR); /* Dummy read needs */
595 641
596 count = length; 642 count = length;
597 } else { 643 } else {
598 int read_index; 644 int read_index;
599 int loop; 645 int loop;
600 pch_i2c_sendack(adap); 646 pch_i2c_sendack(adap);
601 647
602 /* Dummy read */ 648 /* Dummy read */
603 for (loop = 1, read_index = 0; loop < length; loop++) { 649 for (loop = 1, read_index = 0; loop < length; loop++) {
604 buf[read_index] = ioread32(p + PCH_I2CDR); 650 buf[read_index] = ioread32(p + PCH_I2CDR);
605 651
606 if (loop != 1) 652 if (loop != 1)
607 read_index++; 653 read_index++;
608 654
609 if (pch_i2c_wait_for_xfer_complete(adap) != 0) { 655 rtn = pch_i2c_wait_for_xfer_complete(adap);
610 pch_i2c_stop(adap); 656 if (rtn == 0) {
611 return -ETIME; 657 if (pch_i2c_getack(adap)) {
658 pch_dbg(adap, "Receive NACK for slave"
659 "address setting\n");
660 return -EIO;
612 } 661 }
613 } /* end for */ 662 } else { /* wait-event timeout */
663 pch_i2c_stop(adap);
664 return -ETIME;
665 }
614 666
615 pch_i2c_sendnack(adap); 667 } /* end for */
616 668
617 buf[read_index] = ioread32(p + PCH_I2CDR); 669 pch_i2c_sendnack(adap);
618 670
619 if (length != 1) 671 buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */
620 read_index++;
621 672
622 if (pch_i2c_wait_for_xfer_complete(adap) == 0) { 673 if (length != 1)
623 if (last) 674 read_index++;
624 pch_i2c_stop(adap);
625 else
626 pch_i2c_repstart(adap);
627 675
628 buf[read_index++] = ioread32(p + PCH_I2CDR); 676 rtn = pch_i2c_wait_for_xfer_complete(adap);
629 count = read_index; 677 if (rtn == 0) {
630 } else { 678 if (pch_i2c_getack(adap)) {
631 count = -ETIME; 679 pch_dbg(adap, "Receive NACK for slave"
680 "address setting\n");
681 return -EIO;
632 } 682 }
633 683 } else { /* wait-event timeout */
684 pch_i2c_stop(adap);
685 return -ETIME;
634 } 686 }
635 } else { 687
636 count = -ETIME; 688 if (last)
637 pch_i2c_stop(adap); 689 pch_i2c_stop(adap);
690 else
691 pch_i2c_repstart(adap);
692
693 buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
694 count = read_index;
638 } 695 }
639 696
640 return count; 697 return count;