aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-bfin-twi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-bfin-twi.c')
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index fc548b3d002e..26d8987e69bf 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -104,9 +104,14 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
104 write_MASTER_CTL(iface, 104 write_MASTER_CTL(iface,
105 read_MASTER_CTL(iface) | STOP); 105 read_MASTER_CTL(iface) | STOP);
106 else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 106 else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
107 iface->cur_msg+1 < iface->msg_num) 107 iface->cur_msg + 1 < iface->msg_num) {
108 write_MASTER_CTL(iface, 108 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
109 read_MASTER_CTL(iface) | RSTART); 109 write_MASTER_CTL(iface,
110 read_MASTER_CTL(iface) | RSTART | MDIR);
111 else
112 write_MASTER_CTL(iface,
113 (read_MASTER_CTL(iface) | RSTART) & ~MDIR);
114 }
110 SSYNC(); 115 SSYNC();
111 /* Clear status */ 116 /* Clear status */
112 write_INT_STAT(iface, XMTSERV); 117 write_INT_STAT(iface, XMTSERV);
@@ -134,9 +139,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
134 read_MASTER_CTL(iface) | STOP); 139 read_MASTER_CTL(iface) | STOP);
135 SSYNC(); 140 SSYNC();
136 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 141 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
137 iface->cur_msg+1 < iface->msg_num) { 142 iface->cur_msg + 1 < iface->msg_num) {
138 write_MASTER_CTL(iface, 143 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
139 read_MASTER_CTL(iface) | RSTART); 144 write_MASTER_CTL(iface,
145 read_MASTER_CTL(iface) | RSTART | MDIR);
146 else
147 write_MASTER_CTL(iface,
148 (read_MASTER_CTL(iface) | RSTART) & ~MDIR);
140 SSYNC(); 149 SSYNC();
141 } 150 }
142 /* Clear interrupt source */ 151 /* Clear interrupt source */
@@ -196,8 +205,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
196 /* remove restart bit and enable master receive */ 205 /* remove restart bit and enable master receive */
197 write_MASTER_CTL(iface, 206 write_MASTER_CTL(iface,
198 read_MASTER_CTL(iface) & ~RSTART); 207 read_MASTER_CTL(iface) & ~RSTART);
199 write_MASTER_CTL(iface,
200 read_MASTER_CTL(iface) | MEN | MDIR);
201 SSYNC(); 208 SSYNC();
202 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 209 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
203 iface->cur_msg+1 < iface->msg_num) { 210 iface->cur_msg+1 < iface->msg_num) {
@@ -222,18 +229,19 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
222 } 229 }
223 230
224 if (iface->pmsg[iface->cur_msg].len <= 255) 231 if (iface->pmsg[iface->cur_msg].len <= 255)
225 write_MASTER_CTL(iface, 232 write_MASTER_CTL(iface,
226 iface->pmsg[iface->cur_msg].len << 6); 233 (read_MASTER_CTL(iface) &
234 (~(0xff << 6))) |
235 (iface->pmsg[iface->cur_msg].len << 6));
227 else { 236 else {
228 write_MASTER_CTL(iface, 0xff << 6); 237 write_MASTER_CTL(iface,
238 (read_MASTER_CTL(iface) |
239 (0xff << 6)));
229 iface->manual_stop = 1; 240 iface->manual_stop = 1;
230 } 241 }
231 /* remove restart bit and enable master receive */ 242 /* remove restart bit and enable master receive */
232 write_MASTER_CTL(iface, 243 write_MASTER_CTL(iface,
233 read_MASTER_CTL(iface) & ~RSTART); 244 read_MASTER_CTL(iface) & ~RSTART);
234 write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
235 MEN | ((iface->read_write == I2C_SMBUS_READ) ?
236 MDIR : 0));
237 SSYNC(); 245 SSYNC();
238 } else { 246 } else {
239 iface->result = 1; 247 iface->result = 1;
@@ -441,6 +449,16 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
441 } 449 }
442 iface->transPtr = data->block; 450 iface->transPtr = data->block;
443 break; 451 break;
452 case I2C_SMBUS_I2C_BLOCK_DATA:
453 if (read_write == I2C_SMBUS_READ) {
454 iface->readNum = data->block[0];
455 iface->cur_mode = TWI_I2C_MODE_COMBINED;
456 } else {
457 iface->writeNum = data->block[0];
458 iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
459 }
460 iface->transPtr = (u8 *)&data->block[1];
461 break;
444 default: 462 default:
445 return -1; 463 return -1;
446 } 464 }
@@ -564,7 +582,7 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap)
564 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 582 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
565 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 583 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
566 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | 584 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
567 I2C_FUNC_I2C; 585 I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK;
568} 586}
569 587
570static struct i2c_algorithm bfin_twi_algorithm = { 588static struct i2c_algorithm bfin_twi_algorithm = {
@@ -614,6 +632,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
614 struct i2c_adapter *p_adap; 632 struct i2c_adapter *p_adap;
615 struct resource *res; 633 struct resource *res;
616 int rc; 634 int rc;
635 unsigned int clkhilow;
617 636
618 iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL); 637 iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
619 if (!iface) { 638 if (!iface) {
@@ -675,10 +694,14 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
675 /* Set TWI internal clock as 10MHz */ 694 /* Set TWI internal clock as 10MHz */
676 write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); 695 write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
677 696
697 /*
698 * We will not end up with a CLKDIV=0 because no one will specify
699 * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100)
700 */
701 clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ;
702
678 /* Set Twi interface clock as specified */ 703 /* Set Twi interface clock as specified */
679 write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) 704 write_CLKDIV(iface, (clkhilow << 8) | clkhilow);
680 << 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
681 & 0xFF));
682 705
683 /* Enable TWI */ 706 /* Enable TWI */
684 write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); 707 write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);