44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7+ #define DT_DRV_COMPAT nordic_nrf_i2s
8+
79#include <stdlib.h>
810#include <zephyr/drivers/i2s.h>
911#include <zephyr/drivers/clock_control/nrf_clock_control.h>
@@ -33,21 +35,20 @@ struct i2s_nrfx_drv_data {
3335 struct k_msgq tx_queue ;
3436 struct stream_cfg rx ;
3537 struct k_msgq rx_queue ;
36- const nrfx_i2s_t * p_i2s ;
38+ nrfx_i2s_t i2s ;
3739 const uint32_t * last_tx_buffer ;
3840 enum i2s_state state ;
3941 enum i2s_dir active_dir ;
4042 bool stop ; /* stop after the current (TX or RX) block */
4143 bool discard_rx ; /* discard further RX blocks */
4244 volatile bool next_tx_buffer_needed ;
43- bool tx_configured : 1 ;
44- bool rx_configured : 1 ;
45- bool request_clock : 1 ;
45+ bool tx_configured : 1 ;
46+ bool rx_configured : 1 ;
47+ bool request_clock : 1 ;
4648};
4749
4850struct i2s_nrfx_drv_cfg {
4951 nrfx_i2s_data_handler_t data_handler ;
50- nrfx_i2s_t i2s ;
5152 nrfx_i2s_config_t nrfx_def_cfg ;
5253 const struct pinctrl_dev_config * pcfg ;
5354 enum clock_source {
@@ -81,7 +82,7 @@ static void find_suitable_clock(const struct i2s_nrfx_drv_cfg *drv_cfg,
8182 .allow_bypass = IS_ENABLED (CONFIG_I2S_NRFX_ALLOW_MCK_BYPASS ),
8283 };
8384
84- if (nrfx_i2s_prescalers_calc (& clk_params , & config -> prescalers ) != NRFX_SUCCESS ) {
85+ if (nrfx_i2s_prescalers_calc (& clk_params , & config -> prescalers ) != 0 ) {
8586 LOG_ERR ("Failed to find suitable I2S clock configuration." );
8687 }
8788}
@@ -134,7 +135,7 @@ static bool supply_next_buffers(struct i2s_nrfx_drv_data *drv_data,
134135 if (drv_data -> active_dir != I2S_DIR_TX ) { /* -> RX active */
135136 if (!get_next_rx_buffer (drv_data , next )) {
136137 drv_data -> state = I2S_STATE_ERROR ;
137- nrfx_i2s_stop (drv_data -> p_i2s );
138+ nrfx_i2s_stop (& drv_data -> i2s );
138139 return false;
139140 }
140141 /* 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,
149150 drv_data -> last_tx_buffer = next -> p_tx_buffer ;
150151
151152 LOG_DBG ("Next buffers: %p/%p" , next -> p_tx_buffer , next -> p_rx_buffer );
152- nrfx_i2s_next_buffers_set (drv_data -> p_i2s , next );
153+ nrfx_i2s_next_buffers_set (& drv_data -> i2s , next );
153154 return true;
154155}
155156
@@ -181,7 +182,7 @@ static void data_handler(const struct device *dev,
181182 }
182183 drv_data -> last_tx_buffer = NULL ;
183184 }
184- nrfx_i2s_uninit (drv_data -> p_i2s );
185+ nrfx_i2s_uninit (& drv_data -> i2s );
185186 if (drv_data -> request_clock ) {
186187 (void )onoff_release (drv_data -> clk_mgr );
187188 }
@@ -198,7 +199,7 @@ static void data_handler(const struct device *dev,
198199 LOG_ERR ("Next buffers not supplied on time" );
199200 drv_data -> state = I2S_STATE_ERROR ;
200201 }
201- nrfx_i2s_stop (drv_data -> p_i2s );
202+ nrfx_i2s_stop (& drv_data -> i2s );
202203 return ;
203204 }
204205
@@ -248,7 +249,7 @@ static void data_handler(const struct device *dev,
248249 }
249250
250251 if (stop_transfer ) {
251- nrfx_i2s_stop (drv_data -> p_i2s );
252+ nrfx_i2s_stop (& drv_data -> i2s );
252253 } else if (status & NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED ) {
253254 nrfx_i2s_buffers_t next = { 0 };
254255
@@ -419,7 +420,7 @@ static int i2s_nrfx_configure(const struct device *dev, enum i2s_dir dir,
419420 * the MCK output is used), find a suitable clock configuration for it.
420421 */
421422 if (nrfx_cfg .mode == NRF_I2S_MODE_MASTER ||
422- nrf_i2s_mck_pin_connected_check (drv_cfg -> i2s .p_reg )) {
423+ nrf_i2s_mck_pin_connected_check (drv_data -> i2s .p_reg )) {
423424 find_suitable_clock (drv_cfg , & nrfx_cfg , i2s_cfg );
424425 /* Unless the PCLK32M source is used with the HFINT oscillator
425426 * (which is always available without any additional actions),
@@ -577,7 +578,7 @@ static int start_transfer(struct i2s_nrfx_drv_data *drv_data)
577578 /* Failed to allocate next RX buffer */
578579 ret = - ENOMEM ;
579580 } else {
580- nrfx_err_t err ;
581+ int err ;
581582
582583 /* It is necessary to set buffer size here only for I2S_DIR_RX,
583584 * because only then the get_next_tx_buffer() call in the if
@@ -590,16 +591,16 @@ static int start_transfer(struct i2s_nrfx_drv_data *drv_data)
590591
591592 drv_data -> last_tx_buffer = initial_buffers .p_tx_buffer ;
592593
593- err = nrfx_i2s_start (drv_data -> p_i2s , & initial_buffers , 0 );
594- if (err == NRFX_SUCCESS ) {
594+ err = nrfx_i2s_start (& drv_data -> i2s , & initial_buffers , 0 );
595+ if (err == 0 ) {
595596 return 0 ;
596597 }
597598
598- LOG_ERR ("Failed to start I2S transfer: 0x%08x " , err );
599+ LOG_ERR ("Failed to start I2S transfer: %d " , err );
599600 ret = - EIO ;
600601 }
601602
602- nrfx_i2s_uninit (drv_data -> p_i2s );
603+ nrfx_i2s_uninit (& drv_data -> i2s );
603604 if (drv_data -> request_clock ) {
604605 (void )onoff_release (drv_data -> clk_mgr );
605606 }
@@ -628,7 +629,7 @@ static void clock_started_callback(struct onoff_manager *mgr,
628629 * the actual transfer in such case.
629630 */
630631 if (drv_data -> state == I2S_STATE_READY ) {
631- nrfx_i2s_uninit (drv_data -> p_i2s );
632+ nrfx_i2s_uninit (& drv_data -> i2s );
632633 (void )onoff_release (drv_data -> clk_mgr );
633634 } else {
634635 (void )start_transfer (drv_data );
@@ -639,22 +640,22 @@ static int trigger_start(const struct device *dev)
639640{
640641 struct i2s_nrfx_drv_data * drv_data = dev -> data ;
641642 const struct i2s_nrfx_drv_cfg * drv_cfg = dev -> config ;
642- nrfx_err_t err ;
643+ int err ;
643644 int ret ;
644645 const nrfx_i2s_config_t * nrfx_cfg = (drv_data -> active_dir == I2S_DIR_TX )
645646 ? & drv_data -> tx .nrfx_cfg
646647 : & drv_data -> rx .nrfx_cfg ;
647648
648- err = nrfx_i2s_init (drv_data -> p_i2s , nrfx_cfg , drv_cfg -> data_handler );
649- if (err != NRFX_SUCCESS ) {
650- LOG_ERR ("Failed to initialize I2S: 0x%08x " , err );
649+ err = nrfx_i2s_init (& drv_data -> i2s , nrfx_cfg , drv_cfg -> data_handler );
650+ if (err != 0 ) {
651+ LOG_ERR ("Failed to initialize I2S: %d " , err );
651652 return - EIO ;
652653 }
653654
654655 drv_data -> state = I2S_STATE_RUNNING ;
655656
656657#if NRF_I2S_HAS_CLKCONFIG
657- nrf_i2s_clk_configure (drv_cfg -> i2s .p_reg ,
658+ nrf_i2s_clk_configure (drv_data -> i2s .p_reg ,
658659 drv_cfg -> clk_src == ACLK ? NRF_I2S_CLKSRC_ACLK
659660 : NRF_I2S_CLKSRC_PCLK32M ,
660661 nrfx_cfg -> prescalers .enable_bypass );
@@ -668,7 +669,7 @@ static int trigger_start(const struct device *dev)
668669 clock_started_callback );
669670 ret = onoff_request (drv_data -> clk_mgr , & drv_data -> clk_cli );
670671 if (ret < 0 ) {
671- nrfx_i2s_uninit (drv_data -> p_i2s );
672+ nrfx_i2s_uninit (& drv_data -> i2s );
672673 drv_data -> state = I2S_STATE_READY ;
673674
674675 LOG_ERR ("Failed to request clock: %d" , ret );
@@ -775,7 +776,7 @@ static int i2s_nrfx_trigger(const struct device *dev,
775776 case I2S_TRIGGER_DROP :
776777 if (drv_data -> state != I2S_STATE_READY ) {
777778 drv_data -> discard_rx = true;
778- nrfx_i2s_stop (drv_data -> p_i2s );
779+ nrfx_i2s_stop (& drv_data -> i2s );
779780 }
780781 purge_queue (dev , dir );
781782 drv_data -> state = I2S_STATE_READY ;
@@ -820,72 +821,56 @@ static DEVICE_API(i2s, i2s_nrf_drv_api) = {
820821 .trigger = i2s_nrfx_trigger ,
821822};
822823
823- #define I2S (idx ) DT_NODELABEL(i2s##idx)
824- #define I2S_CLK_SRC (idx ) DT_STRING_TOKEN(I2S(idx), clock_source)
825-
826- #define I2S_NRFX_DEVICE (idx ) \
827- static struct i2s_buf tx_msgs##idx[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \
828- static struct i2s_buf rx_msgs##idx[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \
829- static void data_handler##idx(nrfx_i2s_buffers_t const *p_released, \
830- uint32_t status) \
831- { \
832- data_handler(DEVICE_DT_GET(I2S(idx)), p_released, status); \
833- } \
834- PINCTRL_DT_DEFINE(I2S(idx)); \
835- static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##idx = { \
836- .data_handler = data_handler##idx, \
837- .i2s = NRFX_I2S_INSTANCE(idx), \
838- .nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG( \
839- NRF_I2S_PIN_NOT_CONNECTED, \
840- NRF_I2S_PIN_NOT_CONNECTED, \
841- NRF_I2S_PIN_NOT_CONNECTED, \
842- NRF_I2S_PIN_NOT_CONNECTED, \
843- NRF_I2S_PIN_NOT_CONNECTED), \
844- .nrfx_def_cfg.skip_gpio_cfg = true, \
845- .nrfx_def_cfg.skip_psel_cfg = true, \
846- .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2S(idx)), \
847- .clk_src = I2S_CLK_SRC(idx), \
848- }; \
849- static struct i2s_nrfx_drv_data i2s_nrfx_data##idx = { \
850- .state = I2S_STATE_READY, \
851- .p_i2s = &i2s_nrfx_cfg##idx.i2s \
852- }; \
853- static int i2s_nrfx_init##idx(const struct device *dev) \
854- { \
855- IRQ_CONNECT(DT_IRQN(I2S(idx)), DT_IRQ(I2S(idx), priority), \
856- nrfx_isr, nrfx_i2s_##idx##_irq_handler, 0); \
857- const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; \
858- int err = pinctrl_apply_state(drv_cfg->pcfg, \
859- PINCTRL_STATE_DEFAULT); \
860- if (err < 0) { \
861- return err; \
862- } \
863- k_msgq_init(&i2s_nrfx_data##idx.tx_queue, \
864- (char *)tx_msgs##idx, sizeof(struct i2s_buf), \
865- ARRAY_SIZE(tx_msgs##idx)); \
866- k_msgq_init(&i2s_nrfx_data##idx.rx_queue, \
867- (char *)rx_msgs##idx, sizeof(struct i2s_buf), \
868- ARRAY_SIZE(rx_msgs##idx)); \
869- init_clock_manager(dev); \
870- return 0; \
871- } \
872- BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || \
873- (NRF_I2S_HAS_CLKCONFIG && NRF_CLOCK_HAS_HFCLKAUDIO), \
874- "Clock source ACLK is not available."); \
875- BUILD_ASSERT(I2S_CLK_SRC(idx) != ACLK || \
876- DT_NODE_HAS_PROP(DT_NODELABEL(clock), \
877- hfclkaudio_frequency), \
878- "Clock source ACLK requires the hfclkaudio-frequency " \
879- "property to be defined in the nordic,nrf-clock node."); \
880- DEVICE_DT_DEFINE(I2S(idx), i2s_nrfx_init##idx, NULL, \
881- &i2s_nrfx_data##idx, &i2s_nrfx_cfg##idx, \
882- POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, \
883- &i2s_nrf_drv_api);
884-
885- #ifdef CONFIG_HAS_HW_NRF_I2S0
886- I2S_NRFX_DEVICE (0 );
887- #endif
888-
889- #ifdef CONFIG_HAS_HW_NRF_I2S20
890- I2S_NRFX_DEVICE (20 );
891- #endif
824+ #define I2S_CLK_SRC (inst ) DT_STRING_TOKEN(DT_DRV_INST(inst), clock_source)
825+
826+ #define I2S_NRFX_DEVICE (inst ) \
827+ static struct i2s_buf tx_msgs##inst[CONFIG_I2S_NRFX_TX_BLOCK_COUNT]; \
828+ static struct i2s_buf rx_msgs##inst[CONFIG_I2S_NRFX_RX_BLOCK_COUNT]; \
829+ static void data_handler##inst(nrfx_i2s_buffers_t const *p_released, uint32_t status) \
830+ { \
831+ data_handler(DEVICE_DT_GET(DT_DRV_INST(inst)), p_released, status); \
832+ } \
833+ PINCTRL_DT_DEFINE(DT_DRV_INST(inst)); \
834+ static const struct i2s_nrfx_drv_cfg i2s_nrfx_cfg##inst = { \
835+ .data_handler = data_handler##inst, \
836+ .nrfx_def_cfg = NRFX_I2S_DEFAULT_CONFIG( \
837+ NRF_I2S_PIN_NOT_CONNECTED, NRF_I2S_PIN_NOT_CONNECTED, \
838+ NRF_I2S_PIN_NOT_CONNECTED, NRF_I2S_PIN_NOT_CONNECTED, \
839+ NRF_I2S_PIN_NOT_CONNECTED), \
840+ .nrfx_def_cfg.skip_gpio_cfg = true, \
841+ .nrfx_def_cfg.skip_psel_cfg = true, \
842+ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(inst)), \
843+ .clk_src = I2S_CLK_SRC(inst), \
844+ }; \
845+ static struct i2s_nrfx_drv_data i2s_nrfx_data##inst = { \
846+ .state = I2S_STATE_READY, \
847+ .i2s = NRFX_I2S_INSTANCE(DT_INST_REG_ADDR(inst)), \
848+ }; \
849+ static int i2s_nrfx_init##inst(const struct device *dev) \
850+ { \
851+ IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), nrfx_i2s_irq_handler, \
852+ &i2s_nrfx_data##inst.i2s, 0); \
853+ const struct i2s_nrfx_drv_cfg *drv_cfg = dev->config; \
854+ int err = pinctrl_apply_state(drv_cfg->pcfg, PINCTRL_STATE_DEFAULT); \
855+ if (err < 0) { \
856+ return err; \
857+ } \
858+ k_msgq_init(&i2s_nrfx_data##inst.tx_queue, (char *)tx_msgs##inst, \
859+ sizeof(struct i2s_buf), ARRAY_SIZE(tx_msgs##inst)); \
860+ k_msgq_init(&i2s_nrfx_data##inst.rx_queue, (char *)rx_msgs##inst, \
861+ sizeof(struct i2s_buf), ARRAY_SIZE(rx_msgs##inst)); \
862+ init_clock_manager(dev); \
863+ return 0; \
864+ } \
865+ BUILD_ASSERT(I2S_CLK_SRC(inst) != ACLK || \
866+ (NRF_I2S_HAS_CLKCONFIG && NRF_CLOCK_HAS_HFCLKAUDIO), \
867+ "Clock source ACLK is not available."); \
868+ BUILD_ASSERT(I2S_CLK_SRC(inst) != ACLK || \
869+ DT_NODE_HAS_PROP(DT_NODELABEL(clock), hfclkaudio_frequency), \
870+ "Clock source ACLK requires the hfclkaudio-frequency " \
871+ "property to be defined in the nordic,nrf-clock node."); \
872+ DEVICE_DT_INST_DEFINE(inst, i2s_nrfx_init##inst, NULL, &i2s_nrfx_data##inst, \
873+ &i2s_nrfx_cfg##inst, POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, \
874+ &i2s_nrf_drv_api);
875+
876+ DT_INST_FOREACH_STATUS_OKAY (I2S_NRFX_DEVICE )
0 commit comments