1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2013 Broadcom Corporation.
4 */
5
6 /*
7 *
8 * bcm281xx-specific clock tables
9 *
10 */
11
12 #include <common.h>
13 #include <asm/io.h>
14 #include <linux/errno.h>
15 #include <asm/arch/sysmap.h>
16 #include <asm/kona-common/clk.h>
17 #include "clk-core.h"
18
19 #define CLOCK_1K 1000
20 #define CLOCK_1M (CLOCK_1K * 1000)
21
22 /* declare a reference clock */
23 #define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \
24 static struct refclk clk_name = { \
25 .clk = { \
26 .name = #clk_name, \
27 .parent = clk_parent, \
28 .rate = clk_rate, \
29 .div = clk_div, \
30 .ops = &ref_clk_ops, \
31 }, \
32 }
33
34 /*
35 * Reference clocks
36 */
37
38 /* Declare a list of reference clocks */
39 DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1);
40 DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1);
41 DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1);
42 DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0);
43 DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3);
44 DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2);
45 DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4);
46 DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0);
47 DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3);
48 DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2);
49 DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4);
50
51 struct refclk_lkup {
52 struct refclk *procclk;
53 const char *name;
54 };
55
56 /* Lookup table for string to clk tranlation */
57 #define MKSTR(x) {&x, #x}
58 static struct refclk_lkup refclk_str_tbl[] = {
59 MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m),
60 MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m),
61 MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m),
62 MKSTR(var_52m), MKSTR(var_13m),
63 };
64
65 int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
66
67 /* convert ref clock string to clock structure pointer */
refclk_str_to_clk(const char * name)68 struct refclk *refclk_str_to_clk(const char *name)
69 {
70 int i;
71 struct refclk_lkup *tblp = refclk_str_tbl;
72 for (i = 0; i < refclk_entries; i++, tblp++) {
73 if (!(strcmp(name, tblp->name)))
74 return tblp->procclk;
75 }
76 return NULL;
77 }
78
79 /* frequency tables indexed by freq_id */
80 unsigned long master_axi_freq_tbl[8] = {
81 26 * CLOCK_1M,
82 52 * CLOCK_1M,
83 104 * CLOCK_1M,
84 156 * CLOCK_1M,
85 156 * CLOCK_1M,
86 208 * CLOCK_1M,
87 312 * CLOCK_1M,
88 312 * CLOCK_1M
89 };
90
91 unsigned long master_ahb_freq_tbl[8] = {
92 26 * CLOCK_1M,
93 52 * CLOCK_1M,
94 52 * CLOCK_1M,
95 52 * CLOCK_1M,
96 78 * CLOCK_1M,
97 104 * CLOCK_1M,
98 104 * CLOCK_1M,
99 156 * CLOCK_1M
100 };
101
102 unsigned long slave_axi_freq_tbl[8] = {
103 26 * CLOCK_1M,
104 52 * CLOCK_1M,
105 78 * CLOCK_1M,
106 104 * CLOCK_1M,
107 156 * CLOCK_1M,
108 156 * CLOCK_1M
109 };
110
111 unsigned long slave_apb_freq_tbl[8] = {
112 26 * CLOCK_1M,
113 26 * CLOCK_1M,
114 39 * CLOCK_1M,
115 52 * CLOCK_1M,
116 52 * CLOCK_1M,
117 78 * CLOCK_1M
118 };
119
120 unsigned long esub_freq_tbl[8] = {
121 78 * CLOCK_1M,
122 156 * CLOCK_1M,
123 156 * CLOCK_1M,
124 156 * CLOCK_1M,
125 208 * CLOCK_1M,
126 208 * CLOCK_1M,
127 208 * CLOCK_1M
128 };
129
130 static struct bus_clk_data bsc1_apb_data = {
131 .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
132 };
133
134 static struct bus_clk_data bsc2_apb_data = {
135 .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
136 };
137
138 static struct bus_clk_data bsc3_apb_data = {
139 .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
140 };
141
142 /* * Master CCU clocks */
143 static struct peri_clk_data sdio1_data = {
144 .gate = HW_SW_GATE(0x0358, 18, 2, 3),
145 .clocks = CLOCKS("ref_crystal",
146 "var_52m",
147 "ref_52m",
148 "var_96m",
149 "ref_96m"),
150 .sel = SELECTOR(0x0a28, 0, 3),
151 .div = DIVIDER(0x0a28, 4, 14),
152 .trig = TRIGGER(0x0afc, 9),
153 };
154
155 static struct peri_clk_data sdio2_data = {
156 .gate = HW_SW_GATE(0x035c, 18, 2, 3),
157 .clocks = CLOCKS("ref_crystal",
158 "var_52m",
159 "ref_52m",
160 "var_96m",
161 "ref_96m"),
162 .sel = SELECTOR(0x0a2c, 0, 3),
163 .div = DIVIDER(0x0a2c, 4, 14),
164 .trig = TRIGGER(0x0afc, 10),
165 };
166
167 static struct peri_clk_data sdio3_data = {
168 .gate = HW_SW_GATE(0x0364, 18, 2, 3),
169 .clocks = CLOCKS("ref_crystal",
170 "var_52m",
171 "ref_52m",
172 "var_96m",
173 "ref_96m"),
174 .sel = SELECTOR(0x0a34, 0, 3),
175 .div = DIVIDER(0x0a34, 4, 14),
176 .trig = TRIGGER(0x0afc, 12),
177 };
178
179 static struct peri_clk_data sdio4_data = {
180 .gate = HW_SW_GATE(0x0360, 18, 2, 3),
181 .clocks = CLOCKS("ref_crystal",
182 "var_52m",
183 "ref_52m",
184 "var_96m",
185 "ref_96m"),
186 .sel = SELECTOR(0x0a30, 0, 3),
187 .div = DIVIDER(0x0a30, 4, 14),
188 .trig = TRIGGER(0x0afc, 11),
189 };
190
191 static struct peri_clk_data sdio1_sleep_data = {
192 .clocks = CLOCKS("ref_32k"),
193 .gate = SW_ONLY_GATE(0x0358, 20, 4),
194 };
195
196 static struct peri_clk_data sdio2_sleep_data = {
197 .clocks = CLOCKS("ref_32k"),
198 .gate = SW_ONLY_GATE(0x035c, 20, 4),
199 };
200
201 static struct peri_clk_data sdio3_sleep_data = {
202 .clocks = CLOCKS("ref_32k"),
203 .gate = SW_ONLY_GATE(0x0364, 20, 4),
204 };
205
206 static struct peri_clk_data sdio4_sleep_data = {
207 .clocks = CLOCKS("ref_32k"),
208 .gate = SW_ONLY_GATE(0x0360, 20, 4),
209 };
210
211 static struct bus_clk_data usb_otg_ahb_data = {
212 .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
213 };
214
215 static struct bus_clk_data sdio1_ahb_data = {
216 .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
217 };
218
219 static struct bus_clk_data sdio2_ahb_data = {
220 .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
221 };
222
223 static struct bus_clk_data sdio3_ahb_data = {
224 .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
225 };
226
227 static struct bus_clk_data sdio4_ahb_data = {
228 .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
229 };
230
231 /* * Slave CCU clocks */
232 static struct peri_clk_data bsc1_data = {
233 .gate = HW_SW_GATE(0x0458, 18, 2, 3),
234 .clocks = CLOCKS("ref_crystal",
235 "var_104m",
236 "ref_104m",
237 "var_13m",
238 "ref_13m"),
239 .sel = SELECTOR(0x0a64, 0, 3),
240 .trig = TRIGGER(0x0afc, 23),
241 };
242
243 static struct peri_clk_data bsc2_data = {
244 .gate = HW_SW_GATE(0x045c, 18, 2, 3),
245 .clocks = CLOCKS("ref_crystal",
246 "var_104m",
247 "ref_104m",
248 "var_13m",
249 "ref_13m"),
250 .sel = SELECTOR(0x0a68, 0, 3),
251 .trig = TRIGGER(0x0afc, 24),
252 };
253
254 static struct peri_clk_data bsc3_data = {
255 .gate = HW_SW_GATE(0x0484, 18, 2, 3),
256 .clocks = CLOCKS("ref_crystal",
257 "var_104m",
258 "ref_104m",
259 "var_13m",
260 "ref_13m"),
261 .sel = SELECTOR(0x0a84, 0, 3),
262 .trig = TRIGGER(0x0b00, 2),
263 };
264
265 /*
266 * CCU clocks
267 */
268
269 static struct ccu_clock kpm_ccu_clk = {
270 .clk = {
271 .name = "kpm_ccu_clk",
272 .ops = &ccu_clk_ops,
273 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
274 },
275 .num_policy_masks = 1,
276 .policy_freq_offset = 0x00000008,
277 .freq_bit_shift = 8,
278 .policy_ctl_offset = 0x0000000c,
279 .policy0_mask_offset = 0x00000010,
280 .policy1_mask_offset = 0x00000014,
281 .policy2_mask_offset = 0x00000018,
282 .policy3_mask_offset = 0x0000001c,
283 .lvm_en_offset = 0x00000034,
284 .freq_id = 2,
285 .freq_tbl = master_axi_freq_tbl,
286 };
287
288 static struct ccu_clock kps_ccu_clk = {
289 .clk = {
290 .name = "kps_ccu_clk",
291 .ops = &ccu_clk_ops,
292 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
293 },
294 .num_policy_masks = 2,
295 .policy_freq_offset = 0x00000008,
296 .freq_bit_shift = 8,
297 .policy_ctl_offset = 0x0000000c,
298 .policy0_mask_offset = 0x00000010,
299 .policy1_mask_offset = 0x00000014,
300 .policy2_mask_offset = 0x00000018,
301 .policy3_mask_offset = 0x0000001c,
302 .policy0_mask2_offset = 0x00000048,
303 .policy1_mask2_offset = 0x0000004c,
304 .policy2_mask2_offset = 0x00000050,
305 .policy3_mask2_offset = 0x00000054,
306 .lvm_en_offset = 0x00000034,
307 .freq_id = 2,
308 .freq_tbl = slave_axi_freq_tbl,
309 };
310
311 #ifdef CONFIG_BCM_SF2_ETH
312 static struct ccu_clock esub_ccu_clk = {
313 .clk = {
314 .name = "esub_ccu_clk",
315 .ops = &ccu_clk_ops,
316 .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
317 },
318 .num_policy_masks = 1,
319 .policy_freq_offset = 0x00000008,
320 .freq_bit_shift = 8,
321 .policy_ctl_offset = 0x0000000c,
322 .policy0_mask_offset = 0x00000010,
323 .policy1_mask_offset = 0x00000014,
324 .policy2_mask_offset = 0x00000018,
325 .policy3_mask_offset = 0x0000001c,
326 .lvm_en_offset = 0x00000034,
327 .freq_id = 2,
328 .freq_tbl = esub_freq_tbl,
329 };
330 #endif
331
332 /*
333 * Bus clocks
334 */
335
336 /* KPM bus clocks */
337 static struct bus_clock usb_otg_ahb_clk = {
338 .clk = {
339 .name = "usb_otg_ahb_clk",
340 .parent = &kpm_ccu_clk.clk,
341 .ops = &bus_clk_ops,
342 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
343 },
344 .freq_tbl = master_ahb_freq_tbl,
345 .data = &usb_otg_ahb_data,
346 };
347
348 static struct bus_clock sdio1_ahb_clk = {
349 .clk = {
350 .name = "sdio1_ahb_clk",
351 .parent = &kpm_ccu_clk.clk,
352 .ops = &bus_clk_ops,
353 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
354 },
355 .freq_tbl = master_ahb_freq_tbl,
356 .data = &sdio1_ahb_data,
357 };
358
359 static struct bus_clock sdio2_ahb_clk = {
360 .clk = {
361 .name = "sdio2_ahb_clk",
362 .parent = &kpm_ccu_clk.clk,
363 .ops = &bus_clk_ops,
364 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
365 },
366 .freq_tbl = master_ahb_freq_tbl,
367 .data = &sdio2_ahb_data,
368 };
369
370 static struct bus_clock sdio3_ahb_clk = {
371 .clk = {
372 .name = "sdio3_ahb_clk",
373 .parent = &kpm_ccu_clk.clk,
374 .ops = &bus_clk_ops,
375 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
376 },
377 .freq_tbl = master_ahb_freq_tbl,
378 .data = &sdio3_ahb_data,
379 };
380
381 static struct bus_clock sdio4_ahb_clk = {
382 .clk = {
383 .name = "sdio4_ahb_clk",
384 .parent = &kpm_ccu_clk.clk,
385 .ops = &bus_clk_ops,
386 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
387 },
388 .freq_tbl = master_ahb_freq_tbl,
389 .data = &sdio4_ahb_data,
390 };
391
392 static struct bus_clock bsc1_apb_clk = {
393 .clk = {
394 .name = "bsc1_apb_clk",
395 .parent = &kps_ccu_clk.clk,
396 .ops = &bus_clk_ops,
397 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
398 },
399 .freq_tbl = slave_apb_freq_tbl,
400 .data = &bsc1_apb_data,
401 };
402
403 static struct bus_clock bsc2_apb_clk = {
404 .clk = {
405 .name = "bsc2_apb_clk",
406 .parent = &kps_ccu_clk.clk,
407 .ops = &bus_clk_ops,
408 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
409 },
410 .freq_tbl = slave_apb_freq_tbl,
411 .data = &bsc2_apb_data,
412 };
413
414 static struct bus_clock bsc3_apb_clk = {
415 .clk = {
416 .name = "bsc3_apb_clk",
417 .parent = &kps_ccu_clk.clk,
418 .ops = &bus_clk_ops,
419 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
420 },
421 .freq_tbl = slave_apb_freq_tbl,
422 .data = &bsc3_apb_data,
423 };
424
425 /* KPM peripheral */
426 static struct peri_clock sdio1_clk = {
427 .clk = {
428 .name = "sdio1_clk",
429 .parent = &ref_52m.clk,
430 .ops = &peri_clk_ops,
431 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
432 },
433 .data = &sdio1_data,
434 };
435
436 static struct peri_clock sdio2_clk = {
437 .clk = {
438 .name = "sdio2_clk",
439 .parent = &ref_52m.clk,
440 .ops = &peri_clk_ops,
441 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
442 },
443 .data = &sdio2_data,
444 };
445
446 static struct peri_clock sdio3_clk = {
447 .clk = {
448 .name = "sdio3_clk",
449 .parent = &ref_52m.clk,
450 .ops = &peri_clk_ops,
451 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
452 },
453 .data = &sdio3_data,
454 };
455
456 static struct peri_clock sdio4_clk = {
457 .clk = {
458 .name = "sdio4_clk",
459 .parent = &ref_52m.clk,
460 .ops = &peri_clk_ops,
461 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
462 },
463 .data = &sdio4_data,
464 };
465
466 static struct peri_clock sdio1_sleep_clk = {
467 .clk = {
468 .name = "sdio1_sleep_clk",
469 .parent = &kpm_ccu_clk.clk,
470 .ops = &bus_clk_ops,
471 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
472 },
473 .data = &sdio1_sleep_data,
474 };
475
476 static struct peri_clock sdio2_sleep_clk = {
477 .clk = {
478 .name = "sdio2_sleep_clk",
479 .parent = &kpm_ccu_clk.clk,
480 .ops = &bus_clk_ops,
481 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
482 },
483 .data = &sdio2_sleep_data,
484 };
485
486 static struct peri_clock sdio3_sleep_clk = {
487 .clk = {
488 .name = "sdio3_sleep_clk",
489 .parent = &kpm_ccu_clk.clk,
490 .ops = &bus_clk_ops,
491 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
492 },
493 .data = &sdio3_sleep_data,
494 };
495
496 static struct peri_clock sdio4_sleep_clk = {
497 .clk = {
498 .name = "sdio4_sleep_clk",
499 .parent = &kpm_ccu_clk.clk,
500 .ops = &bus_clk_ops,
501 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
502 },
503 .data = &sdio4_sleep_data,
504 };
505
506 /* KPS peripheral clock */
507 static struct peri_clock bsc1_clk = {
508 .clk = {
509 .name = "bsc1_clk",
510 .parent = &ref_13m.clk,
511 .rate = 13 * CLOCK_1M,
512 .div = 1,
513 .ops = &peri_clk_ops,
514 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
515 },
516 .data = &bsc1_data,
517 };
518
519 static struct peri_clock bsc2_clk = {
520 .clk = {
521 .name = "bsc2_clk",
522 .parent = &ref_13m.clk,
523 .rate = 13 * CLOCK_1M,
524 .div = 1,
525 .ops = &peri_clk_ops,
526 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
527 },
528 .data = &bsc2_data,
529 };
530
531 static struct peri_clock bsc3_clk = {
532 .clk = {
533 .name = "bsc3_clk",
534 .parent = &ref_13m.clk,
535 .rate = 13 * CLOCK_1M,
536 .div = 1,
537 .ops = &peri_clk_ops,
538 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
539 },
540 .data = &bsc3_data,
541 };
542
543 /* public table for registering clocks */
544 struct clk_lookup arch_clk_tbl[] = {
545 /* Peripheral clocks */
546 CLK_LK(sdio1),
547 CLK_LK(sdio2),
548 CLK_LK(sdio3),
549 CLK_LK(sdio4),
550 CLK_LK(sdio1_sleep),
551 CLK_LK(sdio2_sleep),
552 CLK_LK(sdio3_sleep),
553 CLK_LK(sdio4_sleep),
554 CLK_LK(bsc1),
555 CLK_LK(bsc2),
556 CLK_LK(bsc3),
557 /* Bus clocks */
558 CLK_LK(usb_otg_ahb),
559 CLK_LK(sdio1_ahb),
560 CLK_LK(sdio2_ahb),
561 CLK_LK(sdio3_ahb),
562 CLK_LK(sdio4_ahb),
563 CLK_LK(bsc1_apb),
564 CLK_LK(bsc2_apb),
565 CLK_LK(bsc3_apb),
566 #ifdef CONFIG_BCM_SF2_ETH
567 CLK_LK(esub_ccu),
568 #endif
569 };
570
571 /* public array size */
572 unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
573