blob: bc8a170b407163b1a23c5b5107dcdc968d2798f8 [file] [log] [blame]
Darwin Ramboc5613142014-02-11 11:06:34 -08001/*
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 <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
121static struct bus_clk_data bsc1_apb_data = {
122 .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
123};
124
125static struct bus_clk_data bsc2_apb_data = {
126 .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1),
127};
128
129static struct bus_clk_data bsc3_apb_data = {
130 .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1),
131};
132
133/* * Master CCU clocks */
134static struct peri_clk_data sdio1_data = {
135 .gate = HW_SW_GATE(0x0358, 18, 2, 3),
136 .clocks = CLOCKS("ref_crystal",
137 "var_52m",
138 "ref_52m",
139 "var_96m",
140 "ref_96m"),
141 .sel = SELECTOR(0x0a28, 0, 3),
142 .div = DIVIDER(0x0a28, 4, 14),
143 .trig = TRIGGER(0x0afc, 9),
144};
145
146static struct peri_clk_data sdio2_data = {
147 .gate = HW_SW_GATE(0x035c, 18, 2, 3),
148 .clocks = CLOCKS("ref_crystal",
149 "var_52m",
150 "ref_52m",
151 "var_96m",
152 "ref_96m"),
153 .sel = SELECTOR(0x0a2c, 0, 3),
154 .div = DIVIDER(0x0a2c, 4, 14),
155 .trig = TRIGGER(0x0afc, 10),
156};
157
158static struct peri_clk_data sdio3_data = {
159 .gate = HW_SW_GATE(0x0364, 18, 2, 3),
160 .clocks = CLOCKS("ref_crystal",
161 "var_52m",
162 "ref_52m",
163 "var_96m",
164 "ref_96m"),
165 .sel = SELECTOR(0x0a34, 0, 3),
166 .div = DIVIDER(0x0a34, 4, 14),
167 .trig = TRIGGER(0x0afc, 12),
168};
169
170static struct peri_clk_data sdio4_data = {
171 .gate = HW_SW_GATE(0x0360, 18, 2, 3),
172 .clocks = CLOCKS("ref_crystal",
173 "var_52m",
174 "ref_52m",
175 "var_96m",
176 "ref_96m"),
177 .sel = SELECTOR(0x0a30, 0, 3),
178 .div = DIVIDER(0x0a30, 4, 14),
179 .trig = TRIGGER(0x0afc, 11),
180};
181
182static struct peri_clk_data sdio1_sleep_data = {
183 .clocks = CLOCKS("ref_32k"),
184 .gate = SW_ONLY_GATE(0x0358, 20, 4),
185};
186
187static struct peri_clk_data sdio2_sleep_data = {
188 .clocks = CLOCKS("ref_32k"),
189 .gate = SW_ONLY_GATE(0x035c, 20, 4),
190};
191
192static struct peri_clk_data sdio3_sleep_data = {
193 .clocks = CLOCKS("ref_32k"),
194 .gate = SW_ONLY_GATE(0x0364, 20, 4),
195};
196
197static struct peri_clk_data sdio4_sleep_data = {
198 .clocks = CLOCKS("ref_32k"),
199 .gate = SW_ONLY_GATE(0x0360, 20, 4),
200};
201
202static struct bus_clk_data sdio1_ahb_data = {
203 .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1),
204};
205
206static struct bus_clk_data sdio2_ahb_data = {
207 .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1),
208};
209
210static struct bus_clk_data sdio3_ahb_data = {
211 .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1),
212};
213
214static struct bus_clk_data sdio4_ahb_data = {
215 .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1),
216};
217
218/* * Slave CCU clocks */
219static struct peri_clk_data bsc1_data = {
220 .gate = HW_SW_GATE(0x0458, 18, 2, 3),
221 .clocks = CLOCKS("ref_crystal",
222 "var_104m",
223 "ref_104m",
224 "var_13m",
225 "ref_13m"),
226 .sel = SELECTOR(0x0a64, 0, 3),
227 .trig = TRIGGER(0x0afc, 23),
228};
229
230static struct peri_clk_data bsc2_data = {
231 .gate = HW_SW_GATE(0x045c, 18, 2, 3),
232 .clocks = CLOCKS("ref_crystal",
233 "var_104m",
234 "ref_104m",
235 "var_13m",
236 "ref_13m"),
237 .sel = SELECTOR(0x0a68, 0, 3),
238 .trig = TRIGGER(0x0afc, 24),
239};
240
241static struct peri_clk_data bsc3_data = {
242 .gate = HW_SW_GATE(0x0484, 18, 2, 3),
243 .clocks = CLOCKS("ref_crystal",
244 "var_104m",
245 "ref_104m",
246 "var_13m",
247 "ref_13m"),
248 .sel = SELECTOR(0x0a84, 0, 3),
249 .trig = TRIGGER(0x0b00, 2),
250};
251
252/*
253 * CCU clocks
254 */
255
256static struct ccu_clock kpm_ccu_clk = {
257 .clk = {
258 .name = "kpm_ccu_clk",
259 .ops = &ccu_clk_ops,
260 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
261 },
262 .num_policy_masks = 1,
263 .policy_freq_offset = 0x00000008,
264 .freq_bit_shift = 8,
265 .policy_ctl_offset = 0x0000000c,
266 .policy0_mask_offset = 0x00000010,
267 .policy1_mask_offset = 0x00000014,
268 .policy2_mask_offset = 0x00000018,
269 .policy3_mask_offset = 0x0000001c,
270 .lvm_en_offset = 0x00000034,
271 .freq_id = 2,
272 .freq_tbl = master_axi_freq_tbl,
273};
274
275static struct ccu_clock kps_ccu_clk = {
276 .clk = {
277 .name = "kps_ccu_clk",
278 .ops = &ccu_clk_ops,
279 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
280 },
281 .num_policy_masks = 2,
282 .policy_freq_offset = 0x00000008,
283 .freq_bit_shift = 8,
284 .policy_ctl_offset = 0x0000000c,
285 .policy0_mask_offset = 0x00000010,
286 .policy1_mask_offset = 0x00000014,
287 .policy2_mask_offset = 0x00000018,
288 .policy3_mask_offset = 0x0000001c,
289 .policy0_mask2_offset = 0x00000048,
290 .policy1_mask2_offset = 0x0000004c,
291 .policy2_mask2_offset = 0x00000050,
292 .policy3_mask2_offset = 0x00000054,
293 .lvm_en_offset = 0x00000034,
294 .freq_id = 2,
295 .freq_tbl = slave_axi_freq_tbl,
296};
297
298/*
299 * Bus clocks
300 */
301
302/* KPM bus clocks */
303static struct bus_clock sdio1_ahb_clk = {
304 .clk = {
305 .name = "sdio1_ahb_clk",
306 .parent = &kpm_ccu_clk.clk,
307 .ops = &bus_clk_ops,
308 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
309 },
310 .freq_tbl = master_ahb_freq_tbl,
311 .data = &sdio1_ahb_data,
312};
313
314static struct bus_clock sdio2_ahb_clk = {
315 .clk = {
316 .name = "sdio2_ahb_clk",
317 .parent = &kpm_ccu_clk.clk,
318 .ops = &bus_clk_ops,
319 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
320 },
321 .freq_tbl = master_ahb_freq_tbl,
322 .data = &sdio2_ahb_data,
323};
324
325static struct bus_clock sdio3_ahb_clk = {
326 .clk = {
327 .name = "sdio3_ahb_clk",
328 .parent = &kpm_ccu_clk.clk,
329 .ops = &bus_clk_ops,
330 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
331 },
332 .freq_tbl = master_ahb_freq_tbl,
333 .data = &sdio3_ahb_data,
334};
335
336static struct bus_clock sdio4_ahb_clk = {
337 .clk = {
338 .name = "sdio4_ahb_clk",
339 .parent = &kpm_ccu_clk.clk,
340 .ops = &bus_clk_ops,
341 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
342 },
343 .freq_tbl = master_ahb_freq_tbl,
344 .data = &sdio4_ahb_data,
345};
346
347static struct bus_clock bsc1_apb_clk = {
348 .clk = {
349 .name = "bsc1_apb_clk",
350 .parent = &kps_ccu_clk.clk,
351 .ops = &bus_clk_ops,
352 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
353 },
354 .freq_tbl = slave_apb_freq_tbl,
355 .data = &bsc1_apb_data,
356};
357
358static struct bus_clock bsc2_apb_clk = {
359 .clk = {
360 .name = "bsc2_apb_clk",
361 .parent = &kps_ccu_clk.clk,
362 .ops = &bus_clk_ops,
363 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
364 },
365 .freq_tbl = slave_apb_freq_tbl,
366 .data = &bsc2_apb_data,
367};
368
369static struct bus_clock bsc3_apb_clk = {
370 .clk = {
371 .name = "bsc3_apb_clk",
372 .parent = &kps_ccu_clk.clk,
373 .ops = &bus_clk_ops,
374 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
375 },
376 .freq_tbl = slave_apb_freq_tbl,
377 .data = &bsc3_apb_data,
378};
379
380/* KPM peripheral */
381static struct peri_clock sdio1_clk = {
382 .clk = {
383 .name = "sdio1_clk",
384 .parent = &ref_52m.clk,
385 .ops = &peri_clk_ops,
386 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
387 },
388 .data = &sdio1_data,
389};
390
391static struct peri_clock sdio2_clk = {
392 .clk = {
393 .name = "sdio2_clk",
394 .parent = &ref_52m.clk,
395 .ops = &peri_clk_ops,
396 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
397 },
398 .data = &sdio2_data,
399};
400
401static struct peri_clock sdio3_clk = {
402 .clk = {
403 .name = "sdio3_clk",
404 .parent = &ref_52m.clk,
405 .ops = &peri_clk_ops,
406 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
407 },
408 .data = &sdio3_data,
409};
410
411static struct peri_clock sdio4_clk = {
412 .clk = {
413 .name = "sdio4_clk",
414 .parent = &ref_52m.clk,
415 .ops = &peri_clk_ops,
416 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
417 },
418 .data = &sdio4_data,
419};
420
421static struct peri_clock sdio1_sleep_clk = {
422 .clk = {
423 .name = "sdio1_sleep_clk",
424 .parent = &kpm_ccu_clk.clk,
425 .ops = &bus_clk_ops,
426 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
427 },
428 .data = &sdio1_sleep_data,
429};
430
431static struct peri_clock sdio2_sleep_clk = {
432 .clk = {
433 .name = "sdio2_sleep_clk",
434 .parent = &kpm_ccu_clk.clk,
435 .ops = &bus_clk_ops,
436 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
437 },
438 .data = &sdio2_sleep_data,
439};
440
441static struct peri_clock sdio3_sleep_clk = {
442 .clk = {
443 .name = "sdio3_sleep_clk",
444 .parent = &kpm_ccu_clk.clk,
445 .ops = &bus_clk_ops,
446 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
447 },
448 .data = &sdio3_sleep_data,
449};
450
451static struct peri_clock sdio4_sleep_clk = {
452 .clk = {
453 .name = "sdio4_sleep_clk",
454 .parent = &kpm_ccu_clk.clk,
455 .ops = &bus_clk_ops,
456 .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR,
457 },
458 .data = &sdio4_sleep_data,
459};
460
461/* KPS peripheral clock */
462static struct peri_clock bsc1_clk = {
463 .clk = {
464 .name = "bsc1_clk",
465 .parent = &ref_13m.clk,
466 .rate = 13 * CLOCK_1M,
467 .div = 1,
468 .ops = &peri_clk_ops,
469 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
470 },
471 .data = &bsc1_data,
472};
473
474static struct peri_clock bsc2_clk = {
475 .clk = {
476 .name = "bsc2_clk",
477 .parent = &ref_13m.clk,
478 .rate = 13 * CLOCK_1M,
479 .div = 1,
480 .ops = &peri_clk_ops,
481 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
482 },
483 .data = &bsc2_data,
484};
485
486static struct peri_clock bsc3_clk = {
487 .clk = {
488 .name = "bsc3_clk",
489 .parent = &ref_13m.clk,
490 .rate = 13 * CLOCK_1M,
491 .div = 1,
492 .ops = &peri_clk_ops,
493 .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR,
494 },
495 .data = &bsc3_data,
496};
497
498/* public table for registering clocks */
499struct clk_lookup arch_clk_tbl[] = {
500 /* Peripheral clocks */
501 CLK_LK(sdio1),
502 CLK_LK(sdio2),
503 CLK_LK(sdio3),
504 CLK_LK(sdio4),
505 CLK_LK(sdio1_sleep),
506 CLK_LK(sdio2_sleep),
507 CLK_LK(sdio3_sleep),
508 CLK_LK(sdio4_sleep),
509 CLK_LK(bsc1),
510 CLK_LK(bsc2),
511 CLK_LK(bsc3),
512 /* Bus clocks */
513 CLK_LK(sdio1_ahb),
514 CLK_LK(sdio2_ahb),
515 CLK_LK(sdio3_ahb),
516 CLK_LK(sdio4_ahb),
517 CLK_LK(bsc1_apb),
518 CLK_LK(bsc2_apb),
519 CLK_LK(bsc3_apb),
520};
521
522/* public array size */
523unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);