From 9d59eaaa58232776e9a03171fbc60e003e1d361c Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Thu, 16 Oct 2025 10:18:49 +0100 Subject: [PATCH 1/5] [nrf fromtree] drivers: clock_control: Add macros for AUXPLL output frequencies These represent the outputted frequencies of the AUXPLL of different settings set in the device tree set using dt-bindings in nrf-auxpll.h. This is added to remove the need for 'magic numbers' in drivers and tests. Signed-off-by: David Jewsbury (cherry picked from commit 077021070c139838771067142a7752b5c95eaf2b) --- .../drivers/clock_control/nrf_clock_control.h | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/zephyr/drivers/clock_control/nrf_clock_control.h b/include/zephyr/drivers/clock_control/nrf_clock_control.h index 37fc4a1f1a8..7fa4530a6a0 100644 --- a/include/zephyr/drivers/clock_control/nrf_clock_control.h +++ b/include/zephyr/drivers/clock_control/nrf_clock_control.h @@ -188,6 +188,29 @@ uint32_t z_nrf_clock_bt_ctlr_hf_get_startup_time_us(void); /* Specifies that default precision of the clock is sufficient. */ #define NRF_CLOCK_CONTROL_PRECISION_DEFAULT 0 +/* AUXPLL devicetree takes in raw register values, these are the actual frequencies outputted */ +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_MIN_HZ 80000000 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_44K1_HZ 11289591 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_USB24M_HZ 24000000 +#define CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_48K_HZ 12287963 + +/* Internal helper macro to map DT property value to output frequency */ +#define _CLOCK_CONTROL_NRF_AUXPLL_MAP_FREQ(freq_val) \ + ((freq_val) == NRF_AUXPLL_FREQ_DIV_MIN ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_MIN_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_44K1_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_USB24M ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_USB24M_HZ : \ + (freq_val) == NRF_AUXPLL_FREQ_DIV_AUDIO_48K ? \ + CLOCK_CONTROL_NRF_AUXPLL_FREQ_OUT_AUDIO_48K_HZ : 0) + +/* Public macro to get output frequency of AUXPLL */ +#define CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(node) \ + COND_CODE_1(DT_NODE_HAS_PROP(node, nordic_frequency), \ + (_CLOCK_CONTROL_NRF_AUXPLL_MAP_FREQ(DT_PROP(node, nordic_frequency))), \ + (0)) + struct nrf_clock_spec { uint32_t frequency; uint16_t accuracy : 15; From 8c717d254887f0ddeb55ce40b48d1c94ea52f9e9 Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Thu, 16 Oct 2025 10:28:05 +0100 Subject: [PATCH 2/5] [nrf fromtree] drivers: audio: dmic_nrfx: Update AUXPLL control with frequency macros Frequencies being for AUXPLL were register assignments and not actual frequencies. Signed-off-by: David Jewsbury (cherry picked from commit eb605628ae0970b7aa80091954c8277794ba24b6) --- drivers/audio/dmic_nrfx_pdm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/audio/dmic_nrfx_pdm.c b/drivers/audio/dmic_nrfx_pdm.c index c2c80a7414c..a2d630f847a 100644 --- a/drivers/audio/dmic_nrfx_pdm.c +++ b/drivers/audio/dmic_nrfx_pdm.c @@ -24,11 +24,15 @@ LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL); #define DMIC_NRFX_CLOCK_FACTOR 8192 #define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(NODE_AUDIOPLL, frequency, 0) #elif DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) -#define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) -BUILD_ASSERT((DMIC_NRFX_AUDIO_CLOCK_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || - (DMIC_NRFX_AUDIO_CLOCK_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), +#define AUXPLL_FREQUENCY_SETTING DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) +BUILD_ASSERT((AUXPLL_FREQUENCY_SETTING == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || + (AUXPLL_FREQUENCY_SETTING == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), "Unsupported Audio AUXPLL frequency selection for PDM"); + +#define DMIC_NRFX_AUDIO_CLOCK_FREQ CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(NODE_AUDIO_AUXPLL) + #define DMIC_NRFX_CLOCK_FREQ MHZ(32) + #else #define DMIC_NRFX_CLOCK_FREQ MHZ(32) #define DMIC_NRFX_CLOCK_FACTOR 4096 From e88c1683868503baef8f02c12a85b03a51bff548 Mon Sep 17 00:00:00 2001 From: David Jewsbury Date: Thu, 16 Oct 2025 10:29:29 +0100 Subject: [PATCH 3/5] [nrf fromtree] tests: drivers: Update AUXPLL test to use frequency Macros Eliminate the need for magic numbers when setting AUXPLL_FREQ_OUT Signed-off-by: David Jewsbury (cherry picked from commit 9a3a954b3497303f0942650d7c65d7c7f7390bf4) --- .../clock_control/nrf_clock_control/src/main.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/tests/drivers/clock_control/nrf_clock_control/src/main.c b/tests/drivers/clock_control/nrf_clock_control/src/main.c index 83fdc98ca19..3612373a867 100644 --- a/tests/drivers/clock_control/nrf_clock_control/src/main.c +++ b/tests/drivers/clock_control/nrf_clock_control/src/main.c @@ -162,17 +162,10 @@ static const struct test_clk_context lfclk_test_clk_contexts[] = { #define AUXPLL_NODE DT_INST(0, AUXPLL_COMPAT) #define AUXPLL_FREQ DT_PROP(AUXPLL_NODE, nordic_frequency) -/* Gets selected AUXPLL DIV and selects the expected frequency */ -#if AUXPLL_FREQ == NRF_AUXPLL_FREQUENCY_DIV_MIN -#define AUXPLL_FREQ_OUT 80000000 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 -#define AUXPLL_FREQ_OUT 11289591 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_USB_24M -#define AUXPLL_FREQ_OUT 24000000 -#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K -#define AUXPLL_FREQ_OUT 12287963 -#else -/*No use case for NRF_AUXPLL_FREQ_DIV_MAX or others yet*/ + +/* Gets expected AUXPLL frequency */ +#define AUXPLL_FREQ_OUT CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(AUXPLL_NODE) +#if AUXPLL_FREQ_OUT == 0 #error "Unsupported AUXPLL frequency selection" #endif From adaba7e0e66d6399712177fe4997a73bf0e59abc Mon Sep 17 00:00:00 2001 From: Erdem Simsek Date: Thu, 16 Oct 2025 09:16:16 +0100 Subject: [PATCH 4/5] [nrf fromtree] drivers: i2s: Support audio auxpll in TDM driver Add support for audio_auxpll clock source as an alternative to audiopll in the i2s_nrf_tdm driver. This enables TDM functionality on platforms that use the auxiliary PLL for audio clocking. - Add audio_auxpll node detection and configuration - Update clock management to support both audiopll and audio_auxpll - Add build assertions for supported frequency configurations Signed-off-by: Erdem Simsek (cherry picked from commit 8338097b1d5008ec88982c42a7bd53223042b5eb) --- drivers/i2s/i2s_nrf_tdm.c | 48 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/i2s/i2s_nrf_tdm.c b/drivers/i2s/i2s_nrf_tdm.c index fc823ce5055..07c561b7750 100644 --- a/drivers/i2s/i2s_nrf_tdm.c +++ b/drivers/i2s/i2s_nrf_tdm.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -47,11 +48,13 @@ LOG_MODULE_REGISTER(tdm_nrf, CONFIG_I2S_LOG_LEVEL); #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(audiopll)) #define NODE_ACLK DT_NODELABEL(audiopll) #define ACLK_FREQUENCY DT_PROP_OR(NODE_ACLK, frequency, 0) - -static const struct device *audiopll = DEVICE_DT_GET(NODE_ACLK); -static const struct nrf_clock_spec aclk_spec = { - .frequency = ACLK_FREQUENCY, -}; +#elif DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(audio_auxpll)) +#define NODE_AUDIO_AUXPLL DT_NODELABEL(audio_auxpll) +#define ACLK_NORDIC_FREQUENCY DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency) +BUILD_ASSERT((ACLK_NORDIC_FREQUENCY == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) || + (ACLK_NORDIC_FREQUENCY == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1), + "Unsupported Audio AUXPLL frequency selection for TDM"); +#define ACLK_FREQUENCY CLOCK_CONTROL_NRF_AUXPLL_GET_FREQ(NODE_AUDIO_AUXPLL) #elif DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(aclk)) #define NODE_ACLK DT_NODELABEL(aclk) #define ACLK_FREQUENCY DT_PROP_OR(NODE_ACLK, clock_frequency, 0) @@ -107,7 +110,10 @@ struct tdm_drv_cfg { }; struct tdm_drv_data { -#if CONFIG_CLOCK_CONTROL_NRF +#if CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL || DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + const struct device *audiopll; + struct nrf_clock_spec aclk_spec; +#elif CONFIG_CLOCK_CONTROL_NRF struct onoff_manager *clk_mgr; #endif struct onoff_client clk_cli; @@ -132,8 +138,10 @@ static int audio_clock_request(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL - return nrf_clock_control_request(audiopll, &aclk_spec, &drv_data->clk_cli); +#elif (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + return nrf_clock_control_request(drv_data->audiopll, &drv_data->aclk_spec, + &drv_data->clk_cli); #else (void)drv_data; @@ -145,10 +153,9 @@ static int audio_clock_release(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_release(drv_data->clk_mgr); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL - (void)drv_data; - - return nrf_clock_control_release(audiopll, &aclk_spec); +#elif (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + return nrf_clock_control_release(drv_data->audiopll, &drv_data->aclk_spec); #else (void)drv_data; @@ -1120,6 +1127,16 @@ static void clock_manager_init(const struct device *dev) subsys = CLOCK_CONTROL_NRF_SUBSYS_HFAUDIO; drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys); __ASSERT_NO_MSG(drv_data->clk_mgr != NULL); +#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL + struct tdm_drv_data *drv_data = dev->data; + + drv_data->audiopll = DEVICE_DT_GET(NODE_ACLK); + drv_data->aclk_spec.frequency = ACLK_FREQUENCY; +#elif DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL) + struct tdm_drv_data *drv_data = dev->data; + + drv_data->audiopll = DEVICE_DT_GET(NODE_AUDIO_AUXPLL); + drv_data->aclk_spec.frequency = ACLK_FREQUENCY; #else (void)dev; #endif @@ -1194,9 +1211,10 @@ static DEVICE_API(i2s, tdm_nrf_drv_api) = { clock_manager_init(dev); \ return 0; \ } \ - BUILD_ASSERT((TDM_SCK_CLK_SRC(idx) != ACLK && TDM_MCK_CLK_SRC(idx) != ACLK) || \ - DT_NODE_HAS_STATUS_OKAY(NODE_ACLK), \ - "Clock source ACLK requires the audiopll node."); \ + BUILD_ASSERT((TDM_SCK_CLK_SRC(idx) != ACLK && TDM_MCK_CLK_SRC(idx) != ACLK) || \ + (DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) || \ + DT_NODE_HAS_STATUS_OKAY(NODE_AUDIO_AUXPLL)), \ + "Clock source ACLK requires the audiopll/audio_auxpll node."); \ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(TDM(idx)); \ DEVICE_DT_DEFINE(TDM(idx), tdm_nrf_init##idx, NULL, &tdm_nrf_data##idx, &tdm_nrf_cfg##idx, \ POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, &tdm_nrf_drv_api); From 624f00305a63f138956e57274c615fd3cb7b5276 Mon Sep 17 00:00:00 2001 From: Erdem Simsek Date: Mon, 20 Oct 2025 17:41:28 +0100 Subject: [PATCH 5/5] [nrf fromtree] tests: drivers: Trigger drop event for proper clean-up Add I2S_TRIGGER_DROP call in the error test to ensure proper cleanup after stopping the I2S device. This validates that the drop trigger is properly handled in error conditions and resources are released. Signed-off-by: Erdem Simsek (cherry picked from commit aec9da060b93d8c9e039233cc75d695d0eb8d007) --- tests/drivers/i2s/i2s_api/src/test_i2s_errors.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c b/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c index 477292d84c2..230a71e95d4 100644 --- a/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c +++ b/tests/drivers/i2s/i2s_api/src/test_i2s_errors.c @@ -76,6 +76,9 @@ ZTEST_USER(i2s_errors, test_i2s_config_attempt_in_wrong_state) err = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_STOP); zassert_equal(err, 0, "I2S_TRIGGER_STOP unexpected error: %d", err); + err = i2s_trigger(dev_i2s, I2S_DIR_TX, I2S_TRIGGER_DROP); + zassert_equal(err, 0, "I2S_TRIGGER_DROP unexpected error: %d", err); + zassert_not_equal( config_err, 0, "I2S configuration should not be possible in states other than I2S_STATE_READY");