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 <declan.snyder@nxp.com>
This commit is contained in:
parent
6bd7f781a3
commit
33ffda4dd6
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
* Copyright (c) 2019 NXP
|
||||
* Copyright (c) 2019, 2022 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -35,6 +35,7 @@ struct mcux_flexcomm_config {
|
|||
struct mcux_flexcomm_data {
|
||||
i2c_master_handle_t handle;
|
||||
struct k_sem device_sync_sem;
|
||||
struct k_sem lock;
|
||||
status_t callback_status;
|
||||
#ifdef CONFIG_I2C_TARGET
|
||||
i2c_slave_handle_t target_handle;
|
||||
|
@ -50,6 +51,7 @@ static int mcux_flexcomm_configure(const struct device *dev,
|
|||
uint32_t dev_config_raw)
|
||||
{
|
||||
const struct mcux_flexcomm_config *config = dev->config;
|
||||
struct mcux_flexcomm_data *data = dev->data;
|
||||
I2C_Type *base = config->base;
|
||||
uint32_t clock_freq;
|
||||
uint32_t baudrate;
|
||||
|
@ -82,7 +84,9 @@ static int mcux_flexcomm_configure(const struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_sem_take(&data->lock, K_FOREVER);
|
||||
I2C_MasterSetBaudRate(base, baudrate, clock_freq);
|
||||
k_sem_give(&data->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -125,11 +129,15 @@ static int mcux_flexcomm_transfer(const struct device *dev,
|
|||
I2C_Type *base = config->base;
|
||||
i2c_master_transfer_t transfer;
|
||||
status_t status;
|
||||
int ret = 0;
|
||||
|
||||
k_sem_take(&data->lock, K_FOREVER);
|
||||
|
||||
/* Iterate over all the messages */
|
||||
for (int i = 0; i < num_msgs; i++) {
|
||||
if (I2C_MSG_ADDR_10_BITS & msgs->flags) {
|
||||
return -ENOTSUP;
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize the transfer descriptor */
|
||||
|
@ -159,7 +167,8 @@ static int mcux_flexcomm_transfer(const struct device *dev,
|
|||
*/
|
||||
if (status != kStatus_Success) {
|
||||
I2C_MasterTransferAbort(base, &data->handle);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
@ -170,14 +179,17 @@ static int mcux_flexcomm_transfer(const struct device *dev,
|
|||
*/
|
||||
if (data->callback_status != kStatus_Success) {
|
||||
I2C_MasterTransferAbort(base, &data->handle);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to the next message */
|
||||
msgs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
k_sem_give(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
|
@ -334,6 +346,7 @@ static int mcux_flexcomm_init(const struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
k_sem_init(&data->lock, 1, 1);
|
||||
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
if (!device_is_ready(config->clock_dev)) {
|
||||
|
|
Loading…
Reference in a new issue