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