diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 949d87d1a66..43f86e8c7d3 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -38,6 +38,8 @@ if(CONFIG_SOC_SERIES_STM32MP1X) zephyr_library_sources(clock_stm32_ll_mp1.c) elseif(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources(clock_stm32_ll_h7.c) +elseif(CONFIG_SOC_SERIES_STM32H7RSX) + zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) elseif(CONFIG_SOC_SERIES_STM32U5X) diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index c5f4f273646..484b331db7c 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -9,7 +9,7 @@ menuconfig CLOCK_CONTROL_STM32_CUBE depends on SOC_FAMILY_STM32 select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help @@ -69,6 +69,7 @@ config CLOCK_STM32_MCO1_SRC_LSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSE as source of MCO1 @@ -80,6 +81,7 @@ config CLOCK_STM32_MCO1_SRC_HSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO1 @@ -102,6 +104,7 @@ config CLOCK_STM32_MCO1_SRC_HSI SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI as source of MCO1 @@ -116,6 +119,7 @@ config CLOCK_STM32_MCO1_SRC_HSI48 bool "HSI48" depends on SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI48 as source of MCO1 @@ -129,6 +133,7 @@ config CLOCK_STM32_MCO1_SRC_PLLCLK config CLOCK_STM32_MCO1_SRC_PLLQCLK bool "PLLQ" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLQ as source of MCO1 @@ -171,11 +176,12 @@ config CLOCK_STM32_MCO1_DIV SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X range 1 16 if SOC_SERIES_STM32L4X help Prescaler for MCO1 output clock @@ -194,6 +200,7 @@ config CLOCK_STM32_MCO2_SRC_SYSCLK depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use SYSCLK as source of MCO2 @@ -209,6 +216,7 @@ config CLOCK_STM32_MCO2_SRC_HSE depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO2 @@ -216,6 +224,7 @@ config CLOCK_STM32_MCO2_SRC_HSE config CLOCK_STM32_MCO2_SRC_LSI bool "LSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSI as source of MCO2 @@ -223,6 +232,7 @@ config CLOCK_STM32_MCO2_SRC_LSI config CLOCK_STM32_MCO2_SRC_CSI bool "CSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use CSI as source of MCO2 @@ -236,6 +246,7 @@ config CLOCK_STM32_MCO2_SRC_PLLCLK config CLOCK_STM32_MCO2_SRC_PLLPCLK bool "PLLPCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLPCLK as source of MC02 @@ -243,6 +254,7 @@ config CLOCK_STM32_MCO2_SRC_PLLPCLK config CLOCK_STM32_MCO2_SRC_PLL2PCLK bool "PLL2PCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLL2PCLK as source of MC02 @@ -254,11 +266,12 @@ config CLOCK_STM32_MCO2_DIV SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H5X || \ - SOC_SERIES_STM32H7X \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X help Prescaler for MCO2 output clock diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index b11e2b5c9f5..c9b7653556f 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -21,7 +21,11 @@ /* Macros to fill up prescaler values */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v +#else #define z_hsi_divider(v) LL_RCC_HSI_DIV ## v +#endif #define hsi_divider(v) z_hsi_divider(v) #define z_sysclk_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v @@ -42,6 +46,9 @@ #define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v #define apb4_prescaler(v) z_apb4_prescaler(v) +#define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v +#define apb5_prescaler(v) z_apb5_prescaler(v) + /* Macro to check for clock feasibility */ /* It is Cortex M7's responsibility to setup clock tree */ /* This check should only be performed for the M7 core code */ @@ -81,12 +88,21 @@ #endif /* ARM Sys CPU Clock before HPRE prescaler */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) +#define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) +#define APB1_FREQ ((AHB_FREQ)/(STM32_PPRE1)) +#define APB2_FREQ ((AHB_FREQ)/(STM32_PPRE2)) +#define APB4_FREQ ((AHB_FREQ)/(STM32_PPRE4)) +#define APB5_FREQ ((AHB_FREQ)/(STM32_PPRE5)) +#else #define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) #define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) #define APB1_FREQ ((AHB_FREQ)/(STM32_D2PPRE1)) #define APB2_FREQ ((AHB_FREQ)/(STM32_D2PPRE2)) #define APB3_FREQ ((AHB_FREQ)/(STM32_D1PPRE)) #define APB4_FREQ ((AHB_FREQ)/(STM32_D3PPRE)) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Datasheet maximum frequency definitions */ #if defined(CONFIG_SOC_STM32H743XX) ||\ @@ -112,6 +128,11 @@ #define SYSCLK_FREQ_MAX 280000000UL #define AHB_FREQ_MAX 280000000UL #define APBx_FREQ_MAX 140000000UL +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* All h7RS SoC with maximum 500MHz SYSCLK (refer to Datasheet DS14359 rev 1) */ +#define SYSCLK_FREQ_MAX 500000000UL +#define AHB_FREQ_MAX 250000000UL +#define APBx_FREQ_MAX 125000000UL #else /* Default: All h7 SoC with maximum 280MHz SYSCLK */ #define SYSCLK_FREQ_MAX 280000000UL @@ -154,7 +175,7 @@ * So, changing this prescaler is not allowed until it is made possible to * use them independently in zephyr clock subsystem. */ -#error "D1CPRE presacler can't be higher than 1" +#error "D1CPRE prescaler can't be higher than 1" #endif #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -255,7 +276,11 @@ static int32_t prepare_regulator_voltage_scale(void) /* Make sure to put the CPU in highest Voltage scale during clock configuration */ /* Highest voltage is SCALE0 */ LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { +#endif } return 0; } @@ -290,8 +315,12 @@ static int32_t optimize_regulator_voltage_scale(uint32_t sysclk_freq) LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); #endif LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { - } +#endif + }; return 0; } @@ -448,10 +477,17 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, #else uint32_t ahb_clock = get_bus_clock(SystemCoreClock, STM32_HPRE); #endif +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_PPRE1); + uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_PPRE2); + uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_PPRE4); + uint32_t apb5_clock = get_bus_clock(ahb_clock, STM32_PPRE5); +#else uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_D2PPRE1); uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_D2PPRE2); uint32_t apb3_clock = get_bus_clock(ahb_clock, STM32_D1PPRE); uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_D3PPRE); +#endif ARG_UNUSED(clock); @@ -469,12 +505,22 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, case STM32_CLOCK_BUS_APB2: *rate = apb2_clock; break; +#if !defined(CONFIG_SOC_SERIES_STM32H7RSX) case STM32_CLOCK_BUS_APB3: *rate = apb3_clock; break; +#endif /* !CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_CLOCK_BUS_APB4: *rate = apb4_clock; break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_CLOCK_BUS_APB5: + *rate = apb5_clock; + break; + case STM32_CLOCK_BUS_AHB5: + *rate = ahb_clock; + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_SRC_SYSCLK: *rate = get_hclk_frequency(); break; @@ -522,6 +568,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL_N_MULTIPLIER, STM32_PLL_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL1_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_S_DIVISOR); + break; + /* PLL 1 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL_ENABLED */ #if defined(STM32_PLL2_ENABLED) case STM32_SRC_PLL2_P: @@ -542,6 +597,20 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL2_N_MULTIPLIER, STM32_PLL2_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL2_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_S_DIVISOR); + break; + case STM32_SRC_PLL2_T: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_T_DIVISOR); + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL2_ENABLED */ #if defined(STM32_PLL3_ENABLED) case STM32_SRC_PLL3_P: @@ -562,6 +631,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL3_N_MULTIPLIER, STM32_PLL3_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL3_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL3_M_DIVISOR, + STM32_PLL3_N_MULTIPLIER, + STM32_PLL3_S_DIVISOR); + break; + /* PLL 3 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL3_ENABLED */ default: return -ENOTSUP; @@ -739,6 +817,12 @@ static int set_up_plls(void) LL_RCC_PLL1R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL_S_ENABLED)) { + 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) { } @@ -777,6 +861,18 @@ static int set_up_plls(void) LL_RCC_PLL2R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL2_S_ENABLED)) { + LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR); + LL_RCC_PLL2S_Enable(); + } + + if (IS_ENABLED(STM32_PLL2_T_ENABLED)) { + 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) { } @@ -815,6 +911,13 @@ static int set_up_plls(void) LL_RCC_PLL3R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL3_S_ENABLED)) { + LL_RCC_PLL3_SetS(STM32_PLL3_S_DIVISOR); + LL_RCC_PLL3S_Enable(); + } + +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL3_Enable(); while (LL_RCC_PLL3_IsReady() != 1U) { } @@ -830,6 +933,91 @@ static int set_up_plls(void) return 0; } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* adapted from the stm32cube SystemCoreClockUpdate*/ +void stm32_system_clock_update(void) +{ + uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc; + float_t pllfracn, pllvco; + + /* Get SYSCLK source */ + switch (RCC->CFGR & RCC_CFGR_SWS) { + case 0x00: /* HSI used as system clock source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) + >> RCC_CR_HSIDIV_Pos)); + break; + + case 0x08: /* CSI used as system clock source */ + sysclk = CSI_VALUE; + break; + + case 0x10: /* HSE used as system clock source */ + sysclk = HSE_VALUE; + break; + + case 0x18: /* PLL1 used as system clock source */ + /* + * PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN + * SYSCLK = PLL1_VCO / PLL1R + */ + pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC); + pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos); + + if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U) { + pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN) + >> RCC_PLL1FRACR_FRACN_Pos)); + } else { + pllfracn = (float_t)0U; + } + + if (pllm != 0U) { + switch (pllsource) { + case 0x02: /* HSE used as PLL1 clock source */ + pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x01: /* CSI used as PLL1 clock source */ + pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x00: /* HSI used as PLL1 clock source */ + default: + hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> + RCC_CR_HSIDIV_Pos)); + pllvco = ((float_t)hsivalue / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + } + + pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >> + RCC_PLL1DIVR1_DIVP_Pos) + 1U); + sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp); + } else { + sysclk = 0U; + } + break; + + default: /* Unexpected, default to HSI used as system clk source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos)); + break; + } + + /* system clock frequency : CM7 CPU frequency */ + core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE); + + if (core_presc >= 8U) { + SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U)); + } else { + SystemCoreClock = sysclk; + } +} +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ + int stm32_clock_control_init(const struct device *dev) { int r = 0; @@ -843,10 +1031,10 @@ int stm32_clock_control_init(const struct device *dev) defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) || \ defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_HSEM); -#else +#elif !defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* The stm32h7RS serie has no HSEM peripheral */ LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM); #endif - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); /* Configure MCO1/MCO2 based on Kconfig */ @@ -871,22 +1059,38 @@ int stm32_clock_control_init(const struct device *dev) STM32_HPRE); /* Set flash latency */ + /* AHB/AXI/HCLK clock is SYSCLK / HPRE */ /* If freq increases, set flash latency before any clock setting */ if (new_hclk_freq > old_hclk_freq) { LL_SetFlashLatency(new_hclk_freq); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* + * The default Flash latency is 3 WS which is not enough, + * set higher and correct later if needed + */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_6); +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Preset the prescalers prior to choosing SYSCLK */ /* Prevents APB clock to go over limits */ /* Set buses (Sys,AHB, APB1, APB2 & APB4) prescalers */ LL_RCC_SetSysPrescaler(sysclk_prescaler(STM32_D1CPRE)); LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_HPRE)); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_PPRE1)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_PPRE2)); + LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_PPRE4)); + LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_PPRE5)); + +#else LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_D2PPRE1)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_D2PPRE2)); LL_RCC_SetAPB3Prescaler(apb3_prescaler(STM32_D1PPRE)); LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_D3PPRE)); +#endif /* Set up sys clock */ if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { /* Set PLL1 as System Clock Source */ diff --git a/drivers/clock_control/clock_stm32_ll_mco.h b/drivers/clock_control/clock_stm32_ll_mco.h index d98c4a116e8..b526f13a1b2 100644 --- a/drivers/clock_control/clock_stm32_ll_mco.h +++ b/drivers/clock_control/clock_stm32_ll_mco.h @@ -33,7 +33,8 @@ #elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLQCLK #if (CONFIG_SOC_SERIES_STM32G0X || CONFIG_SOC_SERIES_STM32WLX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLQCLK - #elif (CONFIG_SOC_SERIES_STM32H5X || CONFIG_SOC_SERIES_STM32H7X) + #elif (CONFIG_SOC_SERIES_STM32H5X || \ + CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H7RSX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL1QCLK #else #error "PLLQCLK is not a valid clock source on your SOC" diff --git a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml index 0d03cc7272a..cb2980dd39c 100644 --- a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml +++ b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml @@ -30,11 +30,11 @@ properties: div-s: type: int description: | - PLL division factor for pllx_s_ck + PLL division factor for pllx_s_ck : valid for PLL1, 2, 3 Valid range: 1 - 8 div-t: type: int description: | - PLL division factor for pllx_t_ck + PLL division factor for pllx_t_ck : valid for PLL2 Valid range: 1 - 8 diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index 062fae034e3..a9ce911e5c7 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -44,6 +44,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32H7X) #include +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +#include #elif defined(CONFIG_SOC_SERIES_STM32U5X) #include #elif defined(CONFIG_SOC_SERIES_STM32WBAX) @@ -61,6 +63,7 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB5_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb5_prescaler) #define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) #define STM32_AHB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb4_prescaler) @@ -86,13 +89,22 @@ #define STM32_ADC12_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc12_prescaler) #define STM32_ADC34_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc34_prescaler) -/** STM2H7 specifics RCC dividers */ +/** STM2H7RS specific RCC dividers */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), dcpre) +#define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) +#define STM32_PPRE1 DT_PROP(DT_NODELABEL(rcc), ppre1) +#define STM32_PPRE2 DT_PROP(DT_NODELABEL(rcc), ppre2) +#define STM32_PPRE4 DT_PROP(DT_NODELABEL(rcc), ppre4) +#define STM32_PPRE5 DT_PROP(DT_NODELABEL(rcc), ppre5) +#else #define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), d1cpre) #define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) #define STM32_D2PPRE1 DT_PROP(DT_NODELABEL(rcc), d2ppre1) #define STM32_D2PPRE2 DT_PROP(DT_NODELABEL(rcc), d2ppre2) #define STM32_D1PPRE DT_PROP(DT_NODELABEL(rcc), d1ppre) #define STM32_D3PPRE DT_PROP(DT_NODELABEL(rcc), d3ppre) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /** STM2WBA specifics RCC dividers */ #define STM32_AHB5_DIV DT_PROP(DT_NODELABEL(rcc), ahb5_div) @@ -133,7 +145,8 @@ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32u5_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wb_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wba_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7rs_pll_clock, okay) #define STM32_PLL_ENABLED 1 #define STM32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(pll), div_m) #define STM32_PLL_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul_n) @@ -143,6 +156,8 @@ #define STM32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_q, 1) #define STM32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_r) #define STM32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_r, 1) +#define STM32_PLL_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_s) +#define STM32_PLL_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_s, 1) #define STM32_PLL_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), fracn) #define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 1) #endif @@ -164,7 +179,8 @@ #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) #define STM32_PLL2_ENABLED 1 #define STM32_PLL2_M_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_m) #define STM32_PLL2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll2), mul_n) @@ -174,12 +190,17 @@ #define STM32_PLL2_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_q, 1) #define STM32_PLL2_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_r) #define STM32_PLL2_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_r, 1) +#define STM32_PLL2_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_s) +#define STM32_PLL2_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_s, 1) +#define STM32_PLL2_T_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_t) +#define STM32_PLL2_T_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_t, 1) #define STM32_PLL2_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), fracn) #define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7rs_pll_clock, okay) #define STM32_PLL3_ENABLED 1 #define STM32_PLL3_M_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_m) #define STM32_PLL3_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll3), mul_n) @@ -189,6 +210,8 @@ #define STM32_PLL3_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_q, 1) #define STM32_PLL3_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_r) #define STM32_PLL3_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_r, 1) +#define STM32_PLL3_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_s) +#define STM32_PLL3_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_s, 1) #define STM32_PLL3_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), fracn) #define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 1) #endif diff --git a/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h new file mode 100644 index 00000000000..579ae56b0e2 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Domain clocks */ + +/* RM0477 */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ + +/** Fixed clocks */ +/* Low speed clocks defined in stm32_common_clocks.h */ +#define STM32_SRC_HSE (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI48 (STM32_SRC_HSE + 1) +#define STM32_SRC_HSI_KER (STM32_SRC_HSI48 + 1) /* HSI + HSIKERON */ +#define STM32_SRC_CSI_KER (STM32_SRC_HSI_KER + 1) /* CSI + CSIKERON */ +/** PLL outputs */ +#define STM32_SRC_PLL1_P (STM32_SRC_CSI_KER + 1) +#define STM32_SRC_PLL1_Q (STM32_SRC_PLL1_P + 1) +#define STM32_SRC_PLL1_R (STM32_SRC_PLL1_Q + 1) +#define STM32_SRC_PLL1_S (STM32_SRC_PLL1_R + 1) +#define STM32_SRC_PLL2_P (STM32_SRC_PLL1_S + 1) +#define STM32_SRC_PLL2_Q (STM32_SRC_PLL2_P + 1) +#define STM32_SRC_PLL2_R (STM32_SRC_PLL2_Q + 1) +#define STM32_SRC_PLL2_S (STM32_SRC_PLL2_R + 1) +#define STM32_SRC_PLL2_T (STM32_SRC_PLL2_S + 1) +#define STM32_SRC_PLL3_P (STM32_SRC_PLL2_T + 1) +#define STM32_SRC_PLL3_Q (STM32_SRC_PLL3_P + 1) +#define STM32_SRC_PLL3_R (STM32_SRC_PLL3_Q + 1) +#define STM32_SRC_PLL3_S (STM32_SRC_PLL3_R + 1) + +/** Clock muxes */ +#define STM32_SRC_CKPER (STM32_SRC_PLL3_S + 1) +/** Others: Not yet supported */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x138 +#define STM32_CLOCK_BUS_AHB2 0x13C +#define STM32_CLOCK_BUS_AHB3 0x158 +#define STM32_CLOCK_BUS_AHB4 0x140 +#define STM32_CLOCK_BUS_AHB5 0x134 +#define STM32_CLOCK_BUS_APB1 0x148 +#define STM32_CLOCK_BUS_APB1_2 0x14C +#define STM32_CLOCK_BUS_APB2 0x150 +#define STM32_CLOCK_BUS_APB4 0x154 +#define STM32_CLOCK_BUS_APB5 0x144 +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB5 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_AHB3 + +#define STM32_CLOCK_REG_MASK 0xFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 8U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 13U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 16U + +/** + * @brief STM32H7RS clock configuration bit field. + * + * - reg (0/1) [ 0 : 7 ] + * - shift (0..31) [ 8 : 12 ] + * - mask (0x1, 0x3, 0x7) [ 13 : 15 ] + * - val (0..3) [ 16 : 18 ] + * + * @param reg RCC_DxCCIP register offset + * @param shift Position within RCC_DxCCIP. + * @param mask Mask for the RCC_DxCCIP field. + * @param val Clock value (0, 1, 2 or 3). + */ +#define STM32_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_DxCCIP register offset (RM0477.pdf) */ +#define D1CCIPR_REG 0x4C +#define D2CCIPR_REG 0x50 +#define D3CCIPR_REG 0x54 +#define D4CCIPR_REG 0x58 + +/** @brief RCC_BDCR register offset */ +#define BDCR_REG 0x70 + +/** @brief Device domain clocks selection helpers (RM0477.pdf) */ + +/* TODO to be completed */ + +/** D1CCIPR devices */ +#define FMC_SEL(val) STM32_CLOCK(val, 3, 0, D1CCIPR_REG) +#define SDMMC_SEL(val) STM32_CLOCK(val, 1, 2, D1CCIPR_REG) +#define XSPI1_SEL(val) STM32_CLOCK(val, 3, 4, D1CCIPR_REG) +#define XSPI2_SEL(val) STM32_CLOCK(val, 3, 6, D1CCIPR_REG) +#define ADC_SEL(val) STM32_CLOCK(val, 3, 24, D1CCIPR_REG) +#define CKPER_SEL(val) STM32_CLOCK(val, 3, 28, D1CCIPR_REG) + +/** D2CCIPR devices */ +#define USART234578_SEL(val) STM32_CLOCK(val, 7, 0, D2CCIPR_REG) +#define SPI23_SEL(val) STM32_CLOCK(val, 7, 4, D2CCIPR_REG) +#define I2C23_SEL(val) STM32_CLOCK(val, 3, 8, D2CCIPR_REG) +#define I2C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define I3C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define LPTIM1_SEL(val) STM32_CLOCK(val, 7, 16, D2CCIPR_REG) +#define FDCAN_SEL(val) STM32_CLOCK(val, 3, 22, D2CCIPR_REG) + +/** D3CCIPR devices */ +#define USART1_SEL(val) STM32_CLOCK(val, 7, 0, D3CCIPR_REG) +#define SPI45_SEL(val) STM32_CLOCK(val, 7, 4, D3CCIPR_REG) +#define SPI1_SEL(val) STM32_CLOCK(val, 7, 8, D3CCIPR_REG) +#define SAI1_SEL(val) STM32_CLOCK(val, 7, 16, D3CCIPR_REG) +#define SAI2_SEL(val) STM32_CLOCK(val, 7, 20, D3CCIPR_REG) + +/** D4CCIPR devices */ +#define LPUART1_SEL(val) STM32_CLOCK(val, 7, 0, D4CCIPR_REG) +#define SPI6_SEL(val) STM32_CLOCK(val, 7, 4, D4CCIPR_REG) +#define LPTIM23_SEL(val) STM32_CLOCK(val, 7, 8, D4CCIPR_REG) +#define LPTIM45_SEL(val) STM32_CLOCK(val, 7, 12, D4CCIPR_REG) + +/** BDCR devices */ +#define RTC_SEL(val) STM32_CLOCK(val, 3, 8, BDCR_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ */