diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 8d7890d1fdf..cccbe5e2e74 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -10,6 +10,8 @@ menuconfig CLOCK_CONTROL_STM32_CUBE select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ + $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help Enable driver for Reset & Clock Control subsystem found in STM32 family of MCUs diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index ba5ba2e4673..d3adbe62535 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -567,6 +567,11 @@ static void set_up_fixed_clock_sources(void) while (LL_RCC_HSE_IsReady() != 1) { /* Wait for HSE ready */ } + /* Check if we need to enable HSE clock security system or not */ +#if STM32_HSE_CSS + z_arm_nmi_set_handler(HAL_RCC_NMI_IRQHandler); + LL_RCC_HSE_EnableCSS(); +#endif /* STM32_HSE_CSS */ } if (IS_ENABLED(STM32_HSI_ENABLED)) { @@ -817,6 +822,16 @@ int stm32_clock_control_init(const struct device *dev) return 0; } +#if defined(STM32_HSE_CSS) +void __weak stm32_hse_css_callback(void) {} + +/* Called by the HAL in response to an HSE CSS interrupt */ +void HAL_RCC_CSSCallback(void) +{ + stm32_hse_css_callback(); +} +#endif + /** * @brief RCC device, note that priority is intentionally set to 1 so * that the device init runs just after SOC init diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index dc9127d277d..23856ff7e2d 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -586,6 +586,11 @@ static void set_up_fixed_clock_sources(void) LL_RCC_HSE_Enable(); while (LL_RCC_HSE_IsReady() != 1) { } + /* Check if we need to enable HSE clock security system or not */ +#if STM32_HSE_CSS + z_arm_nmi_set_handler(HAL_RCC_NMI_IRQHandler); + LL_RCC_HSE_EnableCSS(); +#endif /* STM32_HSE_CSS */ } if (IS_ENABLED(STM32_HSI_ENABLED)) { @@ -930,6 +935,16 @@ int stm32_clock_control_init(const struct device *dev) } #endif /* CONFIG_CPU_CORTEX_M7 */ +#if defined(STM32_HSE_CSS) +void __weak stm32_hse_css_callback(void) {} + +/* Called by the HAL in response to an HSE CSS interrupt */ +void HAL_RCC_CSSCallback(void) +{ + stm32_hse_css_callback(); +} +#endif + /** * @brief RCC device, note that priority is intentionally set to 1 so * that the device init runs just after SOC init diff --git a/dts/bindings/clock/st,stm32-hse-clock.yaml b/dts/bindings/clock/st,stm32-hse-clock.yaml index 833a393595d..45cfa050c50 100644 --- a/dts/bindings/clock/st,stm32-hse-clock.yaml +++ b/dts/bindings/clock/st,stm32-hse-clock.yaml @@ -13,3 +13,19 @@ properties: description: | HSE crystal oscillator bypass Set to the property to by-pass the oscillator with an external clock. + + css-enabled: + type: boolean + description: | + HSE clock security system enabled + Set the property to enable the clock security system (CSS) for the HSE clock. + + If a failure is detected on the HSE clock, the HSE oscillator is automatically disabled, + a clock failure event is sent to timers, and a non-maskable interrupt is generated to + inform the software about the failure, allowing the MCU to perform rescue operations. + See the MCU reference manual for details. + + The interaction of CSS and low-power modes is unclear from the documentation. + For at least some devices Zephyr will reconfigure the clocks on resuming from low-power + modes; this will include re-enabling CSS. However it is important that you verify + this for your own hardware. diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index f18c351c0d5..062fae034e3 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -369,6 +369,7 @@ #define STM32_HSE_ENABLED 1 #define STM32_HSE_BYPASS DT_PROP(DT_NODELABEL(clk_hse), hse_bypass) #define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) +#define STM32_HSE_CSS DT_PROP(DT_NODELABEL(clk_hse), css_enabled) #elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32wl_hse_clock, okay) #define STM32_HSE_ENABLED 1 #define STM32_HSE_TCXO DT_PROP(DT_NODELABEL(clk_hse), hse_tcxo) @@ -460,4 +461,16 @@ struct stm32_pclken { #define STM32_CLOCK_VAL_GET(clock) \ (((clock) >> STM32_CLOCK_VAL_SHIFT) & STM32_CLOCK_VAL_MASK) +#if defined(STM32_HSE_CSS) +/** + * @brief Called if the HSE clock security system detects a clock fault. + * + * The function is called in interrupt context. + * + * The default (weakly-linked) implementation does nothing and should be + * overridden. + */ +void stm32_hse_css_callback(void); +#endif + #endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_STM32_CLOCK_CONTROL_H_ */ diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/boards/hse_css.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/boards/hse_css.overlay new file mode 100644 index 00000000000..e1da83b1fcc --- /dev/null +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/boards/hse_css.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Ferroamp AB (publ) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Warning: This overlay assumes the HSE clock has already been enabled, + * for example by hse_24.overlay. + */ + +&clk_hse { + css-enabled; +}; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/src/test_stm32_clock_configuration.c b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/src/test_stm32_clock_configuration.c index 9b4591e0613..46571164776 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/src/test_stm32_clock_configuration.c +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/src/test_stm32_clock_configuration.c @@ -105,4 +105,17 @@ ZTEST(stm32_sysclck_config, test_pll_src) #endif } + +#if STM32_HSE_ENABLED +ZTEST(stm32_sysclck_config, test_hse_css) +{ + /* there is no function to read CSS status, so read directly from the register */ +#if STM32_HSE_CSS + zassert_true(READ_BIT(RCC->CR, RCC_CR_CSSON), "HSE CSS is not enabled"); +#else + zassert_false(READ_BIT(RCC->CR, RCC_CR_CSSON), "HSE CSS unexpectedly enabled"); +#endif /* STM32_HSE_CSS */ + +} +#endif /* STM32_HSE_ENABLED */ ZTEST_SUITE(stm32_sysclck_config, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml index 563108bfe91..dbc0f6722ea 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32_common_core/testcase.yaml @@ -114,6 +114,10 @@ tests: drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_24.overlay" platform_allow: nucleo_g474re + drivers.clock.stm32_clock_configuration.common_core.g4.sysclksrc_hse_24.css: + extra_args: + DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_24.overlay;boards/hse_css.overlay" + platform_allow: nucleo_g474re drivers.clock.stm32_clock_configuration.common_core.l0_l1.sysclksrc_hse_8: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/clear_msi.overlay;boards/hse_8.overlay" diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/boards/hse_css.overlay b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/boards/hse_css.overlay new file mode 100644 index 00000000000..3fb213cbc4a --- /dev/null +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/boards/hse_css.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Ferroamp AB (publ) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Warning: This overlay assumes the HSE clock has already been enabled, + * for example by hse_8.overlay. + */ + +&clk_hse { + css-enabled; +}; diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/src/test_stm32_clock_configuration.c b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/src/test_stm32_clock_configuration.c index 596edb90280..360fa4877ca 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/src/test_stm32_clock_configuration.c +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/src/test_stm32_clock_configuration.c @@ -76,4 +76,17 @@ ZTEST(stm32_syclck_config, test_pll_src) #endif } + +#if STM32_HSE_ENABLED +ZTEST(stm32_syclck_config, test_hse_css) +{ + /* there is no function to read CSS status, so read directly from the register */ +#if STM32_HSE_CSS + zassert_true(READ_BIT(RCC->CR, RCC_CR_CSSHSEON), "HSE CSS is not enabled"); +#else + zassert_false(READ_BIT(RCC->CR, RCC_CR_CSSHSEON), "HSE CSS unexpectedly enabled"); +#endif /* STM32_HSE_CSS */ + +} +#endif /* STM32_HSE_ENABLED */ ZTEST_SUITE(stm32_syclck_config, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml index f134f811906..8b868d3618a 100644 --- a/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml +++ b/tests/drivers/clock_control/stm32_clock_configuration/stm32h7_core/testcase.yaml @@ -28,6 +28,12 @@ tests: platform_allow: nucleo_h743zi integration_platforms: - nucleo_h743zi + drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_hse_8_css: + extra_args: + DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/hse_8.overlay;boards/hse_css.overlay" + platform_allow: nucleo_h743zi + integration_platforms: + - nucleo_h743zi drivers.clock.stm32_clock_configuration.h7_core.sysclksrc_pll_csi_96: extra_args: DTC_OVERLAY_FILE="boards/clear_clocks.overlay;boards/pll_csi_96.overlay" platform_allow: nucleo_h743zi