diff --git a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts index a6f57928bce2f..f0c72b4b94b92 100644 --- a/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts +++ b/boards/st/nucleo_h7s3l8/nucleo_h7s3l8.dts @@ -217,7 +217,7 @@ status = "okay"; - mx25uw25645: xspi-nor-flash@0 { + ext_flash_ctrl: xspi-nor-flash@0 { compatible = "st,stm32-xspi-nor"; reg = <0>; size = ; /* 256Mbits */ @@ -227,29 +227,40 @@ four-byte-opcodes; status = "okay"; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x00000000 DT_SIZE_K(512)>; - }; - - slot1_partition: partition@80000 { - label = "image-1"; - reg = <0x0080000 DT_SIZE_K(512)>; - }; - - scratch_partition: partition@100000 { - label = "image-scratch"; - reg = <0x00100000 DT_SIZE_K(64)>; - }; - - storage_partition: partition@110000 { - label = "storage"; - reg = <0x00110000 DT_SIZE_K(64)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x70000000 DT_SIZE_M(32)>; + + ext_flash: mx25uw25645: xspi-nor-flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 DT_SIZE_M(32)>; + write-block-size = <1>; + erase-block-size = ; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: partition@0 { + label = "image-0"; + reg = <0x00000000 DT_SIZE_K(512)>; + }; + + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x0080000 DT_SIZE_K(512)>; + }; + + scratch_partition: partition@100000 { + label = "image-scratch"; + reg = <0x00100000 DT_SIZE_K(64)>; + }; + + storage_partition: partition@110000 { + label = "storage"; + reg = <0x00110000 DT_SIZE_K(64)>; + }; }; }; }; diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index 2f0a581d24bec..880ba83755e4b 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -680,10 +680,36 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, return 0; } +static enum clock_control_status stm32_clock_control_get_status(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)sub_system; + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == true) { + /* Gated clocks */ + if ((sys_read32(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus) & pclken->enr) + == pclken->enr) { + return CLOCK_CONTROL_STATUS_ON; + } else { + return CLOCK_CONTROL_STATUS_OFF; + } + } else { + /* Domain clock sources */ + if (enabled_clock(pclken->bus) == 0) { + return CLOCK_CONTROL_STATUS_ON; + } else { + return CLOCK_CONTROL_STATUS_OFF; + } + } +} + static DEVICE_API(clock_control, stm32_clock_control_api) = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, + .get_status = stm32_clock_control_get_status, .configure = stm32_clock_control_configure, }; @@ -788,6 +814,76 @@ static void stm32_clock_switch_to_hsi(void) } } +/* #defines used by set_up_plls() to re-configure only PLLs not used by XiP */ +#ifdef CONFIG_STM32_APP_IN_EXT_FLASH + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + +#define XIP_USE_PLL1 \ + (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) == LL_RCC_OSPI_CLKSOURCE_PLL1Q) +#define XIP_USE_PLL1P 0 +#define XIP_USE_PLL1Q XIP_USE_PLL1 + +#define XIP_USE_PLL2 \ + (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) == LL_RCC_OSPI_CLKSOURCE_PLL2R) +#define XIP_USE_PLL2R XIP_USE_PLL2 +#define XIP_USE_PLL2S 0 +#define XIP_USE_PLL2T 0 + +#elif defined(QUADSPI) + +#define XIP_USE_PLL1 \ + (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) == LL_RCC_QSPI_CLKSOURCE_PLL1Q) +#define XIP_USE_PLL1P 0 +#define XIP_USE_PLL1Q XIP_USE_PLL1 + +#define XIP_USE_PLL2 \ + (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) == LL_RCC_QSPI_CLKSOURCE_PLL2R) +#define XIP_USE_PLL2R XIP_USE_PLL2 +#define XIP_USE_PLL2S 0 +#define XIP_USE_PLL2T 0 + +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + +/* If PLL1 is used as SYSCLK, we can't switch to HSI during PLL reconfiguration, because of clock + * constraints: The XSPI AXI clock has to be greater or equal than the XSPI kernel clock. + * No need to check if XSPI is clocked by HCLK5 or not, PLL1(P) is blocked anyway */ +#define XIP_USE_PLL1 (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) +#define XIP_USE_PLL1P XIP_USE_PLL1 +#define XIP_USE_PLL1Q 0 + +#define XIP_USE_PLL2 \ + (LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2S || \ + LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2T || \ + LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2S || \ + LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2T) +#define XIP_USE_PLL2R 0 +#define XIP_USE_PLL2S \ + (LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2S || \ + LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2S) +#define XIP_USE_PLL2T \ + (LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2T || \ + LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2T) + +#else /* no OCTO/QUAD/X SPI */ + +#error "CONFIG_STM32_MEMMAP & CONFIG_STM32_APP_IN_EXT_FLASH defined but no XiP SPI peripheral found" + +#endif + +#else /* CONFIG_STM32_APP_IN_EXT_FLASH */ +/* Set all checks to false because XiP is not used */ + +#define XIP_USE_PLL1 0 +#define XIP_USE_PLL1P 0 +#define XIP_USE_PLL1Q 0 +#define XIP_USE_PLL2 0 +#define XIP_USE_PLL2R 0 +#define XIP_USE_PLL2S 0 +#define XIP_USE_PLL2T 0 + +#endif /* CONFIG_STM32_APP_IN_EXT_FLASH */ + __unused static int set_up_plls(void) { @@ -802,164 +898,161 @@ static int set_up_plls(void) * (Switching to HSI makes sure we have a SYSCLK source in * case we're currently running from the PLL we're about to * turn off and reconfigure.) - * + * But only if the PLL1 is not by (Q/O/X)SPI while in XiP. */ - if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { + if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1 && !XIP_USE_PLL1) { stm32_clock_switch_to_hsi(); LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); } -#if defined(CONFIG_STM32_MEMMAP) && defined(CONFIG_BOOTLOADER_MCUBOOT) - /* - * Don't disable PLL during application initialization - * that runs in memmap mode when (Q/O)SPI uses PLL - * as its clock source. - */ -#if defined(OCTOSPI1) || defined(OCTOSPI2) - if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL1Q) { + /* Only disable PLLs not used to clock (Q/O/X)SPI */ + if (!XIP_USE_PLL1) { LL_RCC_PLL1_Disable(); } - if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL2R) { + if (!XIP_USE_PLL2) { LL_RCC_PLL2_Disable(); } -#elif defined(QUADSPI) - if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL1Q) { - LL_RCC_PLL1_Disable(); - } - if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL2R) { - LL_RCC_PLL2_Disable(); - } -#else - LL_RCC_PLL1_Disable(); - LL_RCC_PLL2_Disable(); -#endif -#else - LL_RCC_PLL1_Disable(); - LL_RCC_PLL2_Disable(); -#endif LL_RCC_PLL3_Disable(); - /* Configure PLL source */ - +/* Configure PLL source only if not XiP*/ +#ifndef CONFIG_STM32_APP_IN_EXT_FLASH /* Can be HSE , HSI 64Mhz/HSIDIV, CSI 4MHz*/ - if (IS_ENABLED(STM32_PLL_SRC_HSE) || - IS_ENABLED(STM32_PLL2_SRC_HSE) || - IS_ENABLED(STM32_PLL3_SRC_HSE)) { + if (IS_ENABLED(STM32_PLL_SRC_HSE) || IS_ENABLED(STM32_PLL2_SRC_HSE) || + IS_ENABLED(STM32_PLL3_SRC_HSE)) { /* Main PLL configuration and activation */ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE); - } else if (IS_ENABLED(STM32_PLL_SRC_CSI) || - IS_ENABLED(STM32_PLL2_SRC_CSI) || - IS_ENABLED(STM32_PLL3_SRC_CSI)) { + } else if (IS_ENABLED(STM32_PLL_SRC_CSI) || IS_ENABLED(STM32_PLL2_SRC_CSI) || + IS_ENABLED(STM32_PLL3_SRC_CSI)) { /* Main PLL configuration and activation */ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_CSI); - } else if (IS_ENABLED(STM32_PLL_SRC_HSI) || - IS_ENABLED(STM32_PLL2_SRC_HSI) || - IS_ENABLED(STM32_PLL3_SRC_HSI)) { + } else if (IS_ENABLED(STM32_PLL_SRC_HSI) || IS_ENABLED(STM32_PLL2_SRC_HSI) || + IS_ENABLED(STM32_PLL3_SRC_HSI)) { /* Main PLL configuration and activation */ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI); } else { return -ENOTSUP; } +#endif #if defined(STM32_PLL_ENABLED) - r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range); - if (r < 0) { - return r; - } + /* use the isReady flag to skip reconfiguration if PLL was not disabled above */ + if (!LL_RCC_PLL1_IsReady()) { + r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range); + if (r < 0) { + return r; + } - vco_output_range = get_vco_output_range(vco_input_range); + vco_output_range = get_vco_output_range(vco_input_range); + + LL_RCC_PLL1_SetM(STM32_PLL_M_DIVISOR); - LL_RCC_PLL1_SetM(STM32_PLL_M_DIVISOR); + LL_RCC_PLL1_SetVCOInputRange(vco_input_range); + LL_RCC_PLL1_SetVCOOutputRange(vco_output_range); - LL_RCC_PLL1_SetVCOInputRange(vco_input_range); - LL_RCC_PLL1_SetVCOOutputRange(vco_output_range); + LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER); - LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER); + LL_RCC_PLL1FRACN_Disable(); + if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) { + LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE); + LL_RCC_PLL1FRACN_Enable(); + } - LL_RCC_PLL1FRACN_Disable(); - if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) { - LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE); - LL_RCC_PLL1FRACN_Enable(); + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1U) { + } } - if (IS_ENABLED(STM32_PLL_P_ENABLED)) { + /* Reconfigure PLL outputs only if enabled in DTS (and not used by XiP) */ + + if (IS_ENABLED(STM32_PLL_P_ENABLED) && !XIP_USE_PLL1P) { + LL_RCC_PLL1P_Disable(); LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR); LL_RCC_PLL1P_Enable(); } - if (IS_ENABLED(STM32_PLL_Q_ENABLED)) { + if (IS_ENABLED(STM32_PLL_Q_ENABLED) && !XIP_USE_PLL1Q) { + LL_RCC_PLL1Q_Disable(); LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR); LL_RCC_PLL1Q_Enable(); } if (IS_ENABLED(STM32_PLL_R_ENABLED)) { + LL_RCC_PLL1R_Disable(); LL_RCC_PLL1_SetR(STM32_PLL_R_DIVISOR); LL_RCC_PLL1R_Enable(); } #if defined(CONFIG_SOC_SERIES_STM32H7RSX) if (IS_ENABLED(STM32_PLL_S_ENABLED)) { + LL_RCC_PLL1S_Disable(); LL_RCC_PLL1_SetS(STM32_PLL_S_DIVISOR); LL_RCC_PLL1S_Enable(); } #endif /* CONFIG_SOC_SERIES_STM32H7RSX */ - LL_RCC_PLL1_Enable(); - while (LL_RCC_PLL1_IsReady() != 1U) { - } #endif /* STM32_PLL_ENABLED */ #if defined(STM32_PLL2_ENABLED) - r = get_vco_input_range(STM32_PLL2_M_DIVISOR, &vco_input_range); - if (r < 0) { - return r; - } + /* use the isReady flag to skip reconfiguration if PLL was not disabled above */ + if (!LL_RCC_PLL2_IsReady()) { + r = get_vco_input_range(STM32_PLL2_M_DIVISOR, &vco_input_range); + if (r < 0) { + return r; + } - vco_output_range = get_vco_output_range(vco_input_range); + vco_output_range = get_vco_output_range(vco_input_range); + + LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR); - LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR); + LL_RCC_PLL2_SetVCOInputRange(vco_input_range); + LL_RCC_PLL2_SetVCOOutputRange(vco_output_range); - LL_RCC_PLL2_SetVCOInputRange(vco_input_range); - LL_RCC_PLL2_SetVCOOutputRange(vco_output_range); + LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER); - LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER); + LL_RCC_PLL2FRACN_Disable(); + if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) { + LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE); + LL_RCC_PLL2FRACN_Enable(); + } - LL_RCC_PLL2FRACN_Disable(); - if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) { - LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE); - LL_RCC_PLL2FRACN_Enable(); + LL_RCC_PLL2_Enable(); + while (LL_RCC_PLL2_IsReady() != 1U) { + } } + /* Reconfigure PLL outputs only if enabled in DTS (and not used by XiP) */ + if (IS_ENABLED(STM32_PLL2_P_ENABLED)) { + LL_RCC_PLL2P_Disable(); LL_RCC_PLL2_SetP(STM32_PLL2_P_DIVISOR); LL_RCC_PLL2P_Enable(); } if (IS_ENABLED(STM32_PLL2_Q_ENABLED)) { + LL_RCC_PLL2Q_Disable(); LL_RCC_PLL2_SetQ(STM32_PLL2_Q_DIVISOR); LL_RCC_PLL2Q_Enable(); } - if (IS_ENABLED(STM32_PLL2_R_ENABLED)) { + if (IS_ENABLED(STM32_PLL2_R_ENABLED) && !XIP_USE_PLL2R) { + LL_RCC_PLL2R_Disable(); LL_RCC_PLL2_SetR(STM32_PLL2_R_DIVISOR); LL_RCC_PLL2R_Enable(); } #if defined(CONFIG_SOC_SERIES_STM32H7RSX) - if (IS_ENABLED(STM32_PLL2_S_ENABLED)) { + if (IS_ENABLED(STM32_PLL2_S_ENABLED) && !XIP_USE_PLL2S) { + LL_RCC_PLL2S_Disable(); LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR); LL_RCC_PLL2S_Enable(); } - if (IS_ENABLED(STM32_PLL2_T_ENABLED)) { + if (IS_ENABLED(STM32_PLL2_T_ENABLED) && !XIP_USE_PLL2T) { + LL_RCC_PLL2T_Disable(); LL_RCC_PLL2_SetT(STM32_PLL2_T_DIVISOR); LL_RCC_PLL2T_Enable(); } - #endif /* CONFIG_SOC_SERIES_STM32H7RSX */ - LL_RCC_PLL2_Enable(); - while (LL_RCC_PLL2_IsReady() != 1U) { - } #endif /* STM32_PLL2_ENABLED */ @@ -1012,7 +1105,7 @@ static int set_up_plls(void) #endif /* STM32_PLL3_ENABLED */ -#else +#else /* STM32_PLL_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */ /* Init PLL source to None */ LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_NONE); diff --git a/drivers/flash/flash_stm32_xspi.c b/drivers/flash/flash_stm32_xspi.c index feef05889f271..962b051107bac 100644 --- a/drivers/flash/flash_stm32_xspi.c +++ b/drivers/flash/flash_stm32_xspi.c @@ -2118,9 +2118,14 @@ static int flash_stm32_xspi_init(const struct device *dev) return -ENOTSUP; } #if defined(CONFIG_SOC_SERIES_STM32H7RSX) - LL_PWR_EnableXSPIM2(); __HAL_RCC_SBS_CLK_ENABLE(); - LL_SBS_EnableXSPI2SpeedOptim(); + if (dev_data->hxspi.Instance == XSPI1) { + LL_PWR_EnableXSPIM1(); + LL_SBS_EnableXSPI1SpeedOptim(); + } else if (dev_data->hxspi.Instance == XSPI2) { + LL_PWR_EnableXSPIM2(); + LL_SBS_EnableXSPI2SpeedOptim(); + } #endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Signals configuration */ diff --git a/dts/arm/st/h7rs/stm32h7rs.dtsi b/dts/arm/st/h7rs/stm32h7rs.dtsi index 5045a22be0521..aa968c5fd5d52 100644 --- a/dts/arm/st/h7rs/stm32h7rs.dtsi +++ b/dts/arm/st/h7rs/stm32h7rs.dtsi @@ -111,7 +111,7 @@ compatible = "st,stm32h7-hsi-clock"; hsi-div = <1>; /* HSI RC: 64MHz, hsi_clk = 64MHz */ clock-frequency = ; - status = "disabled"; + status = "okay"; /* controller reset default is on */ }; clk_hsi48: clk-hsi48 { diff --git a/samples/sysbuild/with_mcuboot/boards/nucleo_h7s3l8.overlay b/samples/sysbuild/with_mcuboot/boards/nucleo_h7s3l8.overlay index 7af649b38c656..cce6f69c82351 100644 --- a/samples/sysbuild/with_mcuboot/boards/nucleo_h7s3l8.overlay +++ b/samples/sysbuild/with_mcuboot/boards/nucleo_h7s3l8.overlay @@ -11,7 +11,7 @@ / { chosen { zephyr,flash = &mx25uw25645; - zephyr,flash-controller = &mx25uw25645; + zephyr,flash-controller = &ext_flash_ctrl; zephyr,code-partition = &slot0_partition; }; }; diff --git a/soc/st/stm32/stm32h7rsx/soc.c b/soc/st/stm32/stm32h7rsx/soc.c index 7d19774cc2cd2..0bca9d7c0f8a7 100644 --- a/soc/st/stm32/stm32h7rsx/soc.c +++ b/soc/st/stm32/stm32h7rsx/soc.c @@ -55,9 +55,14 @@ void soc_early_init_hook(void) #else LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); #endif + +/* The chain-loaded application must not switch to LL_PWR_REGU_VOLTAGE_SCALE1, because the + * bootloader most likely setup a fast core clock. */ +#if !defined(CONFIG_STM32_APP_IN_EXT_FLASH) LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { } +#endif /* defined(CONFIG_STM32_APP_IN_EXT_FLASH) */ #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioo), okay) || DT_NODE_HAS_STATUS(DT_NODELABEL(gpiop), okay) LL_PWR_EnableXSPIM1(); /* Required for powering GPIO O and P */