1712f99a5SVikas Manocha /* 2712f99a5SVikas Manocha * (C) Copyright 2017 3712f99a5SVikas Manocha * Vikas Manocha, <vikas.manocha@st.com> 4712f99a5SVikas Manocha * 5712f99a5SVikas Manocha * SPDX-License-Identifier: GPL-2.0+ 6712f99a5SVikas Manocha */ 7712f99a5SVikas Manocha #include <common.h> 8712f99a5SVikas Manocha #include <clk-uclass.h> 9712f99a5SVikas Manocha #include <dm.h> 10712f99a5SVikas Manocha #include <asm/io.h> 11712f99a5SVikas Manocha #include <asm/arch/rcc.h> 12712f99a5SVikas Manocha #include <asm/arch/stm32.h> 13712f99a5SVikas Manocha #include <asm/arch/stm32_periph.h> 14712f99a5SVikas Manocha 15712f99a5SVikas Manocha #define RCC_CR_HSION BIT(0) 16712f99a5SVikas Manocha #define RCC_CR_HSEON BIT(16) 17712f99a5SVikas Manocha #define RCC_CR_HSERDY BIT(17) 18712f99a5SVikas Manocha #define RCC_CR_HSEBYP BIT(18) 19712f99a5SVikas Manocha #define RCC_CR_CSSON BIT(19) 20712f99a5SVikas Manocha #define RCC_CR_PLLON BIT(24) 21712f99a5SVikas Manocha #define RCC_CR_PLLRDY BIT(25) 22712f99a5SVikas Manocha 23712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0) 24712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6) 25712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16) 26712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24) 27712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLSRC BIT(22) 28712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLM_SHIFT 0 29712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLN_SHIFT 6 30712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLP_SHIFT 16 31712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLQ_SHIFT 24 32712f99a5SVikas Manocha 33712f99a5SVikas Manocha #define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4) 34712f99a5SVikas Manocha #define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10) 35712f99a5SVikas Manocha #define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13) 36712f99a5SVikas Manocha #define RCC_CFGR_SW0 BIT(0) 37712f99a5SVikas Manocha #define RCC_CFGR_SW1 BIT(1) 38712f99a5SVikas Manocha #define RCC_CFGR_SW_MASK GENMASK(1, 0) 39712f99a5SVikas Manocha #define RCC_CFGR_SW_HSI 0 40712f99a5SVikas Manocha #define RCC_CFGR_SW_HSE RCC_CFGR_SW0 41712f99a5SVikas Manocha #define RCC_CFGR_SW_PLL RCC_CFGR_SW1 42712f99a5SVikas Manocha #define RCC_CFGR_SWS0 BIT(2) 43712f99a5SVikas Manocha #define RCC_CFGR_SWS1 BIT(3) 44712f99a5SVikas Manocha #define RCC_CFGR_SWS_MASK GENMASK(3, 2) 45712f99a5SVikas Manocha #define RCC_CFGR_SWS_HSI 0 46712f99a5SVikas Manocha #define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0 47712f99a5SVikas Manocha #define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1 48712f99a5SVikas Manocha #define RCC_CFGR_HPRE_SHIFT 4 49712f99a5SVikas Manocha #define RCC_CFGR_PPRE1_SHIFT 10 50712f99a5SVikas Manocha #define RCC_CFGR_PPRE2_SHIFT 13 51712f99a5SVikas Manocha 52712f99a5SVikas Manocha /* 53712f99a5SVikas Manocha * Offsets of some PWR registers 54712f99a5SVikas Manocha */ 55712f99a5SVikas Manocha #define PWR_CR1_ODEN BIT(16) 56712f99a5SVikas Manocha #define PWR_CR1_ODSWEN BIT(17) 57712f99a5SVikas Manocha #define PWR_CSR1_ODRDY BIT(16) 58712f99a5SVikas Manocha #define PWR_CSR1_ODSWRDY BIT(17) 59712f99a5SVikas Manocha 60712f99a5SVikas Manocha struct pll_psc { 61712f99a5SVikas Manocha u8 pll_m; 62712f99a5SVikas Manocha u16 pll_n; 63712f99a5SVikas Manocha u8 pll_p; 64712f99a5SVikas Manocha u8 pll_q; 65712f99a5SVikas Manocha u8 ahb_psc; 66712f99a5SVikas Manocha u8 apb1_psc; 67712f99a5SVikas Manocha u8 apb2_psc; 68712f99a5SVikas Manocha }; 69712f99a5SVikas Manocha 70712f99a5SVikas Manocha #define AHB_PSC_1 0 71712f99a5SVikas Manocha #define AHB_PSC_2 0x8 72712f99a5SVikas Manocha #define AHB_PSC_4 0x9 73712f99a5SVikas Manocha #define AHB_PSC_8 0xA 74712f99a5SVikas Manocha #define AHB_PSC_16 0xB 75712f99a5SVikas Manocha #define AHB_PSC_64 0xC 76712f99a5SVikas Manocha #define AHB_PSC_128 0xD 77712f99a5SVikas Manocha #define AHB_PSC_256 0xE 78712f99a5SVikas Manocha #define AHB_PSC_512 0xF 79712f99a5SVikas Manocha 80712f99a5SVikas Manocha #define APB_PSC_1 0 81712f99a5SVikas Manocha #define APB_PSC_2 0x4 82712f99a5SVikas Manocha #define APB_PSC_4 0x5 83712f99a5SVikas Manocha #define APB_PSC_8 0x6 84712f99a5SVikas Manocha #define APB_PSC_16 0x7 85712f99a5SVikas Manocha 86712f99a5SVikas Manocha #if !defined(CONFIG_STM32_HSE_HZ) 87712f99a5SVikas Manocha #error "CONFIG_STM32_HSE_HZ not defined!" 88712f99a5SVikas Manocha #else 89712f99a5SVikas Manocha #if (CONFIG_STM32_HSE_HZ == 25000000) 90712f99a5SVikas Manocha #if (CONFIG_SYS_CLK_FREQ == 200000000) 91712f99a5SVikas Manocha /* 200 MHz */ 92712f99a5SVikas Manocha struct pll_psc sys_pll_psc = { 93712f99a5SVikas Manocha .pll_m = 25, 94712f99a5SVikas Manocha .pll_n = 400, 95712f99a5SVikas Manocha .pll_p = 2, 96712f99a5SVikas Manocha .pll_q = 8, 97712f99a5SVikas Manocha .ahb_psc = AHB_PSC_1, 98712f99a5SVikas Manocha .apb1_psc = APB_PSC_4, 99712f99a5SVikas Manocha .apb2_psc = APB_PSC_2 100712f99a5SVikas Manocha }; 101712f99a5SVikas Manocha #endif 102712f99a5SVikas Manocha #else 103712f99a5SVikas Manocha #error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists" 104712f99a5SVikas Manocha #endif 105712f99a5SVikas Manocha #endif 106712f99a5SVikas Manocha 107712f99a5SVikas Manocha int configure_clocks(void) 108712f99a5SVikas Manocha { 109712f99a5SVikas Manocha /* Reset RCC configuration */ 110712f99a5SVikas Manocha setbits_le32(&STM32_RCC->cr, RCC_CR_HSION); 111712f99a5SVikas Manocha writel(0, &STM32_RCC->cfgr); /* Reset CFGR */ 112712f99a5SVikas Manocha clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON 113712f99a5SVikas Manocha | RCC_CR_PLLON)); 114712f99a5SVikas Manocha writel(0x24003010, &STM32_RCC->pllcfgr); /* Reset value from RM */ 115712f99a5SVikas Manocha clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP); 116712f99a5SVikas Manocha writel(0, &STM32_RCC->cir); /* Disable all interrupts */ 117712f99a5SVikas Manocha 118712f99a5SVikas Manocha /* Configure for HSE+PLL operation */ 119712f99a5SVikas Manocha setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON); 120712f99a5SVikas Manocha while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY)) 121712f99a5SVikas Manocha ; 122712f99a5SVikas Manocha 123712f99a5SVikas Manocha setbits_le32(&STM32_RCC->cfgr, (( 124712f99a5SVikas Manocha sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT) 125712f99a5SVikas Manocha | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT) 126712f99a5SVikas Manocha | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); 127712f99a5SVikas Manocha 128712f99a5SVikas Manocha /* Configure the main PLL */ 129712f99a5SVikas Manocha uint32_t pllcfgr = 0; 130712f99a5SVikas Manocha pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */ 131712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT; 132712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT; 133712f99a5SVikas Manocha pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT; 134712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT; 135712f99a5SVikas Manocha writel(pllcfgr, &STM32_RCC->pllcfgr); 136712f99a5SVikas Manocha 137712f99a5SVikas Manocha /* Enable the main PLL */ 138712f99a5SVikas Manocha setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON); 139712f99a5SVikas Manocha while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY)) 140712f99a5SVikas Manocha ; 141712f99a5SVikas Manocha 142712f99a5SVikas Manocha /* Enable high performance mode, System frequency up to 200 MHz */ 143712f99a5SVikas Manocha setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN); 144712f99a5SVikas Manocha setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN); 145712f99a5SVikas Manocha /* Infinite wait! */ 146712f99a5SVikas Manocha while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY)) 147712f99a5SVikas Manocha ; 148712f99a5SVikas Manocha /* Enable the Over-drive switch */ 149712f99a5SVikas Manocha setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN); 150712f99a5SVikas Manocha /* Infinite wait! */ 151712f99a5SVikas Manocha while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY)) 152712f99a5SVikas Manocha ; 153712f99a5SVikas Manocha 154712f99a5SVikas Manocha stm32_flash_latency_cfg(5); 155712f99a5SVikas Manocha clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1)); 156712f99a5SVikas Manocha setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL); 157712f99a5SVikas Manocha 158712f99a5SVikas Manocha while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) != 159712f99a5SVikas Manocha RCC_CFGR_SWS_PLL) 160712f99a5SVikas Manocha ; 161712f99a5SVikas Manocha 162712f99a5SVikas Manocha return 0; 163712f99a5SVikas Manocha } 164712f99a5SVikas Manocha 165712f99a5SVikas Manocha unsigned long clock_get(enum clock clck) 166712f99a5SVikas Manocha { 167712f99a5SVikas Manocha u32 sysclk = 0; 168712f99a5SVikas Manocha u32 shift = 0; 169712f99a5SVikas Manocha /* Prescaler table lookups for clock computation */ 170712f99a5SVikas Manocha u8 ahb_psc_table[16] = { 171712f99a5SVikas Manocha 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 172712f99a5SVikas Manocha }; 173712f99a5SVikas Manocha u8 apb_psc_table[8] = { 174712f99a5SVikas Manocha 0, 0, 0, 0, 1, 2, 3, 4 175712f99a5SVikas Manocha }; 176712f99a5SVikas Manocha 177712f99a5SVikas Manocha if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) == 178712f99a5SVikas Manocha RCC_CFGR_SWS_PLL) { 179712f99a5SVikas Manocha u16 pllm, plln, pllp; 180712f99a5SVikas Manocha pllm = (readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); 181712f99a5SVikas Manocha plln = ((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLN_MASK) 182712f99a5SVikas Manocha >> RCC_PLLCFGR_PLLN_SHIFT); 183712f99a5SVikas Manocha pllp = ((((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) 184712f99a5SVikas Manocha >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); 185712f99a5SVikas Manocha sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp; 186712f99a5SVikas Manocha } 187712f99a5SVikas Manocha 188712f99a5SVikas Manocha switch (clck) { 189712f99a5SVikas Manocha case CLOCK_CORE: 190712f99a5SVikas Manocha return sysclk; 191712f99a5SVikas Manocha break; 192712f99a5SVikas Manocha case CLOCK_AHB: 193712f99a5SVikas Manocha shift = ahb_psc_table[( 194712f99a5SVikas Manocha (readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK) 195712f99a5SVikas Manocha >> RCC_CFGR_HPRE_SHIFT)]; 196712f99a5SVikas Manocha return sysclk >>= shift; 197712f99a5SVikas Manocha break; 198712f99a5SVikas Manocha case CLOCK_APB1: 199712f99a5SVikas Manocha shift = apb_psc_table[( 200712f99a5SVikas Manocha (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK) 201712f99a5SVikas Manocha >> RCC_CFGR_PPRE1_SHIFT)]; 202712f99a5SVikas Manocha return sysclk >>= shift; 203712f99a5SVikas Manocha break; 204712f99a5SVikas Manocha case CLOCK_APB2: 205712f99a5SVikas Manocha shift = apb_psc_table[( 206712f99a5SVikas Manocha (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK) 207712f99a5SVikas Manocha >> RCC_CFGR_PPRE2_SHIFT)]; 208712f99a5SVikas Manocha return sysclk >>= shift; 209712f99a5SVikas Manocha break; 210712f99a5SVikas Manocha default: 211712f99a5SVikas Manocha return 0; 212712f99a5SVikas Manocha break; 213712f99a5SVikas Manocha } 214712f99a5SVikas Manocha } 215712f99a5SVikas Manocha 216712f99a5SVikas Manocha static int stm32_clk_enable(struct clk *clk) 217712f99a5SVikas Manocha { 218712f99a5SVikas Manocha u32 offset = clk->id / 32; 219712f99a5SVikas Manocha u32 bit_index = clk->id % 32; 220712f99a5SVikas Manocha 221712f99a5SVikas Manocha debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n", 222712f99a5SVikas Manocha __func__, clk->id, offset, bit_index); 223712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr + offset, BIT(bit_index)); 224712f99a5SVikas Manocha 225712f99a5SVikas Manocha return 0; 226712f99a5SVikas Manocha } 227712f99a5SVikas Manocha 228712f99a5SVikas Manocha void clock_setup(int peripheral) 229712f99a5SVikas Manocha { 230712f99a5SVikas Manocha switch (peripheral) { 231712f99a5SVikas Manocha case SYSCFG_CLOCK_CFG: 232712f99a5SVikas Manocha setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN); 233712f99a5SVikas Manocha break; 234712f99a5SVikas Manocha case TIMER2_CLOCK_CFG: 235712f99a5SVikas Manocha setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); 236712f99a5SVikas Manocha break; 237712f99a5SVikas Manocha case STMMAC_CLOCK_CFG: 238712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN); 239712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN); 240712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN); 241712f99a5SVikas Manocha break; 242712f99a5SVikas Manocha default: 243712f99a5SVikas Manocha break; 244712f99a5SVikas Manocha } 245712f99a5SVikas Manocha } 246712f99a5SVikas Manocha 247712f99a5SVikas Manocha static int stm32_clk_probe(struct udevice *dev) 248712f99a5SVikas Manocha { 249712f99a5SVikas Manocha debug("%s: stm32_clk_probe\n", __func__); 250712f99a5SVikas Manocha configure_clocks(); 251712f99a5SVikas Manocha 252712f99a5SVikas Manocha return 0; 253712f99a5SVikas Manocha } 254712f99a5SVikas Manocha 255*a4e0ef50SSimon Glass static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) 256712f99a5SVikas Manocha { 257712f99a5SVikas Manocha debug("%s(clk=%p)\n", __func__, clk); 258712f99a5SVikas Manocha 259712f99a5SVikas Manocha if (args->args_count != 2) { 260712f99a5SVikas Manocha debug("Invaild args_count: %d\n", args->args_count); 261712f99a5SVikas Manocha return -EINVAL; 262712f99a5SVikas Manocha } 263712f99a5SVikas Manocha 264712f99a5SVikas Manocha if (args->args_count) 265712f99a5SVikas Manocha clk->id = args->args[1]; 266712f99a5SVikas Manocha else 267712f99a5SVikas Manocha clk->id = 0; 268712f99a5SVikas Manocha 269712f99a5SVikas Manocha return 0; 270712f99a5SVikas Manocha } 271712f99a5SVikas Manocha 272712f99a5SVikas Manocha static struct clk_ops stm32_clk_ops = { 273712f99a5SVikas Manocha .of_xlate = stm32_clk_of_xlate, 274712f99a5SVikas Manocha .enable = stm32_clk_enable, 275712f99a5SVikas Manocha }; 276712f99a5SVikas Manocha 277712f99a5SVikas Manocha static const struct udevice_id stm32_clk_ids[] = { 278712f99a5SVikas Manocha { .compatible = "st,stm32f42xx-rcc"}, 279712f99a5SVikas Manocha {} 280712f99a5SVikas Manocha }; 281712f99a5SVikas Manocha 282712f99a5SVikas Manocha U_BOOT_DRIVER(stm32f7_clk) = { 283712f99a5SVikas Manocha .name = "stm32f7_clk", 284712f99a5SVikas Manocha .id = UCLASS_CLK, 285712f99a5SVikas Manocha .of_match = stm32_clk_ids, 286712f99a5SVikas Manocha .ops = &stm32_clk_ops, 287712f99a5SVikas Manocha .probe = stm32_clk_probe, 288712f99a5SVikas Manocha .flags = DM_FLAG_PRE_RELOC, 289712f99a5SVikas Manocha }; 290