aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRodolfo Giometti <giometti@linux.it>2010-11-26 11:06:56 -0500
committerBen Dooks <ben-linux@fluff.org>2011-01-03 20:19:43 -0500
commiteda6bee6c7e67b5bd17bdbced0926f5687f686d5 (patch)
tree3f2be4bb958e1fd320494973d55c45f91381ef4a /drivers
parent03ed6a3aa600c48593c3984812fda2d5945ddb46 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c45
1 files changed, 38 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 16242063144f..a9941c65f226 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -59,6 +59,7 @@ enum {
59 MV64XXX_I2C_STATE_INVALID, 59 MV64XXX_I2C_STATE_INVALID,
60 MV64XXX_I2C_STATE_IDLE, 60 MV64XXX_I2C_STATE_IDLE,
61 MV64XXX_I2C_STATE_WAITING_FOR_START_COND, 61 MV64XXX_I2C_STATE_WAITING_FOR_START_COND,
62 MV64XXX_I2C_STATE_WAITING_FOR_RESTART,
62 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, 63 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
63 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, 64 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
64 MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, 65 MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
@@ -70,6 +71,7 @@ enum {
70 MV64XXX_I2C_ACTION_INVALID, 71 MV64XXX_I2C_ACTION_INVALID,
71 MV64XXX_I2C_ACTION_CONTINUE, 72 MV64XXX_I2C_ACTION_CONTINUE,
72 MV64XXX_I2C_ACTION_SEND_START, 73 MV64XXX_I2C_ACTION_SEND_START,
74 MV64XXX_I2C_ACTION_SEND_RESTART,
73 MV64XXX_I2C_ACTION_SEND_ADDR_1, 75 MV64XXX_I2C_ACTION_SEND_ADDR_1,
74 MV64XXX_I2C_ACTION_SEND_ADDR_2, 76 MV64XXX_I2C_ACTION_SEND_ADDR_2,
75 MV64XXX_I2C_ACTION_SEND_DATA, 77 MV64XXX_I2C_ACTION_SEND_DATA,
@@ -91,6 +93,7 @@ struct mv64xxx_i2c_data {
91 u32 addr2; 93 u32 addr2;
92 u32 bytes_left; 94 u32 bytes_left;
93 u32 byte_posn; 95 u32 byte_posn;
96 u32 send_stop;
94 u32 block; 97 u32 block;
95 int rc; 98 int rc;
96 u32 freq_m; 99 u32 freq_m;
@@ -159,8 +162,15 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
159 if ((drv_data->bytes_left == 0) 162 if ((drv_data->bytes_left == 0)
160 || (drv_data->aborting 163 || (drv_data->aborting
161 && (drv_data->byte_posn != 0))) { 164 && (drv_data->byte_posn != 0))) {
162 drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; 165 if (drv_data->send_stop) {
163 drv_data->state = MV64XXX_I2C_STATE_IDLE; 166 drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
167 drv_data->state = MV64XXX_I2C_STATE_IDLE;
168 } else {
169 drv_data->action =
170 MV64XXX_I2C_ACTION_SEND_RESTART;
171 drv_data->state =
172 MV64XXX_I2C_STATE_WAITING_FOR_RESTART;
173 }
164 } else { 174 } else {
165 drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; 175 drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
166 drv_data->state = 176 drv_data->state =
@@ -228,6 +238,15 @@ static void
228mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) 238mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
229{ 239{
230 switch(drv_data->action) { 240 switch(drv_data->action) {
241 case MV64XXX_I2C_ACTION_SEND_RESTART:
242 drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
243 drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
244 writel(drv_data->cntl_bits,
245 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
246 drv_data->block = 0;
247 wake_up_interruptible(&drv_data->waitq);
248 break;
249
231 case MV64XXX_I2C_ACTION_CONTINUE: 250 case MV64XXX_I2C_ACTION_CONTINUE:
232 writel(drv_data->cntl_bits, 251 writel(drv_data->cntl_bits,
233 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); 252 drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
@@ -386,7 +405,8 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
386} 405}
387 406
388static int 407static int
389mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) 408mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
409 int is_first, int is_last)
390{ 410{
391 unsigned long flags; 411 unsigned long flags;
392 412
@@ -406,10 +426,18 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg)
406 drv_data->bytes_left--; 426 drv_data->bytes_left--;
407 } 427 }
408 } else { 428 } else {
409 drv_data->action = MV64XXX_I2C_ACTION_SEND_START; 429 if (is_first) {
410 drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; 430 drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
431 drv_data->state =
432 MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
433 } else {
434 drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;
435 drv_data->state =
436 MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;
437 }
411 } 438 }
412 439
440 drv_data->send_stop = is_last;
413 drv_data->block = 1; 441 drv_data->block = 1;
414 mv64xxx_i2c_do_action(drv_data); 442 mv64xxx_i2c_do_action(drv_data);
415 spin_unlock_irqrestore(&drv_data->lock, flags); 443 spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -437,9 +465,12 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
437 struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); 465 struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
438 int i, rc; 466 int i, rc;
439 467
440 for (i=0; i<num; i++) 468 for (i = 0; i < num; i++) {
441 if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0) 469 rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i],
470 i == 0, i + 1 == num);
471 if (rc < 0)
442 return rc; 472 return rc;
473 }
443 474
444 return num; 475 return num;
445} 476}