1 /* 2 * Copyright (c) 2021 Katsuhiro Suzuki 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <zephyr/init.h> 8 #include <zephyr/devicetree.h> 9 #include <zephyr/sys/util.h> 10 11 #include "prci.h" 12 13 BUILD_ASSERT(MHZ(1000) == DT_PROP(DT_NODELABEL(coreclk), clock_frequency), 14 "Unsupported CORECLK frequency"); 15 BUILD_ASSERT(KHZ(125125) == DT_PROP(DT_NODELABEL(pclk), clock_frequency), 16 "Unsupported PCLK frequency"); 17 wait_controller_cycle(void)18static inline void wait_controller_cycle(void) 19 { 20 /* HACK to get the '1 full controller clock cycle'. */ 21 __asm__ volatile ("fence"); 22 } 23 24 /* 25 * Switch the clock source 26 * - core: to 1GHz PLL (CORE_PLL) from 26MHz oscillator (HFCLK) 27 * - peri: to 250MHz PLL (HFPCLKPLL) from HFCLK 28 * - ddr: to 923MHz PLL (DDRPLL) from HFCLK (half of the data rate) 29 * on the HiFive Unmatched board. 30 * 31 * Note: Valid PLL VCO range is 2400MHz to 4800MHz 32 */ soc_early_init_hook(void)33void soc_early_init_hook(void) 34 { 35 36 PRCI_REG(PRCI_COREPLLCFG) = 37 PLL_R(0) | /* input divider: Fin / (0 + 1) = 26MHz */ 38 PLL_F(76) | /* VCO: 2 x (76 + 1) = 154 = 4004MHz */ 39 PLL_Q(2) | /* output divider: VCO / 2^2 = 1001MHz */ 40 PLL_RANGE(PLL_RANGE_18MHZ) | /* 18MHz <= post divr(= 26MHz) < 30MHz */ 41 PLL_BYPASS(PLL_BYPASS_DISABLE) | 42 PLL_FSE(PLL_FSE_INTERNAL); 43 while ((PRCI_REG(PRCI_COREPLLCFG) & PLL_LOCK(1)) == 0) { 44 ; 45 } 46 47 /* Switch CORE_CLK to CORE_PLL from HFCLK */ 48 PRCI_REG(PRCI_COREPLLSEL) = COREPLLSEL_SEL(COREPLLSEL_COREPLL); 49 PRCI_REG(PRCI_CORECLKSEL) = CLKSEL_SEL(CLKSEL_PLL); 50 51 PRCI_REG(PRCI_HFPCLKPLLCFG) = 52 PLL_R(0) | /* input divider: Fin / (0 + 1) = 26MHz */ 53 PLL_F(76) | /* VCO: 2 x (76 + 1) = 154 = 4004MHz */ 54 PLL_Q(4) | /* output divider: VCO / 2^4 = 250.25MHz */ 55 PLL_RANGE(PLL_RANGE_18MHZ) | /* 18MHz <= post divr(= 26MHz) < 30MHz */ 56 PLL_BYPASS(PLL_BYPASS_DISABLE) | 57 PLL_FSE(PLL_FSE_INTERNAL); 58 while ((PRCI_REG(PRCI_HFPCLKPLLCFG) & PLL_LOCK(1)) == 0) { 59 ; 60 } 61 62 /* Switch PCLK to HFPCLKPLL/2 from HFCLK/2 */ 63 PRCI_REG(PRCI_HFPCLKPLLOUTDIV) = OUTDIV_PLLCKE(OUTDIV_PLLCKE_ENA); 64 PRCI_REG(PRCI_HFPCLKPLLSEL) = CLKSEL_SEL(CLKSEL_PLL); 65 66 PRCI_REG(PRCI_DDRPLLCFG) = 67 PLL_R(0) | /* input divider: Fin / (0 + 1) = 26MHz */ 68 PLL_F(70) | /* VCO: 2 x (70 + 1) = 154 = 1872MHz */ 69 PLL_Q(2) | /* output divider: VCO / 2^2 = 936MHz */ 70 PLL_RANGE(PLL_RANGE_18MHZ) | 71 PLL_BYPASS(PLL_BYPASS_DISABLE) | 72 PLL_FSE(PLL_FSE_INTERNAL); 73 while ((PRCI_REG(PRCI_DDRPLLCFG) & PLL_LOCK(1)) == 0) { 74 ; 75 } 76 77 PRCI_REG(PRCI_DDRPLLOUTDIV) |= OUTDIV_PLLCKE(OUTDIV_PLLCKE_ENA); 78 79 PRCI_REG(PRCI_DEVICESRESETN) |= DEVICERESETN_DDRCTRL; 80 wait_controller_cycle(); 81 82 /* Release DDR reset */ 83 PRCI_REG(PRCI_DEVICESRESETN) |= DEVICERESETN_DDRAXI | 84 DEVICERESETN_DDRAHB | 85 DEVICERESETN_DDRPHY; 86 wait_controller_cycle(); 87 88 /* 89 * These take like 16 cycles to actually propagate. We can't go sending stuff before they 90 * come out of reset. So wait. 91 */ 92 for (int i = 0; i < 256; i++) { 93 __asm__ volatile ("nop"); 94 } 95 } 96