Skip to content

Commit 4cd8bcc

Browse files
fimohamecfriedt
authored andcommitted
drivers: i2c: silabs: add async combined write-read
Added support for combined write-read operations with repeated start for asynchronous (async) operations in the Silabs I2C driver for EFR series 2 devices. Signed-off-by: S Mohamed Fiaz <[email protected]>
1 parent ea6ec6b commit 4cd8bcc

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

drivers/i2c/i2c_silabs.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,23 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
157157
#endif /* CONFIG_I2C_TARGET */
158158

159159
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) {
162177
/* Start DMA receive */
163178
if (sl_i2c_receive_non_blocking(i2c_handle, msgs[i].buf, msgs[i].len, NULL,
164179
NULL) != 0) {
@@ -186,7 +201,7 @@ static int i2c_silabs_transfer_dma(const struct device *dev, struct i2c_msg *msg
186201
break;
187202
}
188203
}
189-
i++;
204+
i += msgs_in_transfer;
190205
}
191206

192207
return err;
@@ -207,8 +222,11 @@ static int i2c_silabs_transfer_sync(const struct device *dev, struct i2c_msg *ms
207222
i2c_silabs_pm_policy_state_lock_get(dev);
208223

209224
while (i < num_msgs) {
225+
uint8_t msgs_in_transfer = 1;
226+
210227
if ((msgs[i].flags & I2C_MSG_WRITE) == 0 && (i + 1 < num_msgs) &&
211228
(msgs[i + 1].flags & I2C_MSG_READ)) {
229+
msgs_in_transfer = 2;
212230
if (sl_i2c_transfer(i2c_handle, msgs[i].buf, msgs[i].len, msgs[i + 1].buf,
213231
msgs[i + 1].len) != 0) {
214232
k_sem_give(&data->bus_lock);
@@ -228,7 +246,7 @@ static int i2c_silabs_transfer_sync(const struct device *dev, struct i2c_msg *ms
228246
return -ETIMEDOUT;
229247
}
230248
}
231-
i++;
249+
i += msgs_in_transfer;
232250
}
233251

234252
/* Release the bus lock semaphore */
@@ -434,7 +452,8 @@ void i2c_silabs_isr_handler(const struct device *dev)
434452
#else
435453
sli_i2c_leader_dispatch_interrupt(sl_i2c_instance);
436454
#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) {
438457
if (!data->asynchronous) {
439458
k_sem_give(&data->transfer_sem);
440459
}

0 commit comments

Comments
 (0)