blob: 416d359239fc5c71e28cc0a9fce43d7e1d0d3b29 [file] [log] [blame]
Loh Tien Hock59400a42019-02-04 16:17:24 +08001/*
BenjaminLimJLa4a43272022-04-06 10:19:16 +08002 * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
Loh Tien Hock59400a42019-02-04 16:17:24 +08003 *
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>
Loh Tien Hock59400a42019-02-04 16:17:24 +080013
14#include "s10_clock_manager.h"
Hadi Asyrafi9f5dfc92019-10-23 16:26:53 +080015#include "socfpga_handoff.h"
Hadi Asyrafi8ebd2372019-12-23 17:58:04 +080016#include "socfpga_system_manager.h"
Loh Tien Hock59400a42019-02-04 16:17:24 +080017
18
19void 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
29void 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
38void 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);
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800191
192 /* Pass clock source frequency into scratch register */
Hadi Asyrafi8ebd2372019-12-23 17:58:04 +0800193 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800194 hoff_ptr->hps_osc_clk_h);
Hadi Asyrafi8ebd2372019-12-23 17:58:04 +0800195 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800196 hoff_ptr->fpga_clk_hz);
197
Loh Tien Hock59400a42019-02-04 16:17:24 +0800198}
199
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800200/* Extract reference clock from platform clock source */
201uint32_t get_ref_clk(uint32_t pllglob)
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800202{
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800203 uint32_t data32, mdiv, refclkdiv, ref_clk;
204 uint32_t scr_reg;
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800205
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800206 switch (ALT_CLKMGR_PSRC(pllglob)) {
207 case ALT_CLKMGR_PLLGLOB_PSRC_EOSC1:
Hadi Asyrafi8ebd2372019-12-23 17:58:04 +0800208 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800209 ref_clk = mmio_read_32(scr_reg);
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800210 break;
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800211 case ALT_CLKMGR_PLLGLOB_PSRC_INTOSC:
212 ref_clk = ALT_CLKMGR_INTOSC_HZ;
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800213 break;
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800214 case ALT_CLKMGR_PLLGLOB_PSRC_F2S:
Hadi Asyrafi8ebd2372019-12-23 17:58:04 +0800215 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800216 ref_clk = mmio_read_32(scr_reg);
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800217 break;
218 default:
219 ref_clk = 0;
220 assert(0);
221 break;
222 }
223
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800224 refclkdiv = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(pllglob);
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800225 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK);
226 mdiv = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(data32);
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800227
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800228 ref_clk = (ref_clk / refclkdiv) * (6 + mdiv);
229
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800230 return ref_clk;
231}
232
233/* Calculate L3 interconnect main clock */
234uint32_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 */
262uint32_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 */
277uint32_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 */
296uint32_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;
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800307
Hadi Asyrafi78fee352019-07-30 22:18:17 +0800308 return mmc_clk;
Muhammad Hadi Asyrafi Abdul Halimc0d4d932019-03-19 17:59:06 +0800309}
BenjaminLimJLa4a43272022-04-06 10:19:16 +0800310
311/* Get cpu freq clock */
312uint32_t get_cpu_clk(void)
313{
314 uint32_t data32, ref_clk, cpu_clk;
315
316 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB);
317 ref_clk = get_ref_clk(data32);
318
Jit Loon Lima9fca832022-12-22 21:52:36 +0800319 cpu_clk = get_l3_clk(ref_clk)/PLAT_HZ_CONVERT_TO_MHZ;
BenjaminLimJLa4a43272022-04-06 10:19:16 +0800320
321 return cpu_clk;
322}