@@ -157,8 +157,23 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
157
157
#endif /* CONFIG_I2C_TARGET */
158
158
159
159
while (i < num_msgs ) {
160
- data -> last_transfer = (i + 1 ) == num_msgs ;
161
- if (msgs [i ].flags & I2C_MSG_READ ) {
160
+ uint8_t msgs_in_transfer = 1 ;
161
+
162
+ /* Combined DMA write-read (repeated start) */
163
+ if ((msgs [i ].flags & I2C_MSG_WRITE ) == 0 && (i + 1 < num_msgs ) &&
164
+ (msgs [i + 1 ].flags & I2C_MSG_READ )) {
165
+ msgs_in_transfer = 2 ;
166
+ }
167
+ data -> last_transfer = (i + msgs_in_transfer ) == num_msgs ;
168
+
169
+ if (msgs_in_transfer == 2 ) {
170
+ if (sl_i2c_transfer_non_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len ,
171
+ msgs [i + 1 ].buf , msgs [i + 1 ].len , NULL ,
172
+ NULL ) != 0 ) {
173
+ k_sem_give (& data -> bus_lock );
174
+ return - EIO ;
175
+ }
176
+ } else if (msgs [i ].flags & I2C_MSG_READ ) {
162
177
/* Start DMA receive */
163
178
if (sl_i2c_receive_non_blocking (i2c_handle , msgs [i ].buf , msgs [i ].len , NULL ,
164
179
NULL ) != 0 ) {
@@ -186,7 +201,7 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
186
201
break ;
187
202
}
188
203
}
189
- i ++ ;
204
+ i += msgs_in_transfer ;
190
205
}
191
206
192
207
return err ;
@@ -207,8 +222,11 @@ static int i2c_silabs_transfer_sync(const struct device *dev, struct i2c_msg *ms
207
222
i2c_silabs_pm_policy_state_lock_get (dev );
208
223
209
224
while (i < num_msgs ) {
225
+ uint8_t msgs_in_transfer = 1 ;
226
+
210
227
if ((msgs [i ].flags & I2C_MSG_WRITE ) == 0 && (i + 1 < num_msgs ) &&
211
228
(msgs [i + 1 ].flags & I2C_MSG_READ )) {
229
+ msgs_in_transfer = 2 ;
212
230
if (sl_i2c_transfer (i2c_handle , msgs [i ].buf , msgs [i ].len , msgs [i + 1 ].buf ,
213
231
msgs [i + 1 ].len ) != 0 ) {
214
232
k_sem_give (& data -> bus_lock );
@@ -228,7 +246,7 @@ static int i2c_silabs_transfer_sync(const struct device *dev, struct i2c_msg *ms
228
246
return - ETIMEDOUT ;
229
247
}
230
248
}
231
- i ++ ;
249
+ i += msgs_in_transfer ;
232
250
}
233
251
234
252
/* Release the bus lock semaphore */
@@ -434,7 +452,8 @@ void i2c_silabs_isr_handler(const struct device *dev)
434
452
#else
435
453
sli_i2c_leader_dispatch_interrupt (sl_i2c_instance );
436
454
#endif
437
- if (sl_i2c_instance -> transfer_event != SL_I2C_EVENT_IN_PROGRESS ) {
455
+ if (sl_i2c_instance -> transfer_event != SL_I2C_EVENT_IN_PROGRESS &&
456
+ sl_i2c_instance -> rstart == 0 ) {
438
457
if (!data -> asynchronous ) {
439
458
k_sem_give (& data -> transfer_sem );
440
459
}
0 commit comments