Skip to content

Commit 66e8eae

Browse files
attie-argentumcarlescufi
authored andcommitted
drivers: i2c: sam0: Implement bus locking
After experiencing a few deadlocks, it was discovered that this bus does not implement any form of mutual exclusion... this patch addresses this and resolves potential deadlocks. Signed-off-by: Attie Grande <[email protected]>
1 parent 008fd88 commit 66e8eae

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

drivers/i2c/i2c_sam0.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct i2c_sam0_msg {
5050
};
5151

5252
struct 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

516528
static 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

Comments
 (0)