blob: 38bcbb91e6e8abdc76098b300b48ff1d5cff0e88 [file] [log] [blame]
Peng Fan690eea12021-08-07 16:00:45 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2021 NXP
4 */
5
6#include <common.h>
7#include <div64.h>
8#include <asm/io.h>
9#include <errno.h>
10#include <asm/arch/imx-regs.h>
11#include <asm/arch/cgc.h>
12#include <asm/arch/sys_proto.h>
13#include <asm/global_data.h>
14#include <linux/delay.h>
15
16DECLARE_GLOBAL_DATA_PTR;
17
18static struct cgc1_regs *cgc1_regs = (struct cgc1_regs *)0x292C0000UL;
19static struct cgc2_regs *cgc2_regs = (struct cgc2_regs *)0x2da60000UL;
20
21void cgc1_soscdiv_init(void)
22{
23 /* Configure SOSC/FRO DIV1 ~ DIV3 */
24 clrbits_le32(&cgc1_regs->soscdiv, BIT(7));
25 clrbits_le32(&cgc1_regs->soscdiv, BIT(15));
26 clrbits_le32(&cgc1_regs->soscdiv, BIT(23));
27 clrbits_le32(&cgc1_regs->soscdiv, BIT(31));
28
29 clrbits_le32(&cgc1_regs->frodiv, BIT(7));
30}
31
32void cgc1_pll2_init(void)
33{
34 u32 reg;
35
36 if (readl(&cgc1_regs->pll2csr) & BIT(23))
37 clrbits_le32(&cgc1_regs->pll2csr, BIT(23));
38
39 /* Disable PLL2 */
40 clrbits_le32(&cgc1_regs->pll2csr, BIT(0));
41 mdelay(1);
42
43 /* wait valid bit false */
44 while ((readl(&cgc1_regs->pll2csr) & BIT(24)))
45 ;
46
47 /* Select SOSC as source, freq = 31 * 24 =744mhz */
48 reg = 31 << 16;
49 writel(reg, &cgc1_regs->pll2cfg);
50
51 /* Enable PLL2 */
52 setbits_le32(&cgc1_regs->pll2csr, BIT(0));
53
54 /* Wait for PLL2 clock ready */
55 while (!(readl(&cgc1_regs->pll2csr) & BIT(24)))
56 ;
57}
58
59static void cgc1_set_a35_clk(u32 clk_src, u32 div_core)
60{
61 u32 reg;
62
63 /* ulock */
64 if (readl(&cgc1_regs->ca35clk) & BIT(31))
65 clrbits_le32(&cgc1_regs->ca35clk, BIT(31));
66
67 reg = readl(&cgc1_regs->ca35clk);
68 reg &= ~GENMASK(29, 21);
69 reg |= ((clk_src & 0x3) << 28);
70 reg |= (((div_core - 1) & 0x3f) << 21);
71 writel(reg, &cgc1_regs->ca35clk);
72
73 while (!(readl(&cgc1_regs->ca35clk) & BIT(27)))
74 ;
75}
76
77void cgc1_init_core_clk(void)
78{
79 u32 reg = readl(&cgc1_regs->ca35clk);
80
81 /* if already selected to PLL2, switch to FRO firstly */
82 if (((reg >> 28) & 0x3) == 0x1)
83 cgc1_set_a35_clk(0, 1);
84
85 /* Set pll2 to 750Mhz for 1V */
86 cgc1_pll2_init();
87
88 /* Set A35 clock to pll2 */
89 cgc1_set_a35_clk(1, 1);
90}
91
92void cgc1_enet_stamp_sel(u32 clk_src)
93{
94 writel((clk_src & 0x7) << 24, &cgc1_regs->enetstamp);
95}
96
97void cgc1_pll3_init(void)
98{
99 /* Gate off VCO */
100 setbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
101
102 /* Disable PLL3 */
103 clrbits_le32(&cgc1_regs->pll3csr, BIT(0));
104
105 /* Gate off PFDxDIV */
106 setbits_le32(&cgc1_regs->pll3div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31));
107 setbits_le32(&cgc1_regs->pll3div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31));
108
109 /* Gate off PFDx */
110 setbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7));
111 setbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15));
112 setbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23));
113 setbits_le32(&cgc1_regs->pll3pfdcfg, BIT(31));
114
115 /* Select SOSC as source */
116 clrbits_le32(&cgc1_regs->pll3cfg, BIT(0));
117
118 //setbits_le32(&cgc1_regs->pll3cfg, 22 << 16);
119 writel(22 << 16, &cgc1_regs->pll3cfg);
120
121 writel(578, &cgc1_regs->pll3num);
122 writel(1000, &cgc1_regs->pll3denom);
123
124 /* Enable PLL3 */
125 setbits_le32(&cgc1_regs->pll3csr, BIT(0));
126
127 /* Wait for PLL3 clock ready */
128 while (!(readl(&cgc1_regs->pll3csr) & BIT(24)))
129 ;
130 /* Gate on VCO */
131 clrbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
132
133 /*
134 * PFD0: 380MHz/396/396/328
135 */
136 clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F);
137 setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0);
138 clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7));
139 while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(6)))
140 ;
141
142 clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 8);
143 setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 8);
144 clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15));
145 while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(14)))
146 ;
147
148 clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 16);
149 setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 16);
150 clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23));
151 while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(22)))
152 ;
153
154 clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 24);
155 setbits_le32(&cgc1_regs->pll3pfdcfg, 29 << 24);
156 clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(31));
157 while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(30)))
158 ;
159
160 clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(7));
161 clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(15));
162 clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(23));
163 clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(31));
164
165 clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(7));
166 clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(15));
167 clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(23));
168 clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(31));
169}
170
171void cgc2_pll4_init(void)
172{
173 /* Disable PFD DIV and clear DIV */
174 writel(0x80808080, &cgc2_regs->pll4div_pfd0);
175 writel(0x80808080, &cgc2_regs->pll4div_pfd1);
176
177 /* Gate off and clear PFD */
178 writel(0x80808080, &cgc2_regs->pll4pfdcfg);
179
180 /* Disable PLL4 */
181 writel(0x0, &cgc2_regs->pll4csr);
182
183 /* Configure PLL4 to 528Mhz and clock source from SOSC */
184 writel(22 << 16, &cgc2_regs->pll4cfg);
185 writel(0x1, &cgc2_regs->pll4csr);
186
187 /* wait for PLL4 output valid */
188 while (!(readl(&cgc2_regs->pll4csr) & BIT(24)))
189 ;
190
191 /* Enable all 4 PFDs */
Ye Lida0469d2021-10-29 09:46:18 +0800192 setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0);
193 setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */
Peng Fan690eea12021-08-07 16:00:45 +0800194 setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16);
195 setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24);
196
197 clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) | BIT(15) | BIT(23) | BIT(31));
198
199 while ((readl(&cgc2_regs->pll4pfdcfg) & (BIT(30) | BIT(22) | BIT(14) | BIT(6)))
200 != (BIT(30) | BIT(22) | BIT(14) | BIT(6)))
201 ;
202
203 /* Enable PFD DIV */
204 clrbits_le32(&cgc2_regs->pll4div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31));
205 clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31));
206}
207
Ye Lida0469d2021-10-29 09:46:18 +0800208void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd)
209{
210 void __iomem *reg = &cgc2_regs->pll4div_pfd0;
211 u32 halt_mask = BIT(7) | BIT(15);
212 u32 pfd_shift = (pllpfd - PLL4_PFD0) * 8;
213 u32 val;
214
215 if (pllpfd < PLL4_PFD0 || pllpfd > PLL4_PFD3)
216 return;
217
218 if ((pllpfd - PLL4_PFD0) >> 1)
219 reg = &cgc2_regs->pll4div_pfd1;
220
221 halt_mask = halt_mask << (((pllpfd - PLL4_PFD0) & 0x1) * 16);
222
223 /* halt pfd div */
224 setbits_le32(reg, halt_mask);
225
226 /* gate pfd */
227 setbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) << pfd_shift);
228
229 val = readl(&cgc2_regs->pll4pfdcfg);
230 val &= ~(0x3f << pfd_shift);
231 val |= (pfd << pfd_shift);
232 writel(val, &cgc2_regs->pll4pfdcfg);
233
234 /* ungate */
235 clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) << pfd_shift);
236
237 /* Wait stable */
238 while ((readl(&cgc2_regs->pll4pfdcfg) & (BIT(6) << pfd_shift))
239 != (BIT(6) << pfd_shift))
240 ;
241
242 /* enable pfd div */
243 clrbits_le32(reg, halt_mask);
244}
245
246void cgc2_pll4_pfddiv_config(enum cgc_clk pllpfddiv, u32 div)
247{
248 void __iomem *reg = &cgc2_regs->pll4div_pfd0;
249 u32 shift = ((pllpfddiv - PLL4_PFD0_DIV1) & 0x3) * 8;
250
251 if (pllpfddiv < PLL4_PFD0_DIV1 || pllpfddiv > PLL4_PFD3_DIV2)
252 return;
253
254 if ((pllpfddiv - PLL4_PFD0_DIV1) >> 2)
255 reg = &cgc2_regs->pll4div_pfd1;
256
257 /* Halt pfd div */
258 setbits_le32(reg, BIT(7) << shift);
259
260 /* Clear div */
261 clrbits_le32(reg, 0x3f << shift);
262
263 /* Set div*/
264 setbits_le32(reg, div << shift);
265
266 /* Enable pfd div */
267 clrbits_le32(reg, BIT(7) << shift);
268}
269
Peng Fan690eea12021-08-07 16:00:45 +0800270void cgc2_ddrclk_config(u32 src, u32 div)
271{
Ye Li88408302021-10-29 09:46:30 +0800272 /* If reg lock is set, wait until unlock by HW */
273 /* This lock is triggered by div updating and ddrclk halt status change, */
274 while ((readl(&cgc2_regs->ddrclk) & BIT(31)))
275 ;
276
Peng Fan690eea12021-08-07 16:00:45 +0800277 writel((src << 28) | (div << 21), &cgc2_regs->ddrclk);
278 /* wait for DDRCLK switching done */
279 while (!(readl(&cgc2_regs->ddrclk) & BIT(27)))
280 ;
281}
282
Ye Li88408302021-10-29 09:46:30 +0800283void cgc2_ddrclk_wait_unlock(void)
284{
285 while ((readl(&cgc2_regs->ddrclk) & BIT(31)))
286 ;
287}
288
Ye Lida0469d2021-10-29 09:46:18 +0800289void cgc2_lpav_init(enum cgc_clk clk)
290{
291 u32 i, scs, reg;
292 const enum cgc_clk src[] = {FRO, PLL4_PFD1, SOSC, LVDS};
293
294 reg = readl(&cgc2_regs->niclpavclk);
295 scs = (reg >> 28) & 0x3;
296
297 for (i = 0; i < 4; i++) {
298 if (clk == src[i]) {
299 if (scs == i)
300 return;
301
302 reg &= ~(0x3 << 28);
303 reg |= (i << 28);
304
305 writel(reg, &cgc2_regs->niclpavclk);
306 break;
307 }
308 }
309
310 if (i == 4)
311 printf("Invalid clock source [%u] for LPAV\n", clk);
312}
313
314u32 cgc2_nic_get_rate(enum cgc_clk clk)
315{
316 u32 reg, rate;
317 u32 scs, lpav_axi_clk, lpav_ahb_clk, lpav_bus_clk;
318 const enum cgc_clk src[] = {FRO, PLL4_PFD1, SOSC, LVDS};
319
320 reg = readl(&cgc2_regs->niclpavclk);
321 scs = (reg >> 28) & 0x3;
322 lpav_axi_clk = ((reg >> 21) & 0x3f) + 1;
323 lpav_ahb_clk = ((reg >> 14) & 0x3f) + 1;
324 lpav_bus_clk = ((reg >> 7) & 0x3f) + 1;
325
326 rate = cgc_clk_get_rate(src[scs]);
327
328 switch (clk) {
329 case LPAV_AXICLK:
330 rate = rate / lpav_axi_clk;
331 break;
332 case LPAV_AHBCLK:
333 rate = rate / (lpav_axi_clk * lpav_ahb_clk);
334 break;
335 case LPAV_BUSCLK:
336 rate = rate / (lpav_axi_clk * lpav_bus_clk);
337 break;
338 default:
339 return 0;
340 }
341
342 return rate;
343}
344
345u32 decode_pll(enum cgc_clk pll)
Peng Fan690eea12021-08-07 16:00:45 +0800346{
347 u32 reg, infreq, mult;
348 u32 num, denom;
349
350 infreq = 24000000U;
351 /*
352 * Alought there are four choices for the bypass src,
353 * we choose SOSC 24M which is the default set in ROM.
354 * TODO: check more the comments
355 */
356 switch (pll) {
357 case PLL2:
358 reg = readl(&cgc1_regs->pll2csr);
359 if (!(reg & BIT(24)))
360 return 0;
361
362 reg = readl(&cgc1_regs->pll2cfg);
363 mult = (reg >> 16) & 0x7F;
364 denom = readl(&cgc1_regs->pll2denom) & 0x3FFFFFFF;
365 num = readl(&cgc1_regs->pll2num) & 0x3FFFFFFF;
366
367 return (u64)infreq * mult + (u64)infreq * num / denom;
368 case PLL3:
369 reg = readl(&cgc1_regs->pll3csr);
370 if (!(reg & BIT(24)))
371 return 0;
372
373 reg = readl(&cgc1_regs->pll3cfg);
374 mult = (reg >> 16) & 0x7F;
375 denom = readl(&cgc1_regs->pll3denom) & 0x3FFFFFFF;
376 num = readl(&cgc1_regs->pll3num) & 0x3FFFFFFF;
377
378 return (u64)infreq * mult + (u64)infreq * num / denom;
Ye Lida0469d2021-10-29 09:46:18 +0800379 case PLL4:
380 reg = readl(&cgc2_regs->pll4csr);
381 if (!(reg & BIT(24)))
382 return 0;
383
384 reg = readl(&cgc2_regs->pll4cfg);
385 mult = (reg >> 16) & 0x7F;
386 denom = readl(&cgc2_regs->pll4denom) & 0x3FFFFFFF;
387 num = readl(&cgc2_regs->pll4num) & 0x3FFFFFFF;
388
389 return (u64)infreq * mult + (u64)infreq * num / denom;
Peng Fan690eea12021-08-07 16:00:45 +0800390 default:
391 printf("Unsupported pll clocks %d\n", pll);
392 break;
393 }
394
395 return 0;
396}
397
Ye Lida0469d2021-10-29 09:46:18 +0800398u32 cgc_pll_vcodiv_rate(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800399{
400 u32 reg, gate, div;
Ye Lida0469d2021-10-29 09:46:18 +0800401 void __iomem *plldiv_vco;
402 enum cgc_clk pll;
403
404 if (clk == PLL3_VCODIV) {
405 plldiv_vco = &cgc1_regs->pll3div_vco;
406 pll = PLL3;
407 } else {
408 plldiv_vco = &cgc2_regs->pll4div_vco;
409 pll = PLL4;
410 }
Peng Fan690eea12021-08-07 16:00:45 +0800411
Ye Lida0469d2021-10-29 09:46:18 +0800412 reg = readl(plldiv_vco);
Peng Fan690eea12021-08-07 16:00:45 +0800413 gate = BIT(7) & reg;
414 div = reg & 0x3F;
415
Ye Lida0469d2021-10-29 09:46:18 +0800416 return gate ? 0 : decode_pll(pll) / (div + 1);
Peng Fan690eea12021-08-07 16:00:45 +0800417}
418
Ye Lida0469d2021-10-29 09:46:18 +0800419u32 cgc_pll_pfd_rate(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800420{
421 u32 index, gate, vld, reg;
Ye Lida0469d2021-10-29 09:46:18 +0800422 void __iomem *pllpfdcfg;
423 enum cgc_clk pll;
Peng Fan690eea12021-08-07 16:00:45 +0800424
425 switch (clk) {
426 case PLL3_PFD0:
Peng Fan690eea12021-08-07 16:00:45 +0800427 case PLL3_PFD1:
Peng Fan690eea12021-08-07 16:00:45 +0800428 case PLL3_PFD2:
Peng Fan690eea12021-08-07 16:00:45 +0800429 case PLL3_PFD3:
Ye Lida0469d2021-10-29 09:46:18 +0800430 index = clk - PLL3_PFD0;
431 pllpfdcfg = &cgc1_regs->pll3pfdcfg;
432 pll = PLL3;
433 break;
434 case PLL4_PFD0:
435 case PLL4_PFD1:
436 case PLL4_PFD2:
437 case PLL4_PFD3:
438 index = clk - PLL4_PFD0;
439 pllpfdcfg = &cgc2_regs->pll4pfdcfg;
440 pll = PLL4;
Peng Fan690eea12021-08-07 16:00:45 +0800441 break;
442 default:
443 return 0;
444 }
445
Ye Lida0469d2021-10-29 09:46:18 +0800446 reg = readl(pllpfdcfg);
Peng Fan690eea12021-08-07 16:00:45 +0800447 gate = reg & (BIT(7) << (index * 8));
448 vld = reg & (BIT(6) << (index * 8));
449
450 if (gate || !vld)
451 return 0;
452
Ye Lida0469d2021-10-29 09:46:18 +0800453 return (u64)decode_pll(pll) * 18 / ((reg >> (index * 8)) & 0x3F);
Peng Fan690eea12021-08-07 16:00:45 +0800454}
455
Ye Lida0469d2021-10-29 09:46:18 +0800456u32 cgc_pll_pfd_div(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800457{
458 void __iomem *base;
459 u32 pfd, index, gate, reg;
460
461 switch (clk) {
462 case PLL3_PFD0_DIV1:
Peng Fan690eea12021-08-07 16:00:45 +0800463 case PLL3_PFD0_DIV2:
464 base = &cgc1_regs->pll3div_pfd0;
465 pfd = PLL3_PFD0;
Ye Lida0469d2021-10-29 09:46:18 +0800466 index = clk - PLL3_PFD0_DIV1;
Peng Fan690eea12021-08-07 16:00:45 +0800467 break;
468 case PLL3_PFD1_DIV1:
Peng Fan690eea12021-08-07 16:00:45 +0800469 case PLL3_PFD1_DIV2:
470 base = &cgc1_regs->pll3div_pfd0;
471 pfd = PLL3_PFD1;
Ye Lida0469d2021-10-29 09:46:18 +0800472 index = clk - PLL3_PFD0_DIV1;
Peng Fan690eea12021-08-07 16:00:45 +0800473 break;
474 case PLL3_PFD2_DIV1:
Peng Fan690eea12021-08-07 16:00:45 +0800475 case PLL3_PFD2_DIV2:
476 base = &cgc1_regs->pll3div_pfd1;
477 pfd = PLL3_PFD2;
Ye Lida0469d2021-10-29 09:46:18 +0800478 index = clk - PLL3_PFD2_DIV1;
Peng Fan690eea12021-08-07 16:00:45 +0800479 break;
480 case PLL3_PFD3_DIV1:
Peng Fan690eea12021-08-07 16:00:45 +0800481 case PLL3_PFD3_DIV2:
482 base = &cgc1_regs->pll3div_pfd1;
483 pfd = PLL3_PFD3;
Ye Lida0469d2021-10-29 09:46:18 +0800484 index = clk - PLL3_PFD2_DIV1;
485 break;
486 case PLL4_PFD0_DIV1:
487 case PLL4_PFD0_DIV2:
488 base = &cgc2_regs->pll4div_pfd0;
489 pfd = PLL4_PFD0;
490 index = clk - PLL4_PFD0_DIV1;
491 break;
492 case PLL4_PFD1_DIV1:
493 case PLL4_PFD1_DIV2:
494 base = &cgc2_regs->pll4div_pfd0;
495 pfd = PLL4_PFD1;
496 index = clk - PLL4_PFD0_DIV1;
497 break;
498 case PLL4_PFD2_DIV1:
499 case PLL4_PFD2_DIV2:
500 base = &cgc2_regs->pll4div_pfd1;
501 pfd = PLL4_PFD2;
502 index = clk - PLL4_PFD2_DIV1;
503 break;
504 case PLL4_PFD3_DIV1:
505 case PLL4_PFD3_DIV2:
506 base = &cgc2_regs->pll4div_pfd1;
507 pfd = PLL4_PFD3;
508 index = clk - PLL4_PFD2_DIV1;
Peng Fan690eea12021-08-07 16:00:45 +0800509 break;
510 default:
511 return 0;
512 }
513
514 reg = readl(base);
515 gate = reg & (BIT(7) << (index * 8));
516
517 if (gate)
518 return 0;
Ye Lida0469d2021-10-29 09:46:18 +0800519
520 return cgc_pll_pfd_rate(pfd) / (((reg >> (index * 8)) & 0x3F) + 1);
521}
522
523u32 cgc1_nic_get_rate(enum cgc_clk clk)
524{
525 u32 reg, rate;
526 u32 scs, nic_ad_divplat, nic_per_divplat;
527 u32 xbar_ad_divplat, xbar_divbus, ad_slow;
528 const enum cgc_clk src[] = {FRO, PLL3_PFD0, SOSC, LVDS};
529
530 reg = readl(&cgc1_regs->nicclk);
531 scs = (reg >> 28) & 0x3;
532 nic_ad_divplat = ((reg >> 21) & 0x3f) + 1;
533 nic_per_divplat = ((reg >> 14) & 0x3f) + 1;
534
535 reg = readl(&cgc1_regs->xbarclk);
536 xbar_ad_divplat = ((reg >> 14) & 0x3f) + 1;
537 xbar_divbus = ((reg >> 7) & 0x3f) + 1;
538 ad_slow = (reg & 0x3f) + 1;
539
540 rate = cgc_clk_get_rate(src[scs]);
541
542 switch (clk) {
543 case NIC_APCLK:
544 rate = rate / nic_ad_divplat;
545 break;
546 case NIC_PERCLK:
547 rate = rate / (nic_ad_divplat * nic_per_divplat);
548 break;
549 case XBAR_APCLK:
550 rate = rate / (nic_ad_divplat * xbar_ad_divplat);
551 break;
552 case XBAR_BUSCLK:
553 rate = rate / (nic_ad_divplat * xbar_ad_divplat * xbar_divbus);
554 break;
555 case AD_SLOWCLK:
556 rate = rate / (nic_ad_divplat * xbar_ad_divplat * ad_slow);
557 break;
558 default:
559 return 0;
560 }
Peng Fan690eea12021-08-07 16:00:45 +0800561
Ye Lida0469d2021-10-29 09:46:18 +0800562 return rate;
Peng Fan690eea12021-08-07 16:00:45 +0800563}
564
Ye Lida0469d2021-10-29 09:46:18 +0800565u32 cgc1_sosc_div(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800566{
567 u32 reg, gate, index;
568
569 switch (clk) {
570 case SOSC:
571 return 24000000;
572 case SOSC_DIV1:
573 index = 0;
574 break;
575 case SOSC_DIV2:
576 index = 1;
577 break;
578 case SOSC_DIV3:
579 index = 2;
580 break;
581 default:
582 return 0;
583 }
584
585 reg = readl(&cgc1_regs->soscdiv);
586 gate = reg & (BIT(7) << (index * 8));
587
588 if (gate)
589 return 0;
590
591 return 24000000 / (((reg >> (index * 8)) & 0x3F) + 1);
592}
593
Ye Lida0469d2021-10-29 09:46:18 +0800594u32 cgc1_fro_div(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800595{
596 u32 reg, gate, vld, index;
597
598 switch (clk) {
599 case FRO:
600 return 192000000;
601 case FRO_DIV1:
602 index = 0;
603 break;
604 case FRO_DIV2:
605 index = 1;
606 break;
607 case FRO_DIV3:
608 index = 2;
609 break;
610 default:
611 return 0;
612 }
613
614 reg = readl(&cgc1_regs->frodiv);
615 gate = reg & (BIT(7) << (index * 8));
616 vld = reg & (BIT(6) << (index * 8));
617
618 if (gate || !vld)
619 return 0;
620
621 return 24000000 / (((reg >> (index * 8)) & 0x3F) + 1);
622}
623
Ye Lida0469d2021-10-29 09:46:18 +0800624u32 cgc_clk_get_rate(enum cgc_clk clk)
Peng Fan690eea12021-08-07 16:00:45 +0800625{
626 switch (clk) {
Ye Lida0469d2021-10-29 09:46:18 +0800627 case LVDS:
628 return 0; /* No external LVDS clock used */
Peng Fan690eea12021-08-07 16:00:45 +0800629 case SOSC:
630 case SOSC_DIV1:
631 case SOSC_DIV2:
632 case SOSC_DIV3:
633 return cgc1_sosc_div(clk);
634 case FRO:
635 case FRO_DIV1:
636 case FRO_DIV2:
637 case FRO_DIV3:
638 return cgc1_fro_div(clk);
639 case PLL2:
Peng Fan690eea12021-08-07 16:00:45 +0800640 case PLL3:
Ye Lida0469d2021-10-29 09:46:18 +0800641 case PLL4:
642 return decode_pll(clk);
Peng Fan690eea12021-08-07 16:00:45 +0800643 case PLL3_VCODIV:
Ye Lida0469d2021-10-29 09:46:18 +0800644 case PLL4_VCODIV:
645 return cgc_pll_vcodiv_rate(clk);
Peng Fan690eea12021-08-07 16:00:45 +0800646 case PLL3_PFD0:
647 case PLL3_PFD1:
648 case PLL3_PFD2:
649 case PLL3_PFD3:
Ye Lida0469d2021-10-29 09:46:18 +0800650 case PLL4_PFD0:
651 case PLL4_PFD1:
652 case PLL4_PFD2:
653 case PLL4_PFD3:
654 return cgc_pll_pfd_rate(clk);
Peng Fan690eea12021-08-07 16:00:45 +0800655 case PLL3_PFD0_DIV1:
656 case PLL3_PFD0_DIV2:
657 case PLL3_PFD1_DIV1:
658 case PLL3_PFD1_DIV2:
659 case PLL3_PFD2_DIV1:
660 case PLL3_PFD2_DIV2:
661 case PLL3_PFD3_DIV1:
662 case PLL3_PFD3_DIV2:
Ye Lida0469d2021-10-29 09:46:18 +0800663 case PLL4_PFD0_DIV1:
664 case PLL4_PFD0_DIV2:
665 case PLL4_PFD1_DIV1:
666 case PLL4_PFD1_DIV2:
667 case PLL4_PFD2_DIV1:
668 case PLL4_PFD2_DIV2:
669 case PLL4_PFD3_DIV1:
670 case PLL4_PFD3_DIV2:
671 return cgc_pll_pfd_div(clk);
672 case NIC_APCLK:
673 case NIC_PERCLK:
674 case XBAR_APCLK:
675 case XBAR_BUSCLK:
676 case AD_SLOWCLK:
677 return cgc1_nic_get_rate(clk);
678 case LPAV_AXICLK:
679 case LPAV_AHBCLK:
680 case LPAV_BUSCLK:
681 return cgc2_nic_get_rate(clk);
Peng Fan690eea12021-08-07 16:00:45 +0800682 default:
Ye Lida0469d2021-10-29 09:46:18 +0800683 printf("Unsupported cgc clock: %d\n", clk);
Peng Fan690eea12021-08-07 16:00:45 +0800684 return 0;
685 }
686}