blob: 218676a98fd6ab567bfa2db9f0fe7f8f628d4898 [file] [log] [blame]
Hadi Asyrafi616da772019-06-27 11:34:03 +08001/*
2 * Copyright (c) 2019, Intel Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <common/debug.h>
9#include <drivers/delay_timer.h>
10#include <errno.h>
11#include <lib/mmio.h>
12
13#include "agilex_clock_manager.h"
14#include "agilex_handoff.h"
Hadi Asyrafia813fed2019-08-14 13:49:00 +080015#include "agilex_system_manager.h"
Hadi Asyrafi616da772019-06-27 11:34:03 +080016
Hadi Asyrafi616da772019-06-27 11:34:03 +080017
18uint32_t wait_pll_lock(void)
19{
20 uint32_t data;
21 uint32_t count = 0;
22
23 do {
24 data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
25 count++;
26 if (count >= 1000)
27 return -ETIMEDOUT;
28
29 } while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
30 (CLKMGR_STAT_PERPLLLOCKED(data) == 0));
31 return 0;
32}
33
34uint32_t wait_fsm(void)
35{
36 uint32_t data;
37 uint32_t count = 0;
38
39 do {
40 data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
41 count++;
42 if (count >= 1000)
43 return -ETIMEDOUT;
44
45 } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
46
47 return 0;
48}
49
50uint32_t pll_source_sync_config(uint32_t pll_mem_offset)
51{
52 uint32_t val = 0;
53 uint32_t count = 0;
54 uint32_t req_status = 0;
55
56 val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
57 CLKMGR_MEM_WDAT << CLKMGR_MEM_WDAT_OFFSET | CLKMGR_MEM_ADDR);
58 mmio_write_32(pll_mem_offset, val);
59
60 do {
61 req_status = mmio_read_32(pll_mem_offset);
62 count++;
63 } while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
64
65 if (count >= 100)
66 return -ETIMEDOUT;
67
68 return 0;
69}
70
71uint32_t pll_source_sync_read(uint32_t pll_mem_offset)
72{
73 uint32_t val = 0;
74 uint32_t rdata = 0;
75 uint32_t count = 0;
76 uint32_t req_status = 0;
77
78 val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR);
79 mmio_write_32(pll_mem_offset, val);
80
81 do {
82 req_status = mmio_read_32(pll_mem_offset);
83 count++;
84 } while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
85
86 if (count >= 100)
87 return -ETIMEDOUT;
88
89 rdata = mmio_read_32(pll_mem_offset + 0x4);
90 INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
91
92 return 0;
93}
94
95void config_clkmgr_handoff(handoff *hoff_ptr)
96{
97 uint32_t mdiv, mscnt, hscnt;
98 uint32_t arefclk_div, drefclk_div;
99
100 /* Bypass all mainpllgrp's clocks */
101 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7);
102 wait_fsm();
103
104 /* Bypass all perpllgrp's clocks */
105 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f);
106 wait_fsm();
107
108 /* Put both PLL in reset and power down */
109 mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800110 CLKMGR_PLLGLOB_PD_SET_MSK |
111 CLKMGR_PLLGLOB_RST_SET_MSK);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800112 mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800113 CLKMGR_PLLGLOB_PD_SET_MSK |
114 CLKMGR_PLLGLOB_RST_SET_MSK);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800115
116 /* Setup main PLL dividers */
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800117 mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800118
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800119 arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
Hadi Asyrafi616da772019-06-27 11:34:03 +0800120 hoff_ptr->main_pll_pllglob);
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800121 drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
Hadi Asyrafi616da772019-06-27 11:34:03 +0800122 hoff_ptr->main_pll_pllglob);
123
124 mscnt = 100 / (mdiv / BIT(drefclk_div));
125 if (!mscnt)
126 mscnt = 1;
127 hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
128
129 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800130 CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
131 CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
Hadi Asyrafi616da772019-06-27 11:34:03 +0800132
133 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
134 hoff_ptr->main_pll_nocdiv);
135 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
136 hoff_ptr->main_pll_pllglob);
137 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
138 hoff_ptr->main_pll_fdbck);
139 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0,
140 hoff_ptr->main_pll_pllc0);
141 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1,
142 hoff_ptr->main_pll_pllc1);
143 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2,
144 hoff_ptr->main_pll_pllc2);
145 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3,
146 hoff_ptr->main_pll_pllc3);
147 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM,
148 hoff_ptr->main_pll_pllm);
149 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK,
150 hoff_ptr->main_pll_mpuclk);
151 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK,
152 hoff_ptr->main_pll_nocclk);
153
154 /* Setup peripheral PLL dividers */
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800155 mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800156
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800157 arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
Hadi Asyrafi616da772019-06-27 11:34:03 +0800158 hoff_ptr->per_pll_pllglob);
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800159 drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
Hadi Asyrafi616da772019-06-27 11:34:03 +0800160 hoff_ptr->per_pll_pllglob);
161
162 mscnt = 100 / (mdiv / BIT(drefclk_div));
163 if (!mscnt)
164 mscnt = 1;
165 hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
166
167 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800168 CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
169 CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
Hadi Asyrafi616da772019-06-27 11:34:03 +0800170
171 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
172 hoff_ptr->per_pll_emacctl);
173 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
174 CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(
175 hoff_ptr->per_pll_gpiodiv));
176 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
177 hoff_ptr->per_pll_pllglob);
178 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
179 hoff_ptr->per_pll_fdbck);
180 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0,
181 hoff_ptr->per_pll_pllc0);
182 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1,
183 hoff_ptr->per_pll_pllc1);
184 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2,
185 hoff_ptr->per_pll_pllc2);
186 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3,
187 hoff_ptr->per_pll_pllc3);
188 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM,
189 hoff_ptr->per_pll_pllm);
190
191 /* Take both PLL out of reset and power up */
192 mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800193 CLKMGR_PLLGLOB_PD_SET_MSK |
194 CLKMGR_PLLGLOB_RST_SET_MSK);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800195 mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800196 CLKMGR_PLLGLOB_PD_SET_MSK |
197 CLKMGR_PLLGLOB_RST_SET_MSK);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800198
199 wait_pll_lock();
200
201 pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
202 pll_source_sync_read(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
203
204 pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
205 pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
206
207 /*Configure Ping Pong counters in altera group */
208 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR,
209 hoff_ptr->alt_emacactr);
210 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR,
211 hoff_ptr->alt_emacbctr);
212 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR,
213 hoff_ptr->alt_emacptpctr);
214 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR,
215 hoff_ptr->alt_gpiodbctr);
216 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR,
217 hoff_ptr->alt_sdmmcctr);
218 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR,
219 hoff_ptr->alt_s2fuser0ctr);
220 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR,
221 hoff_ptr->alt_s2fuser1ctr);
222 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR,
223 hoff_ptr->alt_psirefctr);
224
225 /* Take all PLLs out of bypass */
226 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0);
227 wait_fsm();
228
229 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0);
230 wait_fsm();
231
232 /* Clear loss lock interrupt status register that */
233 /* might be set during configuration */
234 mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
235 CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
236 CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
237
238 /* Take all ping pong counters out of reset */
239 mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST,
240 CLKMGR_ALTERA_EXTCNTRST_RESET);
241
242 /* Set safe mode / out of boot mode */
243 mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
244 CLKMGR_CTRL_BOOTMODE_SET_MSK);
245 wait_fsm();
246
247 /* Enable mainpllgrp's software-managed clock */
248 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN,
249 CLKMGR_MAINPLL_EN_RESET);
250 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
251 CLKMGR_PERPLL_EN_RESET);
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800252
253 /* Pass clock source frequency into scratch register */
254 mmio_write_32(AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_1),
255 hoff_ptr->hps_osc_clk_h);
256 mmio_write_32(AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_2),
257 hoff_ptr->fpga_clk_hz);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800258}
259
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800260/* Extract reference clock from platform clock source */
261uint32_t get_ref_clk(uint32_t pllglob)
Hadi Asyrafi616da772019-06-27 11:34:03 +0800262{
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800263 uint32_t arefclkdiv, ref_clk;
264 uint32_t scr_reg;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800265
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800266 switch (CLKMGR_PSRC(pllglob)) {
267 case CLKMGR_PLLGLOB_PSRC_EOSC1:
268 scr_reg = AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_1);
269 ref_clk = mmio_read_32(scr_reg);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800270 break;
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800271 case CLKMGR_PLLGLOB_PSRC_INTOSC:
272 ref_clk = CLKMGR_INTOSC_HZ;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800273 break;
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800274 case CLKMGR_PLLGLOB_PSRC_F2S:
275 scr_reg = AGX_SYSMGR_CORE(SYSMGR_BOOT_SCRATCH_COLD_2);
276 ref_clk = mmio_read_32(scr_reg);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800277 break;
278 default:
279 ref_clk = 0;
280 assert(0);
281 break;
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800282 }
283
284 arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
285 ref_clk /= arefclkdiv;
286
287 return ref_clk;
288}
289
290/* Calculate clock frequency based on parameter */
291uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
292{
293 uint32_t clk_psrc, mdiv, ref_clk;
294 uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
295
296 clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
297
298 switch (CLKMGR_PSRC(clk_psrc)) {
299 case CLKMGR_PSRC_MAIN:
300 pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
301 pllc_reg = CLKMGR_MAINPLL + main_pllc;
302 pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
303 break;
304 case CLKMGR_PSRC_PER:
305 pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
306 pllc_reg = CLKMGR_PERPLL + per_pllc;
307 pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
308 break;
309 default:
310 return 0;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800311 }
312
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800313 ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
314 mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
315 ref_clk *= mdiv;
316
317 pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
318
319 return ref_clk / pllc_div;
320}
321
322/* Return L3 interconnect clock */
323uint32_t get_l3_clk(void)
324{
325 uint32_t l3_clk;
326
327 l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
328 CLKMGR_PERPLL_PLLC1);
329 return l3_clk;
330}
331
332/* Calculate clock frequency to be used for watchdog timer */
333uint32_t get_wdt_clk(void)
334{
335 uint32_t l3_clk, l4_sys_clk;
336
337 l3_clk = get_l3_clk();
338 l4_sys_clk = l3_clk / 4;
339
340 return l4_sys_clk;
341}
342
343/* Calculate clock frequency to be used for UART driver */
344uint32_t get_uart_clk(void)
345{
346 uint32_t data32, l3_clk, l4_sp_clk;
347
348 l3_clk = get_l3_clk();
349
350 data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
351 data32 = (data32 >> 16) & 0x3;
352
353 l4_sp_clk = l3_clk >> data32;
354
355 return l4_sp_clk;
356}
357
358/* Calculate clock frequency to be used for SDMMC driver */
359uint32_t get_mmc_clk(void)
360{
361 uint32_t data32, mmc_clk;
362
363 mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
364 CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
Hadi Asyrafi616da772019-06-27 11:34:03 +0800365
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800366 data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
367 data32 = (data32 & 0x7ff) + 1;
368 mmc_clk = (mmc_clk / data32) / 4;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800369
Hadi Asyrafia813fed2019-08-14 13:49:00 +0800370 return mmc_clk;
Hadi Asyrafi616da772019-06-27 11:34:03 +0800371}