diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts index cd8b95be664..e6129833778 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -77,6 +77,8 @@ /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ child-owned-channels = <3 4 7 8 9 10 11>; status = "okay"; + /delete-property/ clocks; + /delete-property/ clock-names; }; &cpuapp_rram { diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 2b2473f92b5..80211205ca3 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -185,8 +185,8 @@ #address-cells = <1>; #size-cells = <1>; - cpurad_slot0_partition: partition@66000 { - reg = <0x66000 DT_SIZE_K(256)>; + cpurad_slot0_partition: partition@54000 { + reg = <0x54000 DT_SIZE_K(256)>; }; }; @@ -197,8 +197,8 @@ #address-cells = <1>; #size-cells = <1>; - cpuapp_slot0_partition: partition@a6000 { - reg = <0xa6000 DT_SIZE_K(248)>; + cpuapp_slot0_partition: partition@94000 { + reg = <0x94000 DT_SIZE_K(320)>; }; cpuppr_code_partition: partition@e4000 { @@ -222,7 +222,7 @@ }; storage_partition: partition@1e3000 { - reg = < 0x1e3000 DT_SIZE_K(24) >; + reg = < 0x1e3000 DT_SIZE_K(40) >; }; }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi index 79ac2c6b7ad..9b574a18ec5 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi @@ -98,4 +98,19 @@ low-power-enable; }; }; + + /omit-if-no-ref/ grtc_default: grtc_default { + group1 { + psels = , + ; + }; + }; + + /omit-if-no-ref/ grtc_sleep: grtc_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; }; diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l_05_10_15-pinctrl.dtsi b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l_05_10_15-pinctrl.dtsi index 0b6e2056a82..6b7457a2818 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l_05_10_15-pinctrl.dtsi +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l_05_10_15-pinctrl.dtsi @@ -77,4 +77,19 @@ low-power-enable; }; }; + + /omit-if-no-ref/ grtc_default: grtc_default { + group1 { + psels = , + ; + }; + }; + + /omit-if-no-ref/ grtc_sleep: grtc_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; }; diff --git a/drivers/clock_control/nrf_clock_calibration.c b/drivers/clock_control/nrf_clock_calibration.c index bea799515e1..fc2ce4162aa 100644 --- a/drivers/clock_control/nrf_clock_calibration.c +++ b/drivers/clock_control/nrf_clock_calibration.c @@ -294,3 +294,8 @@ int z_nrf_clock_calibration_skips_count(void) return total_skips_cnt; } + +bool z_nrf_clock_calibration_is_in_progress(void) +{ + return cal_process_in_progress ? true : false; +} 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/drivers/hwinfo/hwinfo_nrf.c b/drivers/hwinfo/hwinfo_nrf.c index d1fca5350a6..50e20906d98 100644 --- a/drivers/hwinfo/hwinfo_nrf.c +++ b/drivers/hwinfo/hwinfo_nrf.c @@ -8,7 +8,7 @@ #include #include #include -#if !defined(CONFIG_SOC_SERIES_NRF54HX) && !defined(CONFIG_BOARD_QEMU_CORTEX_M0) +#if !defined(CONFIG_BOARD_QEMU_CORTEX_M0) #include #endif @@ -63,7 +63,7 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) return length; } -#if !defined(CONFIG_SOC_SERIES_NRF54HX) && !defined(CONFIG_BOARD_QEMU_CORTEX_M0) +#if !defined(CONFIG_BOARD_QEMU_CORTEX_M0) int z_impl_hwinfo_get_reset_cause(uint32_t *cause) { uint32_t flags = 0; @@ -76,16 +76,37 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) if (reason & NRFX_RESET_REASON_DOG_MASK) { flags |= RESET_WATCHDOG; } - if (reason & NRFX_RESET_REASON_LOCKUP_MASK) { + +#if defined(NRF_RESETINFO) + if (reason & NRFX_RESET_REASON_LOCAL_DOG0_MASK) { + flags |= RESET_WATCHDOG; + } +#endif + +#if defined(NRF_RESETINFO) + if ((reason & NRFX_RESET_REASON_LOCKUP) + || (reason & NRFX_RESET_REASON_LOCAL_LOCKUP_MASK)) +#else + if (reason & NRFX_RESET_REASON_LOCKUP_MASK) +#endif + { flags |= RESET_CPU_LOCKUP; } + if (reason & NRFX_RESET_REASON_OFF_MASK) { flags |= RESET_LOW_POWER_WAKE; } if (reason & NRFX_RESET_REASON_DIF_MASK) { flags |= RESET_DEBUG; } - if (reason & NRFX_RESET_REASON_SREQ_MASK) { + +#if defined(NRF_RESETINFO) + if ((reason & NRFX_RESET_REASON_SREQ) + || (reason & NRFX_RESET_REASON_LOCAL_SREQ_MASK)) +#else + if (reason & NRFX_RESET_REASON_SREQ_MASK) +#endif + { flags |= RESET_SOFTWARE; } @@ -124,11 +145,18 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) flags |= RESET_DEBUG; } #endif + #if !NRF_POWER_HAS_RESETREAS - if (reason & NRFX_RESET_REASON_DOG1_MASK) { +#if defined(NRF_RESETINFO) + if (reason & NRFX_RESET_REASON_LOCAL_DOG1_MASK) +#else + if (reason & NRFX_RESET_REASON_DOG1_MASK) +#endif + { flags |= RESET_WATCHDOG; } -#endif +#endif /* !NRF_POWER_HAS_RESETREAS */ + #if NRFX_RESET_REASON_HAS_GRTC if (reason & NRFX_RESET_REASON_GRTC_MASK) { flags |= RESET_CLOCK; diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index 1e80de8fe67..d0354f600a9 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -94,6 +94,15 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { #define NRF_PSEL_QSPI(reg, line) ((NRF_QSPI_Type *)reg)->PSEL.line #endif +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) || defined(CONFIG_NRFX_GRTC) +#if DT_NODE_HAS_PROP(DT_NODELABEL(grtc), clkout_fast_frequency) +#define NRF_GRTC_CLKOUT_FAST 1 +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(grtc), clkout_32k_frequency) +#define NRF_GRTC_CLKOUT_SLOW 1 +#endif +#endif + int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) { @@ -336,6 +345,24 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_DISCONNECT; break; #endif /* defined(NRF_PSEL_QSPI) */ +#if defined(NRF_GRTC_CLKOUT_FAST) + case NRF_FUN_GRTC_CLKOUT_FAST: +#if NRF_GPIO_HAS_SEL && defined(GPIO_PIN_CNF_CTRLSEL_GRTC) + nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_GRTC); +#endif + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + break; +#endif /* defined(NRF_GRTC_CLKOUT_FAST) */ +#if defined(NRF_GRTC_CLKOUT_SLOW) + case NRF_FUN_GRTC_CLKOUT_32K: +#if NRF_GPIO_HAS_SEL && defined(GPIO_PIN_CNF_CTRLSEL_GRTC) + nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_GRTC); +#endif + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + break; +#endif /* defined(NRF_GRTC_CLKOUT_SLOW) */ #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) /* Pin routing is controlled by secure domain, via UICR */ case NRF_FUN_CAN_TX: diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index c1fe5d3bd9b..647d7036679 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -60,6 +60,7 @@ config POWER_DOMAIN_GPIO_MONITOR default y depends on DT_HAS_POWER_DOMAIN_GPIO_MONITOR_ENABLED depends on GPIO + depends on PM_DEVICE select DEVICE_DEPS if POWER_DOMAIN_GPIO_MONITOR diff --git a/drivers/power_domain/power_domain_gpio_monitor.c b/drivers/power_domain/power_domain_gpio_monitor.c index 62dfd60855b..a0a5af8aa7f 100644 --- a/drivers/power_domain/power_domain_gpio_monitor.c +++ b/drivers/power_domain/power_domain_gpio_monitor.c @@ -39,7 +39,7 @@ static int pd_on_domain_visitor(const struct device *dev, void *context) return 0; } - dev->pm->usage = 0; + dev->pm->base.usage = 0; (void)pm_device_action_run(dev, visitor_context->action); return 0; } diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 650404fceec..f964de9ea5d 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 452307acaa8..0e434ea492c 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -23,16 +23,11 @@ #include #include #include - -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif +#include LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); -#if !defined(CONFIG_ARCH_POSIX) #define RX_FLUSH_WORKAROUND 1 -#endif #define UARTE(idx) DT_NODELABEL(uart##idx) #define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop) @@ -112,6 +107,23 @@ 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(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 * is used then baudrate must be set after enabling the peripheral and not before. @@ -271,6 +283,21 @@ struct uarte_nrfx_data { (IS_ENABLED(UARTE_ANY_LOW_POWER) && \ !IS_ENABLED(CONFIG_PM_DEVICE) && \ (_config->flags & UARTE_CFG_FLAG_LOW_POWER)) + +/** @brief Check if device has PM that works in ISR safe mode. + * + * Only fast UARTE instance does not work in that mode so check PM configuration + * flags only if there is any fast instance present. + * + * @retval true if device PM is ISR safe. + * @retval false if device PM is not ISR safe. + */ +#define IS_PM_ISR_SAFE(dev) \ + (!IS_ENABLED(UARTE_ANY_FAST) ||\ + COND_CODE_1(CONFIG_PM_DEVICE,\ + ((dev->pm_base->flags & BIT(PM_DEVICE_FLAG_ISR_SAFE))), \ + (0))) + /** * @brief Structure for UARTE configuration. */ @@ -282,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; @@ -353,16 +384,16 @@ static void uarte_nrfx_isr_int(const void *arg) if (txstopped && (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(config))) { unsigned int key = irq_lock(); - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) && - (data->flags & UARTE_FLAG_POLL_OUT)) { - data->flags &= ~UARTE_FLAG_POLL_OUT; - pm_device_runtime_put(dev); + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (data->flags & UARTE_FLAG_POLL_OUT) { + data->flags &= ~UARTE_FLAG_POLL_OUT; + pm_device_runtime_put_async(dev, K_NO_WAIT); + } } else { nrf_uarte_disable(uarte); } - #ifdef UARTE_INTERRUPT_DRIVEN - if (!data->int_driven || data->int_driven->fifo_fill_lock == 0) + if (!data->int_driven) #endif { nrf_uarte_int_disable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); @@ -378,16 +409,20 @@ static void uarte_nrfx_isr_int(const void *arg) if (txstopped) { data->int_driven->fifo_fill_lock = 0; + if (!data->int_driven->tx_irq_enabled) { + + nrf_uarte_int_disable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); + } + if (data->int_driven->disable_tx_irq) { - nrf_uarte_int_disable(uarte, - NRF_UARTE_INT_TXSTOPPED_MASK); data->int_driven->disable_tx_irq = false; + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_put_async(dev, K_NO_WAIT); + } return; } - } - if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ERROR)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ERROR); } @@ -589,7 +624,20 @@ 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); +#endif #if UARTE_BAUDRATE_RETENTION_WORKAROUND nrf_uarte_baudrate_set(uarte, COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, @@ -667,7 +715,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); } @@ -702,6 +749,11 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask) } #endif +#ifdef CONFIG_SOC_NRF54H20_GPD + const struct uarte_nrfx_config *cfg = dev->config; + + nrf_gpd_retain_pins_set(cfg->pcfg, true); +#endif nrf_uarte_disable(get_uarte_instance(dev)); } @@ -863,6 +915,20 @@ static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf, } if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { + /* If instance does not support PM from ISR device shall + * already be turned on. + */ + enum pm_device_state state; + int err; + + err = pm_device_state_get(dev, &state); + (void)err; + __ASSERT_NO_MSG(err == 0); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -ENOTSUP; + } + } pm_device_runtime_get(dev); } @@ -931,6 +997,10 @@ static void notify_rx_disable(const struct device *dev) }; user_callback(dev, (struct uart_event *)&evt); + + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_put_async(dev, K_NO_WAIT); + } } #ifdef UARTE_HAS_FRAME_TIMEOUT @@ -1005,6 +1075,24 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, async_rx->next_buf = NULL; async_rx->next_buf_len = 0; + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { + /* If instance does not support PM from ISR device shall + * already be turned on. + */ + enum pm_device_state state; + int err; + + err = pm_device_state_get(dev, &state); + (void)err; + __ASSERT_NO_MSG(err == 0); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -ENOTSUP; + } + } + pm_device_runtime_get(dev); + } + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(cfg)) { if (async_rx->flush_cnt) { int cpy_len = MIN(len, async_rx->flush_cnt); @@ -1058,9 +1146,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, async_rx->enabled = true; - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_get(dev); - } else if (LOW_POWER_ENABLED(cfg)) { + if (LOW_POWER_ENABLED(cfg)) { unsigned int key = irq_lock(); uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_RX); @@ -1533,9 +1619,7 @@ static void rxto_isr(const struct device *dev) nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); #endif - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); - } else if (LOW_POWER_ENABLED(config)) { + if (LOW_POWER_ENABLED(config)) { uint32_t key = irq_lock(); uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_RX); @@ -1560,7 +1644,7 @@ static void txstopped_isr(const struct device *dev) if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { nrf_uarte_int_disable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); if (data->flags & UARTE_FLAG_POLL_OUT) { - pm_device_runtime_put(dev); + pm_device_runtime_put_async(dev, K_NO_WAIT); data->flags &= ~UARTE_FLAG_POLL_OUT; } } else if (LOW_POWER_ENABLED(config)) { @@ -1623,11 +1707,11 @@ static void txstopped_isr(const struct device *dev) data->async->tx.buf = NULL; data->async->tx.len = 0; + user_callback(dev, &evt); + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put(dev); + pm_device_runtime_put_async(dev, K_NO_WAIT); } - - user_callback(dev, &evt); } static void rxdrdy_isr(const struct device *dev) @@ -1814,6 +1898,22 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c) } if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (!IS_PM_ISR_SAFE(dev) && k_is_in_isr()) { + /* If instance does not support PM from ISR device shall + * already be turned on. + */ + enum pm_device_state state; + int err; + + err = pm_device_state_get(dev, &state); + (void)err; + __ASSERT_NO_MSG(err == 0); + if (state != PM_DEVICE_STATE_ACTIVE) { + irq_unlock(key); + return; + } + } + if (!(data->flags & UARTE_FLAG_POLL_OUT)) { data->flags |= UARTE_FLAG_POLL_OUT; pm_device_runtime_get(dev); @@ -1892,6 +1992,11 @@ static void uarte_nrfx_irq_tx_enable(const struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = dev->data; + + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_get(dev); + } + unsigned int key = irq_lock(); data->int_driven->disable_tx_irq = false; @@ -2103,9 +2208,6 @@ static void uarte_pm_resume(const struct device *dev) if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || !LOW_POWER_ENABLED(cfg)) { uarte_periph_enable(dev); -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(cfg->pcfg, false); -#endif } } @@ -2116,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 @@ -2299,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. @@ -2311,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) { \ @@ -2366,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), \ @@ -2393,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) \ { \ @@ -2405,15 +2537,16 @@ static int uarte_instance_init(const struct device *dev, } \ \ PM_DEVICE_DT_DEFINE(UARTE(idx), uarte_nrfx_pm_action, \ - PM_DEVICE_ISR_SAFE); \ + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _),\ + (0), (PM_DEVICE_ISR_SAFE))); \ \ DEVICE_DT_DEFINE(UARTE(idx), \ uarte_##idx##_init, \ 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/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index ee3f35e09d0..05779038142 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -10,12 +10,15 @@ #if defined(CONFIG_CLOCK_CONTROL_NRF) #include #endif +#include #include #include #include #include #define GRTC_NODE DT_NODELABEL(grtc) +#define HFCLK_NODE DT_PHANDLE_BY_NAME(GRTC_NODE, clocks, hfclock) +#define LFCLK_NODE DT_PHANDLE_BY_NAME(GRTC_NODE, clocks, lfclock) /* Ensure that GRTC properties in devicetree are defined correctly. */ #if !DT_NODE_HAS_PROP(GRTC_NODE, owned_channels) @@ -49,7 +52,7 @@ #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) -#define LFCLK_FREQUENCY_HZ 32768 +#define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency) #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); @@ -518,7 +521,35 @@ static int sys_clock_driver_init(void) #if defined(CONFIG_NRF_GRTC_ALWAYS_ON) nrfx_grtc_active_request_set(true); #endif + +#if DT_PROP(GRTC_NODE, clkout_32k) + nrfy_grtc_clkout_set(NRF_GRTC, NRF_GRTC_CLKOUT_32K, true); +#endif + +#if DT_NODE_HAS_PROP(GRTC_NODE, clkout_fast_frequency) +#if !DT_NODE_HAS_PROP(HFCLK_NODE, clock_frequency) +#error "hfclock reference required when fast clock output is enabled." +#endif + +#if DT_PROP(GRTC_NODE, clkout_fast_frequency) > (DT_PROP(HFCLK_NODE, clock_frequency) / 2) +#error "Invalid frequency value for fast clock output." +#endif + uint32_t base_frequency = DT_PROP(HFCLK_NODE, clock_frequency); + uint32_t requested_frequency = DT_PROP(GRTC_NODE, clkout_fast_frequency); + uint32_t grtc_div = base_frequency / (requested_frequency * 2); + + nrfy_grtc_clkout_divider_set(NRF_GRTC, (uint8_t)grtc_div); + nrfy_grtc_clkout_set(NRF_GRTC, NRF_GRTC_CLKOUT_FAST, true); +#endif + +#if DT_PROP(GRTC_NODE, clkout_32k) || DT_NODE_HAS_PROP(GRTC_NODE, clkout_fast_frequency) + PINCTRL_DT_DEFINE(GRTC_NODE); + const struct pinctrl_dev_config *pcfg = PINCTRL_DT_DEV_CONFIG_GET(GRTC_NODE); + + return pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); +#else return 0; +#endif } void sys_clock_set_timeout(int32_t ticks, bool idle) diff --git a/drivers/usb/udc/udc_common.c b/drivers/usb/udc/udc_common.c index 86f5a7f854a..bef3f657382 100644 --- a/drivers/usb/udc/udc_common.c +++ b/drivers/usb/udc/udc_common.c @@ -592,6 +592,11 @@ int udc_ep_enqueue(const struct device *dev, struct net_buf *const buf) goto ep_enqueue_error; } + if (!cfg->stat.enabled) { + ret = -ENODEV; + goto ep_enqueue_error; + } + LOG_DBG("Queue ep 0x%02x %p len %u", cfg->addr, buf, USB_EP_DIR_IS_IN(cfg->addr) ? buf->len : buf->size); diff --git a/dts/bindings/timer/nordic,nrf-grtc.yaml b/dts/bindings/timer/nordic,nrf-grtc.yaml index e78e57df97e..4b041d0adc1 100644 --- a/dts/bindings/timer/nordic,nrf-grtc.yaml +++ b/dts/bindings/timer/nordic,nrf-grtc.yaml @@ -4,18 +4,40 @@ # SPDX-License-Identifier: Apache-2.0 # -description: Nordic GRTC (Global RTC) +description: | + Nordic GRTC (Global RTC) + + Example of using clock outputs: + &grtc { + pinctrl-0 = <&grtc_default>; + pinctrl-1 = <&grtc_sleep>; + pinctrl-names = "default", "sleep"; + clkout-fast-frequency = <8000000>; + clkout-32k; + /* In case of nRF54H20 devices: */ + nordic,clockpin-enable = ; + }; compatible: "nordic,nrf-grtc" include: - "base.yaml" - "nordic,split-channels.yaml" + - "pinctrl-device.yaml" + - "nordic-clockpin.yaml" properties: reg: required: true + clkout-fast-frequency: + type: int + description: Fast output clock frequency. + + clkout-32k: + type: boolean + description: 32768 Hz output clock frequency enable. + interrupts: required: true diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 034813bc076..790785ebaaa 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>; }; @@ -939,11 +941,8 @@ reg = <0x99c000 0x1000>; status = "disabled"; cc-num = <16>; - /* GRTC uses both LFCLK and FLL16M, but its accuracy and - * precision are inherited from LFCLK. that's why this - * one is linked here. - */ - clocks = <&lfclk>; + clocks = <&lfclk>, <&fll16m>; + clock-names = "lfclock", "hfclock"; power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; }; diff --git a/dts/common/nordic/nrf54l20.dtsi b/dts/common/nordic/nrf54l20.dtsi index 67ccb152a5f..d06c4814103 100644 --- a/dts/common/nordic/nrf54l20.dtsi +++ b/dts/common/nordic/nrf54l20.dtsi @@ -35,6 +35,12 @@ }; clocks { + pclk: pclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + lfxo: lfxo { compatible = "nordic,nrf-lfxo"; #clock-cells = <0>; @@ -498,6 +504,8 @@ compatible = "nordic,nrf-grtc"; reg = <0xe2000 0x1000>; cc-num = <12>; + clocks = <&lfxo>, <&pclk>; + clock-names = "lfclock", "hfclock"; status = "disabled"; }; diff --git a/dts/common/nordic/nrf54l_05_10_15.dtsi b/dts/common/nordic/nrf54l_05_10_15.dtsi index d997e01c488..eba41095e75 100644 --- a/dts/common/nordic/nrf54l_05_10_15.dtsi +++ b/dts/common/nordic/nrf54l_05_10_15.dtsi @@ -48,6 +48,12 @@ }; clocks { + pclk: pclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + lfxo: lfxo { compatible = "nordic,nrf-lfxo"; #clock-cells = <0>; @@ -548,6 +554,8 @@ compatible = "nordic,nrf-grtc"; reg = <0xe2000 0x1000>; cc-num = <12>; + clocks = <&lfxo>, <&pclk>; + clock-names = "lfclock", "hfclock"; status = "disabled"; }; diff --git a/include/zephyr/drivers/clock_control/nrf_clock_control.h b/include/zephyr/drivers/clock_control/nrf_clock_control.h index d08016d76b0..27ab518920f 100644 --- a/include/zephyr/drivers/clock_control/nrf_clock_control.h +++ b/include/zephyr/drivers/clock_control/nrf_clock_control.h @@ -117,6 +117,13 @@ int z_nrf_clock_calibration_count(void); */ int z_nrf_clock_calibration_skips_count(void); + +/** @brief Returns information if LF clock calibration is in progress. + * + * @return True if calibration is in progress, false otherwise. + */ +bool z_nrf_clock_calibration_is_in_progress(void); + /** @brief Get onoff service for given clock subsystem. * * @param sys Subsystem. @@ -238,6 +245,7 @@ int nrf_clock_control_request(const struct device *dev, /** * @brief Synchronously request a reservation to use a given clock with specified attributes. * + * Function can only be called from thread context as it blocks until request is completed. * @see nrf_clock_control_request(). * * @param dev pointer to the clock device structure. @@ -328,7 +336,7 @@ int nrf_clock_control_cancel_or_release(const struct device *dev, (COND_CODE_1(DT_NODE_HAS_PROP(DT_CLOCKS_CTLR(node), clock_frequency), \ (DT_PROP(DT_CLOCKS_CTLR(node), clock_frequency)), \ (DT_PROP_LAST(DT_CLOCKS_CTLR(node), supported_clock_frequency)))), \ - (NRFX_MHZ_TO_HZ(16))) + (DT_PROP_OR(node, max_frequency, NRFX_MHZ_TO_HZ(16)))) #ifdef __cplusplus } diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index 4611baef95c..a73f59c48b7 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -162,6 +162,10 @@ #define NRF_FUN_CAN_TX 46U /** CAN RX */ #define NRF_FUN_CAN_RX 47U +/** GRTC fast clock output */ +#define NRF_FUN_GRTC_CLKOUT_FAST 55U +/** GRTC slow clock output */ +#define NRF_FUN_GRTC_CLKOUT_32K 56U /** @} */ 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/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index 67634132408..1479f254ac1 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -270,11 +270,6 @@ def program_hex(self): if self.erase: self.exec_op('erase', core='NRFDL_DEVICE_CORE_APPLICATION') self.exec_op('erase', core='NRFDL_DEVICE_CORE_NETWORK') - # A reset is needed if repartitioning the device memory - self.reset_target() - else: - # Ensure that firmware is not executing while erasing/programming - self.exec_op("reset", option="RESET_VIA_SECDOM") # Manage SUIT artifacts. # This logic should be executed only once per build. @@ -326,8 +321,16 @@ def program_hex(self): ) if cpuapp: + if not self.erase and self.build_conf.getboolean('CONFIG_NRF_REGTOOL_GENERATE_UICR'): + self.exec_op('erase', core='NRFDL_DEVICE_CORE_APPLICATION', + option={'chip_erase_mode': 'ERASE_UICR', + 'qspi_erase_mode': 'ERASE_NONE'}) core = 'NRFDL_DEVICE_CORE_APPLICATION' elif cpurad: + if not self.erase and self.build_conf.getboolean('CONFIG_NRF_REGTOOL_GENERATE_UICR'): + self.exec_op('erase', core='NRFDL_DEVICE_CORE_NETWORK', + option={'chip_erase_mode': 'ERASE_UICR', + 'qspi_erase_mode': 'ERASE_NONE'}) core = 'NRFDL_DEVICE_CORE_NETWORK' else: if self.erase: diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index 20c28e42df5..ea9e60973d1 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -132,6 +132,8 @@ void __attribute__((naked)) pm_s2ram_mark_set(void) bool __attribute__((naked)) pm_s2ram_mark_check_and_clear(void) { + register uint32_t link_reg __asm__("r14"); + __asm__ volatile( /* Set return value to 0 */ "mov r0, #0\n" @@ -159,13 +161,14 @@ bool __attribute__((naked)) pm_s2ram_mark_check_and_clear(void) "mov r0, #1\n" "exit:\n" - "bx lr\n" + "bx %[link_reg]\n" : : [resetinfo_addr] "r"(NRF_RESETINFO), [resetreas_offs] "r"(offsetof(NRF_RESETINFO_Type, RESETREAS.LOCAL)), [resetreas_unretained_mask] "r"(NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK), [restorevalid_offs] "r"(offsetof(NRF_RESETINFO_Type, RESTOREVALID)), - [restorevalid_present_mask] "r"(RESETINFO_RESTOREVALID_RESTOREVALID_Msk) + [restorevalid_present_mask] "r"(RESETINFO_RESTOREVALID_RESTOREVALID_Msk), + [link_reg] "r"(link_reg) - : "r0", "r1", "r3", "r4", "memory"); + : "r0", "r1", "r3", "r4", "cc", "memory"); } diff --git a/subsys/usb/device_next/class/bt_hci.c b/subsys/usb/device_next/class/bt_hci.c index 52eddc4e25b..4487726b22a 100644 --- a/subsys/usb/device_next/class/bt_hci.c +++ b/subsys/usb/device_next/class/bt_hci.c @@ -459,11 +459,7 @@ static void *bt_hci_get_desc(struct usbd_class_data *const c_data, static int bt_hci_init(struct usbd_class_data *const c_data) { - - struct bt_hci_data *data = usbd_class_get_private(c_data); - struct usbd_bt_hci_desc *desc = data->desc; - - desc->iad.bFirstInterface = desc->if0.bInterfaceNumber; + ARG_UNUSED(c_data); return 0; } diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index 2237cabcc79..b74a6b44b05 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -135,11 +135,6 @@ static void *lb_get_desc(struct usbd_class_data *const c_data, static int lb_init(struct usbd_class_data *c_data) { - struct lb_data *data = usbd_class_get_private(c_data); - struct loopback_desc *desc = data->desc; - - desc->iad.bFirstInterface = desc->if0.bInterfaceNumber; - LOG_DBG("Init class instance %p", c_data); return 0; diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 80f4a858386..04f4c424f7d 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -473,7 +473,6 @@ static int usbd_cdc_acm_init(struct usbd_class_data *const c_data) struct cdc_acm_uart_data *data = dev->data; struct usbd_cdc_acm_desc *desc = data->desc; - desc->iad.bFirstInterface = desc->if0.bInterfaceNumber; desc->if0_union.bControlInterface = desc->if0.bInterfaceNumber; desc->if0_union.bSubordinateInterface0 = desc->if1.bInterfaceNumber; diff --git a/subsys/usb/device_next/class/usbd_cdc_ecm.c b/subsys/usb/device_next/class/usbd_cdc_ecm.c index 3c3072182be..3b0c656da4e 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ecm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ecm.c @@ -449,7 +449,6 @@ static int usbd_cdc_ecm_init(struct usbd_class_data *const c_data) const uint8_t if_num = desc->if0.bInterfaceNumber; /* Update relevant b*Interface fields */ - desc->iad.bFirstInterface = if_num; desc->if0_union.bControlInterface = if_num; desc->if0_union.bSubordinateInterface0 = if_num + 1; LOG_DBG("CDC ECM class initialized"); diff --git a/subsys/usb/device_next/usbd_init.c b/subsys/usb/device_next/usbd_init.c index 551dc32164f..fc31c8a211a 100644 --- a/subsys/usb/device_next/usbd_init.c +++ b/subsys/usb/device_next/usbd_init.c @@ -115,6 +115,7 @@ static int init_configuration_inst(struct usbd_context *const uds_ctx, uint8_t *const nif) { struct usb_desc_header **dhp; + struct usb_association_descriptor *iad = NULL; struct usb_if_descriptor *ifd = NULL; struct usb_ep_descriptor *ed; uint32_t class_ep_bm = 0; @@ -132,6 +133,14 @@ static int init_configuration_inst(struct usbd_context *const uds_ctx, c_nd->ep_active = 0U; while (*dhp != NULL && (*dhp)->bLength != 0) { + if ((*dhp)->bDescriptorType == USB_DESC_INTERFACE_ASSOC) { + iad = (struct usb_association_descriptor *)(*dhp); + + /* IAD must be before interfaces it associates, so the + * first interface will be the next interface assigned. + */ + iad->bFirstInterface = tmp_nif; + } if ((*dhp)->bDescriptorType == USB_DESC_INTERFACE) { ifd = (struct usb_if_descriptor *)(*dhp); diff --git a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..0bcc82e646b --- /dev/null +++ b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_SOC_NRF54H20_GPD=n 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>; }; }; 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 9aa338deaad..9902d733d35 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 @@ -3,8 +3,11 @@ &pinctrl { uart137_default_alt: uart137_default_alt { group1 { - psels = , - ; + psels = ; + }; + group2 { + psels = ; + bias-pull-up; }; }; @@ -15,6 +18,23 @@ low-power-enable; }; }; + uart120_default_alt: uart120_default_alt { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart120_sleep_alt: uart120_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; }; dut: &uart137 { @@ -23,4 +43,13 @@ dut: &uart137 { pinctrl-1 = <&uart137_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; + zephyr,pm-device-runtime-auto; +}; + +dut2: &uart120 { + pinctrl-0 = <&uart120_default_alt>; + 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 00000000000..74cc8d7691e --- /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 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index be5897fd051..79f5554a33b 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -5,3 +5,12 @@ &dut { memory-regions = <&cpuapp_dma_region>; }; + +&dut2 { + status = "okay"; + memory-regions = <&dma_fast_region>; +}; + +&dma_fast_region { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 2feb201d94c..c087878eee8 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -24,25 +24,32 @@ K_SEM_DEFINE(rx_buf_coherency, 0, 255); K_SEM_DEFINE(rx_buf_released, 0, 1); K_SEM_DEFINE(rx_disabled, 0, 1); -ZTEST_BMEM volatile bool failed_in_isr; -static ZTEST_BMEM const struct device *const uart_dev = - DEVICE_DT_GET(UART_NODE); +static ZTEST_BMEM volatile bool failed_in_isr; -static void read_abort_timeout(struct k_timer *timer); -K_TIMER_DEFINE(read_abort_timer, read_abort_timeout, NULL); +struct dut_data { + const struct device *dev; + const char *name; +}; +ZTEST_DMEM struct dut_data duts[] = { + { + .dev = DEVICE_DT_GET(UART_NODE), + .name = DT_NODE_FULL_NAME(UART_NODE), + }, +#if DT_NODE_EXISTS(DT_NODELABEL(dut2)) && DT_NODE_HAS_STATUS(DT_NODELABEL(dut2), okay) + { + .dev = DEVICE_DT_GET(DT_NODELABEL(dut2)), + .name = DT_NODE_FULL_NAME(DT_NODELABEL(dut2)), + }, +#endif +}; + +static ZTEST_BMEM const struct device *uart_dev; +static ZTEST_BMEM const char *uart_name; + +static void read_abort_timeout(struct k_timer *timer); +static K_TIMER_DEFINE(read_abort_timer, read_abort_timeout, NULL); -static void init_test(void) -{ - __ASSERT_NO_MSG(device_is_ready(uart_dev)); - uart_rx_disable(uart_dev); - uart_tx_abort(uart_dev); - k_sem_reset(&tx_done); - k_sem_reset(&tx_aborted); - k_sem_reset(&rx_rdy); - k_sem_reset(&rx_buf_released); - k_sem_reset(&rx_disabled); -} #ifdef CONFIG_USERSPACE static void set_permissions(void) @@ -50,14 +57,22 @@ static void set_permissions(void) k_thread_access_grant(k_current_get(), &tx_done, &tx_aborted, &rx_rdy, &rx_buf_coherency, &rx_buf_released, &rx_disabled, uart_dev, &read_abort_timer); + + for (size_t i = 0; i < ARRAY_SIZE(duts); i++) { + k_thread_access_grant(k_current_get(), duts[i].dev); + } } #endif -static void uart_async_test_init(void) +static void uart_async_test_init(int idx) { static bool initialized; + uart_dev = duts[idx].dev; + uart_name = duts[idx].name; + __ASSERT_NO_MSG(device_is_ready(uart_dev)); + TC_PRINT("UART instance:%s\n", uart_name); uart_rx_disable(uart_dev); uart_tx_abort(uart_dev); k_sem_reset(&tx_done); @@ -79,7 +94,6 @@ static void uart_async_test_init(void) #endif if (!initialized) { - init_test(); initialized = true; #ifdef CONFIG_USERSPACE set_permissions(); @@ -100,7 +114,7 @@ struct test_data { #if NOCACHE_MEM static struct test_data tdata __used __NOCACHE; #else -ZTEST_BMEM struct test_data tdata; +static ZTEST_BMEM struct test_data tdata; #endif /* NOCACHE_MEM */ static void test_single_read_callback(const struct device *dev, @@ -143,11 +157,13 @@ static void test_single_read_callback(const struct device *dev, } } -ZTEST_BMEM volatile uint32_t tx_aborted_count; +static ZTEST_BMEM volatile uint32_t tx_aborted_count; static void *single_read_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); memset(&tdata, 0, sizeof(tdata)); tdata.supply_second_buffer = true; @@ -228,7 +244,9 @@ ZTEST_USER(uart_async_single_read, test_single_read) static void *multiple_rx_enable_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); memset(&tdata, 0, sizeof(tdata)); /* Reuse the callback from the single_read test case, as this test case @@ -324,16 +342,23 @@ ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) } #if NOCACHE_MEM -static __aligned(32) uint8_t chained_read_buf[2][8] __used __NOCACHE; +/* To ensure 32-bit alignment of the buffer array, + * the two arrays are defined instead using an array of arrays + */ +static __aligned(32) uint8_t chained_read_buf_0[8] __used __NOCACHE; +static __aligned(32) uint8_t chained_read_buf_1[8] __used __NOCACHE; static __aligned(32) uint8_t chained_cpy_buf[10] __used __NOCACHE; #else -ZTEST_BMEM uint8_t chained_read_buf[2][8]; -ZTEST_BMEM uint8_t chained_cpy_buf[10]; +static ZTEST_BMEM uint8_t chained_read_buf_0[8]; +static ZTEST_BMEM uint8_t chained_read_buf_1[8]; +static ZTEST_BMEM uint8_t chained_cpy_buf[10]; #endif /* NOCACHE_MEM */ -ZTEST_BMEM volatile uint8_t rx_data_idx; -ZTEST_BMEM uint8_t rx_buf_idx; +static ZTEST_BMEM volatile uint8_t rx_data_idx; +static ZTEST_BMEM uint8_t rx_buf_idx; -ZTEST_BMEM uint8_t *read_ptr; +static ZTEST_BMEM uint8_t *read_ptr; + +static uint8_t *chained_read_buf[2] = {chained_read_buf_0, chained_read_buf_1}; static void test_chained_read_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -352,9 +377,8 @@ static void test_chained_read_callback(const struct device *dev, rx_data_idx += evt->data.rx.len; break; case UART_RX_BUF_REQUEST: - err = uart_rx_buf_rsp(dev, - chained_read_buf[rx_buf_idx], - sizeof(chained_read_buf[0])); + err = uart_rx_buf_rsp(dev, chained_read_buf[rx_buf_idx], + sizeof(chained_read_buf_0)); zassert_equal(err, 0); rx_buf_idx = !rx_buf_idx ? 1 : 0; break; @@ -369,7 +393,9 @@ static void test_chained_read_callback(const struct device *dev, static void *chained_read_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); uart_callback_set(uart_dev, test_chained_read_callback, NULL); @@ -387,11 +413,10 @@ ZTEST_USER(uart_async_chain_read, test_chained_read) uint32_t rx_timeout_ms = 50; int err; - err = uart_rx_enable(uart_dev, - chained_read_buf[rx_buf_idx++], - sizeof(chained_read_buf[0]), + err = uart_rx_enable(uart_dev, chained_read_buf[rx_buf_idx++], sizeof(chained_read_buf_0), rx_timeout_ms * USEC_PER_MSEC); zassert_equal(err, 0); + rx_data_idx = 0; for (int i = 0; i < iter; i++) { zassert_not_equal(k_sem_take(&rx_disabled, K_MSEC(10)), @@ -406,7 +431,7 @@ ZTEST_USER(uart_async_chain_read, test_chained_read) "Unexpected amount of data received %d exp:%d", rx_data_idx, sizeof(tx_buf)); zassert_equal(memcmp(tx_buf, chained_cpy_buf, sizeof(tx_buf)), 0, - "Buffers not equal"); + "Buffers not equal exp %s, real %s", tx_buf, chained_cpy_buf); rx_data_idx = 0; } uart_rx_disable(uart_dev); @@ -417,9 +442,9 @@ ZTEST_USER(uart_async_chain_read, test_chained_read) #if NOCACHE_MEM static __aligned(32) uint8_t double_buffer[2][12] __used __NOCACHE; #else -ZTEST_BMEM uint8_t double_buffer[2][12]; +static ZTEST_BMEM uint8_t double_buffer[2][12]; #endif /* NOCACHE_MEM */ -ZTEST_DMEM uint8_t *next_buf = double_buffer[1]; +static ZTEST_DMEM uint8_t *next_buf = double_buffer[1]; static void test_double_buffer_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -450,7 +475,9 @@ static void test_double_buffer_callback(const struct device *dev, static void *double_buffer_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); uart_callback_set(uart_dev, test_double_buffer_callback, NULL); @@ -492,10 +519,11 @@ ZTEST_USER(uart_async_double_buf, test_double_buffer) static __aligned(32) uint8_t test_read_abort_rx_buf[2][100] __used __NOCACHE; static __aligned(32) uint8_t test_read_abort_read_buf[100] __used __NOCACHE; #else -ZTEST_BMEM uint8_t test_read_abort_rx_buf[2][100]; -ZTEST_BMEM uint8_t test_read_abort_read_buf[100]; +static ZTEST_BMEM uint8_t test_read_abort_rx_buf[2][100]; +static ZTEST_BMEM uint8_t test_read_abort_read_buf[100]; #endif /* NOCACHE_MEM */ -ZTEST_BMEM int test_read_abort_rx_cnt; +static ZTEST_BMEM int test_read_abort_rx_cnt; +static ZTEST_BMEM bool test_read_abort_rx_buf_req_once; static void test_read_abort_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -510,14 +538,12 @@ static void test_read_abort_callback(const struct device *dev, break; case UART_RX_BUF_REQUEST: { - static bool once; - - if (!once) { + if (!test_read_abort_rx_buf_req_once) { k_sem_give(&rx_buf_coherency); uart_rx_buf_rsp(dev, test_read_abort_rx_buf[1], sizeof(test_read_abort_rx_buf[1])); - once = true; + test_read_abort_rx_buf_req_once = true; } break; } @@ -553,8 +579,11 @@ static void read_abort_timeout(struct k_timer *timer) static void *read_abort_setup(void) { - uart_async_test_init(); + static int idx; + uart_async_test_init(idx++); + + test_read_abort_rx_buf_req_once = false; failed_in_isr = false; uart_callback_set(uart_dev, test_read_abort_callback, NULL); @@ -608,12 +637,12 @@ ZTEST_USER(uart_async_read_abort, test_read_abort) } -ZTEST_BMEM volatile size_t sent; -ZTEST_BMEM volatile size_t received; +static ZTEST_BMEM volatile size_t sent; +static ZTEST_BMEM volatile size_t received; #if NOCACHE_MEM static __aligned(32) uint8_t test_rx_buf[2][100] __used __NOCACHE; #else -ZTEST_BMEM uint8_t test_rx_buf[2][100]; +static ZTEST_BMEM uint8_t test_rx_buf[2][100]; #endif /* NOCACHE_MEM */ static void test_write_abort_callback(const struct device *dev, @@ -649,7 +678,9 @@ static void test_write_abort_callback(const struct device *dev, static void *write_abort_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); uart_callback_set(uart_dev, test_write_abort_callback, NULL); @@ -722,7 +753,9 @@ static void test_forever_timeout_callback(const struct device *dev, static void *forever_timeout_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); uart_callback_set(uart_dev, test_forever_timeout_callback, NULL); @@ -771,12 +804,12 @@ ZTEST_USER(uart_async_timeout, test_forever_timeout) #if NOCACHE_MEM -const uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; +static const uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; #else -ZTEST_DMEM uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; +static ZTEST_DMEM uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"}; #endif /* NOCACHE_MEM */ -ZTEST_DMEM bool chained_write_next_buf = true; -ZTEST_BMEM volatile uint8_t tx_sent; +static ZTEST_DMEM bool chained_write_next_buf = true; +static ZTEST_BMEM volatile uint8_t tx_sent; static void test_chained_write_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -811,8 +844,12 @@ static void test_chained_write_callback(const struct device *dev, static void *chained_write_setup(void) { - uart_async_test_init(); + static int idx; + uart_async_test_init(idx++); + + tx_sent = 0; + chained_write_next_buf = true; uart_callback_set(uart_dev, test_chained_write_callback, NULL); return NULL; @@ -858,17 +895,17 @@ static __aligned(32) uint8_t long_rx_buf[RX_LONG_BUFFER] __used __NOCACHE; static __aligned(32) uint8_t long_rx_buf2[RX_LONG_BUFFER] __used __NOCACHE; static __aligned(32) uint8_t long_tx_buf[TX_LONG_BUFFER] __used __NOCACHE; #else -ZTEST_BMEM uint8_t long_rx_buf[RX_LONG_BUFFER]; -ZTEST_BMEM uint8_t long_rx_buf2[RX_LONG_BUFFER]; -ZTEST_BMEM uint8_t long_tx_buf[TX_LONG_BUFFER]; +static ZTEST_BMEM uint8_t long_rx_buf[RX_LONG_BUFFER]; +static ZTEST_BMEM uint8_t long_rx_buf2[RX_LONG_BUFFER]; +static ZTEST_BMEM uint8_t long_tx_buf[TX_LONG_BUFFER]; #endif /* NOCACHE_MEM */ -ZTEST_BMEM volatile uint8_t evt_num; -ZTEST_BMEM size_t long_received[2]; +static ZTEST_BMEM volatile uint8_t evt_num; +static ZTEST_BMEM size_t long_received[2]; +static ZTEST_BMEM uint8_t *long_next_buffer; static void test_long_buffers_callback(const struct device *dev, struct uart_event *evt, void *user_data) { - static uint8_t *next_buffer = long_rx_buf2; switch (evt->type) { case UART_TX_DONE: @@ -890,8 +927,8 @@ static void test_long_buffers_callback(const struct device *dev, k_sem_give(&rx_disabled); break; case UART_RX_BUF_REQUEST: - uart_rx_buf_rsp(dev, next_buffer, RX_LONG_BUFFER); - next_buffer = (next_buffer == long_rx_buf2) ? long_rx_buf : long_rx_buf2; + uart_rx_buf_rsp(dev, long_next_buffer, RX_LONG_BUFFER); + long_next_buffer = (long_next_buffer == long_rx_buf2) ? long_rx_buf : long_rx_buf2; break; default: break; @@ -900,8 +937,12 @@ static void test_long_buffers_callback(const struct device *dev, static void *long_buffers_setup(void) { - uart_async_test_init(); + static int idx; + + uart_async_test_init(idx++); + evt_num = 0; + long_next_buffer = long_rx_buf2; uart_callback_set(uart_dev, test_long_buffers_callback, NULL); return NULL; @@ -983,3 +1024,12 @@ ZTEST_SUITE(uart_async_write_abort, NULL, write_abort_setup, ZTEST_SUITE(uart_async_timeout, NULL, forever_timeout_setup, NULL, NULL, NULL); + +void test_main(void) +{ + /* Run all suites for each dut UART. Setup function for each suite is picking + * next UART from the array. + */ + ztest_run_all(NULL, false, ARRAY_SIZE(duts), 1); + ztest_verify_all_test_suites_ran(); +}