diff --git a/soc/nordic/nrf54h/CMakeLists.txt b/soc/nordic/nrf54h/CMakeLists.txt index 10c59b04583..a630a85fe79 100644 --- a/soc/nordic/nrf54h/CMakeLists.txt +++ b/soc/nordic/nrf54h/CMakeLists.txt @@ -9,6 +9,7 @@ if(CONFIG_ARM) endif() zephyr_library_sources_ifdef(CONFIG_PM_S2RAM pm_s2ram.c) +zephyr_library_sources_ifdef(CONFIG_SOC_NRF54H20_GLOBAL_HSFLL_RESTRICT_MIN_FREQ global_hsfll.c) zephyr_include_directories(.) diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index 888c483e591..74bd21dd02e 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -73,3 +73,36 @@ config SOC_NRF54H20_NO_MRAM_LATENCY imply NRFS imply NRFS_MRAM_SERVICE_ENABLED default y if SOC_NRF54H20_CPUAPP + +config SOC_NRF54H20_GLOBAL_HSFLL_RESTRICT_MIN_FREQ + bool "Restrict minimum global HSFLL clock frequency" + select NRFS + select NRFS_GDFS_SERVICE_ENABLED + select CLOCK_CONTROL + default y if SOC_NRF54H20_CPUAPP + +if SOC_NRF54H20_GLOBAL_HSFLL_RESTRICT_MIN_FREQ + +choice SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_CHOICE + prompt "Minimum global HSFLL clock frequency in MHz" + default SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_320_MHZ + +config SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_64_MHZ + bool "Restrict minimum global HSFLL clock frequency to 64MHz" + +config SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_128_MHZ + bool "Restrict minimum global HSFLL clock frequency to 128MHz" + +config SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_256_MHZ + bool "Restrict minimum global HSFLL clock frequency to 256MHz" + +config SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_320_MHZ + bool "Restrict minimum global HSFLL clock frequency to 320MHz" + +endchoice + +config SOC_NRF54H20_GLOBAL_HSFLL_TIMEOUT_MS + int "Global HSFLL clock frequency timeout in milliseconds" + default 10000 + +endif # SOC_NRF54H20_RESTRICT_GLOBAL_HSFLL_FREQ diff --git a/soc/nordic/nrf54h/global_hsfll.c b/soc/nordic/nrf54h/global_hsfll.c new file mode 100644 index 00000000000..ae155a7df4c --- /dev/null +++ b/soc/nordic/nrf54h/global_hsfll.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +#if CONFIG_SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_64_MHZ +#define GLOBAL_HSFLL_MIN_FREQ_HZ 64000000 +#elif CONFIG_SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_128_MHZ +#define GLOBAL_HSFLL_MIN_FREQ_HZ 128000000 +#elif CONFIG_SOC_NRF54H20_GLOBAL_HSFLL_MIN_FREQ_256_MHZ +#define GLOBAL_HSFLL_MIN_FREQ_HZ 256000000 +#else +#define GLOBAL_HSFLL_MIN_FREQ_HZ 320000000 +#endif + +#define GLOBAL_HSFLL_REQUEST_TIMEOUT_US \ + (CONFIG_SOC_NRF54H20_GLOBAL_HSFLL_TIMEOUT_MS * USEC_PER_SEC) + +static struct onoff_client cli; +static const struct device *global_hsfll = DEVICE_DT_GET(DT_NODELABEL(hsfll120)); +static const struct nrf_clock_spec spec = { + .frequency = GLOBAL_HSFLL_MIN_FREQ_HZ, +}; + +static int nordicsemi_nrf54h_global_hsfll_init(void) +{ + int ret; + int res; + bool completed; + + sys_notify_init_spinwait(&cli.notify); + + ret = nrf_clock_control_request(global_hsfll, &spec, &cli); + if (ret) { + return ret; + } + + res = -EIO; + completed = WAIT_FOR(sys_notify_fetch_result(&cli.notify, &res) == 0, + GLOBAL_HSFLL_REQUEST_TIMEOUT_US, + k_msleep(1)); + + if (!completed) { + LOG_ERR("%s request timed out", "Restrict global HSFLL"); + return -EIO; + } + + if (res) { + LOG_ERR("%s request failed: (res=%i)", "Restrict global HSFLL", res); + return res; + } + + LOG_INF("%s to %uHz", "Restrict global HSFLL", GLOBAL_HSFLL_MIN_FREQ_HZ); + return 0; +} + +SYS_INIT(nordicsemi_nrf54h_global_hsfll_init, POST_KERNEL, 99);