@@ -50,6 +50,7 @@ struct i2c_sam0_msg {
5050};
5151
5252struct i2c_sam0_dev_data {
53+ struct k_sem lock ;
5354 struct k_sem sem ;
5455 struct i2c_sam0_msg msg ;
5556 struct i2c_msg * msgs ;
@@ -381,17 +382,21 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
381382 const struct i2c_sam0_dev_config * const cfg = dev -> config ;
382383 SercomI2cm * i2c = cfg -> regs ;
383384 uint32_t addr_reg ;
385+ int ret ;
384386
385387 if (!num_msgs ) {
386388 return 0 ;
387389 }
388390 data -> num_msgs = num_msgs ;
389391 data -> msgs = msgs ;
390392
393+ k_sem_take (& data -> lock , K_FOREVER );
394+
391395 for (; data -> num_msgs > 0 ;) {
392396 if (!data -> msgs -> len ) {
393397 if ((data -> msgs -> flags & I2C_MSG_RW_MASK ) == I2C_MSG_READ ) {
394- return - EINVAL ;
398+ ret = - EINVAL ;
399+ goto unlock ;
395400 }
396401 }
397402
@@ -423,7 +428,8 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
423428#ifdef SERCOM_I2CM_ADDR_TENBITEN
424429 addr_reg |= SERCOM_I2CM_ADDR_TENBITEN ;
425430#else
426- return - ENOTSUP ;
431+ ret = - ENOTSUP ;
432+ goto unlock ;
427433#endif
428434 }
429435
@@ -481,12 +487,14 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
481487 if (data -> msg .status & SERCOM_I2CM_STATUS_ARBLOST ) {
482488 LOG_DBG ("Arbitration lost on %s" ,
483489 dev -> name );
484- return - EAGAIN ;
490+ ret = - EAGAIN ;
491+ goto unlock ;
485492 }
486493
487494 LOG_ERR ("Transaction error on %s: %08X" ,
488495 dev -> name , data -> msg .status );
489- return - EIO ;
496+ ret = - EIO ;
497+ goto unlock ;
490498 }
491499
492500 /*
@@ -510,7 +518,11 @@ static int i2c_sam0_transfer(const struct device *dev, struct i2c_msg *msgs,
510518 data -> msgs ++ ;
511519 }
512520
513- return 0 ;
521+ ret = 0 ;
522+ unlock :
523+ k_sem_give (& data -> lock );
524+
525+ return ret ;
514526}
515527
516528static int i2c_sam0_set_apply_bitrate (const struct device * dev ,
@@ -717,6 +729,7 @@ static int i2c_sam0_initialize(const struct device *dev)
717729 return retval ;
718730 }
719731
732+ k_sem_init (& data -> lock , 1 , 1 );
720733 k_sem_init (& data -> sem , 0 , 1 );
721734
722735 cfg -> irq_config_func (dev );
0 commit comments