@@ -52,6 +52,8 @@ struct i2c_sam0_msg {
5252struct i2c_sam0_dev_data {
5353 struct k_sem sem ;
5454 struct i2c_sam0_msg msg ;
55+ struct i2c_msg * msgs ;
56+ uint8_t num_msgs ;
5557};
5658
5759#define DEV_NAME (dev ) ((dev)->name)
@@ -137,6 +139,18 @@ static void i2c_sam0_isr(const struct device *dev)
137139 return ;
138140 }
139141
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+
140154 if (status & SERCOM_I2CM_INTFLAG_MB ) {
141155 if (!data -> msg .size ) {
142156 i2c -> INTENCLR .reg = SERCOM_I2CM_INTENCLR_MASK ;
@@ -147,12 +161,8 @@ static void i2c_sam0_isr(const struct device *dev)
147161 i2c -> DATA .reg = * data -> msg .buffer ;
148162 data -> msg .buffer ++ ;
149163 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 ) {
156166 /*
157167 * If this is the last byte, then prepare for an auto
158168 * NACK before doing the actual read. This does not
@@ -165,12 +175,20 @@ static void i2c_sam0_isr(const struct device *dev)
165175 data -> msg .buffer ++ ;
166176 data -> msg .size -- ;
167177
168- if (!data -> msg . size ) {
178+ if (!continue_next ) {
169179 i2c -> INTENCLR .reg = SERCOM_I2CM_INTENCLR_MASK ;
170180 k_sem_give (& data -> sem );
171181 return ;
172182 }
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 ;
174192 }
175193}
176194
@@ -373,10 +391,12 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
373391 if (!num_msgs ) {
374392 return 0 ;
375393 }
394+ data -> num_msgs = num_msgs ;
395+ data -> msgs = msgs ;
376396
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 ) {
380400 return - EINVAL ;
381401 }
382402 }
@@ -392,20 +412,20 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
392412 SERCOM_I2CM_STATUS_BUSERR ;
393413 wait_synchronization (i2c );
394414
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 ;
397417 data -> msg .status = 0 ;
398418
399419 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 ) {
401421 addr_reg |= 1U ;
402422
403423 /* Set to auto ACK */
404424 i2c -> CTRLB .bit .ACKACT = 0 ;
405425 wait_synchronization (i2c );
406426 }
407427
408- if (msgs -> flags & I2C_MSG_ADDR_10_BITS ) {
428+ if (data -> msgs -> flags & I2C_MSG_ADDR_10_BITS ) {
409429#ifdef SERCOM_I2CM_ADDR_TENBITEN
410430 addr_reg |= SERCOM_I2CM_ADDR_TENBITEN ;
411431#else
@@ -432,7 +452,7 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
432452 i2c -> INTENSET .reg = SERCOM_I2CM_INTENSET_ERROR ;
433453#endif
434454
435- if ((msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
455+ if ((data -> msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
436456 /*
437457 * Always set MB even when reading, since that's how
438458 * some errors are indicated.
@@ -472,9 +492,9 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
472492 return - EIO ;
473493 }
474494
475- if (msgs -> flags & I2C_MSG_STOP ) {
495+ if (data -> msgs -> flags & I2C_MSG_STOP ) {
476496 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 ) {
478498 /*
479499 * No action, since we do this automatically if we
480500 * don't send an explicit stop
@@ -487,8 +507,8 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
487507 i2c -> CTRLB .bit .CMD = 3 ;
488508 }
489509
490- num_msgs -- ;
491- msgs ++ ;
510+ data -> num_msgs -- ;
511+ data -> msgs ++ ;
492512 }
493513
494514 return 0 ;
0 commit comments