blob: 39217c5b2bf1d9ea6aa58a5fb80e5f27f597ec24 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Steve Rae45f2c702016-06-02 15:10:56 -07002/*
3 * Copyright 2013 Broadcom Corporation.
Steve Rae45f2c702016-06-02 15:10:56 -07004 */
5
6/*
7 *
8 * bcm235xx-specific clock tables
9 *
10 */
11
12#include <common.h>
13#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090014#include <linux/errno.h>
Steve Rae45f2c702016-06-02 15:10:56 -070015#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) \
24static 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 */
39DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1);
40DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1);
41DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1);
42DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0);
43DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3);
44DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2);
45DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4);
46DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0);
47DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3);
48DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2);
49DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4);
50
51struct 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}
58static 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
65int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
66
67/* convert ref clock string to clock structure pointer */
68struct 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 */
80unsigned 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
91unsigned 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
102unsigned 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
111unsigned 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
120unsigned 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
130static struct bus_clk_data bsc1_apb_data = {
131 .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
132};
133
134static struct bus_clk_data bsc2_apb_data = {
135 .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
136};
137
138static struct bus_clk_data bsc3_apb_data = {
139 .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
140};
141
142/* * Master CCU clocks */
143static 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
155static 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
167static 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
179static 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
191static struct peri_clk_data sdio1_sleep_data = {
192 .clocks = CLOCKS("ref_32k"),
193 .gate = SW_ONLY_GATE(0x0358, 20, 4),
194};
195
196static struct peri_clk_data sdio2_sleep_data = {
197 .clocks = CLOCKS("ref_32k"),
198 .gate = SW_ONLY_GATE(0x035c, 20, 4),
199};
200
201static struct peri_clk_data sdio3_sleep_data = {
202 .clocks = CLOCKS("ref_32k"),
203 .gate = SW_ONLY_GATE(0x0364, 20, 4),
204};
205
206static struct peri_clk_data sdio4_sleep_data = {
207 .clocks = CLOCKS("ref_32k"),
208 .gate = SW_ONLY_GATE(0x0360, 20, 4),
209};
210
211static struct bus_clk_data usb_otg_ahb_data = {
212 .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
213};
214
215static struct bus_clk_data sdio1_ahb_data = {
216 .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
217};
218
219static struct bus_clk_data sdio2_ahb_data = {
220 .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
221};
222
223static struct bus_clk_data sdio3_ahb_data = {
224 .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
225};
226
227static struct bus_clk_data sdio4_ahb_data = {
228 .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
229};
230
231/* * Slave CCU clocks */
232static 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
243static 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
254static 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
269static 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
288static 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 },
Chris Brand8b051892016-06-21 16:43:06 -0700294 .num_policy_masks = 1,
Steve Rae45f2c702016-06-02 15:10:56 -0700295 .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,
Steve Rae45f2c702016-06-02 15:10:56 -0700302 .lvm_en_offset = 0x00000034,
303 .freq_id = 2,
304 .freq_tbl = slave_axi_freq_tbl,
305};
306
307#ifdef CONFIG_BCM_SF2_ETH
308static struct ccu_clock esub_ccu_clk = {
309 .clk = {
310 .name = "esub_ccu_clk",
311 .ops = &ccu_clk_ops,
312 .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
313 },
314 .num_policy_masks = 1,
315 .policy_freq_offset = 0x00000008,
316 .freq_bit_shift = 8,
317 .policy_ctl_offset = 0x0000000c,
318 .policy0_mask_offset = 0x00000010,
319 .policy1_mask_offset = 0x00000014,
320 .policy2_mask_offset = 0x00000018,
321 .policy3_mask_offset = 0x0000001c,
322 .lvm_en_offset = 0x00000034,
323 .freq_id = 2,
324 .freq_tbl = esub_freq_tbl,
325};
326#endif
327
328/*
329 * Bus clocks
330 */
331
332/* KPM bus clocks */
333static struct bus_clock usb_otg_ahb_clk = {
334 .clk = {
335 .name = "usb_otg_ahb_clk",
336 .parent = &kpm_ccu_clk.clk,
337 .ops = &bus_clk_ops,
338 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
339 },
340 .freq_tbl = master_ahb_freq_tbl,
341 .data = &usb_otg_ahb_data,
342};
343
344static struct bus_clock sdio1_ahb_clk = {
345 .clk = {
346 .name = "sdio1_ahb_clk",
347 .parent = &kpm_ccu_clk.clk,
348 .ops = &bus_clk_ops,
349 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
350 },
351 .freq_tbl = master_ahb_freq_tbl,
352 .data = &sdio1_ahb_data,
353};
354
355static struct bus_clock sdio2_ahb_clk = {
356 .clk = {
357 .name = "sdio2_ahb_clk",
358 .parent = &kpm_ccu_clk.clk,
359 .ops = &bus_clk_ops,
360 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
361 },
362 .freq_tbl = master_ahb_freq_tbl,
363 .data = &sdio2_ahb_data,
364};
365
366static struct bus_clock sdio3_ahb_clk = {
367 .clk = {
368 .name = "sdio3_ahb_clk",
369 .parent = &kpm_ccu_clk.clk,
370 .ops = &bus_clk_ops,
371 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
372 },
373 .freq_tbl = master_ahb_freq_tbl,
374 .data = &sdio3_ahb_data,
375};
376
377static struct bus_clock sdio4_ahb_clk = {
378 .clk = {
379 .name = "sdio4_ahb_clk",
380 .parent = &kpm_ccu_clk.clk,
381 .ops = &bus_clk_ops,
382 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
383 },
384 .freq_tbl = master_ahb_freq_tbl,
385 .data = &sdio4_ahb_data,
386};
387
388static struct bus_clock bsc1_apb_clk = {
389 .clk = {
390 .name = "bsc1_apb_clk",
391 .parent = &kps_ccu_clk.clk,
392 .ops = &bus_clk_ops,
393 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
394 },
395 .freq_tbl = slave_apb_freq_tbl,
396 .data = &bsc1_apb_data,
397};
398
399static struct bus_clock bsc2_apb_clk = {
400 .clk = {
401 .name = "bsc2_apb_clk",
402 .parent = &kps_ccu_clk.clk,
403 .ops = &bus_clk_ops,
404 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
405 },
406 .freq_tbl = slave_apb_freq_tbl,
407 .data = &bsc2_apb_data,
408};
409
410static struct bus_clock bsc3_apb_clk = {
411 .clk = {
412 .name = "bsc3_apb_clk",
413 .parent = &kps_ccu_clk.clk,
414 .ops = &bus_clk_ops,
415 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
416 },
417 .freq_tbl = slave_apb_freq_tbl,
418 .data = &bsc3_apb_data,
419};
420
421/* KPM peripheral */
422static struct peri_clock sdio1_clk = {
423 .clk = {
424 .name = "sdio1_clk",
425 .parent = &ref_52m.clk,
426 .ops = &peri_clk_ops,
427 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
428 },
429 .data = &sdio1_data,
430};
431
432static struct peri_clock sdio2_clk = {
433 .clk = {
434 .name = "sdio2_clk",
435 .parent = &ref_52m.clk,
436 .ops = &peri_clk_ops,
437 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
438 },
439 .data = &sdio2_data,
440};
441
442static struct peri_clock sdio3_clk = {
443 .clk = {
444 .name = "sdio3_clk",
445 .parent = &ref_52m.clk,
446 .ops = &peri_clk_ops,
447 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
448 },
449 .data = &sdio3_data,
450};
451
452static struct peri_clock sdio4_clk = {
453 .clk = {
454 .name = "sdio4_clk",
455 .parent = &ref_52m.clk,
456 .ops = &peri_clk_ops,
457 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
458 },
459 .data = &sdio4_data,
460};
461
462static struct peri_clock sdio1_sleep_clk = {
463 .clk = {
464 .name = "sdio1_sleep_clk",
465 .parent = &kpm_ccu_clk.clk,
466 .ops = &bus_clk_ops,
467 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
468 },
469 .data = &sdio1_sleep_data,
470};
471
472static struct peri_clock sdio2_sleep_clk = {
473 .clk = {
474 .name = "sdio2_sleep_clk",
475 .parent = &kpm_ccu_clk.clk,
476 .ops = &bus_clk_ops,
477 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
478 },
479 .data = &sdio2_sleep_data,
480};
481
482static struct peri_clock sdio3_sleep_clk = {
483 .clk = {
484 .name = "sdio3_sleep_clk",
485 .parent = &kpm_ccu_clk.clk,
486 .ops = &bus_clk_ops,
487 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
488 },
489 .data = &sdio3_sleep_data,
490};
491
492static struct peri_clock sdio4_sleep_clk = {
493 .clk = {
494 .name = "sdio4_sleep_clk",
495 .parent = &kpm_ccu_clk.clk,
496 .ops = &bus_clk_ops,
497 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
498 },
499 .data = &sdio4_sleep_data,
500};
501
502/* KPS peripheral clock */
503static struct peri_clock bsc1_clk = {
504 .clk = {
505 .name = "bsc1_clk",
506 .parent = &ref_13m.clk,
507 .rate = 13 * CLOCK_1M,
508 .div = 1,
509 .ops = &peri_clk_ops,
510 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
511 },
512 .data = &bsc1_data,
513};
514
515static struct peri_clock bsc2_clk = {
516 .clk = {
517 .name = "bsc2_clk",
518 .parent = &ref_13m.clk,
519 .rate = 13 * CLOCK_1M,
520 .div = 1,
521 .ops = &peri_clk_ops,
522 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
523 },
524 .data = &bsc2_data,
525};
526
527static struct peri_clock bsc3_clk = {
528 .clk = {
529 .name = "bsc3_clk",
530 .parent = &ref_13m.clk,
531 .rate = 13 * CLOCK_1M,
532 .div = 1,
533 .ops = &peri_clk_ops,
534 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
535 },
536 .data = &bsc3_data,
537};
538
539/* public table for registering clocks */
540struct clk_lookup arch_clk_tbl[] = {
541 /* Peripheral clocks */
542 CLK_LK(sdio1),
543 CLK_LK(sdio2),
544 CLK_LK(sdio3),
545 CLK_LK(sdio4),
546 CLK_LK(sdio1_sleep),
547 CLK_LK(sdio2_sleep),
548 CLK_LK(sdio3_sleep),
549 CLK_LK(sdio4_sleep),
550 CLK_LK(bsc1),
551 CLK_LK(bsc2),
552 CLK_LK(bsc3),
553 /* Bus clocks */
554 CLK_LK(usb_otg_ahb),
555 CLK_LK(sdio1_ahb),
556 CLK_LK(sdio2_ahb),
557 CLK_LK(sdio3_ahb),
558 CLK_LK(sdio4_ahb),
559 CLK_LK(bsc1_apb),
560 CLK_LK(bsc2_apb),
561 CLK_LK(bsc3_apb),
562#ifdef CONFIG_BCM_SF2_ETH
563 CLK_LK(esub_ccu),
564#endif
565};
566
567/* public array size */
568unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);