diff --git a/drivers/i2s/Kconfig.nrfx b/drivers/i2s/Kconfig.nrfx index 7337f9974c0..786de1ba68b 100644 --- a/drivers/i2s/Kconfig.nrfx +++ b/drivers/i2s/Kconfig.nrfx @@ -5,8 +5,7 @@ menuconfig I2S_NRFX bool "nRF I2S nrfx driver" default y depends on DT_HAS_NORDIC_NRF_I2S_ENABLED - select NRFX_I2S0 if HAS_HW_NRF_I2S0 - select NRFX_I2S20 if HAS_HW_NRF_I2S20 + select NRFX_I2S select PINCTRL help Enable support for nrfx I2S driver for nRF MCU series. diff --git a/drivers/i2s/i2s_nrfx.c b/drivers/i2s/i2s_nrfx.c index eb41b229293..3991c806044 100644 --- a/drivers/i2s/i2s_nrfx.c +++ b/drivers/i2s/i2s_nrfx.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT nordic_nrf_i2s + #include #include #include @@ -33,21 +35,20 @@ struct i2s_nrfx_drv_data { struct k_msgq tx_queue; struct stream_cfg rx; struct k_msgq rx_queue; - const nrfx_i2s_t *p_i2s; + nrfx_i2s_t i2s; const uint32_t *last_tx_buffer; enum i2s_state state; enum i2s_dir active_dir; bool stop; /* stop after the current (TX or RX) block */ bool discard_rx; /* discard further RX blocks */ volatile bool next_tx_buffer_needed; - bool tx_configured : 1; - bool rx_configured : 1; - bool request_clock : 1; + bool tx_configured: 1; + bool rx_configured: 1; + bool request_clock: 1; }; struct i2s_nrfx_drv_cfg { nrfx_i2s_data_handler_t data_handler; - nrfx_i2s_t i2s; nrfx_i2s_config_t nrfx_def_cfg; const struct pinctrl_dev_config *pcfg; enum clock_source { @@ -81,7 +82,7 @@ static void find_suitable_clock(const struct i2s_nrfx_drv_cfg *drv_cfg, .allow_bypass = IS_ENABLED(CONFIG_I2S_NRFX_ALLOW_MCK_BYPASS), }; - if (nrfx_i2s_prescalers_calc(&clk_params, &config->prescalers) != NRFX_SUCCESS) { + if (nrfx_i2s_prescalers_calc(&clk_params, &config->prescalers) != 0) { LOG_ERR("Failed to find suitable I2S clock configuration."); } } @@ -134,7 +135,7 @@ static bool supply_next_buffers(struct i2s_nrfx_drv_data *drv_data, if (drv_data->active_dir != I2S_DIR_TX) { /* -> RX active */ if (!get_next_rx_buffer(drv_data, next)) { drv_data->state = I2S_STATE_ERROR; - nrfx_i2s_stop(drv_data->p_i2s); + nrfx_i2s_stop(&drv_data->i2s); return false; } /* Set buffer size if there is no TX buffer (which effectively @@ -149,7 +150,7 @@ static bool supply_next_buffers(struct i2s_nrfx_drv_data *drv_data, drv_data->last_tx_buffer = next->p_tx_buffer; LOG_DBG("Next buffers: %p/%p", next->p_tx_buffer, next->p_rx_buffer); - nrfx_i2s_next_buffers_set(drv_data->p_i2s, next); + nrfx_i2s_next_buffers_set(&drv_data->i2s, next); return true; } @@ -181,7 +182,7 @@ static void data_handler(const struct device *dev, } drv_data->last_tx_buffer = NULL; } - nrfx_i2s_uninit(drv_data->p_i2s); + nrfx_i2s_uninit(&drv_data->i2s); if (drv_data->request_clock) { (void)onoff_release(drv_data->clk_mgr); } @@ -198,7 +199,7 @@ static void data_handler(const struct device *dev, LOG_ERR("Next buffers not supplied on time"); drv_data->state = I2S_STATE_ERROR; } - nrfx_i2s_stop(drv_data->p_i2s); + nrfx_i2s_stop(&drv_data->i2s); return; } @@ -248,7 +249,7 @@ static void data_handler(const struct device *dev, } if (stop_transfer) { - nrfx_i2s_stop(drv_data->p_i2s); + nrfx_i2s_stop(&drv_data->i2s); } else if (status & NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED) { nrfx_i2s_buffers_t next = { 0 }; @@ -419,8 +420,8 @@ static int i2s_nrfx_configure(const struct device *dev, enum i2s_dir dir, * the MCK output is used), find a suitable clock configuration for it. */ if (nrfx_cfg.mode == NRF_I2S_MODE_MASTER || - (nrf_i2s_mck_pin_get(drv_cfg->i2s.p_reg) & I2S_PSEL_MCK_CONNECT_Msk) - == I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos) { + (nrf_i2s_mck_pin_get(drv_data->i2s.p_reg) & I2S_PSEL_MCK_CONNECT_Msk) == + I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos) { find_suitable_clock(drv_cfg, &nrfx_cfg, i2s_cfg); /* Unless the PCLK32M source is used with the HFINT oscillator * (which is always available without any additional actions), @@ -578,7 +579,7 @@ static int start_transfer(struct i2s_nrfx_drv_data *drv_data) /* Failed to allocate next RX buffer */ ret = -ENOMEM; } else { - nrfx_err_t err; + int err; /* It is necessary to set buffer size here only for I2S_DIR_RX, * because only then the get_next_tx_buffer() call in the if @@ -591,16 +592,16 @@ static int start_transfer(struct i2s_nrfx_drv_data *drv_data) drv_data->last_tx_buffer = initial_buffers.p_tx_buffer; - err = nrfx_i2s_start(drv_data->p_i2s, &initial_buffers, 0); - if (err == NRFX_SUCCESS) { + err = nrfx_i2s_start(&drv_data->i2s, &initial_buffers, 0); + if (err == 0) { return 0; } - LOG_ERR("Failed to start I2S transfer: 0x%08x", err); + LOG_ERR("Failed to start I2S transfer: %d", err); ret = -EIO; } - nrfx_i2s_uninit(drv_data->p_i2s); + nrfx_i2s_uninit(&drv_data->i2s); if (drv_data->request_clock) { (void)onoff_release(drv_data->clk_mgr); } @@ -629,7 +630,7 @@ static void clock_started_callback(struct onoff_manager *mgr, * the actual transfer in such case. */ if (drv_data->state == I2S_STATE_READY) { - nrfx_i2s_uninit(drv_data->p_i2s); + nrfx_i2s_uninit(&drv_data->i2s); (void)onoff_release(drv_data->clk_mgr); } else { (void)start_transfer(drv_data); @@ -640,22 +641,22 @@ static int trigger_start(const struct device *dev) { struct i2s_nrfx_drv_data *drv_data = dev->data; const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; - nrfx_err_t err; + int err; int ret; const nrfx_i2s_config_t *nrfx_cfg = (drv_data->active_dir == I2S_DIR_TX) ? &drv_data->tx.nrfx_cfg : &drv_data->rx.nrfx_cfg; - err = nrfx_i2s_init(drv_data->p_i2s, nrfx_cfg, drv_cfg->data_handler); - if (err != NRFX_SUCCESS) { - LOG_ERR("Failed to initialize I2S: 0x%08x", err); + err = nrfx_i2s_init(&drv_data->i2s, nrfx_cfg, drv_cfg->data_handler); + if (err != 0) { + LOG_ERR("Failed to initialize I2S: %d", err); return -EIO; } drv_data->state = I2S_STATE_RUNNING; #if NRF_I2S_HAS_CLKCONFIG - nrf_i2s_clk_configure(drv_cfg->i2s.p_reg, + nrf_i2s_clk_configure(drv_data->i2s.p_reg, drv_cfg->clk_src == ACLK ? NRF_I2S_CLKSRC_ACLK : NRF_I2S_CLKSRC_PCLK32M, nrfx_cfg->prescalers.enable_bypass); @@ -669,7 +670,7 @@ static int trigger_start(const struct device *dev) clock_started_callback); ret = onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); if (ret < 0) { - nrfx_i2s_uninit(drv_data->p_i2s); + nrfx_i2s_uninit(&drv_data->i2s); drv_data->state = I2S_STATE_READY; LOG_ERR("Failed to request clock: %d", ret); @@ -776,7 +777,7 @@ static int i2s_nrfx_trigger(const struct device *dev, case I2S_TRIGGER_DROP: if (drv_data->state != I2S_STATE_READY) { drv_data->discard_rx = true; - nrfx_i2s_stop(drv_data->p_i2s); + nrfx_i2s_stop(&drv_data->i2s); } purge_queue(dev, dir); drv_data->state = I2S_STATE_READY; @@ -821,72 +822,56 @@ static DEVICE_API(i2s, i2s_nrf_drv_api) = { .trigger = i2s_nrfx_trigger, }; -#define I2S(idx) DT_NODELABEL(i2s##idx) -#define I2S_CLK_SRC(idx) DT_STRING_TOKEN(I2S(idx), clock_source) - -#define I2S_NRFX_DEVICE(idx) \ - static struct i2s_buf tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \ - static struct i2s_buf rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \ - static void data_handler##idx(nrfx_i2s_buffers_t const *p_released, \ - uint32_t status) \ - { \ - data_handler(DEVICE_DT_GET(I2S(idx)), p_released, status); \ - } \ - PINCTRL_DT_DEFINE(I2S(idx)); \ - static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##idx = { \ - .data_handler = data_handler##idx, \ - .i2s = NRFX_I2S_INSTANCE(idx), \ - .nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG( \ - NRF_I2S_PIN_NOT_CONNECTED, \ - NRF_I2S_PIN_NOT_CONNECTED, \ - NRF_I2S_PIN_NOT_CONNECTED, \ - NRF_I2S_PIN_NOT_CONNECTED, \ - NRF_I2S_PIN_NOT_CONNECTED), \ - .nrfx_def_cfg.skip_gpio_cfg = true, \ - .nrfx_def_cfg.skip_psel_cfg = true, \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2S(idx)), \ - .clk_src = I2S_CLK_SRC(idx), \ - }; \ - static struct i2s_nrfx_drv_data i2s_nrfx_data##idx = { \ - .state = I2S_STATE_READY, \ - .p_i2s = &i2s_nrfx_cfg##idx.i2s \ - }; \ - static int i2s_nrfx_init##idx(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_IRQN(I2S(idx)), DT_IRQ(I2S(idx), priority), \ - nrfx_isr, nrfx_i2s_##idx##_irq_handler, 0); \ - const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; \ - int err = pinctrl_apply_state(drv_cfg->pcfg, \ - PINCTRL_STATE_DEFAULT); \ - if (err < 0) { \ - return err; \ - } \ - k_msgq_init(&i2s_nrfx_data##idx.tx_queue, \ - (char *)tx_msgs##idx, sizeof(struct i2s_buf), \ - ARRAY_SIZE(tx_msgs##idx)); \ - k_msgq_init(&i2s_nrfx_data##idx.rx_queue, \ - (char *)rx_msgs##idx, sizeof(struct i2s_buf), \ - ARRAY_SIZE(rx_msgs##idx)); \ - init_clock_manager(dev); \ - return 0; \ - } \ - BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || \ - (NRF_I2S_HAS_CLKCONFIG && NRF_CLOCK_HAS_HFCLKAUDIO), \ - "Clock source ACLK is not available."); \ - BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || \ - DT_NODE_HAS_PROP(DT_NODELABEL(clock), \ - hfclkaudio_frequency), \ - "Clock source ACLK requires the hfclkaudio-frequency " \ - "property to be defined in the nordic,nrf-clock node."); \ - DEVICE_DT_DEFINE(I2S(idx), i2s_nrfx_init##idx, NULL, \ - &i2s_nrfx_data##idx, &i2s_nrfx_cfg##idx, \ - POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, \ - &i2s_nrf_drv_api); - -#ifdef CONFIG_HAS_HW_NRF_I2S0 -I2S_NRFX_DEVICE(0); -#endif - -#ifdef CONFIG_HAS_HW_NRF_I2S20 -I2S_NRFX_DEVICE(20); -#endif +#define I2S_CLK_SRC(inst) DT_STRING_TOKEN(DT_DRV_INST(inst), clock_source) + +#define I2S_NRFX_DEVICE(inst) \ + static struct i2s_buf tx_msgs##inst[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \ + static struct i2s_buf rx_msgs##inst[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \ + static void data_handler##inst(nrfx_i2s_buffers_t const *p_released, uint32_t status) \ + { \ + data_handler(DEVICE_DT_GET(DT_DRV_INST(inst)), p_released, status); \ + } \ + PINCTRL_DT_DEFINE(DT_DRV_INST(inst)); \ + static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##inst = { \ + .data_handler = data_handler##inst, \ + .nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG( \ + NRF_I2S_PIN_NOT_CONNECTED, NRF_I2S_PIN_NOT_CONNECTED, \ + NRF_I2S_PIN_NOT_CONNECTED, NRF_I2S_PIN_NOT_CONNECTED, \ + NRF_I2S_PIN_NOT_CONNECTED), \ + .nrfx_def_cfg.skip_gpio_cfg = true, \ + .nrfx_def_cfg.skip_psel_cfg = true, \ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(inst)), \ + .clk_src = I2S_CLK_SRC(inst), \ + }; \ + static struct i2s_nrfx_drv_data i2s_nrfx_data##inst = { \ + .state = I2S_STATE_READY, \ + .i2s = NRFX_I2S_INSTANCE(DT_INST_REG_ADDR(inst)), \ + }; \ + static int i2s_nrfx_init##inst(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), nrfx_i2s_irq_handler, \ + &i2s_nrfx_data##inst.i2s, 0); \ + const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; \ + int err = pinctrl_apply_state(drv_cfg->pcfg, PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + k_msgq_init(&i2s_nrfx_data##inst.tx_queue, (char *)tx_msgs##inst, \ + sizeof(struct i2s_buf), ARRAY_SIZE(tx_msgs##inst)); \ + k_msgq_init(&i2s_nrfx_data##inst.rx_queue, (char *)rx_msgs##inst, \ + sizeof(struct i2s_buf), ARRAY_SIZE(rx_msgs##inst)); \ + init_clock_manager(dev); \ + return 0; \ + } \ + BUILD_ASSERT(I2S_CLK_SRC(inst) != ACLK || \ + (NRF_I2S_HAS_CLKCONFIG && NRF_CLOCK_HAS_HFCLKAUDIO), \ + "Clock source ACLK is not available."); \ + BUILD_ASSERT(I2S_CLK_SRC(inst) != ACLK || \ + DT_NODE_HAS_PROP(DT_NODELABEL(clock), hfclkaudio_frequency), \ + "Clock source ACLK requires the hfclkaudio-frequency " \ + "property to be defined in the nordic,nrf-clock node."); \ + DEVICE_DT_INST_DEFINE(inst, i2s_nrfx_init##inst, NULL, &i2s_nrfx_data##inst, \ + &i2s_nrfx_cfg##inst, POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, \ + &i2s_nrf_drv_api); + +DT_INST_FOREACH_STATUS_OKAY(I2S_NRFX_DEVICE) diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 523931be649..521dd3f64c0 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -252,17 +252,7 @@ config NRFX_GRTC depends on $(dt_nodelabel_exists,grtc) config NRFX_I2S - bool - -config NRFX_I2S0 - bool "I2S0 driver instance" - depends on $(dt_nodelabel_exists,i2s0) - select NRFX_I2S - -config NRFX_I2S20 - bool "I2S20 driver instance" - depends on $(dt_nodelabel_exists,i2s20) - select NRFX_I2S + bool "I2S driver" config NRFX_IPC bool "IPC driver" diff --git a/modules/hal_nordic/nrfx/nrfx_glue.c b/modules/hal_nordic/nrfx/nrfx_glue.c index 4e7fc94e11d..1f8054eb76b 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.c +++ b/modules/hal_nordic/nrfx/nrfx_glue.c @@ -45,3 +45,27 @@ char const *nrfx_error_string_get(nrfx_err_t code) default: return "unknown"; } } + +char const *nrfx_new_error_string_get(int code) +{ +#define NRFX_NEW_ERROR_STRING_CASE(code) \ + case code: \ + return #code + switch (-code) { + NRFX_NEW_ERROR_STRING_CASE(0); + NRFX_NEW_ERROR_STRING_CASE(ECANCELED); + NRFX_NEW_ERROR_STRING_CASE(ENOMEM); + NRFX_NEW_ERROR_STRING_CASE(ENOTSUP); + NRFX_NEW_ERROR_STRING_CASE(EINVAL); + NRFX_NEW_ERROR_STRING_CASE(EINPROGRESS); + NRFX_NEW_ERROR_STRING_CASE(E2BIG); + NRFX_NEW_ERROR_STRING_CASE(ETIMEDOUT); + NRFX_NEW_ERROR_STRING_CASE(EPERM); + NRFX_NEW_ERROR_STRING_CASE(EFAULT); + NRFX_NEW_ERROR_STRING_CASE(EACCES); + NRFX_NEW_ERROR_STRING_CASE(EBUSY); + NRFX_NEW_ERROR_STRING_CASE(EALREADY); + default: + return "unknown"; + } +} diff --git a/modules/hal_nordic/nrfx/nrfx_kconfig.h b/modules/hal_nordic/nrfx/nrfx_kconfig.h index 8103f041a4a..16f36e45914 100644 --- a/modules/hal_nordic/nrfx/nrfx_kconfig.h +++ b/modules/hal_nordic/nrfx/nrfx_kconfig.h @@ -224,12 +224,6 @@ #ifdef CONFIG_NRFX_I2S_LOG #define NRFX_I2S_CONFIG_LOG_ENABLED 1 #endif -#ifdef CONFIG_NRFX_I2S0 -#define NRFX_I2S0_ENABLED 1 -#endif -#ifdef CONFIG_NRFX_I2S20 -#define NRFX_I2S20_ENABLED 1 -#endif #ifdef CONFIG_NRFX_IPC #define NRFX_IPC_ENABLED 1 diff --git a/modules/hal_nordic/nrfx/nrfx_log.h b/modules/hal_nordic/nrfx/nrfx_log.h index 682388d7dd1..88efb029556 100644 --- a/modules/hal_nordic/nrfx/nrfx_log.h +++ b/modules/hal_nordic/nrfx/nrfx_log.h @@ -128,6 +128,16 @@ LOG_MODULE_REGISTER(NRFX_MODULE_PREFIX, NRFX_MODULE_LOG_LEVEL); #define NRFX_LOG_ERROR_STRING_GET(error_code) nrfx_error_string_get(error_code) extern char const *nrfx_error_string_get(nrfx_err_t code); +/** + * @brief Macro for getting the textual representation of a given errno error code. + * + * @param[in] error_code Errno error code. + * + * @return String containing the textual representation of the errno error code. + */ +#define NRFX_NEW_LOG_ERROR_STRING_GET(error_code) nrfx_new_error_string_get(error_code) +extern char const *nrfx_new_error_string_get(int code); + /** @} */ #ifdef __cplusplus diff --git a/soc/nordic/common/Kconfig.peripherals b/soc/nordic/common/Kconfig.peripherals index fa7fd2a411a..8606f957728 100644 --- a/soc/nordic/common/Kconfig.peripherals +++ b/soc/nordic/common/Kconfig.peripherals @@ -98,12 +98,6 @@ config HAS_HW_NRF_GPIOTE131 config HAS_HW_NRF_GRTC def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_GRTC)) -config HAS_HW_NRF_I2S0 - def_bool $(dt_nodelabel_enabled_with_compat,i2s0,$(DT_COMPAT_NORDIC_NRF_I2S)) - -config HAS_HW_NRF_I2S20 - def_bool $(dt_nodelabel_enabled_with_compat,i2s20,$(DT_COMPAT_NORDIC_NRF_I2S)) - config HAS_HW_NRF_KMU def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_KMU))