Skip to content
Closed
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
2 changes: 1 addition & 1 deletion boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ arduino_serial: &uart1 {
};

arduino_i2c: &i2c0 {
compatible = "nordic,nrf-twi";
compatible = "nordic,nrf-twim";
status = "okay";
pinctrl-0 = <&i2c0_default>;
pinctrl-1 = <&i2c0_sleep>;
Expand Down
18 changes: 1 addition & 17 deletions drivers/i2c/Kconfig.nrfx
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,7 @@ config I2C_NRFX_TWI
config I2C_NRFX_TWIM
def_bool y
depends on DT_HAS_NORDIC_NRF_TWIM_ENABLED
select NRFX_TWIM0 if HAS_HW_NRF_TWIM0
select NRFX_TWIM1 if HAS_HW_NRF_TWIM1
select NRFX_TWIM2 if HAS_HW_NRF_TWIM2
select NRFX_TWIM3 if HAS_HW_NRF_TWIM3
select NRFX_TWIM20 if HAS_HW_NRF_TWIM20
select NRFX_TWIM21 if HAS_HW_NRF_TWIM21
select NRFX_TWIM22 if HAS_HW_NRF_TWIM22
select NRFX_TWIM30 if HAS_HW_NRF_TWIM30
select NRFX_TWIM120 if HAS_HW_NRF_TWIM120
select NRFX_TWIM130 if HAS_HW_NRF_TWIM130
select NRFX_TWIM131 if HAS_HW_NRF_TWIM131
select NRFX_TWIM132 if HAS_HW_NRF_TWIM132
select NRFX_TWIM133 if HAS_HW_NRF_TWIM133
select NRFX_TWIM134 if HAS_HW_NRF_TWIM134
select NRFX_TWIM135 if HAS_HW_NRF_TWIM135
select NRFX_TWIM136 if HAS_HW_NRF_TWIM136
select NRFX_TWIM137 if HAS_HW_NRF_TWIM137
select NRFX_TWIM

config I2C_NRFX_TRANSFER_TIMEOUT
int "Transfer timeout [ms]"
Expand Down
7 changes: 3 additions & 4 deletions drivers/i2c/i2c_nrfx_twi_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ extern "C" {
: bitrate == 250000 ? NRF_TWI_FREQ_250K \
: bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \
: I2C_NRFX_TWI_INVALID_FREQUENCY)
#define I2C(idx) DT_NODELABEL(i2c##idx)
#define I2C_FREQUENCY(idx) \
I2C_NRFX_TWI_FREQUENCY(DT_PROP_OR(I2C(idx), clock_frequency, \
I2C_BITRATE_STANDARD))
#define I2C_FREQUENCY(inst) \
I2C_NRFX_TWI_FREQUENCY(DT_INST_PROP_OR(inst, clock_frequency, \
I2C_BITRATE_STANDARD))

struct i2c_nrfx_twi_common_data {
uint32_t dev_config;
Expand Down
165 changes: 49 additions & 116 deletions drivers/i2c/i2c_nrfx_twim.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nordic_nrf_twim

#include <zephyr/drivers/i2c.h>
#include <zephyr/dt-bindings/i2c/i2c.h>
#include <zephyr/pm/device.h>
Expand All @@ -27,12 +29,6 @@ LOG_MODULE_REGISTER(i2c_nrfx_twim, CONFIG_I2C_LOG_LEVEL);
#define I2C_TRANSFER_TIMEOUT_MSEC K_FOREVER
#endif

struct i2c_nrfx_twim_data {
struct k_sem transfer_sync;
struct k_sem completion_sync;
volatile nrfx_err_t res;
};

static int i2c_nrfx_twim_transfer(const struct device *dev,
struct i2c_msg *msgs,
uint8_t num_msgs, uint16_t addr)
Expand All @@ -59,7 +55,7 @@ static int i2c_nrfx_twim_transfer(const struct device *dev,
break;
}

bool dma_accessible = nrf_dma_accessible_check(&dev_config->twim, msgs[i].buf);
bool dma_accessible = nrf_dma_accessible_check(&dev_data->twim, msgs[i].buf);

/* This fragment needs to be merged with the next one if:
* - it is not the last fragment
Expand Down Expand Up @@ -213,132 +209,69 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = {
.recover_bus = i2c_nrfx_twim_recover_bus,
};

#define CONCAT_BUF_SIZE(idx) \
COND_CODE_1(DT_NODE_HAS_PROP(I2C(idx), zephyr_concat_buf_size), \
(DT_PROP(I2C(idx), zephyr_concat_buf_size)), (0))
#define FLASH_BUF_MAX_SIZE(idx) \
COND_CODE_1(DT_NODE_HAS_PROP(I2C(idx), zephyr_flash_buf_max_size), \
(DT_PROP(I2C(idx), zephyr_flash_buf_max_size)), (0))
#define CONCAT_BUF_SIZE(inst) \
COND_CODE_1(DT_INST_HAS_PROP(inst, zephyr_concat_buf_size), \
(DT_INST_PROP(inst, zephyr_concat_buf_size)), (0))
#define FLASH_BUF_MAX_SIZE(inst) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, zephyr_flash_buf_max_size), \
(DT_INST_PROP(inst, zephyr_flash_buf_max_size)), (0))

#define USES_MSG_BUF(idx) \
COND_CODE_0(CONCAT_BUF_SIZE(idx), \
(COND_CODE_0(FLASH_BUF_MAX_SIZE(idx), (0), (1))), \
#define USES_MSG_BUF(inst) \
COND_CODE_0(CONCAT_BUF_SIZE(inst), \
(COND_CODE_0(FLASH_BUF_MAX_SIZE(inst), (0), (1))), \
(1))
#define MSG_BUF_SIZE(idx) MAX(CONCAT_BUF_SIZE(idx), FLASH_BUF_MAX_SIZE(idx))
#define MSG_BUF_SIZE(inst) MAX(CONCAT_BUF_SIZE(inst), FLASH_BUF_MAX_SIZE(inst))

#define I2C_NRFX_TWIM_DEVICE(idx) \
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \
BUILD_ASSERT(I2C_FREQUENCY(idx) != \
#define I2C_NRFX_TWIM_DEVICE(inst) \
static void irq_connect##inst(void); \
NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(DT_DRV_INST(inst)); \
BUILD_ASSERT(I2C_FREQUENCY(inst) != \
I2C_NRFX_TWIM_INVALID_FREQUENCY, \
"Wrong I2C " #idx " frequency setting in dts"); \
static void irq_connect##idx(void) \
{ \
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);)) \
static struct i2c_nrfx_twim_data twim_##idx##_data; \
PINCTRL_DT_DEFINE(I2C(idx)); \
"Wrong I2C " #inst" frequency setting in dts"); \
IF_ENABLED(USES_MSG_BUF(inst), \
(static uint8_t twim_##inst##_msg_buf[MSG_BUF_SIZE(inst)] \
I2C_MEMORY_SECTION(inst);)) \
static struct i2c_nrfx_twim_data twim_##inst##_data = { \
.twim = NRFX_TWIM_INSTANCE(DT_INST_REG_ADDR(inst)), \
}; \
PINCTRL_DT_INST_DEFINE(inst); \
static const \
struct i2c_nrfx_twim_common_config twim_##idx##z_config = { \
.twim = NRFX_TWIM_INSTANCE(idx), \
struct i2c_nrfx_twim_common_config twim_##inst##z_config = { \
.twim_config = { \
.skip_gpio_cfg = true, \
.skip_psel_cfg = true, \
.frequency = I2C_FREQUENCY(idx), \
.frequency = I2C_FREQUENCY(inst), \
}, \
.event_handler = event_handler, \
.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,)) \
.msg_buf_size = MSG_BUF_SIZE(inst), \
.irq_connect = irq_connect##inst, \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
IF_ENABLED(USES_MSG_BUF(inst), \
(.msg_buf = twim_##inst##_msg_buf,)) \
.max_transfer_size = BIT_MASK( \
DT_PROP(I2C(idx), easydma_maxcnt_bits)), \
DT_INST_PROP(inst, easydma_maxcnt_bits)), \
}; \
PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, \
PM_DEVICE_ISR_SAFE); \
I2C_DEVICE_DT_DEFINE(I2C(idx), \
static void irq_connect##inst(void) \
{ \
IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \
nrfx_twim_irq_handler, \
&twim_##inst##_data.twim, 0); \
} \
PM_DEVICE_DT_INST_DEFINE(int, twim_nrfx_pm_action, \
PM_DEVICE_ISR_SAFE); \
I2C_DEVICE_DT_INST_DEFINE(inst, \
i2c_nrfx_twim_init, \
PM_DEVICE_DT_GET(I2C(idx)), \
&twim_##idx##_data, \
&twim_##idx##z_config, \
PM_DEVICE_DT_INST_GET(inst), \
&twim_##inst##_data, \
&twim_##inst##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), \
#define I2C_MEMORY_SECTION(inst) \
COND_CODE_1(DT_INST_HAS_PROP(inst, memory_regions), \
(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
DT_PHANDLE(I2C(idx), memory_regions)))))), \
DT_INST_PHANDLE(inst, memory_regions)))))), \
())

#ifdef CONFIG_HAS_HW_NRF_TWIM0
I2C_NRFX_TWIM_DEVICE(0);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM1
I2C_NRFX_TWIM_DEVICE(1);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM2
I2C_NRFX_TWIM_DEVICE(2);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM3
I2C_NRFX_TWIM_DEVICE(3);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM20
I2C_NRFX_TWIM_DEVICE(20);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM21
I2C_NRFX_TWIM_DEVICE(21);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM22
I2C_NRFX_TWIM_DEVICE(22);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM30
I2C_NRFX_TWIM_DEVICE(30);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM120
I2C_NRFX_TWIM_DEVICE(120);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM130
I2C_NRFX_TWIM_DEVICE(130);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM131
I2C_NRFX_TWIM_DEVICE(131);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM132
I2C_NRFX_TWIM_DEVICE(132);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM133
I2C_NRFX_TWIM_DEVICE(133);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM134
I2C_NRFX_TWIM_DEVICE(134);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM135
I2C_NRFX_TWIM_DEVICE(135);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM136
I2C_NRFX_TWIM_DEVICE(136);
#endif

#ifdef CONFIG_HAS_HW_NRF_TWIM137
I2C_NRFX_TWIM_DEVICE(137);
#endif
DT_INST_FOREACH_STATUS_OKAY(I2C_NRFX_TWIM_DEVICE)
28 changes: 16 additions & 12 deletions drivers/i2c/i2c_nrfx_twim_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,50 @@ LOG_MODULE_DECLARE(i2c_nrfx_twim);
int i2c_nrfx_twim_recover_bus(const struct device *dev)
{
const struct i2c_nrfx_twim_common_config *config = dev->config;
struct i2c_nrfx_twim_data *data = dev->data;
enum pm_device_state state;
uint32_t scl_pin;
uint32_t sda_pin;
nrfx_err_t err;

scl_pin = nrf_twim_scl_pin_get(config->twim.p_twim);
sda_pin = nrf_twim_sda_pin_get(config->twim.p_twim);
scl_pin = nrf_twim_scl_pin_get(data->twim.p_twim);
sda_pin = nrf_twim_sda_pin_get(data->twim.p_twim);

/* disable peripheral if active (required to release SCL/SDA lines) */
(void)pm_device_state_get(dev, &state);
if (state == PM_DEVICE_STATE_ACTIVE) {
nrfx_twim_disable(&config->twim);
nrfx_twim_disable(&data->twim);
}

err = nrfx_twim_bus_recover(scl_pin, sda_pin);

/* restore peripheral if it was active before */
if (state == PM_DEVICE_STATE_ACTIVE) {
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
nrfx_twim_enable(&config->twim);
nrfx_twim_enable(&data->twim);
}

return (err == NRFX_SUCCESS ? 0 : -EBUSY);
}

int i2c_nrfx_twim_configure(const struct device *dev, uint32_t i2c_config)
{
const struct i2c_nrfx_twim_common_config *config = dev->config;
struct i2c_nrfx_twim_data *data = dev->data;

if (I2C_ADDR_10_BITS & i2c_config) {
return -EINVAL;
}

switch (I2C_SPEED_GET(i2c_config)) {
case I2C_SPEED_STANDARD:
nrf_twim_frequency_set(config->twim.p_twim, NRF_TWIM_FREQ_100K);
nrf_twim_frequency_set(data->twim.p_twim, NRF_TWIM_FREQ_100K);
break;
case I2C_SPEED_FAST:
nrf_twim_frequency_set(config->twim.p_twim, NRF_TWIM_FREQ_400K);
nrf_twim_frequency_set(data->twim.p_twim, NRF_TWIM_FREQ_400K);
break;
#if NRF_TWIM_HAS_1000_KHZ_FREQ
case I2C_SPEED_FAST_PLUS:
nrf_twim_frequency_set(config->twim.p_twim, NRF_TWIM_FREQ_1000K);
nrf_twim_frequency_set(data->twim.p_twim, NRF_TWIM_FREQ_1000K);
break;
#endif
default:
Expand All @@ -74,6 +75,7 @@ int i2c_nrfx_twim_msg_transfer(const struct device *dev, uint8_t flags, uint8_t
size_t buf_len, uint16_t i2c_addr)
{
const struct i2c_nrfx_twim_common_config *config = dev->config;
struct i2c_nrfx_twim_data *data = dev->data;
nrfx_twim_xfer_desc_t cur_xfer = {
.address = i2c_addr,
.type = (flags & I2C_MSG_READ) ? NRFX_TWIM_XFER_RX : NRFX_TWIM_XFER_TX,
Expand All @@ -90,7 +92,7 @@ int i2c_nrfx_twim_msg_transfer(const struct device *dev, uint8_t flags, uint8_t
return -ENOSPC;
}

res = nrfx_twim_xfer(&config->twim, &cur_xfer,
res = nrfx_twim_xfer(&data->twim, &cur_xfer,
(flags & I2C_MSG_STOP) ? 0 : NRFX_TWIM_FLAG_TX_NO_STOP);
if (res != NRFX_SUCCESS) {
if (res == NRFX_ERROR_BUSY) {
Expand All @@ -105,14 +107,15 @@ int i2c_nrfx_twim_msg_transfer(const struct device *dev, uint8_t flags, uint8_t
int twim_nrfx_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct i2c_nrfx_twim_common_config *config = dev->config;
struct i2c_nrfx_twim_data *data = dev->data;

switch (action) {
case PM_DEVICE_ACTION_RESUME:
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
nrfx_twim_enable(&config->twim);
nrfx_twim_enable(&data->twim);
break;
case PM_DEVICE_ACTION_SUSPEND:
nrfx_twim_disable(&config->twim);
nrfx_twim_disable(&data->twim);
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
break;
default:
Expand All @@ -125,12 +128,13 @@ int twim_nrfx_pm_action(const struct device *dev, enum pm_device_action action)
int i2c_nrfx_twim_common_init(const struct device *dev)
{
const struct i2c_nrfx_twim_common_config *config = dev->config;
struct i2c_nrfx_twim_data *data = dev->data;

config->irq_connect();

(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);

if (nrfx_twim_init(&config->twim, &config->twim_config, config->event_handler,
if (nrfx_twim_init(&data->twim, &config->twim_config, config->event_handler,
(void *)dev) != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize device: %s", dev->name);
return -EIO;
Expand Down
8 changes: 7 additions & 1 deletion drivers/i2c/i2c_nrfx_twim_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ extern "C" {
#define I2C_FREQUENCY(idx) I2C_NRFX_TWIM_FREQUENCY(DT_PROP_OR(I2C(idx), clock_frequency, \
I2C_BITRATE_STANDARD))

struct i2c_nrfx_twim_common_config {
struct i2c_nrfx_twim_data {
nrfx_twim_t twim;
struct k_sem transfer_sync;
struct k_sem completion_sync;
volatile nrfx_err_t res;
};

struct i2c_nrfx_twim_common_config {
nrfx_twim_config_t twim_config;
nrfx_twim_evt_handler_t event_handler;
uint16_t msg_buf_size;
Expand Down
Loading
Loading