• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "socfpga_handoff.h"
16 
clk_get_pll_output_hz(void)17 uint64_t clk_get_pll_output_hz(void)
18 {
19 	uint32_t clksrc;
20 	uint32_t scr_reg;
21 	uint32_t divf;
22 	uint32_t divr;
23 	uint32_t divq;
24 	uint32_t power = 1;
25 	uint64_t clock = 0;
26 
27 	clksrc = ((get_clk_freq(CLKMGR_PERPLL_PLLGLOB)) &
28 			CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET;
29 
30 	switch (clksrc) {
31 	case CLKMGR_VCO_PSRC_EOSC1:
32 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
33 		clock = mmio_read_32(scr_reg);
34 		break;
35 
36 	case CLKMGR_VCO_PSRC_INTOSC:
37 		clock = CLKMGR_INTOSC_HZ;
38 		break;
39 
40 	case CLKMGR_VCO_PSRC_F2S:
41 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
42 		clock = mmio_read_32(scr_reg);
43 		break;
44 	}
45 
46 	divf = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) &
47 			CLKMGR_PLLDIV_FDIV_MASK) >> CLKMGR_PLLDIV_FDIV_OFFSET;
48 	divr = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) &
49 			CLKMGR_PLLDIV_REFCLKDIV_MASK) >> CLKMGR_PLLDIV_REFCLKDIV_OFFSET;
50 	divq = ((get_clk_freq(CLKMGR_PERPLL_PLLDIV)) &
51 			CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >> CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET;
52 
53 	while (divq) {
54 		power *= 2;
55 		divq--;
56 	}
57 
58 	return ((clock * 2 * (divf + 1)) / ((divr + 1) * power));
59 }
60 
get_l4_clk(void)61 uint64_t get_l4_clk(void)
62 {
63 	uint32_t clock = 0;
64 	uint32_t mainpll_c1cnt;
65 	uint32_t perpll_c1cnt;
66 	uint32_t clksrc;
67 
68 	mainpll_c1cnt = ((get_clk_freq(CLKMGR_MAINPLL_PLLOUTDIV)) &
69 			CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
70 
71 	perpll_c1cnt = ((get_clk_freq(CLKMGR_PERPLL_PLLOUTDIV)) &
72 			CLKMGR_PLLOUTDIV_C1CNT_MASK) >> CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
73 
74 	clksrc = ((get_clk_freq(CLKMGR_MAINPLL_NOCCLK)) & CLKMGR_CLKSRC_MASK) >>
75 			CLKMGR_CLKSRC_OFFSET;
76 
77 	switch (clksrc) {
78 	case CLKMGR_CLKSRC_MAIN:
79 		clock = clk_get_pll_output_hz();
80 		clock /= 1 + mainpll_c1cnt;
81 		break;
82 
83 	case CLKMGR_CLKSRC_PER:
84 		clock = clk_get_pll_output_hz();
85 		clock /= 1 + perpll_c1cnt;
86 		break;
87 
88 	default:
89 		return 0;
90 		break;
91 	}
92 
93 	clock /= BIT(((get_clk_freq(CLKMGR_MAINPLL_NOCDIV)) >>
94 			CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_NOCDIV_DIVIDER_MASK);
95 
96 	return clock;
97 }
98 
99 /* Return MPU clock */
get_mpu_clk(void)100 uint32_t get_mpu_clk(void)
101 {
102 	uint32_t clock = 0;
103 	uint32_t mainpll_c0cnt;
104 	uint32_t perpll_c0cnt;
105 	uint32_t clksrc;
106 
107 	mainpll_c0cnt = ((get_clk_freq(CLKMGR_MAINPLL_PLLOUTDIV)) &
108 			CLKMGR_PLLOUTDIV_C0CNT_MASK) >> CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
109 
110 	perpll_c0cnt = ((get_clk_freq(CLKMGR_PERPLL_PLLOUTDIV)) &
111 			CLKMGR_PLLOUTDIV_C0CNT_MASK) >> CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
112 
113 	clksrc = ((get_clk_freq(CLKMGR_MAINPLL_NOCCLK)) & CLKMGR_CLKSRC_MASK) >>
114 			CLKMGR_CLKSRC_OFFSET;
115 
116 	switch (clksrc) {
117 	case CLKMGR_CLKSRC_MAIN:
118 		clock = clk_get_pll_output_hz();
119 		clock /= 1 + mainpll_c0cnt;
120 		break;
121 
122 	case CLKMGR_CLKSRC_PER:
123 		clock = clk_get_pll_output_hz();
124 		clock /= 1 + perpll_c0cnt;
125 		break;
126 
127 	default:
128 		return 0;
129 		break;
130 	}
131 
132 	clock /= BIT(((get_clk_freq(CLKMGR_MAINPLL_NOCDIV)) >>
133 			CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_NOCDIV_DIVIDER_MASK);
134 
135 	return clock;
136 }
137 
138 /* Calculate clock frequency based on parameter */
get_clk_freq(uint32_t psrc_reg)139 uint32_t get_clk_freq(uint32_t psrc_reg)
140 {
141 	uint32_t clk_psrc;
142 
143 	clk_psrc = mmio_read_32(CLKMGR_N5X_BASE + psrc_reg);
144 
145 	return clk_psrc;
146 }
147 
148 /* Get cpu freq clock */
get_cpu_clk(void)149 uint32_t get_cpu_clk(void)
150 {
151 	uint32_t cpu_clk = 0;
152 
153 	cpu_clk = get_l4_clk()/PLAT_HZ_CONVERT_TO_MHZ;
154 
155 	return cpu_clk;
156 }
157 
158 /* Return mpu_periph_clk clock frequency */
get_mpu_periph_clk(void)159 uint32_t get_mpu_periph_clk(void)
160 {
161 	uint32_t mpu_periph_clk = 0;
162 	/* mpu_periph_clk is mpu_clk, via a static /4 divider  */
163 	mpu_periph_clk = (get_mpu_clk()/4)/PLAT_HZ_CONVERT_TO_MHZ;
164 	return mpu_periph_clk;
165 }
166 
167 /* Return mpu_periph_clk tick */
plat_get_syscnt_freq2(void)168 unsigned int plat_get_syscnt_freq2(void)
169 {
170 	return PLAT_SYS_COUNTER_FREQ_IN_TICKS;
171 }
172