1 /*
2  * Copyright (c) 2019, Intel Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <assert.h>
10 #include <drivers/delay_timer.h>
11 #include <lib/mmio.h>
12 #include <platform_def.h>
13 
14 #include "s10_clock_manager.h"
15 #include "socfpga_handoff.h"
16 #include "socfpga_system_manager.h"
17 
18 
wait_pll_lock(void)19 void wait_pll_lock(void)
20 {
21 	uint32_t data;
22 
23 	do {
24 		data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT);
25 	} while ((ALT_CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
26 			(ALT_CLKMGR_STAT_PERPLLLOCKED(data) == 0));
27 }
28 
wait_fsm(void)29 void wait_fsm(void)
30 {
31 	uint32_t data;
32 
33 	do {
34 		data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT);
35 	} while (ALT_CLKMGR_STAT_BUSY(data) == ALT_CLKMGR_STAT_BUSY_E_BUSY);
36 }
37 
config_clkmgr_handoff(handoff * hoff_ptr)38 void config_clkmgr_handoff(handoff *hoff_ptr)
39 {
40 	uint32_t m_div, refclk_div, mscnt, hscnt;
41 
42 	/* Bypass all mainpllgrp's clocks */
43 	mmio_write_32(ALT_CLKMGR_MAINPLL +
44 			ALT_CLKMGR_MAINPLL_BYPASS,
45 			0x7);
46 	wait_fsm();
47 	/* Bypass all perpllgrp's clocks */
48 	mmio_write_32(ALT_CLKMGR_PERPLL +
49 			ALT_CLKMGR_PERPLL_BYPASS,
50 			0x7f);
51 	wait_fsm();
52 
53 	/* Setup main PLL dividers */
54 	m_div = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(hoff_ptr->main_pll_fdbck);
55 	refclk_div = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(
56 			hoff_ptr->main_pll_pllglob);
57 	mscnt = 200 / ((6 + m_div) / refclk_div);
58 	hscnt = (m_div + 6) * mscnt / refclk_div - 9;
59 
60 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB,
61 			hoff_ptr->main_pll_pllglob);
62 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK,
63 			hoff_ptr->main_pll_fdbck);
64 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_VCOCALIB,
65 			ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) |
66 			ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt));
67 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC0,
68 			hoff_ptr->main_pll_pllc0);
69 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1,
70 			hoff_ptr->main_pll_pllc1);
71 
72 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV,
73 			hoff_ptr->main_pll_nocdiv);
74 
75 	/* Setup peripheral PLL dividers */
76 	m_div = ALT_CLKMGR_PERPLL_FDBCK_MDIV(hoff_ptr->per_pll_fdbck);
77 	refclk_div = ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(
78 			hoff_ptr->per_pll_pllglob);
79 	mscnt = 200 / ((6 + m_div) / refclk_div);
80 	hscnt = (m_div + 6) * mscnt / refclk_div - 9;
81 
82 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB,
83 			hoff_ptr->per_pll_pllglob);
84 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_FDBCK,
85 			hoff_ptr->per_pll_fdbck);
86 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_VCOCALIB,
87 			ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) |
88 			ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt));
89 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC0,
90 			hoff_ptr->per_pll_pllc0);
91 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1,
92 			hoff_ptr->per_pll_pllc1);
93 
94 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_GPIODIV,
95 			ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(
96 			hoff_ptr->per_pll_gpiodiv));
97 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EMACCTL,
98 			hoff_ptr->per_pll_emacctl);
99 
100 
101 	/* Take both PLL out of reset and power up */
102 	mmio_setbits_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB,
103 			ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
104 			ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
105 	mmio_setbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB,
106 			ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
107 			ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
108 
109 	wait_pll_lock();
110 
111 	/* Dividers for C2 to C9 only init after PLLs are lock. */
112 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, 0xff);
113 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, 0xff);
114 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, 0xff);
115 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, 0xff);
116 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, 0xff);
117 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, 0xff);
118 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, 0xff);
119 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, 0xff);
120 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, 0xff);
121 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, 0xff);
122 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, 0xff);
123 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, 0xff);
124 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, 0xff);
125 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, 0xff);
126 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, 0xff);
127 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, 0xff);
128 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, 0xff);
129 
130 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK,
131 			hoff_ptr->main_pll_mpuclk);
132 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK,
133 			hoff_ptr->main_pll_nocclk);
134 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK,
135 			hoff_ptr->main_pll_cntr2clk);
136 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK,
137 			hoff_ptr->main_pll_cntr3clk);
138 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK,
139 			hoff_ptr->main_pll_cntr4clk);
140 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK,
141 			hoff_ptr->main_pll_cntr5clk);
142 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK,
143 			hoff_ptr->main_pll_cntr6clk);
144 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK,
145 			hoff_ptr->main_pll_cntr7clk);
146 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK,
147 			hoff_ptr->main_pll_cntr8clk);
148 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK,
149 			hoff_ptr->main_pll_cntr9clk);
150 
151 	/* Peripheral PLL Clock Source and Counters/Divider */
152 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK,
153 			hoff_ptr->per_pll_cntr2clk);
154 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK,
155 			hoff_ptr->per_pll_cntr3clk);
156 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK,
157 			hoff_ptr->per_pll_cntr4clk);
158 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK,
159 			hoff_ptr->per_pll_cntr5clk);
160 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK,
161 			hoff_ptr->per_pll_cntr6clk);
162 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK,
163 			hoff_ptr->per_pll_cntr7clk);
164 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK,
165 			hoff_ptr->per_pll_cntr8clk);
166 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR9CLK,
167 			hoff_ptr->per_pll_cntr9clk);
168 
169 	/* Take all PLLs out of bypass */
170 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_BYPASS, 0);
171 	wait_fsm();
172 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_BYPASS, 0);
173 	wait_fsm();
174 
175 	/* Set safe mode/ out of boot mode */
176 	mmio_clrbits_32(ALT_CLKMGR + ALT_CLKMGR_CTRL,
177 		ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK);
178 	wait_fsm();
179 
180 	/* 10 Enable mainpllgrp's software-managed clock */
181 	mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_EN,
182 			ALT_CLKMGR_MAINPLL_EN_RESET);
183 	mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN,
184 			ALT_CLKMGR_PERPLL_EN_RESET);
185 
186 	/* Clear loss lock  interrupt status register that */
187 	/* might be set during configuration */
188 	mmio_write_32(ALT_CLKMGR + ALT_CLKMGR_INTRCLR,
189 			ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
190 			ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
191 
192 	/* Pass clock source frequency into scratch register */
193 	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
194 			hoff_ptr->hps_osc_clk_h);
195 	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
196 			hoff_ptr->fpga_clk_hz);
197 
198 }
199 
200 /* Extract reference clock from platform clock source */
get_ref_clk(uint32_t pllglob)201 uint32_t get_ref_clk(uint32_t pllglob)
202 {
203 	uint32_t data32, mdiv, refclkdiv, ref_clk;
204 	uint32_t scr_reg;
205 
206 	switch (ALT_CLKMGR_PSRC(pllglob)) {
207 	case ALT_CLKMGR_PLLGLOB_PSRC_EOSC1:
208 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
209 		ref_clk = mmio_read_32(scr_reg);
210 		break;
211 	case ALT_CLKMGR_PLLGLOB_PSRC_INTOSC:
212 		ref_clk = ALT_CLKMGR_INTOSC_HZ;
213 		break;
214 	case ALT_CLKMGR_PLLGLOB_PSRC_F2S:
215 		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
216 		ref_clk = mmio_read_32(scr_reg);
217 		break;
218 	default:
219 		ref_clk = 0;
220 		assert(0);
221 		break;
222 	}
223 
224 	refclkdiv = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(pllglob);
225 	data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK);
226 	mdiv = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(data32);
227 
228 	ref_clk = (ref_clk / refclkdiv) * (6 + mdiv);
229 
230 	return ref_clk;
231 }
232 
233 /* Calculate L3 interconnect main clock */
get_l3_clk(uint32_t ref_clk)234 uint32_t get_l3_clk(uint32_t ref_clk)
235 {
236 	uint32_t noc_base_clk, l3_clk, noc_clk, data32;
237 	uint32_t pllc1_reg;
238 
239 	noc_clk = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK);
240 
241 	switch (ALT_CLKMGR_PSRC(noc_clk)) {
242 	case ALT_CLKMGR_SRC_MAIN:
243 		pllc1_reg = ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1;
244 		break;
245 	case ALT_CLKMGR_SRC_PER:
246 		pllc1_reg = ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1;
247 		break;
248 	default:
249 		pllc1_reg = 0;
250 		assert(0);
251 		break;
252 	}
253 
254 	data32 = mmio_read_32(pllc1_reg);
255 	noc_base_clk = ref_clk / (data32 & 0xff);
256 	l3_clk = noc_base_clk / (noc_clk + 1);
257 
258 	return l3_clk;
259 }
260 
261 /* Calculate clock frequency to be used for watchdog timer */
get_wdt_clk(void)262 uint32_t get_wdt_clk(void)
263 {
264 	uint32_t data32, ref_clk, l3_clk, l4_sys_clk;
265 
266 	data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB);
267 	ref_clk = get_ref_clk(data32);
268 
269 	l3_clk = get_l3_clk(ref_clk);
270 
271 	l4_sys_clk = l3_clk / 4;
272 
273 	return l4_sys_clk;
274 }
275 
276 /* Calculate clock frequency to be used for UART driver */
get_uart_clk(void)277 uint32_t get_uart_clk(void)
278 {
279 	uint32_t data32, ref_clk, l3_clk, l4_sp_clk;
280 
281 	data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB);
282 	ref_clk = get_ref_clk(data32);
283 
284 	l3_clk = get_l3_clk(ref_clk);
285 
286 	data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV);
287 	data32 = (data32 >> 16) & 0x3;
288 	data32 = 1 << data32;
289 
290 	l4_sp_clk = (l3_clk / data32);
291 
292 	return l4_sp_clk;
293 }
294 
295 /* Calculate clock frequency to be used for SDMMC driver */
get_mmc_clk(void)296 uint32_t get_mmc_clk(void)
297 {
298 	uint32_t data32, ref_clk, l3_clk, mmc_clk;
299 
300 	data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB);
301 	ref_clk = get_ref_clk(data32);
302 
303 	l3_clk = get_l3_clk(ref_clk);
304 
305 	data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK);
306 	mmc_clk = (l3_clk / (data32 + 1)) / 4;
307 
308 	return mmc_clk;
309 }
310