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