1 /* 2 * 3 * Copyright (c) 2017 Linaro Limited. 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 9 #include <soc.h> 10 #include <stm32_ll_bus.h> 11 #include <stm32_ll_rcc.h> 12 #include <stm32_ll_utils.h> 13 #include <zephyr/drivers/clock_control.h> 14 #include <zephyr/sys/util.h> 15 #include <zephyr/drivers/clock_control/stm32_clock_control.h> 16 #include "clock_stm32_ll_common.h" 17 18 #if defined(RCC_CFGR_USBPRE) 19 #define STM32_USB_PRE_ENABLED RCC_CFGR_USBPRE 20 #elif defined(RCC_CFGR_OTGFSPRE) 21 #define STM32_USB_PRE_ENABLED RCC_CFGR_OTGFSPRE 22 #endif 23 24 #if defined(STM32_PLL_ENABLED) 25 get_pllout_frequency(void)26uint32_t get_pllout_frequency(void) 27 { 28 /* Stub implementation for compatibility with clock_stm32_ll_common. 29 * The PLL domain clock is only used for MCO configuration, but the 30 * MCO driver never queries the PLL output clock frequency. 31 */ 32 return 0; 33 } 34 35 /* 36 * Select PLL source for STM32F1 Connectivity line devices (STM32F105xx and 37 * STM32F107xx). 38 * Both flags are defined in STM32Cube LL API. Keep only the selected one. 39 */ 40 41 /** 42 * @brief Set up pll configuration 43 */ 44 __unused config_pll_sysclock(void)45void config_pll_sysclock(void) 46 { 47 uint32_t pll_source, pll_mul, pll_div; 48 49 /* 50 * PLLMUL on SOC_STM32F10X_DENSITY_DEVICE 51 * 2 -> LL_RCC_PLL_MUL_2 -> 0x00000000 52 * 3 -> LL_RCC_PLL_MUL_3 -> 0x00040000 53 * 4 -> LL_RCC_PLL_MUL_4 -> 0x00080000 54 * ... 55 * 16 -> LL_RCC_PLL_MUL_16 -> 0x00380000 56 * 57 * PLLMUL on SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE 58 * 4 -> LL_RCC_PLL_MUL_4 -> 0x00080000 59 * ... 60 * 9 -> LL_RCC_PLL_MUL_9 -> 0x001C0000 61 * 13 -> LL_RCC_PLL_MUL_6_5 -> 0x00340000 62 */ 63 pll_mul = ((STM32_PLL_MULTIPLIER - 2) << RCC_CFGR_PLLMULL_Pos); 64 65 if (!IS_ENABLED(STM32_PLL_SRC_HSI)) { 66 /* In case PLL source is not HSI, set prediv case by case */ 67 #ifdef CONFIG_SOC_STM32F10X_DENSITY_DEVICE 68 /* PLL prediv */ 69 if (IS_ENABLED(STM32_PLL_XTPRE)) { 70 /* 71 * SOC_STM32F10X_DENSITY_DEVICE: 72 * PLLXPTRE (depends on PLL source HSE) 73 * HSE/2 used as PLL source 74 */ 75 pll_div = LL_RCC_PREDIV_DIV_2; 76 } else { 77 /* 78 * SOC_STM32F10X_DENSITY_DEVICE: 79 * PLLXPTRE (depends on PLL source HSE) 80 * HSE used as direct PLL source 81 */ 82 pll_div = LL_RCC_PREDIV_DIV_1; 83 } 84 #else 85 /* 86 * SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE 87 * 1 -> LL_RCC_PREDIV_DIV_1 -> 0x00000000 88 * 2 -> LL_RCC_PREDIV_DIV_2 -> 0x00000001 89 * 3 -> LL_RCC_PREDIV_DIV_3 -> 0x00000002 90 * ... 91 * 16 -> LL_RCC_PREDIV_DIV_16 -> 0x0000000F 92 */ 93 pll_div = STM32_PLL_PREDIV - 1; 94 #endif /* CONFIG_SOC_STM32F10X_DENSITY_DEVICE */ 95 } 96 97 /* Configure PLL source */ 98 if (IS_ENABLED(STM32_PLL_SRC_HSI)) { 99 pll_source = LL_RCC_PLLSOURCE_HSI_DIV_2; 100 } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { 101 pll_source = LL_RCC_PLLSOURCE_HSE | pll_div; 102 #if defined(RCC_CFGR2_PREDIV1SRC) 103 } else if (IS_ENABLED(STM32_PLL_SRC_PLL2)) { 104 pll_source = LL_RCC_PLLSOURCE_PLL2 | pll_div; 105 #endif 106 } else { 107 __ASSERT(0, "Invalid source"); 108 } 109 110 LL_RCC_PLL_ConfigDomain_SYS(pll_source, pll_mul); 111 112 #ifdef STM32_USB_PRE_ENABLED 113 /* Prescaler is enabled: PLL clock is not divided */ 114 LL_RCC_SetUSBClockSource(IS_ENABLED(STM32_PLL_USBPRE) ? 115 STM32_USB_PRE_ENABLED : 0); 116 #endif 117 } 118 119 #endif /* defined(STM32_PLL_ENABLED) */ 120 121 #if defined(STM32_PLL2_ENABLED) 122 123 /** 124 * @brief Set up pll2 configuration 125 */ 126 __unused config_pll2(void)127void config_pll2(void) 128 { 129 uint32_t pll_mul, pll_div; 130 131 /* 132 * PLL2MUL on SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE 133 * 8 -> LL_RCC_PLL2_MUL_8 -> 0x00000600 134 * 9 -> LL_RCC_PLL2_MUL_9 -> 0x00000700 135 * ... 136 * 14 -> LL_RCC_PLL2_MUL_14 -> 0x00000C00 137 * 16 -> LL_RCC_PLL2_MUL_16 -> 0x00000E00 138 * 20 -> LL_RCC_PLL2_MUL_20 -> 0x00000F00 139 */ 140 if (STM32_PLL2_MULTIPLIER == 20) { 141 pll_mul = RCC_CFGR2_PLL2MUL20; 142 } else { 143 pll_mul = ((STM32_PLL2_MULTIPLIER - 2) << RCC_CFGR2_PLL2MUL_Pos); 144 } 145 146 /* 147 * SOC_STM32F10X_CONNECTIVITY_LINE_DEVICE 148 * 1 -> LL_RCC_HSE_PREDIV2_DIV_1 -> 0x00000000 149 * 2 -> LL_RCC_HSE_PREDIV2_DIV_2 -> 0x00000010 150 * ... 151 * 16 -> LL_RCC_HSE_PREDIV2_DIV_16 -> 0x000000F0 152 */ 153 pll_div = ((STM32_PLL2_PREDIV - 1) << RCC_CFGR2_PREDIV2_Pos); 154 155 /* Check PLL2 source */ 156 if (!IS_ENABLED(STM32_PLL2_SRC_HSE)) { 157 __ASSERT(0, "Invalid source"); 158 } 159 160 LL_RCC_PLL_ConfigDomain_PLL2(pll_div, pll_mul); 161 } 162 163 #endif /* defined(STM32_PLL2_ENABLED) */ 164 165 /** 166 * @brief Activate default clocks 167 */ config_enable_default_clocks(void)168void config_enable_default_clocks(void) 169 { 170 if (IS_ENABLED(STM32_LSE_ENABLED)) { 171 /* Set the PWREN and BKPEN bits in the RCC_APB1ENR register */ 172 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); 173 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_BKP); 174 } 175 } 176