@@ -242,9 +242,10 @@ struct tegra_i2c_hw_feature {
242
242
* @is_dvc: identifies the DVC I2C controller, has a different register layout
243
243
* @is_vi: identifies the VI I2C controller, has a different register layout
244
244
* @msg_complete: transfer completion notifier
245
+ * @msg_buf_remaining: size of unsent data in the message buffer
246
+ * @msg_len: length of message in current transfer
245
247
* @msg_err: error code for completed message
246
248
* @msg_buf: pointer to current message data
247
- * @msg_buf_remaining: size of unsent data in the message buffer
248
249
* @msg_read: indicates that the transfer is a read access
249
250
* @timings: i2c timings information like bus frequency
250
251
* @multimaster_mode: indicates that I2C controller is in multi-master mode
@@ -277,6 +278,7 @@ struct tegra_i2c_dev {
277
278
278
279
struct completion msg_complete ;
279
280
size_t msg_buf_remaining ;
281
+ unsigned int msg_len ;
280
282
int msg_err ;
281
283
u8 * msg_buf ;
282
284
@@ -1169,7 +1171,7 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
1169
1171
else
1170
1172
i2c_writel (i2c_dev , packet_header , I2C_TX_FIFO );
1171
1173
1172
- packet_header = msg -> len - 1 ;
1174
+ packet_header = i2c_dev -> msg_len - 1 ;
1173
1175
1174
1176
if (i2c_dev -> dma_mode && !i2c_dev -> msg_read )
1175
1177
* dma_buf ++ = packet_header ;
@@ -1242,20 +1244,32 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
1242
1244
return err ;
1243
1245
1244
1246
i2c_dev -> msg_buf = msg -> buf ;
1247
+ i2c_dev -> msg_len = msg -> len ;
1245
1248
1246
- /* The condition true implies smbus block read and len is already read */
1247
- if (msg -> flags & I2C_M_RECV_LEN && end_state != MSG_END_CONTINUE )
1248
- i2c_dev -> msg_buf = msg -> buf + 1 ;
1249
-
1250
- i2c_dev -> msg_buf_remaining = msg -> len ;
1251
1249
i2c_dev -> msg_err = I2C_ERR_NONE ;
1252
1250
i2c_dev -> msg_read = !!(msg -> flags & I2C_M_RD );
1253
1251
reinit_completion (& i2c_dev -> msg_complete );
1254
1252
1253
+ /*
1254
+ * For SMBUS block read command, read only 1 byte in the first transfer.
1255
+ * Adjust that 1 byte for the next transfer in the msg buffer and msg
1256
+ * length.
1257
+ */
1258
+ if (msg -> flags & I2C_M_RECV_LEN ) {
1259
+ if (end_state == MSG_END_CONTINUE ) {
1260
+ i2c_dev -> msg_len = 1 ;
1261
+ } else {
1262
+ i2c_dev -> msg_buf += 1 ;
1263
+ i2c_dev -> msg_len -= 1 ;
1264
+ }
1265
+ }
1266
+
1267
+ i2c_dev -> msg_buf_remaining = i2c_dev -> msg_len ;
1268
+
1255
1269
if (i2c_dev -> msg_read )
1256
- xfer_size = msg -> len ;
1270
+ xfer_size = i2c_dev -> msg_len ;
1257
1271
else
1258
- xfer_size = msg -> len + I2C_PACKET_HEADER_SIZE ;
1272
+ xfer_size = i2c_dev -> msg_len + I2C_PACKET_HEADER_SIZE ;
1259
1273
1260
1274
xfer_size = ALIGN (xfer_size , BYTES_PER_FIFO_WORD );
1261
1275
@@ -1295,7 +1309,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
1295
1309
if (!i2c_dev -> msg_read ) {
1296
1310
if (i2c_dev -> dma_mode ) {
1297
1311
memcpy (i2c_dev -> dma_buf + I2C_PACKET_HEADER_SIZE ,
1298
- msg -> buf , msg -> len );
1312
+ msg -> buf , i2c_dev -> msg_len );
1299
1313
1300
1314
dma_sync_single_for_device (i2c_dev -> dma_dev ,
1301
1315
i2c_dev -> dma_phys ,
@@ -1352,7 +1366,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
1352
1366
i2c_dev -> dma_phys ,
1353
1367
xfer_size , DMA_FROM_DEVICE );
1354
1368
1355
- memcpy (i2c_dev -> msg_buf , i2c_dev -> dma_buf , msg -> len );
1369
+ memcpy (i2c_dev -> msg_buf , i2c_dev -> dma_buf , i2c_dev -> msg_len );
1356
1370
}
1357
1371
}
1358
1372
@@ -1408,8 +1422,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
1408
1422
ret = tegra_i2c_xfer_msg (i2c_dev , & msgs [i ], MSG_END_CONTINUE );
1409
1423
if (ret )
1410
1424
break ;
1411
- /* Set the read byte as msg len */
1412
- msgs [i ].len = msgs [i ].buf [0 ];
1425
+ /* Set the msg length from first byte */
1426
+ msgs [i ].len + = msgs [i ].buf [0 ];
1413
1427
dev_dbg (i2c_dev -> dev , "reading %d bytes\n" , msgs [i ].len );
1414
1428
}
1415
1429
ret = tegra_i2c_xfer_msg (i2c_dev , & msgs [i ], end_type );
0 commit comments