• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Broadcom Corporation.
4  */
5 
6 /*
7  *
8  * bcm235xx-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 = 1,
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 	.lvm_en_offset = 0x00000034,
303 	.freq_id = 2,
304 	.freq_tbl = slave_axi_freq_tbl,
305 };
306 
307 #ifdef CONFIG_BCM_SF2_ETH
308 static 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 */
333 static 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 
344 static 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 
355 static 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 
366 static 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 
377 static 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 
388 static 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 
399 static 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 
410 static 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 */
422 static 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 
432 static 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 
442 static 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 
452 static 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 
462 static 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 
472 static 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 
482 static 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 
492 static 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 */
503 static 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 
515 static 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 
527 static 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 */
540 struct 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 */
568 unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
569