diff --git a/drivers/counter/Kconfig.nrfx b/drivers/counter/Kconfig.nrfx index 321cf9de63479..775406a5198ca 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 ed67dbde06267..afbdb4ed1adac 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 DEVICE_API(counter, 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 DEVICE_API(counter, 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 DEVICE_API(counter, 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/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 77c48c9b22cba..d6f561967cfb2 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -101,6 +101,11 @@ rsource "Kconfig.nrfx_uart_instance" endif if HAS_HW_NRF_UARTE120 + +config UART_NRFX_UARTE_USE_CLOCK_CONTROL + def_bool y + select CLOCK_CONTROL + nrfx_uart_num = 120 rsource "Kconfig.nrfx_uart_instance" endif diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 4c69ad430fd4b..274afcbabf79d 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -23,10 +23,7 @@ #include #include #include - -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif +#include LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); @@ -110,17 +107,22 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_ANY_LOW_POWER 1 #endif +#ifdef CONFIG_SOC_NRF54H20_GPD +#include + /* Macro must resolve to literal 0 or 1 */ -#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(idx)), \ - (COND_CODE_1(UTIL_AND(IS_ENABLED(CONFIG_SOC_NRF54H20_GPD), \ - DT_NODE_HAS_PROP(UARTE(idx), power_domains)), \ - (COND_CODE_0(DT_PHA(UARTE(idx), power_domains, id), (1), (0))),\ - (0))), (0)) +#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(idx)), \ + (COND_CODE_1(DT_NODE_HAS_PROP(UARTE(idx), power_domains), \ + (IS_EQ(DT_PHA(UARTE(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ + (0))), (0)) #if UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0)) +/* Fast instance requires special PM treatment so device runtime PM must be enabled. */ +BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)); #define UARTE_ANY_FAST 1 #endif +#endif #ifdef UARTE_ANY_CACHE /* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance @@ -307,6 +309,10 @@ struct uarte_nrfx_config { #ifdef CONFIG_HAS_NORDIC_DMM void *mem_reg; #endif +#ifdef UARTE_ANY_FAST + const struct device *clk_dev; + struct nrf_clock_spec clk_spec; +#endif #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE /* None-zero in case of high speed instances. Baudrate is adjusted by that ratio. */ uint32_t clock_freq; @@ -656,6 +662,16 @@ static void uarte_periph_enable(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; +#ifdef UARTE_ANY_FAST + if (config->clk_dev) { + int err; + + err = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, K_FOREVER); + (void)err; + __ASSERT_NO_MSG(err >= 0); + } +#endif + nrf_uarte_enable(uarte); #ifdef CONFIG_SOC_NRF54H20_GPD nrf_gpd_retain_pins_set(config->pcfg, false); @@ -737,7 +753,6 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) if (LOW_POWER_ENABLED(config)) { uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX); } - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); } @@ -2203,6 +2218,16 @@ static void uarte_pm_suspend(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; +#ifdef UARTE_ANY_FAST + if (cfg->clk_dev) { + int err; + + err = nrf_clock_control_release(cfg->clk_dev, &cfg->clk_spec); + (void)err; + __ASSERT_NO_MSG(err >= 0); + } +#endif + #ifdef UARTE_ANY_ASYNC if (data->async) { /* Entering inactive state requires device to be no @@ -2386,11 +2411,11 @@ static int uarte_instance_init(const struct device *dev, #define UARTE_DISABLE_RX_INIT(node_id) \ .disable_rx = DT_PROP(node_id, disable_rx) -#define UARTE_GET_FREQ(idx) DT_PROP(DT_CLOCKS_CTLR(UARTE(idx)), clock_frequency) - -#define UARTE_GET_BAUDRATE_DIV(idx) \ - COND_CODE_1(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \ - ((UARTE_GET_FREQ(idx) / NRF_UARTE_BASE_FREQUENCY_16MHZ)), (1)) +/* Get frequency of the clock that driver the UARTE peripheral. Clock node can + * have fixed or variable frequency. For fast UARTE use highest supported frequency. + */ +#define UARTE_GET_BAUDRATE_DIV(idx) \ + (NRF_PERIPH_GET_FREQUENCY(UARTE(idx)) / NRF_UARTE_BASE_FREQUENCY_16MHZ) /* When calculating baudrate we need to take into account that high speed instances * must have baudrate adjust to the ratio between UARTE clocking frequency and 16 MHz. @@ -2398,6 +2423,19 @@ static int uarte_instance_init(const struct device *dev, #define UARTE_GET_BAUDRATE(idx) \ (NRF_BAUDRATE(UARTE_PROP(idx, current_speed)) / UARTE_GET_BAUDRATE_DIV(idx)) +/* Get initialization level of an instance. Instances that requires clock control + * which is using nrfs (IPC) are initialized later. + */ +#define UARTE_INIT_LEVEL(idx) \ + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, 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 UARTE_INIT_PRIO(idx) \ + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + (CONFIG_SERIAL_INIT_PRIORITY)) /* Macro for setting nRF specific configuration structures. */ #define UARTE_NRF_CONFIG(idx) { \ @@ -2453,7 +2491,7 @@ static int uarte_instance_init(const struct device *dev, static const struct uarte_nrfx_config uarte_##idx##z_config = { \ COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, \ (IF_ENABLED(DT_CLOCKS_HAS_IDX(UARTE(idx), 0), \ - (.clock_freq = UARTE_GET_FREQ(idx),))), \ + (.clock_freq = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),))), \ (IF_ENABLED(UARTE_HAS_FRAME_TIMEOUT, \ (.baudrate = UARTE_PROP(idx, current_speed),)) \ .nrf_baudrate = UARTE_GET_BAUDRATE(idx), \ @@ -2480,6 +2518,13 @@ static int uarte_instance_init(const struct device *dev, IF_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC, \ (.timer = NRFX_TIMER_INSTANCE( \ CONFIG_UART_##idx##_NRF_HW_ASYNC_TIMER),)) \ + IF_ENABLED(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ + (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(UARTE(idx))), \ + .clk_spec = { \ + .frequency = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),\ + .accuracy = 0, \ + .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,\ + },)) \ }; \ static int uarte_##idx##_init(const struct device *dev) \ { \ @@ -2500,8 +2545,8 @@ static int uarte_instance_init(const struct device *dev, PM_DEVICE_DT_GET(UARTE(idx)), \ &uarte_##idx##_data, \ &uarte_##idx##z_config, \ - PRE_KERNEL_1, \ - CONFIG_SERIAL_INIT_PRIORITY, \ + UARTE_INIT_LEVEL(idx), \ + UARTE_INIT_PRIO(idx), \ &uart_nrfx_uarte_driver_api) #define UARTE_INT_DRIVEN(idx) \ diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 9df096ab710e9..cc9f2d3d8e434 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -627,6 +627,7 @@ power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; max-bit-width = <32>; max-frequency = ; + clocks = <&hsfll120>; prescaler = <0>; }; @@ -639,6 +640,7 @@ power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; max-bit-width = <32>; max-frequency = ; + clocks = <&hsfll120>; prescaler = <0>; }; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi index ae810c2796616..9902d733d3579 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -43,6 +43,7 @@ dut: &uart137 { pinctrl-1 = <&uart137_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; + zephyr,pm-device-runtime-auto; }; dut2: &uart120 { @@ -50,4 +51,5 @@ dut2: &uart120 { pinctrl-1 = <&uart120_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; + zephyr,pm-device-runtime-auto; }; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 0000000000000..74cc8d7691e15 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y