aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.lapis-semi.com>2011-10-12 00:13:02 -0400
committerBen Dooks <ben-linux@fluff.org>2011-10-29 06:09:33 -0400
commitc249ac207f2cedb49f2c9442afbaac35bfcfcd25 (patch)
tree1d888cf780719716141d54c50346ed45f471109b /drivers/i2c/busses
parentc7b41f3affc63644f398b5faa170b1f531b406a8 (diff)
i2c-eg20t: Fix 10bit access issue
Reported-by: Jeffrey (Sheng-Hui) Chu <jeffchu@broadcom.com> 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')
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 543d39c73c37..38e44d959f00 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -64,6 +64,7 @@
64#define TEN_BIT_ADDR_DEFAULT 0xF000 64#define TEN_BIT_ADDR_DEFAULT 0xF000
65#define TEN_BIT_ADDR_MASK 0xF0 65#define TEN_BIT_ADDR_MASK 0xF0
66#define PCH_START 0x0020 66#define PCH_START 0x0020
67#define PCH_RESTART 0x0004
67#define PCH_ESR_START 0x0001 68#define PCH_ESR_START 0x0001
68#define PCH_BUFF_START 0x1 69#define PCH_BUFF_START 0x1
69#define PCH_REPSTART 0x0004 70#define PCH_REPSTART 0x0004
@@ -408,7 +409,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
408 } 409 }
409 410
410 if (msgs->flags & I2C_M_TEN) { 411 if (msgs->flags & I2C_M_TEN) {
411 addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7); 412 addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06;
412 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); 413 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
413 if (first) 414 if (first)
414 pch_i2c_start(adap); 415 pch_i2c_start(adap);
@@ -480,6 +481,19 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
480} 481}
481 482
482/** 483/**
484 * pch_i2c_restart() - Generate I2C restart condition in normal mode.
485 * @adap: Pointer to struct i2c_algo_pch_data.
486 *
487 * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA.
488 */
489static void pch_i2c_restart(struct i2c_algo_pch_data *adap)
490{
491 void __iomem *p = adap->pch_base_address;
492 pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL));
493 pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART);
494}
495
496/**
483 * pch_i2c_readbytes() - read data from I2C bus in normal mode. 497 * pch_i2c_readbytes() - read data from I2C bus in normal mode.
484 * @i2c_adap: Pointer to the struct i2c_adapter. 498 * @i2c_adap: Pointer to the struct i2c_adapter.
485 * @msgs: Pointer to i2c_msg structure. 499 * @msgs: Pointer to i2c_msg structure.
@@ -496,6 +510,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
496 u32 length; 510 u32 length;
497 u32 addr; 511 u32 addr;
498 u32 addr_2_msb; 512 u32 addr_2_msb;
513 u32 addr_8_lsb;
499 void __iomem *p = adap->pch_base_address; 514 void __iomem *p = adap->pch_base_address;
500 515
501 length = msgs->len; 516 length = msgs->len;
@@ -511,9 +526,55 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
511 } 526 }
512 527
513 if (msgs->flags & I2C_M_TEN) { 528 if (msgs->flags & I2C_M_TEN) {
514 addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD)); 529 addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
515 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); 530 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
531 if (first)
532 pch_i2c_start(adap);
516 533
534 rtn = pch_i2c_wait_for_xfer_complete(adap);
535 if (rtn == 0) {
536 if (pch_i2c_getack(adap)) {
537 pch_dbg(adap, "Receive NACK for slave address"
538 "setting\n");
539 return -EIO;
540 }
541 addr_8_lsb = (addr & I2C_ADDR_MSK);
542 iowrite32(addr_8_lsb, p + PCH_I2CDR);
543 } else if (rtn == -EIO) { /* Arbitration Lost */
544 pch_err(adap, "Lost Arbitration\n");
545 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
546 I2CMAL_BIT);
547 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
548 I2CMIF_BIT);
549 pch_i2c_init(adap);
550 return -EAGAIN;
551 } else { /* wait-event timeout */
552 pch_i2c_stop(adap);
553 return -ETIME;
554 }
555 pch_i2c_restart(adap);
556 rtn = pch_i2c_wait_for_xfer_complete(adap);
557 if (rtn == 0) {
558 if (pch_i2c_getack(adap)) {
559 pch_dbg(adap, "Receive NACK for slave address"
560 "setting\n");
561 return -EIO;
562 }
563 addr_2_msb |= I2C_RD;
564 iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
565 p + PCH_I2CDR);
566 } else if (rtn == -EIO) { /* Arbitration Lost */
567 pch_err(adap, "Lost Arbitration\n");
568 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
569 I2CMAL_BIT);
570 pch_clrbit(adap->pch_base_address, PCH_I2CSR,
571 I2CMIF_BIT);
572 pch_i2c_init(adap);
573 return -EAGAIN;
574 } else { /* wait-event timeout */
575 pch_i2c_stop(adap);
576 return -ETIME;
577 }
517 } else { 578 } else {
518 /* 7 address bits + R/W bit */ 579 /* 7 address bits + R/W bit */
519 addr = (((addr) << 1) | (I2C_RD)); 580 addr = (((addr) << 1) | (I2C_RD));