i2c i2c-mv64xxx: send repeated START between messages in xfer
PATCH 1/3 i2c 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.
--- drivers/i2c/busses/i2c-mv64xxx.c | 45 ++++++++++++++++++++++++++++++++------ 1 files changed, 38 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-mv64xxx.c +38 -7
@@ -59,6 +59,7 @@ enum {MV64XXX_I2C_STATE_INVALID ,MV64XXX_I2C_STATE_IDLE ,MV64XXX_I2C_STATE_WAITING_FOR_START_COND , +MV64XXX_I2C_STATE_WAITING_FOR_RESTART ,MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK ,MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK , MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
@@ -70,6 +71,7 @@ enum {MV64XXX_I2C_ACTION_INVALID ,MV64XXX_I2C_ACTION_CONTINUE ,MV64XXX_I2C_ACTION_SEND_START , +MV64XXX_I2C_ACTION_SEND_RESTART ,MV64XXX_I2C_ACTION_SEND_ADDR_1 ,MV64XXX_I2C_ACTION_SEND_ADDR_2 , MV64XXX_I2C_ACTION_SEND_DATA,
@@ -91,6 +93,7 @@ struct mv64xxx_i2c_data {u32 addr2;u32 bytes_left;u32 byte_posn; +u32 send_stop;u32 block;int rc;u32 freq_m;
@@ -159,8 +162,15 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)if ((drv_data->bytes_left ==0 ) || (drv_data->aborting && (drv_data->byte_posn !=0 ))) { - drv_data->action =MV64XXX_I2C_ACTION_SEND_STOP ; - drv_data->state =MV64XXX_I2C_STATE_IDLE ; +if (drv_data->send_stop) { + drv_data->action =MV64XXX_I2C_ACTION_SEND_STOP ; + drv_data->state =MV64XXX_I2C_STATE_IDLE ; + }else { + drv_data->action = +MV64XXX_I2C_ACTION_SEND_RESTART ; + drv_data->state = +MV64XXX_I2C_STATE_WAITING_FOR_RESTART ; + } }else { drv_data->action =MV64XXX_I2C_ACTION_SEND_DATA ; drv_data->state =
@@ -228,6 +238,15 @@ static void mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) {switch (drv_data->action) { +case MV64XXX_I2C_ACTION_SEND_RESTART : + drv_data->cntl_bits |=MV64XXX_I2C_REG_CONTROL_START ; + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN ; +writel (drv_data->cntl_bits, + drv_data->reg_base +MV64XXX_I2C_REG_CONTROL ); + drv_data->block =0 ; +wake_up_interruptible (&drv_data->waitq); +break ; +case MV64XXX_I2C_ACTION_CONTINUE :writel (drv_data->cntl_bits, drv_data->reg_base +MV64XXX_I2C_REG_CONTROL );
@@ -386,7 +405,8 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) }static int -mv64xxx_i2c_execute_msg (struct mv64xxx_i2c_data *drv_data,struct i2c_msg *msg) +mv64xxx_i2c_execute_msg (struct mv64xxx_i2c_data *drv_data,struct i2c_msg *msg, +int is_first,int is_last) {unsigned long flags;
@@ -406,10 +426,18 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) drv_data->bytes_left--; } }else { - drv_data->action =MV64XXX_I2C_ACTION_SEND_START ; - drv_data->state =MV64XXX_I2C_STATE_WAITING_FOR_START_COND ; +if (is_first) { + drv_data->action =MV64XXX_I2C_ACTION_SEND_START ; + drv_data->state = +MV64XXX_I2C_STATE_WAITING_FOR_START_COND ; + }else { + drv_data->action =MV64XXX_I2C_ACTION_SEND_ADDR_1 ; + drv_data->state = +MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK ; + } } + drv_data->send_stop = is_last; drv_data->block =1 ;mv64xxx_i2c_do_action (drv_data);spin_unlock_irqrestore (&drv_data->lock, flags);
@@ -437,9 +465,12 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)struct mv64xxx_i2c_data *drv_data =i2c_get_adapdata (adap);int i, rc; -for (i=0 ; i<num; i++) -if ((rc =mv64xxx_i2c_execute_msg (drv_data, &msgs[i])) <0 ) +for (i =0 ; i < num; i++) { + rc =mv64xxx_i2c_execute_msg (drv_data, &msgs[i], + i ==0 , i +1 == num); +if (rc <0 )return rc; + }return num; }
Signature · 1 line
1.7.1
A message that is not in the archive (sent off-list or not yet received): 1290787616-27106-1-git-send-email-giometti-k2GhghHVRtY@public.gmane.org
Quoted 2 lines · Rodolfo Giometti
As stated into file
include/linux/i2c.hwe must send a repeated START between messages in the same xfer groupset:
patch says 1/3, but only one turned up?
Quoted 9 lines
* 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.
Quoted 4 lines
Signed-off-by Rodolfo Giometti <[email protected]>Signed-off-by Mauro Barella <[email protected]>--- drivers/i2c/busses/i2c-mv64xxx.c | 45 ++++++++++++++++++++++++++++++++------
Anyone got any commentson whether this is an -rc fix or for next merge window... I'd be tempted to merge it as soon as possible.
Signature · 4 lines
Ben Q: What's a light-year? A: One-third less calories than a regular year.
A message that is not in the archive (sent off-list or not yet received): 20101203023020.GE20097-SMNkleLxa3Z6Wcw2j4pizdi2O/[email protected]
Quoted 5 lines · Ben Dooks
Quoted 2 lines · Rodolfo Giometti
As stated into file
include/linux/i2c.hwe must send a repeated START between messages in the same xfer groupset:patch says 1/3, but only one turned up?
Yes, sorry. It was my mistake in numbering the patch. :'( This is the only patch regarding this topic.
Ciao,
Rodolfo
Signature · 5 lines
GNU/Linux Solutions e-mail: giometti-AVVDYK/kqiJWk0Htik3J/[email protected] Linux Device Driver [email protected] Embedded Systems phone: +39 349 2432127 UNIX programming skype: rodolfo.giometti Freelance ICT Italia - Consulente ICT Italia - www.consulenti-ict.it