1 /* 2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com> 3 * Copyright (c) 2017 Palmer Dabbelt <palmer@dabbelt.com> 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 #include <zephyr/init.h> 9 #include <zephyr/devicetree.h> 10 #include "prci.h" 11 12 #define CORECLK_HZ (DT_PROP(DT_NODELABEL(coreclk), clock_frequency)) 13 BUILD_ASSERT(DT_PROP(DT_NODELABEL(tlclk), clock_div) == 1, 14 "Unsupported TLCLK divider"); 15 soc_early_init_hook(void)16void soc_early_init_hook(void) 17 { 18 19 /* 20 * HFXOSC (16 MHz) is used to produce coreclk (and therefore tlclk / 21 * peripheral clock). This code supports the following frequencies: 22 * - 16 MHz (bypass HFPLL). 23 * - 48 MHz - 320 MHz, in 8 MHz steps (use HFPLL). 24 */ 25 BUILD_ASSERT(MHZ(16) == CORECLK_HZ || 26 (MHZ(48) <= CORECLK_HZ && MHZ(320) >= CORECLK_HZ && 27 (CORECLK_HZ % MHZ(8)) == 0), 28 "Unsupported CORECLK frequency"); 29 30 uint32_t prci; 31 32 if (MHZ(16) == CORECLK_HZ) { 33 /* Bypass HFPLL. */ 34 prci = PLL_REFSEL(1) | PLL_BYPASS(1); 35 } else { 36 /* refr = 8 MHz. */ 37 const int pll_r = 0x1; 38 int pll_q; 39 40 /* Select Q divisor to produce vco on [384 MHz, 768 MHz]. */ 41 if (MHZ(768) / 8 >= CORECLK_HZ) { 42 pll_q = 0x3; 43 } else if (MHZ(768) / 4 >= CORECLK_HZ) { 44 pll_q = 0x2; 45 } else { 46 pll_q = 0x1; 47 } 48 /* Select F multiplier to produce vco target. */ 49 const int pll_f = ((CORECLK_HZ / MHZ(1)) >> (4 - pll_q)) - 1; 50 51 prci = PLL_REFSEL(1) | PLL_R(pll_r) | PLL_F(pll_f) | PLL_Q(pll_q); 52 } 53 54 PRCI_REG(PRCI_PLLCFG) = prci; 55 PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0)); 56 PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1); 57 PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1); 58 } 59