Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c-mv64xxx: send repeated START between messages in xfer

As stated into file include/linux/i2c.h we must send a repeated START
between messages in the same xfer groupset:

* Except when I2C "protocol mangling" is used, all I2C adapters implement
* the standard rules for I2C transactions. Each transaction begins with a
* START. That is followed by the slave address, and a bit encoding read
* versus write. Then follow all the data bytes, possibly including a byte
* with SMBus PEC. The transfer terminates with a NAK, or when all those
* bytes have been transferred and ACKed. If this is the last message in a
* group, it is followed by a STOP. Otherwise it is followed by the next
* @i2c_msg transaction segment, beginning with a (repeated) START.

Signed-off-by: Rodolfo Giometti <giometti@linux.it>
Signed-off-by: Mauro Barella <mbarella@vds-it.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>

authored by

Rodolfo Giometti and committed by
Ben Dooks
eda6bee6 03ed6a3a

+38 -7
+38 -7
drivers/i2c/busses/i2c-mv64xxx.c
··· 59 59 MV64XXX_I2C_STATE_INVALID, 60 60 MV64XXX_I2C_STATE_IDLE, 61 61 MV64XXX_I2C_STATE_WAITING_FOR_START_COND, 62 + MV64XXX_I2C_STATE_WAITING_FOR_RESTART, 62 63 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, 63 64 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, 64 65 MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, ··· 71 70 MV64XXX_I2C_ACTION_INVALID, 72 71 MV64XXX_I2C_ACTION_CONTINUE, 73 72 MV64XXX_I2C_ACTION_SEND_START, 73 + MV64XXX_I2C_ACTION_SEND_RESTART, 74 74 MV64XXX_I2C_ACTION_SEND_ADDR_1, 75 75 MV64XXX_I2C_ACTION_SEND_ADDR_2, 76 76 MV64XXX_I2C_ACTION_SEND_DATA, ··· 93 91 u32 addr2; 94 92 u32 bytes_left; 95 93 u32 byte_posn; 94 + u32 send_stop; 96 95 u32 block; 97 96 int rc; 98 97 u32 freq_m; ··· 162 159 if ((drv_data->bytes_left == 0) 163 160 || (drv_data->aborting 164 161 && (drv_data->byte_posn != 0))) { 165 - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; 166 - drv_data->state = MV64XXX_I2C_STATE_IDLE; 162 + if (drv_data->send_stop) { 163 + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; 164 + drv_data->state = MV64XXX_I2C_STATE_IDLE; 165 + } else { 166 + drv_data->action = 167 + MV64XXX_I2C_ACTION_SEND_RESTART; 168 + drv_data->state = 169 + MV64XXX_I2C_STATE_WAITING_FOR_RESTART; 170 + } 167 171 } else { 168 172 drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; 169 173 drv_data->state = ··· 238 228 mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) 239 229 { 240 230 switch(drv_data->action) { 231 + case MV64XXX_I2C_ACTION_SEND_RESTART: 232 + drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; 233 + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; 234 + writel(drv_data->cntl_bits, 235 + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); 236 + drv_data->block = 0; 237 + wake_up_interruptible(&drv_data->waitq); 238 + break; 239 + 241 240 case MV64XXX_I2C_ACTION_CONTINUE: 242 241 writel(drv_data->cntl_bits, 243 242 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); ··· 405 386 } 406 387 407 388 static int 408 - mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) 389 + mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, 390 + int is_first, int is_last) 409 391 { 410 392 unsigned long flags; 411 393 ··· 426 406 drv_data->bytes_left--; 427 407 } 428 408 } else { 429 - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; 430 - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; 409 + if (is_first) { 410 + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; 411 + drv_data->state = 412 + MV64XXX_I2C_STATE_WAITING_FOR_START_COND; 413 + } else { 414 + drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; 415 + drv_data->state = 416 + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; 417 + } 431 418 } 432 419 420 + drv_data->send_stop = is_last; 433 421 drv_data->block = 1; 434 422 mv64xxx_i2c_do_action(drv_data); 435 423 spin_unlock_irqrestore(&drv_data->lock, flags); ··· 465 437 struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); 466 438 int i, rc; 467 439 468 - for (i=0; i<num; i++) 469 - if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0) 440 + for (i = 0; i < num; i++) { 441 + rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], 442 + i == 0, i + 1 == num); 443 + if (rc < 0) 470 444 return rc; 445 + } 471 446 472 447 return num; 473 448 }