diff --git a/drivers/counter/Kconfig.nrfx b/drivers/counter/Kconfig.nrfx index 321cf9de634..775406a5198 100644 --- a/drivers/counter/Kconfig.nrfx +++ b/drivers/counter/Kconfig.nrfx @@ -9,6 +9,12 @@ config COUNTER_NRF_RTC def_bool y depends on DT_HAS_NORDIC_NRF_RTC_ENABLED +config COUNTER_NRFX_TIMER_USE_CLOCK_CONTROL + def_bool y + depends on $(dt_nodelabel_enabled,timer120) || \ + $(dt_nodelabel_enabled,timer121) + select CLOCK_CONTROL + # Internal flag which detects if PPI wrap feature is enabled for any instance config COUNTER_RTC_WITH_PPI_WRAP def_bool $(dt_nodelabel_bool_prop,rtc0,ppi-wrap) || \ diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 333a436c80e..ea8edb08b6f 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include +#include #include #include @@ -32,11 +34,32 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL); #define MAYBE_CONST_CONFIG const #endif +#ifdef CONFIG_SOC_NRF54H20_GPD +#include + +#define NRF_CLOCKS_INSTANCE_IS_FAST(node) \ + COND_CODE_1(DT_NODE_HAS_PROP(node, power_domains), \ + (IS_EQ(DT_PHA(node, power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ + (0)) + +/* Macro must resolve to literal 0 or 1 */ +#define INSTANCE_IS_FAST(idx) NRF_CLOCKS_INSTANCE_IS_FAST(DT_DRV_INST(idx)) + +#define INSTANCE_IS_FAST_OR(idx) INSTANCE_IS_FAST(idx) || + +#if (DT_INST_FOREACH_STATUS_OKAY(INSTANCE_IS_FAST_OR) 0) +#define COUNTER_ANY_FAST 1 +#endif +#endif + struct counter_nrfx_data { counter_top_callback_t top_cb; void *top_user_data; uint32_t guard_period; atomic_t cc_int_pending; +#ifdef COUNTER_ANY_FAST + atomic_t active; +#endif }; struct counter_nrfx_ch_data { @@ -48,6 +71,10 @@ struct counter_nrfx_config { struct counter_config_info info; struct counter_nrfx_ch_data *ch_data; NRF_TIMER_Type *timer; +#ifdef COUNTER_ANY_FAST + const struct device *clk_dev; + struct nrf_clock_spec clk_spec; +#endif LOG_INSTANCE_PTR_DECLARE(log); }; @@ -61,6 +88,18 @@ static int start(const struct device *dev) { const struct counter_nrfx_config *config = dev->config; +#ifdef COUNTER_ANY_FAST + struct counter_nrfx_data *data = dev->data; + + if (config->clk_dev && atomic_cas(&data->active, 0, 1)) { + int err; + + err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER); + if (err < 0) { + return err; + } + } +#endif nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_START); return 0; @@ -71,6 +110,18 @@ static int stop(const struct device *dev) const struct counter_nrfx_config *config = dev->config; nrf_timer_task_trigger(config->timer, NRF_TIMER_TASK_STOP); +#ifdef COUNTER_ANY_FAST + struct counter_nrfx_data *data = dev->data; + + if (config->clk_dev && atomic_cas(&data->active, 1, 0)) { + int err; + + err = nrf_clock_control_release(config->clk_dev, &config->clk_spec); + if (err < 0) { + return err; + } + } +#endif return 0; } @@ -403,6 +454,20 @@ static const struct counter_driver_api counter_nrfx_driver_api = { .set_guard_period = set_guard_period, }; +/* Get initialization level of an instance. Instances that requires clock control + * which is using nrfs (IPC) are initialized later. + */ +#define TIMER_INIT_LEVEL(idx) \ + COND_CODE_1(INSTANCE_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1)) + +/* Get initialization priority of an instance. Instances that requires clock control + * which is using nrfs (IPC) are initialized later. + */ +#define TIMER_INIT_PRIO(idx) \ + COND_CODE_1(INSTANCE_IS_FAST(idx), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + (CONFIG_COUNTER_INIT_PRIORITY)) + /* * Device instantiation is done with node labels due to HAL API * requirements. In particular, TIMERx_MAX_SIZE values from HALs @@ -419,14 +484,6 @@ static const struct counter_driver_api counter_nrfx_driver_api = { irq_handler, DEVICE_DT_INST_GET(idx), 0)) \ ) -#if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX) -#define CHECK_MAX_FREQ(idx) \ - BUILD_ASSERT(DT_INST_PROP(idx, max_frequency) == \ - NRF_TIMER_BASE_FREQUENCY_GET((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx))) -#else -#define CHECK_MAX_FREQ(idx) -#endif - #define COUNTER_NRFX_TIMER_DEVICE(idx) \ BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \ TIMER_PRESCALER_PRESCALER_Msk, \ @@ -456,22 +513,29 @@ static const struct counter_driver_api counter_nrfx_driver_api = { static MAYBE_CONST_CONFIG struct counter_nrfx_config nrfx_counter_##idx##_config = { \ .info = { \ .max_top_value = (uint32_t)BIT64_MASK(DT_INST_PROP(idx, max_bit_width)),\ - .freq = DT_INST_PROP(idx, max_frequency) / \ + .freq = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)) / \ BIT(DT_INST_PROP(idx, prescaler)), \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ .channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \ }, \ .ch_data = counter##idx##_ch_data, \ .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ + IF_ENABLED(INSTANCE_IS_FAST(idx), \ + (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(idx))), \ + .clk_spec = { \ + .frequency = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)), \ + .accuracy = 0, \ + .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \ + }, \ + )) \ LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \ }; \ - CHECK_MAX_FREQ(idx); \ DEVICE_DT_INST_DEFINE(idx, \ counter_##idx##_init, \ NULL, \ &counter_##idx##_data, \ &nrfx_counter_##idx##_config.info, \ - PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ + TIMER_INIT_LEVEL(idx), TIMER_INIT_PRIO(idx), \ &counter_nrfx_driver_api); DT_INST_FOREACH_STATUS_OKAY(COUNTER_NRFX_TIMER_DEVICE) diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 034813bc076..5be5428b230 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -623,6 +623,7 @@ power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; max-bit-width = <32>; max-frequency = ; + clocks = <&hsfll120>; prescaler = <0>; }; @@ -635,6 +636,7 @@ power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; max-bit-width = <32>; max-frequency = ; + clocks = <&hsfll120>; prescaler = <0>; }; diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c index c28d9187a55..4a418585463 100644 --- a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c @@ -139,9 +139,19 @@ static void dvfs_service_handler_scaling_background_job(enum dvfs_frequency_sett } } +/* Update MDK variable which is used by nrfx_coredep_delay_us (k_busy_wait). */ +static void dvfs_service_update_core_clock(enum dvfs_frequency_setting oppoint_freq) +{ + extern uint32_t SystemCoreClock; + + SystemCoreClock = oppoint_freq == DVFS_FREQ_HIGH ? 320000000 : + oppoint_freq == DVFS_FREQ_MEDLOW ? 128000000 : 64000000; +} + /* Perform scaling finnish procedure. */ static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppoint_freq) { + LOG_DBG("Scaling finnish oppoint freq %d", oppoint_freq); ld_dvfs_scaling_finish(dvfs_service_handler_is_downscaling(oppoint_freq)); if (!dvfs_service_handler_is_downscaling(oppoint_freq)) { @@ -153,6 +163,7 @@ static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppo } dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_REQ_PENDING_BIT_POS); current_freq_setting = oppoint_freq; + dvfs_service_update_core_clock(oppoint_freq); LOG_DBG("Current LD freq setting: %d", current_freq_setting); if (dvfs_frequency_change_applied_clb) { dvfs_frequency_change_applied_clb(current_freq_setting); @@ -216,6 +227,7 @@ static void nrfs_dvfs_evt_handler(nrfs_dvfs_evt_t const *p_evt, void *context) dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_REQ_PENDING_BIT_POS); LOG_DBG("DVFS handler EVT_OPPOINT_REQ_CONFIRMED %d", (uint32_t)p_evt->freq); if (dvfs_service_handler_get_requested_oppoint() == p_evt->freq) { + dvfs_service_update_core_clock(p_evt->freq); if (dvfs_frequency_change_applied_clb) { dvfs_frequency_change_applied_clb(p_evt->freq); } diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay index a1a0dc42a36..8ce5342be23 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf52840dk_nrf52840.overlay @@ -53,6 +53,7 @@ zephyr,pm-device-runtime-auto; dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; + spi-max-frequency = ; reg = <0>; }; };