drivers: i2c: nrf5: Make the driver thread-safe
Locking is added to externally callable API functions.
Signed-off-by: Aapo Vienamo <aapo.vienamo@iki.fi>
diff --git a/drivers/i2c/i2c_nrf5.c b/drivers/i2c/i2c_nrf5.c
index 93720cb..22ca8a6 100644
--- a/drivers/i2c/i2c_nrf5.c
+++ b/drivers/i2c/i2c_nrf5.c
@@ -46,13 +46,17 @@
u32_t err:1;
u32_t stopped:1;
struct device *gpio;
+ struct k_sem lock;
};
static int i2c_nrf5_configure(struct device *dev, u32_t dev_config_raw)
{
const struct i2c_nrf5_config *config = dev->config->config_info;
+ struct i2c_nrf5_data *data = dev->driver_data;
volatile NRF_TWI_Type *twi = config->base;
+ int ret = 0;
+
SYS_LOG_DBG("");
@@ -60,6 +64,8 @@
return -EINVAL;
}
+ k_sem_take(&data->lock, K_FOREVER);
+
switch (I2C_SPEED_GET(dev_config_raw)) {
case I2C_SPEED_STANDARD:
twi->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100;
@@ -69,10 +75,12 @@
break;
default:
SYS_LOG_ERR("unsupported speed");
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ k_sem_give(&data->lock);
+
+ return ret;
}
static int i2c_nrf5_read(struct device *dev, struct i2c_msg *msg)
@@ -199,7 +207,11 @@
u8_t num_msgs, u16_t addr)
{
const struct i2c_nrf5_config *config = dev->config->config_info;
+ struct i2c_nrf5_data *data = dev->driver_data;
volatile NRF_TWI_Type *twi = config->base;
+ int ret = 0;
+
+ k_sem_take(&data->lock, K_FOREVER);
SYS_LOG_DBG("transaction-start addr=0x%x", addr);
@@ -212,8 +224,6 @@
twi->ENABLE = TWI_ENABLE_ENABLE_Enabled;
twi->ADDRESS = addr;
for (int i = 0; i < num_msgs; i++) {
- int r;
-
SYS_LOG_DBG("msg len=%d %s%s%s", msgs[i].len,
(msgs[i].flags & I2C_MSG_READ) ? "R":"W",
(msgs[i].flags & I2C_MSG_STOP) ? "S":"-",
@@ -225,19 +235,20 @@
| NRF5_TWI_INT_RXDREADY
| NRF5_TWI_INT_ERROR
| NRF5_TWI_INT_STOPPED);
- r = i2c_nrf5_read(dev, msgs + i);
+ ret = i2c_nrf5_read(dev, msgs + i);
} else {
- r = i2c_nrf5_write(dev, msgs + i);
+ ret = i2c_nrf5_write(dev, msgs + i);
}
- if (r != 0) {
- twi->ENABLE = TWI_ENABLE_ENABLE_Disabled;
- return r;
+ if (ret != 0) {
+ break;
}
}
twi->ENABLE = TWI_ENABLE_ENABLE_Disabled;
- return 0;
+ k_sem_give(&data->lock);
+
+ return ret;
}
static void i2c_nrf5_isr(void *arg)
@@ -313,11 +324,10 @@
| NRF5_TWI_INT_STOPPED);
status = i2c_nrf5_configure(dev, config->default_cfg);
- if (status) {
- return status;
- }
- return 0;
+ k_sem_give(&data->lock);
+
+ return status;
}
static const struct i2c_driver_api i2c_nrf5_driver_api = {
@@ -339,7 +349,9 @@
.scl_pin = CONFIG_I2C_NRF5_0_GPIO_SCL_PIN,
};
-static struct i2c_nrf5_data i2c_nrf5_data_0;
+static struct i2c_nrf5_data i2c_nrf5_data_0 = {
+ .lock = _K_SEM_INITIALIZER(i2c_nrf5_data_0.lock, 1, 1),
+};
DEVICE_AND_API_INIT(i2c_nrf5_0, CONFIG_I2C_0_NAME, i2c_nrf5_init,
&i2c_nrf5_data_0, &i2c_nrf5_config_0,
@@ -366,7 +378,9 @@
.scl_pin = CONFIG_I2C_NRF5_1_GPIO_SCL_PIN,
};
-static struct i2c_nrf5_data i2c_nrf5_data_1;
+static struct i2c_nrf5_data i2c_nrf5_data_1 = {
+ .lock = _K_SEM_INITIALIZER(i2c_nrf5_data_1.lock, 1, 1),
+};
DEVICE_AND_API_INIT(i2c_nrf5_1, CONFIG_I2C_1_NAME, i2c_nrf5_init,
&i2c_nrf5_data_1, &i2c_nrf5_config_1,