1 /*
2  * Copyright 2013 Broadcom Corporation.
3  *
4  * SPDX-License-Identifier:      GPL-2.0+
5  */
6 
7 /*
8  *
9  * bcm281xx-specific clock tables
10  *
11  */
12 
13 #include <common.h>
14 #include <asm/io.h>
15 #include <linux/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) \
25 static 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 */
40 DECLARE_REF_CLK(ref_crystal,	0,		26  * CLOCK_1M,	1);
41 DECLARE_REF_CLK(var_96m,	0,		96  * CLOCK_1M,	1);
42 DECLARE_REF_CLK(ref_96m,	0,		96  * CLOCK_1M,	1);
43 DECLARE_REF_CLK(ref_312m,	0,		312 * CLOCK_1M,	0);
44 DECLARE_REF_CLK(ref_104m,	&ref_312m.clk,	104 * CLOCK_1M,	3);
45 DECLARE_REF_CLK(ref_52m,	&ref_104m.clk,	52  * CLOCK_1M,	2);
46 DECLARE_REF_CLK(ref_13m,	&ref_52m.clk,	13  * CLOCK_1M,	4);
47 DECLARE_REF_CLK(var_312m,	0,		312 * CLOCK_1M,	0);
48 DECLARE_REF_CLK(var_104m,	&var_312m.clk,	104 * CLOCK_1M,	3);
49 DECLARE_REF_CLK(var_52m,	&var_104m.clk,	52  * CLOCK_1M,	2);
50 DECLARE_REF_CLK(var_13m,	&var_52m.clk,	13  * CLOCK_1M,	4);
51 
52 struct 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}
59 static 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 
66 int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]);
67 
68 /* convert ref clock string to clock structure pointer */
69 struct 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 */
81 unsigned 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 
92 unsigned 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 
103 unsigned 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 
112 unsigned 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 
121 unsigned 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 
131 static struct bus_clk_data bsc1_apb_data = {
132 	.gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
133 };
134 
135 static struct bus_clk_data bsc2_apb_data = {
136 	.gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
137 };
138 
139 static struct bus_clk_data bsc3_apb_data = {
140 	.gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
141 };
142 
143 /* * Master CCU clocks */
144 static 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 
156 static 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 
168 static 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 
180 static 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 
192 static struct peri_clk_data sdio1_sleep_data = {
193 	.clocks		= CLOCKS("ref_32k"),
194 	.gate		= SW_ONLY_GATE(0x0358, 20, 4),
195 };
196 
197 static struct peri_clk_data sdio2_sleep_data = {
198 	.clocks		= CLOCKS("ref_32k"),
199 	.gate		= SW_ONLY_GATE(0x035c, 20, 4),
200 };
201 
202 static struct peri_clk_data sdio3_sleep_data = {
203 	.clocks		= CLOCKS("ref_32k"),
204 	.gate		= SW_ONLY_GATE(0x0364, 20, 4),
205 };
206 
207 static struct peri_clk_data sdio4_sleep_data = {
208 	.clocks		= CLOCKS("ref_32k"),
209 	.gate		= SW_ONLY_GATE(0x0360, 20, 4),
210 };
211 
212 static struct bus_clk_data usb_otg_ahb_data = {
213 	.gate		= HW_SW_GATE_AUTO(0x0348, 16, 0, 1),
214 };
215 
216 static struct bus_clk_data sdio1_ahb_data = {
217 	.gate		= HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
218 };
219 
220 static struct bus_clk_data sdio2_ahb_data = {
221 	.gate		= HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
222 };
223 
224 static struct bus_clk_data sdio3_ahb_data = {
225 	.gate		= HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
226 };
227 
228 static struct bus_clk_data sdio4_ahb_data = {
229 	.gate		= HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
230 };
231 
232 /* * Slave CCU clocks */
233 static 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 
244 static 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 
255 static 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 
270 static 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 
289 static 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
313 static 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 */
338 static 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 
349 static 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 
360 static 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 
371 static 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 
382 static 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 
393 static 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 
404 static 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 
415 static 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 */
427 static 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 
437 static 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 
447 static 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 
457 static 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 
467 static 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 
477 static 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 
487 static 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 
497 static 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 */
508 static 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 
520 static 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 
532 static 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 */
545 struct 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 */
573 unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
574