Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions drivers/i2c/i2c_nrfx_twim.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/i2c/i2c_nrfx_twim.h>
#include <zephyr/dt-bindings/i2c/i2c.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
Expand Down Expand Up @@ -33,6 +34,29 @@ struct i2c_nrfx_twim_data {
volatile nrfx_err_t res;
};

int i2c_nrfx_twim_exclusive_access_acquire(const struct device *dev, k_timeout_t timeout)
{
struct i2c_nrfx_twim_data *dev_data = dev->data;
int ret;

ret = k_sem_take(&dev_data->transfer_sync, timeout);

if (ret == 0) {
(void)pm_device_runtime_get(dev);
}

return ret;
}

void i2c_nrfx_twim_exclusive_access_release(const struct device *dev)
{
struct i2c_nrfx_twim_data *dev_data = dev->data;

(void)pm_device_runtime_put(dev);

k_sem_give(&dev_data->transfer_sync);
}

static int i2c_nrfx_twim_transfer(const struct device *dev,
struct i2c_msg *msgs,
uint8_t num_msgs, uint16_t addr)
Expand All @@ -46,13 +70,11 @@ static int i2c_nrfx_twim_transfer(const struct device *dev,
uint8_t *buf;
uint16_t buf_len;

k_sem_take(&dev_data->transfer_sync, K_FOREVER);
(void)i2c_nrfx_twim_exclusive_access_acquire(dev, K_FOREVER);

/* Dummy take on completion_sync sem to be sure that it is empty */
k_sem_take(&dev_data->completion_sync, K_NO_WAIT);

(void)pm_device_runtime_get(dev);

for (size_t i = 0; i < num_msgs; i++) {
if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) {
ret = -ENOTSUP;
Expand Down Expand Up @@ -164,9 +186,7 @@ static int i2c_nrfx_twim_transfer(const struct device *dev,
msg_buf_used = 0;
}

(void)pm_device_runtime_put(dev);

k_sem_give(&dev_data->transfer_sync);
i2c_nrfx_twim_exclusive_access_release(dev);

return ret;
}
Expand Down
34 changes: 34 additions & 0 deletions include/zephyr/drivers/i2c/i2c_nrfx_twim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_DRIVERS_I2C_NRFX_TWIM_H
#define ZEPHYR_INCLUDE_DRIVERS_I2C_NRFX_TWIM_H

#include <zephyr/kernel.h>
#include <zephyr/drivers/i2c.h>

/** @brief Acquires exclusive access to the i2c bus controller.
*
* @param dev Pointer to the device structure for an I2C controller
* driver configured in controller mode.
* @param timeout Timeout for waiting to acquire exclusive access.
*
* @retval 0 If successful.
* @retval -EBUSY Returned without waiting.
* @retval -EAGAIN Waiting period timed out,
* or the underlying semaphore was reset during the waiting period.
*/
int i2c_nrfx_twim_exclusive_access_acquire(const struct device *dev, k_timeout_t timeout);

/** @brief Releases exclusive access to the i2c bus controller.
*
* @param dev Pointer to the device structure for an I2C controller
* driver on which @ref i2c_nrfx_twim_exclusive_access_acquire
* has been successfully called.
*/
void i2c_nrfx_twim_exclusive_access_release(const struct device *dev);

#endif /* ZEPHYR_INCLUDE_DRIVERS_I2C_NRFX_TWIM_H */
8 changes: 8 additions & 0 deletions tests/drivers/i2c/i2c_nrfx_twim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(i2c_api)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/*
* SDA = P0.26 and P1.2
* SCL = P0.25 and P1.3
*/

/ {
aliases {
i2c-controller = &i2c1;
i2c-controller-target = &i2c2;
};
};

&pinctrl {
i2c2_default: i2c2_default {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 0, 26)>,
<NRF_PSEL(TWIS_SCL, 0, 25)>;
bias-pull-up;
};
};

i2c2_sleep: i2c2_sleep {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 0, 26)>,
<NRF_PSEL(TWIS_SCL, 0, 25)>;
low-power-enable;
};
};
};

&i2c2 {
compatible = "nordic,nrf-twis";
pinctrl-0 = <&i2c2_default>;
pinctrl-1 = <&i2c2_sleep>;
pinctrl-names = "default", "sleep";
status = "okay";
};

&i2c1 {
compatible = "nordic,nrf-twim";
zephyr,concat-buf-size = <256>;
status = "okay";
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/*
* SDA = P2.8 and P2.9
* SCL = P1.2 and P1.3
*/

/ {
aliases {
i2c-controller = &i2c130;
i2c-controller-target = &i2c131;
};
};

&pinctrl {
i2c130_default: i2c130_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 2, 8)>,
<NRF_PSEL(TWIM_SCL, 1, 2)>;
bias-pull-up;
};
};

i2c130_sleep: i2c130_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 2, 8)>,
<NRF_PSEL(TWIM_SCL, 1, 2)>;
low-power-enable;
};
};

i2c131_default: i2c131_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 2, 9)>,
<NRF_PSEL(TWIM_SCL, 1, 3)>;
bias-pull-up;
};
};

i2c131_sleep: i2c131_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 2, 9)>,
<NRF_PSEL(TWIM_SCL, 1, 3)>;
low-power-enable;
};
};
};

&i2c130 {
compatible = "nordic,nrf-twim";
clock-frequency = <I2C_BITRATE_STANDARD>;
pinctrl-0 = <&i2c130_default>;
pinctrl-1 = <&i2c130_sleep>;
pinctrl-names = "default", "sleep";
zephyr,concat-buf-size = <256>;
memory-regions = <&cpuapp_dma_region>;
status = "okay";
};

&i2c131 {
compatible = "nordic,nrf-twis";
clock-frequency = <I2C_BITRATE_STANDARD>;
pinctrl-0 = <&i2c131_default>;
pinctrl-1 = <&i2c131_sleep>;
pinctrl-names = "default", "sleep";
memory-regions = <&cpuapp_dma_region>;
status = "okay";
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/*
* SDA = P1.8 and P1.9
* SCL = P1.10 and P1.11
*/

/ {
aliases {
i2c-controller = &i2c21;
i2c-controller-target = &i2c22;
};
};

&pinctrl {
i2c21_default: i2c21_default {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 1, 8)>,
<NRF_PSEL(TWIS_SCL, 1, 10)>;
bias-pull-up;
};
};

i2c21_sleep: i2c21_sleep {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 1, 8)>,
<NRF_PSEL(TWIS_SCL, 1, 10)>;
low-power-enable;
};
};

i2c22_default: i2c22_default {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 1, 9)>,
<NRF_PSEL(TWIS_SCL, 1, 11)>;
bias-pull-up;
};
};

i2c22_sleep: i2c22_sleep {
group1 {
psels = <NRF_PSEL(TWIS_SDA, 1, 9)>,
<NRF_PSEL(TWIS_SCL, 1, 11)>;
low-power-enable;
};
};
};

&i2c21 {
compatible = "nordic,nrf-twim";
pinctrl-0 = <&i2c21_default>;
pinctrl-1 = <&i2c21_sleep>;
pinctrl-names = "default", "sleep";
zephyr,concat-buf-size = <256>;
status = "okay";
};

&i2c22 {
compatible = "nordic,nrf-twis";
pinctrl-0 = <&i2c22_default>;
pinctrl-1 = <&i2c22_sleep>;
pinctrl-names = "default", "sleep";
status = "okay";
};
11 changes: 11 additions & 0 deletions tests/drivers/i2c/i2c_nrfx_twim/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CONFIG_ZTEST=y
CONFIG_BOOT_BANNER=n

CONFIG_LOG=y
CONFIG_I2C_LOG_LEVEL_INF=y
CONFIG_I2C=y
CONFIG_I2C_TARGET=y
CONFIG_I2C_TARGET_BUFFER_MODE=y
CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256

CONFIG_ZERO_LATENCY_IRQS=y
Loading