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