1 /* 2 * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <common/debug.h> 10 #include <drivers/delay_timer.h> 11 #include <lib/mmio.h> 12 13 #include "n5x_clock_manager.h" 14 #include "n5x_system_manager.h" 15 16 17 clk_get_pll_output_hz(void)18uint64_t clk_get_pll_output_hz(void) 19 { 20 uint32_t clksrc; 21 uint32_t scr_reg; 22 uint32_t divf; 23 uint32_t divr; 24 uint32_t divq; 25 uint32_t power = 1; 26 uint64_t clock = 0; 27 28 clksrc = ((get_clk_freq(CLKMGR_PERPLL_PLLGLOB)) & 29 CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET; 30 31 switch (clksrc) { 32 case CLKMGR_VCO_PSRC_EOSC1: 33 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); 34 clock = mmio_read_32(scr_reg); 35 break; 36 37 case CLKMGR_VCO_PSRC_INTOSC: 38 clock = CLKMGR_INTOSC_HZ; 39 break; 40 41 case CLKMGR_VCO_PSRC_F2S: 42 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); 43 clock = mmio_read_32(scr_reg); 44 break; 45 } 46 47 divf = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & 48 CLKMGR_PLLDIV_FDIV_MASK) >> CLKMGR_PLLDIV_FDIV_OFFSET; 49 divr = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & 50 CLKMGR_PLLDIV_REFCLKDIV_MASK) >> CLKMGR_PLLDIV_REFCLKDIV_OFFSET; 51 divq = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) & 52 CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >> CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET; 53 54 while (divq) { 55 power *= 2; 56 divq--; 57 } 58 59 return ((clock * 2 * (divf + 1)) / ((divr + 1) * power)); 60 } 61 get_l4_clk(void)62uint64_t get_l4_clk(void) 63 { 64 uint32_t clock = 0; 65 uint32_t mainpll_c1cnt; 66 uint32_t perpll_c1cnt; 67 uint32_t clksrc; 68 69 mainpll_c1cnt = ((get_clk_freq(CLKMGR_MAINPLL_PLLOUTDIV)) & 70 CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET; 71 72 perpll_c1cnt = ((get_clk_freq(CLKMGR_PERPLL_PLLOUTDIV)) & 73 CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET; 74 75 clksrc = ((get_clk_freq(CLKMGR_MAINPLL_NOCCLK)) & CLKMGR_CLKSRC_MASK) >> 76 CLKMGR_CLKSRC_OFFSET; 77 78 switch (clksrc) { 79 case CLKMGR_CLKSRC_MAIN: 80 clock = clk_get_pll_output_hz(); 81 clock /= 1 + mainpll_c1cnt; 82 break; 83 84 case CLKMGR_CLKSRC_PER: 85 clock = clk_get_pll_output_hz(); 86 clock /= 1 + perpll_c1cnt; 87 break; 88 89 default: 90 return 0; 91 break; 92 } 93 94 clock /= BIT(((get_clk_freq(CLKMGR_MAINPLL_NOCDIV)) >> 95 CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_NOCDIV_DIVIDER_MASK); 96 97 return clock; 98 } 99 100 /* Return MPU clock */ get_mpu_clk(void)101uint32_t get_mpu_clk(void) 102 { 103 uint32_t clock = 0; 104 uint32_t mainpll_c0cnt; 105 uint32_t perpll_c0cnt; 106 uint32_t clksrc; 107 108 mainpll_c0cnt = ((get_clk_freq(CLKMGR_MAINPLL_PLLOUTDIV)) & 109 CLKMGR_PLLOUTDIV_C0CNT_MASK) >> CLKMGR_PLLOUTDIV_C0CNT_OFFSET; 110 111 perpll_c0cnt = ((get_clk_freq(CLKMGR_PERPLL_PLLOUTDIV)) & 112 CLKMGR_PLLOUTDIV_C0CNT_MASK) >> CLKMGR_PLLOUTDIV_C0CNT_OFFSET; 113 114 clksrc = ((get_clk_freq(CLKMGR_MAINPLL_NOCCLK)) & CLKMGR_CLKSRC_MASK) >> 115 CLKMGR_CLKSRC_OFFSET; 116 117 switch (clksrc) { 118 case CLKMGR_CLKSRC_MAIN: 119 clock = clk_get_pll_output_hz(); 120 clock /= 1 + mainpll_c0cnt; 121 break; 122 123 case CLKMGR_CLKSRC_PER: 124 clock = clk_get_pll_output_hz(); 125 clock /= 1 + perpll_c0cnt; 126 break; 127 128 default: 129 return 0; 130 break; 131 } 132 133 clock /= BIT(((get_clk_freq(CLKMGR_MAINPLL_NOCDIV)) >> 134 CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_NOCDIV_DIVIDER_MASK); 135 136 return clock; 137 } 138 139 /* Calculate clock frequency based on parameter */ get_clk_freq(uint32_t psrc_reg)140uint32_t get_clk_freq(uint32_t psrc_reg) 141 { 142 uint32_t clk_psrc; 143 144 clk_psrc = mmio_read_32(CLKMGR_N5X_BASE + psrc_reg); 145 146 return clk_psrc; 147 } 148 149 /* Get cpu freq clock */ get_cpu_clk(void)150uint32_t get_cpu_clk(void) 151 { 152 uint32_t cpu_clk = 0; 153 154 cpu_clk = get_mpu_clk()/PLAT_HZ_CONVERT_TO_MHZ; 155 156 return cpu_clk; 157 } 158