diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-bfin-twi.c')
-rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 59 |
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 | ||
570 | static struct i2c_algorithm bfin_twi_algorithm = { | 588 | static 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); |