Skip to content

Commit 90bc050

Browse files
committed
drivers: clock: stm32_ll_h7: Disable clock configuration for XiP
Extent set_up_plls() to check if we are running the app in XiP and only reconfigure PLLs and PLL outputs when they are not used in the clock path of Q/O/X-SPI or have other constraints like XSPI AXI clock >= XSPI kernel clock. Signed-off-by: Thomas Decker <[email protected]>
1 parent 025fd7e commit 90bc050

File tree

1 file changed

+143
-76
lines changed

1 file changed

+143
-76
lines changed

drivers/clock_control/clock_stm32_ll_h7.c

Lines changed: 143 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,76 @@ static void stm32_clock_switch_to_hsi(void)
814814
}
815815
}
816816

817+
/* #defines used by set_up_plls() to re-configure only PLLs not used by XiP */
818+
#ifdef CONFIG_STM32_APP_IN_EXT_FLASH
819+
820+
#if defined(OCTOSPI1) || defined(OCTOSPI2)
821+
822+
#define XIP_USE_PLL1 \
823+
(LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) == LL_RCC_OSPI_CLKSOURCE_PLL1Q)
824+
#define XIP_USE_PLL1P 0
825+
#define XIP_USE_PLL1Q XIP_USE_PLL1
826+
827+
#define XIP_USE_PLL2 \
828+
(LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) == LL_RCC_OSPI_CLKSOURCE_PLL2R)
829+
#define XIP_USE_PLL2R XIP_USE_PLL2
830+
#define XIP_USE_PLL2S 0
831+
#define XIP_USE_PLL2T 0
832+
833+
#elif defined(QUADSPI)
834+
835+
#define XIP_USE_PLL1 \
836+
(LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) == LL_RCC_QSPI_CLKSOURCE_PLL1Q)
837+
#define XIP_USE_PLL1P 0
838+
#define XIP_USE_PLL1Q XIP_USE_PLL1
839+
840+
#define XIP_USE_PLL2 \
841+
(LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) == LL_RCC_QSPI_CLKSOURCE_PLL2R)
842+
#define XIP_USE_PLL2R XIP_USE_PLL2
843+
#define XIP_USE_PLL2S 0
844+
#define XIP_USE_PLL2T 0
845+
846+
#elif defined(CONFIG_SOC_SERIES_STM32H7RSX)
847+
848+
/* If PLL1 is used as SYSCLK, we can't switch to HSI during PLL reconfiguration, because of clock
849+
* constraints: The XSPI AXI clock has to be greater or equal than the XSPI kernel clock.
850+
* No need to check if XSPI is clocked by HCLK5 or not, PLL1(P) is blocked anyway */
851+
#define XIP_USE_PLL1 (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1)
852+
#define XIP_USE_PLL1P XIP_USE_PLL1
853+
#define XIP_USE_PLL1Q 0
854+
855+
#define XIP_USE_PLL2 \
856+
(LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2S || \
857+
LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2T || \
858+
LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2S || \
859+
LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2T)
860+
#define XIP_USE_PLL2R 0
861+
#define XIP_USE_PLL2S \
862+
(LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2S || \
863+
LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2S)
864+
#define XIP_USE_PLL2T \
865+
(LL_RCC_GetXSPI1SwitchPosition() == LL_RCC_SWP_XSPI1_PLL2T || \
866+
LL_RCC_GetXSPI2SwitchPosition() == LL_RCC_SWP_XSPI2_PLL2T)
867+
868+
#else /* no OCTO/QUAD/X SPI */
869+
870+
#error "CONFIG_STM32_MEMMAP & CONFIG_STM32_APP_IN_EXT_FLASH defined but no XiP SPI peripheral found"
871+
872+
#endif
873+
874+
#else /* CONFIG_STM32_APP_IN_EXT_FLASH */
875+
/* Set all checks to false because XiP is not used */
876+
877+
#define XIP_USE_PLL1 0
878+
#define XIP_USE_PLL1P 0
879+
#define XIP_USE_PLL1Q 0
880+
#define XIP_USE_PLL2 0
881+
#define XIP_USE_PLL2R 0
882+
#define XIP_USE_PLL2S 0
883+
#define XIP_USE_PLL2T 0
884+
885+
#endif /* CONFIG_STM32_APP_IN_EXT_FLASH */
886+
817887
__unused
818888
static int set_up_plls(void)
819889
{
@@ -828,164 +898,161 @@ static int set_up_plls(void)
828898
* (Switching to HSI makes sure we have a SYSCLK source in
829899
* case we're currently running from the PLL we're about to
830900
* turn off and reconfigure.)
831-
*
901+
* But only if the PLL1 is not by (Q/O/X)SPI while in XiP.
832902
*/
833-
if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) {
903+
if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1 && !XIP_USE_PLL1) {
834904
stm32_clock_switch_to_hsi();
835905
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
836906
}
837907

838-
#if defined(CONFIG_STM32_MEMMAP) && defined(CONFIG_BOOTLOADER_MCUBOOT)
839-
/*
840-
* Don't disable PLL during application initialization
841-
* that runs in memmap mode when (Q/O)SPI uses PLL
842-
* as its clock source.
843-
*/
844-
#if defined(OCTOSPI1) || defined(OCTOSPI2)
845-
if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL1Q) {
908+
/* Only disable PLLs not used to clock (Q/O/X)SPI */
909+
if (!XIP_USE_PLL1) {
846910
LL_RCC_PLL1_Disable();
847911
}
848-
if (LL_RCC_GetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE) != LL_RCC_OSPI_CLKSOURCE_PLL2R) {
912+
if (!XIP_USE_PLL2) {
849913
LL_RCC_PLL2_Disable();
850914
}
851-
#elif defined(QUADSPI)
852-
if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL1Q) {
853-
LL_RCC_PLL1_Disable();
854-
}
855-
if (LL_RCC_GetQSPIClockSource(LL_RCC_QSPI_CLKSOURCE) != LL_RCC_QSPI_CLKSOURCE_PLL2R) {
856-
LL_RCC_PLL2_Disable();
857-
}
858-
#else
859-
LL_RCC_PLL1_Disable();
860-
LL_RCC_PLL2_Disable();
861-
#endif
862-
#else
863-
LL_RCC_PLL1_Disable();
864-
LL_RCC_PLL2_Disable();
865-
#endif
866915
LL_RCC_PLL3_Disable();
867916

868-
/* Configure PLL source */
869-
917+
/* Configure PLL source only if not XiP*/
918+
#ifndef CONFIG_STM32_APP_IN_EXT_FLASH
870919
/* Can be HSE , HSI 64Mhz/HSIDIV, CSI 4MHz*/
871-
if (IS_ENABLED(STM32_PLL_SRC_HSE) ||
872-
IS_ENABLED(STM32_PLL2_SRC_HSE) ||
873-
IS_ENABLED(STM32_PLL3_SRC_HSE)) {
920+
if (IS_ENABLED(STM32_PLL_SRC_HSE) || IS_ENABLED(STM32_PLL2_SRC_HSE) ||
921+
IS_ENABLED(STM32_PLL3_SRC_HSE)) {
874922
/* Main PLL configuration and activation */
875923
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
876-
} else if (IS_ENABLED(STM32_PLL_SRC_CSI) ||
877-
IS_ENABLED(STM32_PLL2_SRC_CSI) ||
878-
IS_ENABLED(STM32_PLL3_SRC_CSI)) {
924+
} else if (IS_ENABLED(STM32_PLL_SRC_CSI) || IS_ENABLED(STM32_PLL2_SRC_CSI) ||
925+
IS_ENABLED(STM32_PLL3_SRC_CSI)) {
879926
/* Main PLL configuration and activation */
880927
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_CSI);
881-
} else if (IS_ENABLED(STM32_PLL_SRC_HSI) ||
882-
IS_ENABLED(STM32_PLL2_SRC_HSI) ||
883-
IS_ENABLED(STM32_PLL3_SRC_HSI)) {
928+
} else if (IS_ENABLED(STM32_PLL_SRC_HSI) || IS_ENABLED(STM32_PLL2_SRC_HSI) ||
929+
IS_ENABLED(STM32_PLL3_SRC_HSI)) {
884930
/* Main PLL configuration and activation */
885931
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
886932
} else {
887933
return -ENOTSUP;
888934
}
935+
#endif
889936

890937
#if defined(STM32_PLL_ENABLED)
891-
r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range);
892-
if (r < 0) {
893-
return r;
894-
}
938+
/* use the isReady flag to skip reconfiguration if PLL was not disabled above */
939+
if (!LL_RCC_PLL1_IsReady()) {
940+
r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range);
941+
if (r < 0) {
942+
return r;
943+
}
895944

896-
vco_output_range = get_vco_output_range(vco_input_range);
945+
vco_output_range = get_vco_output_range(vco_input_range);
946+
947+
LL_RCC_PLL1_SetM(STM32_PLL_M_DIVISOR);
897948

898-
LL_RCC_PLL1_SetM(STM32_PLL_M_DIVISOR);
949+
LL_RCC_PLL1_SetVCOInputRange(vco_input_range);
950+
LL_RCC_PLL1_SetVCOOutputRange(vco_output_range);
899951

900-
LL_RCC_PLL1_SetVCOInputRange(vco_input_range);
901-
LL_RCC_PLL1_SetVCOOutputRange(vco_output_range);
952+
LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER);
902953

903-
LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER);
954+
LL_RCC_PLL1FRACN_Disable();
955+
if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) {
956+
LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE);
957+
LL_RCC_PLL1FRACN_Enable();
958+
}
904959

905-
LL_RCC_PLL1FRACN_Disable();
906-
if (IS_ENABLED(STM32_PLL_FRACN_ENABLED)) {
907-
LL_RCC_PLL1_SetFRACN(STM32_PLL_FRACN_VALUE);
908-
LL_RCC_PLL1FRACN_Enable();
960+
LL_RCC_PLL1_Enable();
961+
while (LL_RCC_PLL1_IsReady() != 1U) {
962+
}
909963
}
910964

911-
if (IS_ENABLED(STM32_PLL_P_ENABLED)) {
965+
/* Reconfigure PLL outputs only if enabled in DTS (and not used by XiP) */
966+
967+
if (IS_ENABLED(STM32_PLL_P_ENABLED) && !XIP_USE_PLL1P) {
968+
LL_RCC_PLL1P_Disable();
912969
LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR);
913970
LL_RCC_PLL1P_Enable();
914971
}
915972

916-
if (IS_ENABLED(STM32_PLL_Q_ENABLED)) {
973+
if (IS_ENABLED(STM32_PLL_Q_ENABLED) && !XIP_USE_PLL1Q) {
974+
LL_RCC_PLL1Q_Disable();
917975
LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR);
918976
LL_RCC_PLL1Q_Enable();
919977
}
920978

921979
if (IS_ENABLED(STM32_PLL_R_ENABLED)) {
980+
LL_RCC_PLL1R_Disable();
922981
LL_RCC_PLL1_SetR(STM32_PLL_R_DIVISOR);
923982
LL_RCC_PLL1R_Enable();
924983
}
925984

926985
#if defined(CONFIG_SOC_SERIES_STM32H7RSX)
927986
if (IS_ENABLED(STM32_PLL_S_ENABLED)) {
987+
LL_RCC_PLL1S_Disable();
928988
LL_RCC_PLL1_SetS(STM32_PLL_S_DIVISOR);
929989
LL_RCC_PLL1S_Enable();
930990
}
931991
#endif /* CONFIG_SOC_SERIES_STM32H7RSX */
932-
LL_RCC_PLL1_Enable();
933-
while (LL_RCC_PLL1_IsReady() != 1U) {
934-
}
935992

936993
#endif /* STM32_PLL_ENABLED */
937994

938995
#if defined(STM32_PLL2_ENABLED)
939-
r = get_vco_input_range(STM32_PLL2_M_DIVISOR, &vco_input_range);
940-
if (r < 0) {
941-
return r;
942-
}
996+
/* use the isReady flag to skip reconfiguration if PLL was not disabled above */
997+
if (!LL_RCC_PLL2_IsReady()) {
998+
r = get_vco_input_range(STM32_PLL2_M_DIVISOR, &vco_input_range);
999+
if (r < 0) {
1000+
return r;
1001+
}
9431002

944-
vco_output_range = get_vco_output_range(vco_input_range);
1003+
vco_output_range = get_vco_output_range(vco_input_range);
9451004

946-
LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR);
1005+
LL_RCC_PLL2_SetM(STM32_PLL2_M_DIVISOR);
9471006

948-
LL_RCC_PLL2_SetVCOInputRange(vco_input_range);
949-
LL_RCC_PLL2_SetVCOOutputRange(vco_output_range);
1007+
LL_RCC_PLL2_SetVCOInputRange(vco_input_range);
1008+
LL_RCC_PLL2_SetVCOOutputRange(vco_output_range);
9501009

951-
LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER);
1010+
LL_RCC_PLL2_SetN(STM32_PLL2_N_MULTIPLIER);
9521011

953-
LL_RCC_PLL2FRACN_Disable();
954-
if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) {
955-
LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE);
956-
LL_RCC_PLL2FRACN_Enable();
1012+
LL_RCC_PLL2FRACN_Disable();
1013+
if (IS_ENABLED(STM32_PLL2_FRACN_ENABLED)) {
1014+
LL_RCC_PLL2_SetFRACN(STM32_PLL2_FRACN_VALUE);
1015+
LL_RCC_PLL2FRACN_Enable();
1016+
}
1017+
1018+
LL_RCC_PLL2_Enable();
1019+
while (LL_RCC_PLL2_IsReady() != 1U) {
1020+
}
9571021
}
9581022

1023+
/* Reconfigure PLL outputs only if enabled in DTS (and not used by XiP) */
1024+
9591025
if (IS_ENABLED(STM32_PLL2_P_ENABLED)) {
1026+
LL_RCC_PLL2P_Disable();
9601027
LL_RCC_PLL2_SetP(STM32_PLL2_P_DIVISOR);
9611028
LL_RCC_PLL2P_Enable();
9621029
}
9631030

9641031
if (IS_ENABLED(STM32_PLL2_Q_ENABLED)) {
1032+
LL_RCC_PLL2Q_Disable();
9651033
LL_RCC_PLL2_SetQ(STM32_PLL2_Q_DIVISOR);
9661034
LL_RCC_PLL2Q_Enable();
9671035
}
9681036

969-
if (IS_ENABLED(STM32_PLL2_R_ENABLED)) {
1037+
if (IS_ENABLED(STM32_PLL2_R_ENABLED) && !XIP_USE_PLL2R) {
1038+
LL_RCC_PLL2R_Disable();
9701039
LL_RCC_PLL2_SetR(STM32_PLL2_R_DIVISOR);
9711040
LL_RCC_PLL2R_Enable();
9721041
}
9731042

9741043
#if defined(CONFIG_SOC_SERIES_STM32H7RSX)
975-
if (IS_ENABLED(STM32_PLL2_S_ENABLED)) {
1044+
if (IS_ENABLED(STM32_PLL2_S_ENABLED) && !XIP_USE_PLL2S) {
1045+
LL_RCC_PLL2S_Disable();
9761046
LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR);
9771047
LL_RCC_PLL2S_Enable();
9781048
}
9791049

980-
if (IS_ENABLED(STM32_PLL2_T_ENABLED)) {
1050+
if (IS_ENABLED(STM32_PLL2_T_ENABLED) && !XIP_USE_PLL2T) {
1051+
LL_RCC_PLL2T_Disable();
9811052
LL_RCC_PLL2_SetT(STM32_PLL2_T_DIVISOR);
9821053
LL_RCC_PLL2T_Enable();
9831054
}
984-
9851055
#endif /* CONFIG_SOC_SERIES_STM32H7RSX */
986-
LL_RCC_PLL2_Enable();
987-
while (LL_RCC_PLL2_IsReady() != 1U) {
988-
}
9891056

9901057
#endif /* STM32_PLL2_ENABLED */
9911058

@@ -1038,7 +1105,7 @@ static int set_up_plls(void)
10381105

10391106
#endif /* STM32_PLL3_ENABLED */
10401107

1041-
#else
1108+
#else /* STM32_PLL_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */
10421109
/* Init PLL source to None */
10431110
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_NONE);
10441111

0 commit comments

Comments
 (0)