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
78 changes: 62 additions & 16 deletions drivers/i2c/i2c_nrfx_twim_rtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <zephyr/drivers/pinctrl.h>
#include <soc.h>
#include <nrfx_twim.h>
#include <zephyr/linker/devicetree_regions.h>

#include "i2c_nrfx_twim_common.h"

Expand All @@ -25,6 +26,11 @@ struct i2c_nrfx_twim_rtio_config {
struct i2c_rtio *ctx;
};

struct i2c_nrfx_twim_rtio_data {
uint8_t *user_rx_buf;
uint16_t user_rx_buf_size;
};

static bool i2c_nrfx_twim_rtio_msg_start(const struct device *dev, uint8_t flags, uint8_t *buf,
size_t buf_len, uint16_t i2c_addr)
{
Expand All @@ -43,12 +49,28 @@ static bool i2c_nrfx_twim_rtio_msg_start(const struct device *dev, uint8_t flags
static bool i2c_nrfx_twim_rtio_start(const struct device *dev)
{
const struct i2c_nrfx_twim_rtio_config *config = dev->config;
struct i2c_nrfx_twim_rtio_data *data = dev->data;
struct i2c_rtio *ctx = config->ctx;
struct rtio_sqe *sqe = &ctx->txn_curr->sqe;
struct i2c_dt_spec *dt_spec = sqe->iodev->data;

switch (sqe->op) {
case RTIO_OP_RX:
if (!nrf_dma_accessible_check(&config->common.twim, sqe->rx.buf)) {
if (sqe->rx.buf_len > config->common.msg_buf_size) {
return i2c_rtio_complete(ctx, -ENOSPC);
}

data->user_rx_buf = sqe->rx.buf;
data->user_rx_buf_size = sqe->rx.buf_len;
return i2c_nrfx_twim_rtio_msg_start(dev,
I2C_MSG_READ | sqe->iodev_flags,
config->common.msg_buf,
data->user_rx_buf_size,
dt_spec->addr);
}

data->user_rx_buf = NULL;
return i2c_nrfx_twim_rtio_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags,
sqe->rx.buf, sqe->rx.buf_len, dt_spec->addr);
case RTIO_OP_TINY_TX:
Expand All @@ -74,7 +96,8 @@ static bool i2c_nrfx_twim_rtio_start(const struct device *dev)
sqe->tx.buf = config->common.msg_buf;
}
return i2c_nrfx_twim_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags,
sqe->tx.buf, sqe->tx.buf_len, dt_spec->addr);
(uint8_t *)sqe->tx.buf, sqe->tx.buf_len,
dt_spec->addr);
case RTIO_OP_I2C_CONFIGURE:
(void)i2c_nrfx_twim_configure(dev, sqe->i2c_config);
return false;
Expand Down Expand Up @@ -143,8 +166,14 @@ static void i2c_nrfx_twim_rtio_submit(const struct device *dev, struct rtio_iode
static void event_handler(nrfx_twim_evt_t const *p_event, void *p_context)
{
const struct device *dev = p_context;
const struct i2c_nrfx_twim_rtio_config *config = dev->config;
struct i2c_nrfx_twim_rtio_data *data = dev->data;
int status = p_event->type == NRFX_TWIM_EVT_DONE ? 0 : -EIO;

if (data->user_rx_buf) {
memcpy(data->user_rx_buf, config->common.msg_buf, data->user_rx_buf_size);
}

i2c_nrfx_twim_rtio_complete(dev, status);
}

Expand Down Expand Up @@ -174,6 +203,31 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev)
COND_CODE_0(CONCAT_BUF_SIZE(idx), (COND_CODE_0(FLASH_BUF_MAX_SIZE(idx), (0), (1))), (1))
#define MSG_BUF_SIZE(idx) MAX(CONCAT_BUF_SIZE(idx), FLASH_BUF_MAX_SIZE(idx))

#define MSG_BUF_HAS_MEMORY_REGIONS(idx) \
DT_NODE_HAS_PROP(I2C(idx), memory_regions)

#define MSG_BUF_LINKER_REGION_NAME(idx) \
LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(I2C(idx), memory_regions))

#define MSG_BUF_ATTR_SECTION(idx) \
__attribute__((__section__(MSG_BUF_LINKER_REGION_NAME(idx))))

#define MSG_BUF_ATTR(idx) \
COND_CODE_1( \
MSG_BUF_HAS_MEMORY_REGIONS(idx), \
(MSG_BUF_ATTR_SECTION(idx)), \
() \
)

#define MSG_BUF_SYM(idx) \
_CONCAT_3(twim_, idx, _msg_buf)

#define MSG_BUF_DEFINE(idx) \
static uint8_t MSG_BUF_SYM(idx)[MSG_BUF_SIZE(idx)] MSG_BUF_ATTR(idx)

#define MAX_TRANSFER_SIZE(idx) \
BIT_MASK(DT_PROP(I2C(idx), easydma_maxcnt_bits))

#define I2C_NRFX_TWIM_RTIO_DEVICE(idx) \
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \
BUILD_ASSERT(I2C_FREQUENCY(idx) != I2C_NRFX_TWIM_INVALID_FREQUENCY, \
Expand All @@ -183,13 +237,12 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev)
IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority), nrfx_isr, \
nrfx_twim_##idx##_irq_handler, 0); \
} \
IF_ENABLED( \
USES_MSG_BUF(idx), \
(static uint8_t twim_##idx##_msg_buf[MSG_BUF_SIZE(idx)] I2C_MEMORY_SECTION(idx);)) \
IF_ENABLED(USES_MSG_BUF(idx), (MSG_BUF_DEFINE(idx);)) \
I2C_RTIO_DEFINE(_i2c##idx##_twim_rtio, \
DT_INST_PROP_OR(n, sq_size, CONFIG_I2C_RTIO_SQ_SIZE), \
DT_INST_PROP_OR(n, cq_size, CONFIG_I2C_RTIO_CQ_SIZE)); \
PINCTRL_DT_DEFINE(I2C(idx)); \
static struct i2c_nrfx_twim_rtio_data twim_##idx##z_data; \
static const struct i2c_nrfx_twim_rtio_config twim_##idx##z_config = { \
.common = \
{ \
Expand All @@ -204,22 +257,15 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev)
.msg_buf_size = MSG_BUF_SIZE(idx), \
.irq_connect = irq_connect##idx, \
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \
IF_ENABLED(USES_MSG_BUF(idx), (.msg_buf = twim_##idx##_msg_buf,)) \
.max_transfer_size = \
BIT_MASK(DT_PROP(I2C(idx), easydma_maxcnt_bits)), \
IF_ENABLED(USES_MSG_BUF(idx), (.msg_buf = MSG_BUF_SYM(idx),)) \
.max_transfer_size = MAX_TRANSFER_SIZE(idx), \
}, \
.ctx = &_i2c##idx##_twim_rtio, \
}; \
PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \
I2C_DEVICE_DT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, PM_DEVICE_DT_GET(I2C(idx)), NULL, \
&twim_##idx##z_config, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \
&i2c_nrfx_twim_driver_api)

#define I2C_MEMORY_SECTION(idx) \
COND_CODE_1(I2C_HAS_PROP(idx, memory_regions), \
(__attribute__((__section__( \
LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(I2C(idx), memory_regions)))))), \
())
I2C_DEVICE_DT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, PM_DEVICE_DT_GET(I2C(idx)), \
&twim_##idx##z_data, &twim_##idx##z_config, POST_KERNEL, \
CONFIG_I2C_INIT_PRIORITY, &i2c_nrfx_twim_driver_api);

#ifdef CONFIG_HAS_HW_NRF_TWIM0
I2C_NRFX_TWIM_RTIO_DEVICE(0);
Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/i2c_nrfx_twis.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
DT_IRQ(SHIM_NRF_TWIS_NODE(id), priority)

#define SHIM_NRF_TWIS_HAS_MEMORY_REGIONS(id) \
DT_NODE_HAS_PROP(id, memory_regions)
DT_NODE_HAS_PROP(SHIM_NRF_TWIS_NODE(id), memory_regions)

#define SHIM_NRF_TWIS_LINKER_REGION_NAME(id) \
LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(SHIM_NRF_TWIS_NODE(id), memory_regions))

#define SHIM_NRF_TWIS_BUF_ATTR_SECTION(id) \
__attribute__((__section__(SHIM_NRF_TWIS_LINKER_REGION_NAME, ())))
__attribute__((__section__(SHIM_NRF_TWIS_LINKER_REGION_NAME(id))))

#define SHIM_NRF_TWIS_BUF_ATTR(id) \
COND_CODE_1( \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_I2C_TARGET_BUFFER_MODE=y
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2024 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";
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 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 {
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,4 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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 {
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";
};
9 changes: 9 additions & 0 deletions samples/drivers/i2c/rtio_loopback/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ tests:
tags:
- rtio
- i2c_target
harness: console
harness_config:
fixture: i2c_bus_short
type: one_line
regex:
- "sample complete"
platform_allow:
- b_u585i_iot02a
- nrf5340dk/nrf5340/cpuapp
- nrf54l15dk/nrf54l15/cpuapp
- nrf54h20dk/nrf54h20/cpuapp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) 2025 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256
Loading