aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2012-06-13 04:22:44 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-07-13 02:37:04 -0400
commit28a377c79af918fc40c70553216571314c5f42a4 (patch)
treea84d58d7b4870d3acae9989af9102784fef08808 /drivers/i2c/busses
parent2ee74eb95cf36b1a69e483f9ba2191bd8022b2c1 (diff)
i2c:i2c-bfin-twi: TWI fails to restart next transfer in high system load.
Current driver was developed based on BF537 0.2 HRM. In high system load, BUFRDERR error interrupt may be raised if XMTSERV interrupt of last TX byte is not served in time (set RSTART bit), which breaks restart tranfer as expected. "Buffer Read Error (BUFRDERR)" description in Blackfin HRM only applys to BF537 rev. < 0.3. In later rev. and later announced Blackfin chips, such as BF527 and BF548, a new TWI master feature "Clock Stretching" is added into the TWI controller, BUFRDERR interrupt is not triggered after TX FIFO is empty. This patch sets RSTART bit at the beginning of the first transfer. The SCL and SDA is hold till XMTSERV interrupt of last TX byte is served. Restart transfer is not broken in high system load. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> [wsa: fixed spaces around operators] Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 71be486a224..2288e1bcf01 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -99,7 +99,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
99 */ 99 */
100 else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) 100 else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
101 write_MASTER_CTL(iface, 101 write_MASTER_CTL(iface,
102 read_MASTER_CTL(iface) | MDIR | RSTART); 102 read_MASTER_CTL(iface) | MDIR);
103 else if (iface->manual_stop) 103 else if (iface->manual_stop)
104 write_MASTER_CTL(iface, 104 write_MASTER_CTL(iface,
105 read_MASTER_CTL(iface) | STOP); 105 read_MASTER_CTL(iface) | STOP);
@@ -107,10 +107,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
107 iface->cur_msg + 1 < iface->msg_num) { 107 iface->cur_msg + 1 < iface->msg_num) {
108 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) 108 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
109 write_MASTER_CTL(iface, 109 write_MASTER_CTL(iface,
110 read_MASTER_CTL(iface) | RSTART | MDIR); 110 read_MASTER_CTL(iface) | MDIR);
111 else 111 else
112 write_MASTER_CTL(iface, 112 write_MASTER_CTL(iface,
113 (read_MASTER_CTL(iface) | RSTART) & ~MDIR); 113 read_MASTER_CTL(iface) & ~MDIR);
114 } 114 }
115 } 115 }
116 if (twi_int_status & RCVSERV) { 116 if (twi_int_status & RCVSERV) {
@@ -144,10 +144,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
144 iface->cur_msg + 1 < iface->msg_num) { 144 iface->cur_msg + 1 < iface->msg_num) {
145 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) 145 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
146 write_MASTER_CTL(iface, 146 write_MASTER_CTL(iface,
147 read_MASTER_CTL(iface) | RSTART | MDIR); 147 read_MASTER_CTL(iface) | MDIR);
148 else 148 else
149 write_MASTER_CTL(iface, 149 write_MASTER_CTL(iface,
150 (read_MASTER_CTL(iface) | RSTART) & ~MDIR); 150 read_MASTER_CTL(iface) & ~MDIR);
151 } 151 }
152 } 152 }
153 } 153 }
@@ -230,7 +230,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
230 write_MASTER_CTL(iface, 230 write_MASTER_CTL(iface,
231 read_MASTER_CTL(iface) & ~RSTART); 231 read_MASTER_CTL(iface) & ~RSTART);
232 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 232 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
233 iface->cur_msg+1 < iface->msg_num) { 233 iface->cur_msg + 1 < iface->msg_num) {
234 iface->cur_msg++; 234 iface->cur_msg++;
235 iface->transPtr = iface->pmsg[iface->cur_msg].buf; 235 iface->transPtr = iface->pmsg[iface->cur_msg].buf;
236 iface->writeNum = iface->readNum = 236 iface->writeNum = iface->readNum =
@@ -262,9 +262,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
262 (0xff << 6))); 262 (0xff << 6)));
263 iface->manual_stop = 1; 263 iface->manual_stop = 1;
264 } 264 }
265 /* remove restart bit and enable master receive */ 265 /* remove restart bit before last message */
266 write_MASTER_CTL(iface, 266 if (iface->cur_msg + 1 == iface->msg_num)
267 read_MASTER_CTL(iface) & ~RSTART); 267 write_MASTER_CTL(iface,
268 read_MASTER_CTL(iface) & ~RSTART);
268 } else { 269 } else {
269 iface->result = 1; 270 iface->result = 1;
270 write_INT_MASK(iface, 0); 271 write_INT_MASK(iface, 0);
@@ -321,7 +322,8 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
321 return -EINVAL; 322 return -EINVAL;
322 } 323 }
323 324
324 iface->cur_mode = TWI_I2C_MODE_REPEAT; 325 if (iface->msg_num > 1)
326 iface->cur_mode = TWI_I2C_MODE_REPEAT;
325 iface->manual_stop = 0; 327 iface->manual_stop = 0;
326 iface->transPtr = pmsg->buf; 328 iface->transPtr = pmsg->buf;
327 iface->writeNum = iface->readNum = pmsg->len; 329 iface->writeNum = iface->readNum = pmsg->len;
@@ -366,6 +368,7 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
366 368
367 /* Master enable */ 369 /* Master enable */
368 write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | 370 write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
371 (iface->msg_num > 1 ? RSTART : 0) |
369 ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | 372 ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
370 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); 373 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
371 SSYNC(); 374 SSYNC();
@@ -530,7 +533,7 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
530 else 533 else
531 write_MASTER_CTL(iface, 0x1 << 6); 534 write_MASTER_CTL(iface, 0x1 << 6);
532 /* Master enable */ 535 /* Master enable */
533 write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | 536 write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | RSTART |
534 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); 537 ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
535 break; 538 break;
536 default: 539 default: