Skip to content

Commit 33ffda4

Browse files
decsnydleach02
authored andcommitted
drivers: i2c_mcux_flexcomm: Add thread safe lock
Add a locking semaphore so that multiple threads doing transfers with the same i2c will not produce unexpected results. The lock will ensure that only one transfer will happen at a time and it must be completed before another thread can request a new transfer. Signed-off-by: Declan Snyder <[email protected]>
1 parent 6bd7f78 commit 33ffda4

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

drivers/i2c/i2c_mcux_flexcomm.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2016 Freescale Semiconductor, Inc.
3-
* Copyright (c) 2019 NXP
3+
* Copyright (c) 2019, 2022 NXP
44
*
55
* SPDX-License-Identifier: Apache-2.0
66
*/
@@ -35,6 +35,7 @@ struct mcux_flexcomm_config {
3535
struct mcux_flexcomm_data {
3636
i2c_master_handle_t handle;
3737
struct k_sem device_sync_sem;
38+
struct k_sem lock;
3839
status_t callback_status;
3940
#ifdef CONFIG_I2C_TARGET
4041
i2c_slave_handle_t target_handle;
@@ -50,6 +51,7 @@ static int mcux_flexcomm_configure(const struct device *dev,
5051
uint32_t dev_config_raw)
5152
{
5253
const struct mcux_flexcomm_config *config = dev->config;
54+
struct mcux_flexcomm_data *data = dev->data;
5355
I2C_Type *base = config->base;
5456
uint32_t clock_freq;
5557
uint32_t baudrate;
@@ -82,7 +84,9 @@ static int mcux_flexcomm_configure(const struct device *dev,
8284
return -EINVAL;
8385
}
8486

87+
k_sem_take(&data->lock, K_FOREVER);
8588
I2C_MasterSetBaudRate(base, baudrate, clock_freq);
89+
k_sem_give(&data->lock);
8690

8791
return 0;
8892
}
@@ -125,11 +129,15 @@ static int mcux_flexcomm_transfer(const struct device *dev,
125129
I2C_Type *base = config->base;
126130
i2c_master_transfer_t transfer;
127131
status_t status;
132+
int ret = 0;
133+
134+
k_sem_take(&data->lock, K_FOREVER);
128135

129136
/* Iterate over all the messages */
130137
for (int i = 0; i < num_msgs; i++) {
131138
if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
132-
return -ENOTSUP;
139+
ret = -ENOTSUP;
140+
break;
133141
}
134142

135143
/* Initialize the transfer descriptor */
@@ -159,7 +167,8 @@ static int mcux_flexcomm_transfer(const struct device *dev,
159167
*/
160168
if (status != kStatus_Success) {
161169
I2C_MasterTransferAbort(base, &data->handle);
162-
return -EIO;
170+
ret = -EIO;
171+
break;
163172
}
164173

165174
/* Wait for the transfer to complete */
@@ -170,14 +179,17 @@ static int mcux_flexcomm_transfer(const struct device *dev,
170179
*/
171180
if (data->callback_status != kStatus_Success) {
172181
I2C_MasterTransferAbort(base, &data->handle);
173-
return -EIO;
182+
ret = -EIO;
183+
break;
174184
}
175185

176186
/* Move to the next message */
177187
msgs++;
178188
}
179189

180-
return 0;
190+
k_sem_give(&data->lock);
191+
192+
return ret;
181193
}
182194

183195
#if defined(CONFIG_I2C_TARGET)
@@ -334,6 +346,7 @@ static int mcux_flexcomm_init(const struct device *dev)
334346
}
335347
#endif
336348

349+
k_sem_init(&data->lock, 1, 1);
337350
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
338351

339352
if (!device_is_ready(config->clock_dev)) {

0 commit comments

Comments
 (0)