+additional lists > I2C QUP driver relies on SMBus emulation support from the framework. > To handle SMBus block reads, the driver should check I2C_M_RECV_LEN flag > and should read the first byte received as the message length. > > The driver configures the QUP hardware to read one byte. Once the message > length is known from this byte, the QUP hardware is configured to read the > rest. > > Signed-off-by: Naveen Kaje <nkaje@xxxxxxxxxxxxxx> > --- > drivers/i2c/busses/i2c-qup.c | 95 ++++++++++++++++++++++++++++++------- > ------- > 1 file changed, 66 insertions(+), 29 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index > ef31b26..2658b67 100644 > --- a/drivers/i2c/busses/i2c-qup.c > +++ b/drivers/i2c/busses/i2c-qup.c > @@ -526,38 +526,49 @@ static int qup_i2c_set_tags(u8 *tags, struct > qup_i2c_dev *qup, > > int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last); > > - if (qup->blk.pos == 0) { > - tags[len++] = QUP_TAG_V2_START; > - tags[len++] = addr & 0xff; > + /* Handle SMBus block data read */ > + if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN) > && > + (msg->len > 1)) { > + tags[len++] = QUP_TAG_V2_DATARD_STOP; > + data_len = qup_i2c_get_data_len(qup); > + tags[len++] = data_len - 1; > + } else { > + if (qup->blk.pos == 0) { > + tags[len++] = QUP_TAG_V2_START; > + tags[len++] = addr & 0xff; > > - if (msg->flags & I2C_M_TEN) > - tags[len++] = addr >> 8; > - } > + if (msg->flags & I2C_M_TEN) > + tags[len++] = addr >> 8; > + } > > - /* Send _STOP commands for the last block */ > - if (last) { > - if (msg->flags & I2C_M_RD) > - tags[len++] = QUP_TAG_V2_DATARD_STOP; > - else > - tags[len++] = QUP_TAG_V2_DATAWR_STOP; > - } else { > - if (msg->flags & I2C_M_RD) > + /* Send _STOP commands for the last block */ > + if ((msg->flags & I2C_M_RD) > + && (msg->flags & I2C_M_RECV_LEN)) { > tags[len++] = QUP_TAG_V2_DATARD; > - else > - tags[len++] = QUP_TAG_V2_DATAWR; > - } > + } else if (last) { > + if (msg->flags & I2C_M_RD) > + tags[len++] = QUP_TAG_V2_DATARD_STOP; > + else > + tags[len++] = QUP_TAG_V2_DATAWR_STOP; > + } else { > + if (msg->flags & I2C_M_RD) > + tags[len++] = QUP_TAG_V2_DATARD; > + else > + tags[len++] = QUP_TAG_V2_DATAWR; > + } > > - data_len = qup_i2c_get_data_len(qup); > + data_len = qup_i2c_get_data_len(qup); > > - /* 0 implies 256 bytes */ > - if (data_len == QUP_READ_LIMIT) > - tags[len++] = 0; > - else > - tags[len++] = data_len; > + /* 0 implies 256 bytes */ > + if (data_len == QUP_READ_LIMIT) > + tags[len++] = 0; > + else > + tags[len++] = data_len; > > - if ((msg->flags & I2C_M_RD) && last && is_dma) { > - tags[len++] = QUP_BAM_INPUT_EOT; > - tags[len++] = QUP_BAM_FLUSH_STOP; > + if ((msg->flags & I2C_M_RD) && last && is_dma) { > + tags[len++] = QUP_BAM_INPUT_EOT; > + tags[len++] = QUP_BAM_FLUSH_STOP; > + } > } > Will it look simpler if we add a qup_i2c_set_tags_smb instead and add an Comment ? Here it is not clear how this is different from a normal read. <snip..> > + > + /* Handle SMBus block read length */ > + if ((msg->flags & I2C_M_RECV_LEN) && (msg->len == 1)) { > + if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) { > + ret = -EPROTO; > + goto err; > + } > + msg->len += msg->buf[0]; > + qup->pos = 0; > + qup_i2c_set_read_mode_v2(qup, msg->len); > + qup_i2c_issue_xfer_v2(qup, msg); > + ret = qup_i2c_wait_for_complete(qup, msg); > + if (ret) > + goto err; > + qup_i2c_set_blk_data(qup, msg); > + } > } while (qup->blk.pos < qup->blk.count); When v2 mode is not supported this should return an error, in qup_i2c_xfer for msg->flags & I2C_M_RECV_LEN Regards, Sricharan -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html