@@ -52,6 +52,8 @@ struct i2c_sam0_msg {
52
52
struct i2c_sam0_dev_data {
53
53
struct k_sem sem ;
54
54
struct i2c_sam0_msg msg ;
55
+ struct i2c_msg * msgs ;
56
+ uint8_t num_msgs ;
55
57
};
56
58
57
59
#define DEV_NAME (dev ) ((dev)->name)
@@ -137,6 +139,18 @@ static void i2c_sam0_isr(const struct device *dev)
137
139
return ;
138
140
}
139
141
142
+ /*
143
+ * Directly send/receive next message if it is in the same direction and
144
+ * the current message has no stop flag and the next message has no
145
+ * restart flag.
146
+ */
147
+ const bool continue_next = (data -> msg .size == 1 ) && (data -> num_msgs > 1 ) &&
148
+ ((data -> msgs [0 ].flags & I2C_MSG_RW_MASK ) ==
149
+ (data -> msgs [1 ].flags & I2C_MSG_RW_MASK )) &&
150
+ !(data -> msgs [0 ].flags & I2C_MSG_STOP ) &&
151
+ !(data -> msgs [1 ].flags & I2C_MSG_RESTART ) &&
152
+ ((status & (SERCOM_I2CM_INTFLAG_MB | SERCOM_I2CM_INTFLAG_SB )));
153
+
140
154
if (status & SERCOM_I2CM_INTFLAG_MB ) {
141
155
if (!data -> msg .size ) {
142
156
i2c -> INTENCLR .reg = SERCOM_I2CM_INTENCLR_MASK ;
@@ -147,12 +161,8 @@ static void i2c_sam0_isr(const struct device *dev)
147
161
i2c -> DATA .reg = * data -> msg .buffer ;
148
162
data -> msg .buffer ++ ;
149
163
data -> msg .size -- ;
150
-
151
- return ;
152
- }
153
-
154
- if (status & SERCOM_I2CM_INTFLAG_SB ) {
155
- if (data -> msg .size == 1 ) {
164
+ } else if (status & SERCOM_I2CM_INTFLAG_SB ) {
165
+ if (!continue_next ) {
156
166
/*
157
167
* If this is the last byte, then prepare for an auto
158
168
* NACK before doing the actual read. This does not
@@ -165,12 +175,20 @@ static void i2c_sam0_isr(const struct device *dev)
165
175
data -> msg .buffer ++ ;
166
176
data -> msg .size -- ;
167
177
168
- if (!data -> msg . size ) {
178
+ if (!continue_next ) {
169
179
i2c -> INTENCLR .reg = SERCOM_I2CM_INTENCLR_MASK ;
170
180
k_sem_give (& data -> sem );
171
181
return ;
172
182
}
173
- return ;
183
+ }
184
+
185
+ if (continue_next ) {
186
+ data -> msgs ++ ;
187
+ data -> num_msgs -- ;
188
+
189
+ data -> msg .buffer = data -> msgs -> buf ;
190
+ data -> msg .size = data -> msgs -> len ;
191
+ data -> msg .status = 0 ;
174
192
}
175
193
}
176
194
@@ -373,10 +391,12 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
373
391
if (!num_msgs ) {
374
392
return 0 ;
375
393
}
394
+ data -> num_msgs = num_msgs ;
395
+ data -> msgs = msgs ;
376
396
377
- for (; num_msgs > 0 ;) {
378
- if (!msgs -> len ) {
379
- if ((msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
397
+ for (; data -> num_msgs > 0 ;) {
398
+ if (!data -> msgs -> len ) {
399
+ if ((data -> msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
380
400
return - EINVAL ;
381
401
}
382
402
}
@@ -392,20 +412,20 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
392
412
SERCOM_I2CM_STATUS_BUSERR ;
393
413
wait_synchronization (i2c );
394
414
395
- data -> msg .buffer = msgs -> buf ;
396
- data -> msg .size = msgs -> len ;
415
+ data -> msg .buffer = data -> msgs -> buf ;
416
+ data -> msg .size = data -> msgs -> len ;
397
417
data -> msg .status = 0 ;
398
418
399
419
addr_reg = addr << 1U ;
400
- if ((msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
420
+ if ((data -> msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
401
421
addr_reg |= 1U ;
402
422
403
423
/* Set to auto ACK */
404
424
i2c -> CTRLB .bit .ACKACT = 0 ;
405
425
wait_synchronization (i2c );
406
426
}
407
427
408
- if (msgs -> flags & I2C_MSG_ADDR_10_BITS ) {
428
+ if (data -> msgs -> flags & I2C_MSG_ADDR_10_BITS ) {
409
429
#ifdef SERCOM_I2CM_ADDR_TENBITEN
410
430
addr_reg |= SERCOM_I2CM_ADDR_TENBITEN ;
411
431
#else
@@ -432,7 +452,7 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
432
452
i2c -> INTENSET .reg = SERCOM_I2CM_INTENSET_ERROR ;
433
453
#endif
434
454
435
- if ((msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
455
+ if ((data -> msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
436
456
/*
437
457
* Always set MB even when reading, since that's how
438
458
* some errors are indicated.
@@ -472,9 +492,9 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
472
492
return - EIO ;
473
493
}
474
494
475
- if (msgs -> flags & I2C_MSG_STOP ) {
495
+ if (data -> msgs -> flags & I2C_MSG_STOP ) {
476
496
i2c -> CTRLB .bit .CMD = 3 ;
477
- } else if ((msgs -> flags & I2C_MSG_RESTART ) && num_msgs > 1 ) {
497
+ } else if ((data -> msgs -> flags & I2C_MSG_RESTART ) && data -> num_msgs > 1 ) {
478
498
/*
479
499
* No action, since we do this automatically if we
480
500
* don't send an explicit stop
@@ -487,8 +507,8 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
487
507
i2c -> CTRLB .bit .CMD = 3 ;
488
508
}
489
509
490
- num_msgs -- ;
491
- msgs ++ ;
510
+ data -> num_msgs -- ;
511
+ data -> msgs ++ ;
492
512
}
493
513
494
514
return 0 ;
0 commit comments