diff --git a/drivers/i2c/i2c_nrfx_twim_rtio.c b/drivers/i2c/i2c_nrfx_twim_rtio.c index acc2576c1bac..8b5f2c625f8f 100644 --- a/drivers/i2c/i2c_nrfx_twim_rtio.c +++ b/drivers/i2c/i2c_nrfx_twim_rtio.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "i2c_nrfx_twim_common.h" @@ -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) { @@ -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: @@ -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; @@ -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); } @@ -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, \ @@ -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 = \ { \ @@ -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); diff --git a/drivers/i2c/i2c_nrfx_twis.c b/drivers/i2c/i2c_nrfx_twis.c index c70750286b69..9e2b0759f2a3 100644 --- a/drivers/i2c/i2c_nrfx_twis.c +++ b/drivers/i2c/i2c_nrfx_twis.c @@ -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( \ diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 000000000000..64627ec86880 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_TARGET_BUFFER_MODE=y diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 000000000000..21bf0e503a4d --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -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 = , + ; + bias-pull-up; + }; + }; + + i2c2_sleep: i2c2_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c2 { + compatible = "nordic,nrf-twis"; + pinctrl-0 = <&i2c2_default>; + pinctrl-1 = <&i2c2_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 000000000000..9a83d7afb811 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..928b52a66f57 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -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 = , + ; + bias-pull-up; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default: i2c131_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep: i2c131_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + clock-frequency = ; + 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 = ; + pinctrl-0 = <&i2c131_default>; + pinctrl-1 = <&i2c131_sleep>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; + status = "okay"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000000..9a83d7afb811 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..4a7d2fe02a6f --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -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 = , + ; + bias-pull-up; + }; + }; + + i2c21_sleep: i2c21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default: i2c22_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep: i2c22_sleep { + group1 { + psels = , + ; + 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"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/sample.yaml b/samples/drivers/i2c/rtio_loopback/sample.yaml index 6effc59a9f8c..a9d41fbf8cd4 100644 --- a/samples/drivers/i2c/rtio_loopback/sample.yaml +++ b/samples/drivers/i2c/rtio_loopback/sample.yaml @@ -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 diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 000000000000..7dfef7da2839 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000000..2fc033d534a6 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P2.8 and P2.9 + * SCL = P1.2 and P1.3 + */ + +&pinctrl { + i2c130_default: i2c130_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c131_default: i2c131_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c131_sleep: i2c131_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + clock-frequency = ; + pinctrl-0 = <&i2c130_default>; + pinctrl-1 = <&i2c130_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + memory-regions = <&cpuapp_dma_region>; + status = "okay"; + + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + address-width = <8>; + size = <256>; + }; +}; + +&i2c131 { + compatible = "nordic,nrf-twis"; + clock-frequency = ; + pinctrl-0 = <&i2c131_default>; + pinctrl-1 = <&i2c131_sleep>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; + status = "okay"; + + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + address-width = <8>; + size = <256>; + }; +}; diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000000..9a83d7afb811 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 000000000000..dee8b41f0483 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P1.8 and P1.9 + * SCL = P1.10 and P1.11 + */ + +&pinctrl { + i2c21_default: i2c21_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c21_sleep: i2c21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default: i2c22_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep: i2c22_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c21 { + pinctrl-0 = <&i2c21_default>; + pinctrl-1 = <&i2c21_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; + + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + address-width = <8>; + size = <256>; + }; +}; + +&i2c22 { + compatible = "nordic,nrf-twis"; + pinctrl-0 = <&i2c22_default>; + pinctrl-1 = <&i2c22_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; + + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + address-width = <8>; + size = <256>; + }; +}; diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index fe3efa19615c..588b7f7a43d9 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -54,5 +54,8 @@ tests: - max32675evkit - max32680evkit/max32680/m4 - max32690evkit/max32690/m4 + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp integration_platforms: - max32690evkit/max32690/m4