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,