1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved. |
4 | */ |
5 | |
6 | #include <linux/clk-provider.h> |
7 | #include <linux/io.h> |
8 | #include <linux/module.h> |
9 | #include <linux/platform_device.h> |
10 | |
11 | #include "ccu_common.h" |
12 | #include "ccu_reset.h" |
13 | |
14 | #include "ccu_div.h" |
15 | #include "ccu_gate.h" |
16 | #include "ccu_mp.h" |
17 | #include "ccu_nkmp.h" |
18 | #include "ccu_nm.h" |
19 | #include "ccu_phase.h" |
20 | |
21 | #include "ccu-sun9i-a80.h" |
22 | |
23 | #define CCU_SUN9I_LOCK_REG 0x09c |
24 | |
25 | /* |
26 | * The CPU PLLs are actually NP clocks, with P being /1 or /4. However |
27 | * P should only be used for output frequencies lower than 228 MHz. |
28 | * Neither mainline Linux, U-boot, nor the vendor BSPs use these. |
29 | * |
30 | * For now we can just model it as a multiplier clock, and force P to /1. |
31 | */ |
32 | #define SUN9I_A80_PLL_C0CPUX_REG 0x000 |
33 | #define SUN9I_A80_PLL_C1CPUX_REG 0x004 |
34 | |
35 | static struct ccu_mult pll_c0cpux_clk = { |
36 | .enable = BIT(31), |
37 | .lock = BIT(0), |
38 | .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
39 | .common = { |
40 | .reg = SUN9I_A80_PLL_C0CPUX_REG, |
41 | .lock_reg = CCU_SUN9I_LOCK_REG, |
42 | .features = CCU_FEATURE_LOCK_REG, |
43 | .hw.init = CLK_HW_INIT("pll-c0cpux" , "osc24M" , |
44 | &ccu_mult_ops, |
45 | CLK_SET_RATE_UNGATE), |
46 | }, |
47 | }; |
48 | |
49 | static struct ccu_mult pll_c1cpux_clk = { |
50 | .enable = BIT(31), |
51 | .lock = BIT(1), |
52 | .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
53 | .common = { |
54 | .reg = SUN9I_A80_PLL_C1CPUX_REG, |
55 | .lock_reg = CCU_SUN9I_LOCK_REG, |
56 | .features = CCU_FEATURE_LOCK_REG, |
57 | .hw.init = CLK_HW_INIT("pll-c1cpux" , "osc24M" , |
58 | &ccu_mult_ops, |
59 | CLK_SET_RATE_UNGATE), |
60 | }, |
61 | }; |
62 | |
63 | /* |
64 | * The Audio PLL has d1, d2 dividers in addition to the usual N, M |
65 | * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz |
66 | * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0. |
67 | */ |
68 | #define SUN9I_A80_PLL_AUDIO_REG 0x008 |
69 | |
70 | static struct ccu_nm pll_audio_clk = { |
71 | .enable = BIT(31), |
72 | .lock = BIT(2), |
73 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
74 | .m = _SUNXI_CCU_DIV_OFFSET(0, 6, 0), |
75 | .common = { |
76 | .reg = 0x008, |
77 | .lock_reg = CCU_SUN9I_LOCK_REG, |
78 | .features = CCU_FEATURE_LOCK_REG, |
79 | .hw.init = CLK_HW_INIT("pll-audio" , "osc24M" , |
80 | &ccu_nm_ops, CLK_SET_RATE_UNGATE), |
81 | }, |
82 | }; |
83 | |
84 | /* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */ |
85 | static struct ccu_nkmp pll_periph0_clk = { |
86 | .enable = BIT(31), |
87 | .lock = BIT(3), |
88 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
89 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
90 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
91 | .common = { |
92 | .reg = 0x00c, |
93 | .lock_reg = CCU_SUN9I_LOCK_REG, |
94 | .features = CCU_FEATURE_LOCK_REG, |
95 | .hw.init = CLK_HW_INIT("pll-periph0" , "osc24M" , |
96 | &ccu_nkmp_ops, |
97 | CLK_SET_RATE_UNGATE), |
98 | }, |
99 | }; |
100 | |
101 | static struct ccu_nkmp pll_ve_clk = { |
102 | .enable = BIT(31), |
103 | .lock = BIT(4), |
104 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
105 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
106 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
107 | .common = { |
108 | .reg = 0x010, |
109 | .lock_reg = CCU_SUN9I_LOCK_REG, |
110 | .features = CCU_FEATURE_LOCK_REG, |
111 | .hw.init = CLK_HW_INIT("pll-ve" , "osc24M" , |
112 | &ccu_nkmp_ops, |
113 | CLK_SET_RATE_UNGATE), |
114 | }, |
115 | }; |
116 | |
117 | static struct ccu_nkmp pll_ddr_clk = { |
118 | .enable = BIT(31), |
119 | .lock = BIT(5), |
120 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
121 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
122 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
123 | .common = { |
124 | .reg = 0x014, |
125 | .lock_reg = CCU_SUN9I_LOCK_REG, |
126 | .features = CCU_FEATURE_LOCK_REG, |
127 | .hw.init = CLK_HW_INIT("pll-ddr" , "osc24M" , |
128 | &ccu_nkmp_ops, |
129 | CLK_SET_RATE_UNGATE), |
130 | }, |
131 | }; |
132 | |
133 | static struct ccu_nm pll_video0_clk = { |
134 | .enable = BIT(31), |
135 | .lock = BIT(6), |
136 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
137 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
138 | .common = { |
139 | .reg = 0x018, |
140 | .lock_reg = CCU_SUN9I_LOCK_REG, |
141 | .features = CCU_FEATURE_LOCK_REG, |
142 | .hw.init = CLK_HW_INIT("pll-video0" , "osc24M" , |
143 | &ccu_nm_ops, |
144 | CLK_SET_RATE_UNGATE), |
145 | }, |
146 | }; |
147 | |
148 | static struct ccu_nkmp pll_video1_clk = { |
149 | .enable = BIT(31), |
150 | .lock = BIT(7), |
151 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
152 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
153 | .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */ |
154 | .common = { |
155 | .reg = 0x01c, |
156 | .lock_reg = CCU_SUN9I_LOCK_REG, |
157 | .features = CCU_FEATURE_LOCK_REG, |
158 | .hw.init = CLK_HW_INIT("pll-video1" , "osc24M" , |
159 | &ccu_nkmp_ops, |
160 | CLK_SET_RATE_UNGATE), |
161 | }, |
162 | }; |
163 | |
164 | static struct ccu_nkmp pll_gpu_clk = { |
165 | .enable = BIT(31), |
166 | .lock = BIT(8), |
167 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
168 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
169 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
170 | .common = { |
171 | .reg = 0x020, |
172 | .lock_reg = CCU_SUN9I_LOCK_REG, |
173 | .features = CCU_FEATURE_LOCK_REG, |
174 | .hw.init = CLK_HW_INIT("pll-gpu" , "osc24M" , |
175 | &ccu_nkmp_ops, |
176 | CLK_SET_RATE_UNGATE), |
177 | }, |
178 | }; |
179 | |
180 | static struct ccu_nkmp pll_de_clk = { |
181 | .enable = BIT(31), |
182 | .lock = BIT(9), |
183 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
184 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
185 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
186 | .common = { |
187 | .reg = 0x024, |
188 | .lock_reg = CCU_SUN9I_LOCK_REG, |
189 | .features = CCU_FEATURE_LOCK_REG, |
190 | .hw.init = CLK_HW_INIT("pll-de" , "osc24M" , |
191 | &ccu_nkmp_ops, |
192 | CLK_SET_RATE_UNGATE), |
193 | }, |
194 | }; |
195 | |
196 | static struct ccu_nkmp pll_isp_clk = { |
197 | .enable = BIT(31), |
198 | .lock = BIT(10), |
199 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
200 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
201 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
202 | .common = { |
203 | .reg = 0x028, |
204 | .lock_reg = CCU_SUN9I_LOCK_REG, |
205 | .features = CCU_FEATURE_LOCK_REG, |
206 | .hw.init = CLK_HW_INIT("pll-isp" , "osc24M" , |
207 | &ccu_nkmp_ops, |
208 | CLK_SET_RATE_UNGATE), |
209 | }, |
210 | }; |
211 | |
212 | static struct ccu_nkmp pll_periph1_clk = { |
213 | .enable = BIT(31), |
214 | .lock = BIT(11), |
215 | .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0), |
216 | .m = _SUNXI_CCU_DIV(16, 1), /* input divider */ |
217 | .p = _SUNXI_CCU_DIV(18, 1), /* output divider */ |
218 | .common = { |
219 | .reg = 0x028, |
220 | .lock_reg = CCU_SUN9I_LOCK_REG, |
221 | .features = CCU_FEATURE_LOCK_REG, |
222 | .hw.init = CLK_HW_INIT("pll-periph1" , "osc24M" , |
223 | &ccu_nkmp_ops, |
224 | CLK_SET_RATE_UNGATE), |
225 | }, |
226 | }; |
227 | |
228 | static const char * const c0cpux_parents[] = { "osc24M" , "pll-c0cpux" }; |
229 | static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux" , c0cpux_parents, |
230 | 0x50, 0, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); |
231 | |
232 | static const char * const c1cpux_parents[] = { "osc24M" , "pll-c1cpux" }; |
233 | static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux" , c1cpux_parents, |
234 | 0x50, 8, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); |
235 | |
236 | static struct clk_div_table axi_div_table[] = { |
237 | { .val = 0, .div = 1 }, |
238 | { .val = 1, .div = 2 }, |
239 | { .val = 2, .div = 3 }, |
240 | { .val = 3, .div = 4 }, |
241 | { .val = 4, .div = 4 }, |
242 | { .val = 5, .div = 4 }, |
243 | { .val = 6, .div = 4 }, |
244 | { .val = 7, .div = 4 }, |
245 | { /* Sentinel */ }, |
246 | }; |
247 | |
248 | static SUNXI_CCU_M(atb0_clk, "atb0" , "c0cpux" , 0x054, 8, 2, 0); |
249 | |
250 | static SUNXI_CCU_DIV_TABLE(axi0_clk, "axi0" , "c0cpux" , |
251 | 0x054, 0, 3, axi_div_table, 0); |
252 | |
253 | static SUNXI_CCU_M(atb1_clk, "atb1" , "c1cpux" , 0x058, 8, 2, 0); |
254 | |
255 | static SUNXI_CCU_DIV_TABLE(axi1_clk, "axi1" , "c1cpux" , |
256 | 0x058, 0, 3, axi_div_table, 0); |
257 | |
258 | static const char * const gtbus_parents[] = { "osc24M" , "pll-periph0" , |
259 | "pll-periph1" , "pll-periph1" }; |
260 | static SUNXI_CCU_M_WITH_MUX(gtbus_clk, "gtbus" , gtbus_parents, |
261 | 0x05c, 0, 2, 24, 2, CLK_IS_CRITICAL); |
262 | |
263 | static const char * const ahb_parents[] = { "gtbus" , "pll-periph0" , |
264 | "pll-periph1" , "pll-periph1" }; |
265 | static struct ccu_div ahb0_clk = { |
266 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
267 | .mux = _SUNXI_CCU_MUX(24, 2), |
268 | .common = { |
269 | .reg = 0x060, |
270 | .hw.init = CLK_HW_INIT_PARENTS("ahb0" , |
271 | ahb_parents, |
272 | &ccu_div_ops, |
273 | 0), |
274 | }, |
275 | }; |
276 | |
277 | static struct ccu_div ahb1_clk = { |
278 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
279 | .mux = _SUNXI_CCU_MUX(24, 2), |
280 | .common = { |
281 | .reg = 0x064, |
282 | .hw.init = CLK_HW_INIT_PARENTS("ahb1" , |
283 | ahb_parents, |
284 | &ccu_div_ops, |
285 | 0), |
286 | }, |
287 | }; |
288 | |
289 | static struct ccu_div ahb2_clk = { |
290 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
291 | .mux = _SUNXI_CCU_MUX(24, 2), |
292 | .common = { |
293 | .reg = 0x068, |
294 | .hw.init = CLK_HW_INIT_PARENTS("ahb2" , |
295 | ahb_parents, |
296 | &ccu_div_ops, |
297 | 0), |
298 | }, |
299 | }; |
300 | |
301 | static const char * const apb_parents[] = { "osc24M" , "pll-periph0" }; |
302 | |
303 | static struct ccu_div apb0_clk = { |
304 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
305 | .mux = _SUNXI_CCU_MUX(24, 1), |
306 | .common = { |
307 | .reg = 0x070, |
308 | .hw.init = CLK_HW_INIT_PARENTS("apb0" , |
309 | apb_parents, |
310 | &ccu_div_ops, |
311 | 0), |
312 | }, |
313 | }; |
314 | |
315 | static struct ccu_div apb1_clk = { |
316 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
317 | .mux = _SUNXI_CCU_MUX(24, 1), |
318 | .common = { |
319 | .reg = 0x074, |
320 | .hw.init = CLK_HW_INIT_PARENTS("apb1" , |
321 | apb_parents, |
322 | &ccu_div_ops, |
323 | 0), |
324 | }, |
325 | }; |
326 | |
327 | static struct ccu_div cci400_clk = { |
328 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), |
329 | .mux = _SUNXI_CCU_MUX(24, 2), |
330 | .common = { |
331 | .reg = 0x078, |
332 | .hw.init = CLK_HW_INIT_PARENTS("cci400" , |
333 | ahb_parents, |
334 | &ccu_div_ops, |
335 | CLK_IS_CRITICAL), |
336 | }, |
337 | }; |
338 | |
339 | static SUNXI_CCU_M_WITH_MUX_GATE(ats_clk, "ats" , apb_parents, |
340 | 0x080, 0, 3, 24, 2, BIT(31), 0); |
341 | |
342 | static SUNXI_CCU_M_WITH_MUX_GATE(trace_clk, "trace" , apb_parents, |
343 | 0x084, 0, 3, 24, 2, BIT(31), 0); |
344 | |
345 | static const char * const out_parents[] = { "osc24M" , "osc32k" , "osc24M" }; |
346 | static const struct ccu_mux_fixed_prediv out_prediv = { |
347 | .index = 0, .div = 750 |
348 | }; |
349 | |
350 | static struct ccu_mp out_a_clk = { |
351 | .enable = BIT(31), |
352 | .m = _SUNXI_CCU_DIV(8, 5), |
353 | .p = _SUNXI_CCU_DIV(20, 2), |
354 | .mux = { |
355 | .shift = 24, |
356 | .width = 4, |
357 | .fixed_predivs = &out_prediv, |
358 | .n_predivs = 1, |
359 | }, |
360 | .common = { |
361 | .reg = 0x180, |
362 | .features = CCU_FEATURE_FIXED_PREDIV, |
363 | .hw.init = CLK_HW_INIT_PARENTS("out-a" , |
364 | out_parents, |
365 | &ccu_mp_ops, |
366 | 0), |
367 | }, |
368 | }; |
369 | |
370 | static struct ccu_mp out_b_clk = { |
371 | .enable = BIT(31), |
372 | .m = _SUNXI_CCU_DIV(8, 5), |
373 | .p = _SUNXI_CCU_DIV(20, 2), |
374 | .mux = { |
375 | .shift = 24, |
376 | .width = 4, |
377 | .fixed_predivs = &out_prediv, |
378 | .n_predivs = 1, |
379 | }, |
380 | .common = { |
381 | .reg = 0x184, |
382 | .features = CCU_FEATURE_FIXED_PREDIV, |
383 | .hw.init = CLK_HW_INIT_PARENTS("out-b" , |
384 | out_parents, |
385 | &ccu_mp_ops, |
386 | 0), |
387 | }, |
388 | }; |
389 | |
390 | static const char * const mod0_default_parents[] = { "osc24M" , "pll-periph0" }; |
391 | |
392 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_0_clk, "nand0-0" , mod0_default_parents, |
393 | 0x400, |
394 | 0, 4, /* M */ |
395 | 16, 2, /* P */ |
396 | 24, 4, /* mux */ |
397 | BIT(31), /* gate */ |
398 | 0); |
399 | |
400 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_1_clk, "nand0-1" , mod0_default_parents, |
401 | 0x404, |
402 | 0, 4, /* M */ |
403 | 16, 2, /* P */ |
404 | 24, 4, /* mux */ |
405 | BIT(31), /* gate */ |
406 | 0); |
407 | |
408 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_0_clk, "nand1-0" , mod0_default_parents, |
409 | 0x408, |
410 | 0, 4, /* M */ |
411 | 16, 2, /* P */ |
412 | 24, 4, /* mux */ |
413 | BIT(31), /* gate */ |
414 | 0); |
415 | |
416 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_1_clk, "nand1-1" , mod0_default_parents, |
417 | 0x40c, |
418 | 0, 4, /* M */ |
419 | 16, 2, /* P */ |
420 | 24, 4, /* mux */ |
421 | BIT(31), /* gate */ |
422 | 0); |
423 | |
424 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0" , mod0_default_parents, |
425 | 0x410, |
426 | 0, 4, /* M */ |
427 | 16, 2, /* P */ |
428 | 24, 4, /* mux */ |
429 | BIT(31), /* gate */ |
430 | 0); |
431 | |
432 | static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample" , "mmc0" , |
433 | 0x410, 20, 3, 0); |
434 | static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output" , "mmc0" , |
435 | 0x410, 8, 3, 0); |
436 | |
437 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1" , mod0_default_parents, |
438 | 0x414, |
439 | 0, 4, /* M */ |
440 | 16, 2, /* P */ |
441 | 24, 4, /* mux */ |
442 | BIT(31), /* gate */ |
443 | 0); |
444 | |
445 | static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample" , "mmc1" , |
446 | 0x414, 20, 3, 0); |
447 | static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output" , "mmc1" , |
448 | 0x414, 8, 3, 0); |
449 | |
450 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2" , mod0_default_parents, |
451 | 0x418, |
452 | 0, 4, /* M */ |
453 | 16, 2, /* P */ |
454 | 24, 4, /* mux */ |
455 | BIT(31), /* gate */ |
456 | 0); |
457 | |
458 | static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample" , "mmc2" , |
459 | 0x418, 20, 3, 0); |
460 | static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output" , "mmc2" , |
461 | 0x418, 8, 3, 0); |
462 | |
463 | static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3" , mod0_default_parents, |
464 | 0x41c, |
465 | 0, 4, /* M */ |
466 | 16, 2, /* P */ |
467 | 24, 4, /* mux */ |
468 | BIT(31), /* gate */ |
469 | 0); |
470 | |
471 | static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3-sample" , "mmc3" , |
472 | 0x41c, 20, 3, 0); |
473 | static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3-output" , "mmc3" , |
474 | 0x41c, 8, 3, 0); |
475 | |
476 | static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts" , mod0_default_parents, |
477 | 0x428, |
478 | 0, 4, /* M */ |
479 | 16, 2, /* P */ |
480 | 24, 4, /* mux */ |
481 | BIT(31), /* gate */ |
482 | 0); |
483 | |
484 | static const char * const ss_parents[] = { "osc24M" , "pll-periph" , |
485 | "pll-periph1" }; |
486 | static const u8 ss_table[] = { 0, 1, 13 }; |
487 | static struct ccu_mp ss_clk = { |
488 | .enable = BIT(31), |
489 | .m = _SUNXI_CCU_DIV(0, 4), |
490 | .p = _SUNXI_CCU_DIV(16, 2), |
491 | .mux = _SUNXI_CCU_MUX_TABLE(24, 4, ss_table), |
492 | .common = { |
493 | .reg = 0x42c, |
494 | .hw.init = CLK_HW_INIT_PARENTS("ss" , |
495 | ss_parents, |
496 | &ccu_mp_ops, |
497 | 0), |
498 | }, |
499 | }; |
500 | |
501 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0" , mod0_default_parents, |
502 | 0x430, |
503 | 0, 4, /* M */ |
504 | 16, 2, /* P */ |
505 | 24, 4, /* mux */ |
506 | BIT(31), /* gate */ |
507 | 0); |
508 | |
509 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1" , mod0_default_parents, |
510 | 0x434, |
511 | 0, 4, /* M */ |
512 | 16, 2, /* P */ |
513 | 24, 4, /* mux */ |
514 | BIT(31), /* gate */ |
515 | 0); |
516 | |
517 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2" , mod0_default_parents, |
518 | 0x438, |
519 | 0, 4, /* M */ |
520 | 16, 2, /* P */ |
521 | 24, 4, /* mux */ |
522 | BIT(31), /* gate */ |
523 | 0); |
524 | |
525 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3" , mod0_default_parents, |
526 | 0x43c, |
527 | 0, 4, /* M */ |
528 | 16, 2, /* P */ |
529 | 24, 4, /* mux */ |
530 | BIT(31), /* gate */ |
531 | 0); |
532 | |
533 | static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0" , "pll-audio" , |
534 | 0x440, 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
535 | static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1" , "pll-audio" , |
536 | 0x444, 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
537 | static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif" , "pll-audio" , |
538 | 0x44c, 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
539 | |
540 | static const char * const sdram_parents[] = { "pll-periph0" , "pll-ddr" }; |
541 | static const u8 sdram_table[] = { 0, 3 }; |
542 | |
543 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(sdram_clk, "sdram" , |
544 | sdram_parents, sdram_table, |
545 | 0x484, |
546 | 8, 4, /* M */ |
547 | 12, 4, /* mux */ |
548 | 0, /* no gate */ |
549 | CLK_IS_CRITICAL); |
550 | |
551 | static SUNXI_CCU_M_WITH_GATE(de_clk, "de" , "pll-de" , 0x490, |
552 | 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
553 | |
554 | static SUNXI_CCU_GATE(edp_clk, "edp" , "osc24M" , 0x494, BIT(31), 0); |
555 | |
556 | static const char * const mp_parents[] = { "pll-video1" , "pll-gpu" , "pll-de" }; |
557 | static const u8 mp_table[] = { 9, 10, 11 }; |
558 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mp_clk, "mp" , mp_parents, mp_table, |
559 | 0x498, |
560 | 0, 4, /* M */ |
561 | 24, 4, /* mux */ |
562 | BIT(31), /* gate */ |
563 | 0); |
564 | |
565 | static const char * const display_parents[] = { "pll-video0" , "pll-video1" }; |
566 | static const u8 display_table[] = { 8, 9 }; |
567 | |
568 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd0_clk, "lcd0" , |
569 | display_parents, display_table, |
570 | 0x49c, |
571 | 0, 4, /* M */ |
572 | 24, 4, /* mux */ |
573 | BIT(31), /* gate */ |
574 | CLK_SET_RATE_NO_REPARENT | |
575 | CLK_SET_RATE_PARENT); |
576 | |
577 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd1_clk, "lcd1" , |
578 | display_parents, display_table, |
579 | 0x4a0, |
580 | 0, 4, /* M */ |
581 | 24, 4, /* mux */ |
582 | BIT(31), /* gate */ |
583 | CLK_SET_RATE_NO_REPARENT | |
584 | CLK_SET_RATE_PARENT); |
585 | |
586 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0" , |
587 | display_parents, display_table, |
588 | 0x4a8, |
589 | 0, 4, /* M */ |
590 | 24, 4, /* mux */ |
591 | BIT(31), /* gate */ |
592 | CLK_SET_RATE_PARENT); |
593 | |
594 | static const char * const mipi_dsi1_parents[] = { "osc24M" , "pll-video1" }; |
595 | static const u8 mipi_dsi1_table[] = { 0, 9 }; |
596 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1" , |
597 | mipi_dsi1_parents, mipi_dsi1_table, |
598 | 0x4ac, |
599 | 0, 4, /* M */ |
600 | 24, 4, /* mux */ |
601 | BIT(31), /* gate */ |
602 | CLK_SET_RATE_PARENT); |
603 | |
604 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi" , |
605 | display_parents, display_table, |
606 | 0x4b0, |
607 | 0, 4, /* M */ |
608 | 24, 4, /* mux */ |
609 | BIT(31), /* gate */ |
610 | CLK_SET_RATE_NO_REPARENT | |
611 | CLK_SET_RATE_PARENT); |
612 | |
613 | static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow" , "osc24M" , 0x4b4, BIT(31), 0); |
614 | |
615 | static SUNXI_CCU_M_WITH_GATE(mipi_csi_clk, "mipi-csi" , "osc24M" , 0x4bc, |
616 | 0, 4, BIT(31), 0); |
617 | |
618 | static SUNXI_CCU_M_WITH_GATE(csi_isp_clk, "csi-isp" , "pll-isp" , 0x4c0, |
619 | 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
620 | |
621 | static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc" , "osc24M" , 0x4c0, BIT(16), 0); |
622 | |
623 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_mclk_clk, "csi0-mclk" , |
624 | mipi_dsi1_parents, mipi_dsi1_table, |
625 | 0x4c4, |
626 | 0, 4, /* M */ |
627 | 24, 4, /* mux */ |
628 | BIT(31), /* gate */ |
629 | CLK_SET_RATE_PARENT); |
630 | |
631 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_mclk_clk, "csi1-mclk" , |
632 | mipi_dsi1_parents, mipi_dsi1_table, |
633 | 0x4c8, |
634 | 0, 4, /* M */ |
635 | 24, 4, /* mux */ |
636 | BIT(31), /* gate */ |
637 | CLK_SET_RATE_PARENT); |
638 | |
639 | static const char * const fd_parents[] = { "pll-periph0" , "pll-isp" }; |
640 | static const u8 fd_table[] = { 1, 12 }; |
641 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(fd_clk, "fd" , fd_parents, fd_table, |
642 | 0x4cc, |
643 | 0, 4, /* M */ |
644 | 24, 4, /* mux */ |
645 | BIT(31), /* gate */ |
646 | 0); |
647 | static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve" , "pll-ve" , 0x4d0, |
648 | 16, 3, BIT(31), CLK_SET_RATE_PARENT); |
649 | |
650 | static SUNXI_CCU_GATE(avs_clk, "avs" , "osc24M" , 0x4d4, BIT(31), 0); |
651 | |
652 | static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core" , "pll-gpu" , 0x4f0, |
653 | 0, 3, BIT(31), CLK_SET_RATE_PARENT); |
654 | static SUNXI_CCU_M_WITH_GATE(gpu_memory_clk, "gpu-memory" , "pll-gpu" , 0x4f4, |
655 | 0, 3, BIT(31), CLK_SET_RATE_PARENT); |
656 | |
657 | static const char * const gpu_axi_parents[] = { "pll-periph0" , "pll-gpu" }; |
658 | static const u8 gpu_axi_table[] = { 1, 10 }; |
659 | static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_axi_clk, "gpu-axi" , |
660 | gpu_axi_parents, gpu_axi_table, |
661 | 0x4f8, |
662 | 0, 4, /* M */ |
663 | 24, 4, /* mux */ |
664 | BIT(31), /* gate */ |
665 | CLK_SET_RATE_PARENT); |
666 | |
667 | static SUNXI_CCU_M_WITH_GATE(sata_clk, "sata" , "pll-periph0" , 0x500, |
668 | 0, 4, BIT(31), 0); |
669 | |
670 | static SUNXI_CCU_M_WITH_GATE(ac97_clk, "ac97" , "pll-audio" , |
671 | 0x504, 0, 4, BIT(31), CLK_SET_RATE_PARENT); |
672 | |
673 | static SUNXI_CCU_M_WITH_MUX_GATE(mipi_hsi_clk, "mipi-hsi" , |
674 | mod0_default_parents, 0x508, |
675 | 0, 4, /* M */ |
676 | 24, 4, /* mux */ |
677 | BIT(31), /* gate */ |
678 | 0); |
679 | |
680 | static const char * const gpadc_parents[] = { "osc24M" , "pll-audio" , "osc32k" }; |
681 | static const u8 gpadc_table[] = { 0, 4, 7 }; |
682 | static struct ccu_mp gpadc_clk = { |
683 | .enable = BIT(31), |
684 | .m = _SUNXI_CCU_DIV(0, 4), |
685 | .p = _SUNXI_CCU_DIV(16, 2), |
686 | .mux = _SUNXI_CCU_MUX_TABLE(24, 4, gpadc_table), |
687 | .common = { |
688 | .reg = 0x50c, |
689 | .hw.init = CLK_HW_INIT_PARENTS("gpadc" , |
690 | gpadc_parents, |
691 | &ccu_mp_ops, |
692 | 0), |
693 | }, |
694 | }; |
695 | |
696 | static const char * const cir_tx_parents[] = { "osc24M" , "osc32k" }; |
697 | static const u8 cir_tx_table[] = { 0, 7 }; |
698 | static struct ccu_mp cir_tx_clk = { |
699 | .enable = BIT(31), |
700 | .m = _SUNXI_CCU_DIV(0, 4), |
701 | .p = _SUNXI_CCU_DIV(16, 2), |
702 | .mux = _SUNXI_CCU_MUX_TABLE(24, 4, cir_tx_table), |
703 | .common = { |
704 | .reg = 0x510, |
705 | .hw.init = CLK_HW_INIT_PARENTS("cir-tx" , |
706 | cir_tx_parents, |
707 | &ccu_mp_ops, |
708 | 0), |
709 | }, |
710 | }; |
711 | |
712 | /* AHB0 bus gates */ |
713 | static SUNXI_CCU_GATE(bus_fd_clk, "bus-fd" , "ahb0" , |
714 | 0x580, BIT(0), 0); |
715 | static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve" , "ahb0" , |
716 | 0x580, BIT(1), 0); |
717 | static SUNXI_CCU_GATE(bus_gpu_ctrl_clk, "bus-gpu-ctrl" , "ahb0" , |
718 | 0x580, BIT(3), 0); |
719 | static SUNXI_CCU_GATE(bus_ss_clk, "bus-ss" , "ahb0" , |
720 | 0x580, BIT(5), 0); |
721 | static SUNXI_CCU_GATE(bus_mmc_clk, "bus-mmc" , "ahb0" , |
722 | 0x580, BIT(8), 0); |
723 | static SUNXI_CCU_GATE(bus_nand0_clk, "bus-nand0" , "ahb0" , |
724 | 0x580, BIT(12), 0); |
725 | static SUNXI_CCU_GATE(bus_nand1_clk, "bus-nand1" , "ahb0" , |
726 | 0x580, BIT(13), 0); |
727 | static SUNXI_CCU_GATE(bus_sdram_clk, "bus-sdram" , "ahb0" , |
728 | 0x580, BIT(14), 0); |
729 | static SUNXI_CCU_GATE(bus_mipi_hsi_clk, "bus-mipi-hsi" , "ahb0" , |
730 | 0x580, BIT(15), 0); |
731 | static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata" , "ahb0" , |
732 | 0x580, BIT(16), 0); |
733 | static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts" , "ahb0" , |
734 | 0x580, BIT(18), 0); |
735 | static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0" , "ahb0" , |
736 | 0x580, BIT(20), 0); |
737 | static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1" , "ahb0" , |
738 | 0x580, BIT(21), 0); |
739 | static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2" , "ahb0" , |
740 | 0x580, BIT(22), 0); |
741 | static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3" , "ahb0" , |
742 | 0x580, BIT(23), 0); |
743 | |
744 | /* AHB1 bus gates */ |
745 | static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg" , "ahb1" , |
746 | 0x584, BIT(0), 0); |
747 | static SUNXI_CCU_GATE(bus_usb_clk, "bus-usb" , "ahb1" , |
748 | 0x584, BIT(1), 0); |
749 | static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac" , "ahb1" , |
750 | 0x584, BIT(17), 0); |
751 | static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox" , "ahb1" , |
752 | 0x584, BIT(21), 0); |
753 | static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock" , "ahb1" , |
754 | 0x584, BIT(22), 0); |
755 | static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer" , "ahb1" , |
756 | 0x584, BIT(23), 0); |
757 | static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma" , "ahb1" , |
758 | 0x584, BIT(24), 0); |
759 | |
760 | /* AHB2 bus gates */ |
761 | static SUNXI_CCU_GATE(bus_lcd0_clk, "bus-lcd0" , "ahb2" , |
762 | 0x588, BIT(0), 0); |
763 | static SUNXI_CCU_GATE(bus_lcd1_clk, "bus-lcd1" , "ahb2" , |
764 | 0x588, BIT(1), 0); |
765 | static SUNXI_CCU_GATE(bus_edp_clk, "bus-edp" , "ahb2" , |
766 | 0x588, BIT(2), 0); |
767 | static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi" , "ahb2" , |
768 | 0x588, BIT(4), 0); |
769 | static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi" , "ahb2" , |
770 | 0x588, BIT(5), 0); |
771 | static SUNXI_CCU_GATE(bus_de_clk, "bus-de" , "ahb2" , |
772 | 0x588, BIT(7), 0); |
773 | static SUNXI_CCU_GATE(bus_mp_clk, "bus-mp" , "ahb2" , |
774 | 0x588, BIT(8), 0); |
775 | static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi" , "ahb2" , |
776 | 0x588, BIT(11), 0); |
777 | |
778 | /* APB0 bus gates */ |
779 | static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif" , "apb0" , |
780 | 0x590, BIT(1), 0); |
781 | static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio" , "apb0" , |
782 | 0x590, BIT(5), 0); |
783 | static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97" , "apb0" , |
784 | 0x590, BIT(11), 0); |
785 | static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0" , "apb0" , |
786 | 0x590, BIT(12), 0); |
787 | static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1" , "apb0" , |
788 | 0x590, BIT(13), 0); |
789 | static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc" , "apb0" , |
790 | 0x590, BIT(15), 0); |
791 | static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc" , "apb0" , |
792 | 0x590, BIT(17), 0); |
793 | static SUNXI_CCU_GATE(bus_twd_clk, "bus-twd" , "apb0" , |
794 | 0x590, BIT(18), 0); |
795 | static SUNXI_CCU_GATE(bus_cir_tx_clk, "bus-cir-tx" , "apb0" , |
796 | 0x590, BIT(19), 0); |
797 | |
798 | /* APB1 bus gates */ |
799 | static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0" , "apb1" , |
800 | 0x594, BIT(0), 0); |
801 | static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1" , "apb1" , |
802 | 0x594, BIT(1), 0); |
803 | static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2" , "apb1" , |
804 | 0x594, BIT(2), 0); |
805 | static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3" , "apb1" , |
806 | 0x594, BIT(3), 0); |
807 | static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4" , "apb1" , |
808 | 0x594, BIT(4), 0); |
809 | static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0" , "apb1" , |
810 | 0x594, BIT(16), 0); |
811 | static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1" , "apb1" , |
812 | 0x594, BIT(17), 0); |
813 | static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2" , "apb1" , |
814 | 0x594, BIT(18), 0); |
815 | static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3" , "apb1" , |
816 | 0x594, BIT(19), 0); |
817 | static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4" , "apb1" , |
818 | 0x594, BIT(20), 0); |
819 | static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5" , "apb1" , |
820 | 0x594, BIT(21), 0); |
821 | |
822 | static struct ccu_common *sun9i_a80_ccu_clks[] = { |
823 | &pll_c0cpux_clk.common, |
824 | &pll_c1cpux_clk.common, |
825 | &pll_audio_clk.common, |
826 | &pll_periph0_clk.common, |
827 | &pll_ve_clk.common, |
828 | &pll_ddr_clk.common, |
829 | &pll_video0_clk.common, |
830 | &pll_video1_clk.common, |
831 | &pll_gpu_clk.common, |
832 | &pll_de_clk.common, |
833 | &pll_isp_clk.common, |
834 | &pll_periph1_clk.common, |
835 | &c0cpux_clk.common, |
836 | &c1cpux_clk.common, |
837 | &atb0_clk.common, |
838 | &axi0_clk.common, |
839 | &atb1_clk.common, |
840 | &axi1_clk.common, |
841 | >bus_clk.common, |
842 | &ahb0_clk.common, |
843 | &ahb1_clk.common, |
844 | &ahb2_clk.common, |
845 | &apb0_clk.common, |
846 | &apb1_clk.common, |
847 | &cci400_clk.common, |
848 | &ats_clk.common, |
849 | &trace_clk.common, |
850 | |
851 | &out_a_clk.common, |
852 | &out_b_clk.common, |
853 | |
854 | /* module clocks */ |
855 | &nand0_0_clk.common, |
856 | &nand0_1_clk.common, |
857 | &nand1_0_clk.common, |
858 | &nand1_1_clk.common, |
859 | &mmc0_clk.common, |
860 | &mmc0_sample_clk.common, |
861 | &mmc0_output_clk.common, |
862 | &mmc1_clk.common, |
863 | &mmc1_sample_clk.common, |
864 | &mmc1_output_clk.common, |
865 | &mmc2_clk.common, |
866 | &mmc2_sample_clk.common, |
867 | &mmc2_output_clk.common, |
868 | &mmc3_clk.common, |
869 | &mmc3_sample_clk.common, |
870 | &mmc3_output_clk.common, |
871 | &ts_clk.common, |
872 | &ss_clk.common, |
873 | &spi0_clk.common, |
874 | &spi1_clk.common, |
875 | &spi2_clk.common, |
876 | &spi3_clk.common, |
877 | &i2s0_clk.common, |
878 | &i2s1_clk.common, |
879 | &spdif_clk.common, |
880 | &sdram_clk.common, |
881 | &de_clk.common, |
882 | &edp_clk.common, |
883 | &mp_clk.common, |
884 | &lcd0_clk.common, |
885 | &lcd1_clk.common, |
886 | &mipi_dsi0_clk.common, |
887 | &mipi_dsi1_clk.common, |
888 | &hdmi_clk.common, |
889 | &hdmi_slow_clk.common, |
890 | &mipi_csi_clk.common, |
891 | &csi_isp_clk.common, |
892 | &csi_misc_clk.common, |
893 | &csi0_mclk_clk.common, |
894 | &csi1_mclk_clk.common, |
895 | &fd_clk.common, |
896 | &ve_clk.common, |
897 | &avs_clk.common, |
898 | &gpu_core_clk.common, |
899 | &gpu_memory_clk.common, |
900 | &gpu_axi_clk.common, |
901 | &sata_clk.common, |
902 | &ac97_clk.common, |
903 | &mipi_hsi_clk.common, |
904 | &gpadc_clk.common, |
905 | &cir_tx_clk.common, |
906 | |
907 | /* AHB0 bus gates */ |
908 | &bus_fd_clk.common, |
909 | &bus_ve_clk.common, |
910 | &bus_gpu_ctrl_clk.common, |
911 | &bus_ss_clk.common, |
912 | &bus_mmc_clk.common, |
913 | &bus_nand0_clk.common, |
914 | &bus_nand1_clk.common, |
915 | &bus_sdram_clk.common, |
916 | &bus_mipi_hsi_clk.common, |
917 | &bus_sata_clk.common, |
918 | &bus_ts_clk.common, |
919 | &bus_spi0_clk.common, |
920 | &bus_spi1_clk.common, |
921 | &bus_spi2_clk.common, |
922 | &bus_spi3_clk.common, |
923 | |
924 | /* AHB1 bus gates */ |
925 | &bus_otg_clk.common, |
926 | &bus_usb_clk.common, |
927 | &bus_gmac_clk.common, |
928 | &bus_msgbox_clk.common, |
929 | &bus_spinlock_clk.common, |
930 | &bus_hstimer_clk.common, |
931 | &bus_dma_clk.common, |
932 | |
933 | /* AHB2 bus gates */ |
934 | &bus_lcd0_clk.common, |
935 | &bus_lcd1_clk.common, |
936 | &bus_edp_clk.common, |
937 | &bus_csi_clk.common, |
938 | &bus_hdmi_clk.common, |
939 | &bus_de_clk.common, |
940 | &bus_mp_clk.common, |
941 | &bus_mipi_dsi_clk.common, |
942 | |
943 | /* APB0 bus gates */ |
944 | &bus_spdif_clk.common, |
945 | &bus_pio_clk.common, |
946 | &bus_ac97_clk.common, |
947 | &bus_i2s0_clk.common, |
948 | &bus_i2s1_clk.common, |
949 | &bus_lradc_clk.common, |
950 | &bus_gpadc_clk.common, |
951 | &bus_twd_clk.common, |
952 | &bus_cir_tx_clk.common, |
953 | |
954 | /* APB1 bus gates */ |
955 | &bus_i2c0_clk.common, |
956 | &bus_i2c1_clk.common, |
957 | &bus_i2c2_clk.common, |
958 | &bus_i2c3_clk.common, |
959 | &bus_i2c4_clk.common, |
960 | &bus_uart0_clk.common, |
961 | &bus_uart1_clk.common, |
962 | &bus_uart2_clk.common, |
963 | &bus_uart3_clk.common, |
964 | &bus_uart4_clk.common, |
965 | &bus_uart5_clk.common, |
966 | }; |
967 | |
968 | static struct clk_hw_onecell_data sun9i_a80_hw_clks = { |
969 | .hws = { |
970 | [CLK_PLL_C0CPUX] = &pll_c0cpux_clk.common.hw, |
971 | [CLK_PLL_C1CPUX] = &pll_c1cpux_clk.common.hw, |
972 | [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw, |
973 | [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, |
974 | [CLK_PLL_VE] = &pll_ve_clk.common.hw, |
975 | [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, |
976 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, |
977 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, |
978 | [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, |
979 | [CLK_PLL_DE] = &pll_de_clk.common.hw, |
980 | [CLK_PLL_ISP] = &pll_isp_clk.common.hw, |
981 | [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, |
982 | [CLK_C0CPUX] = &c0cpux_clk.common.hw, |
983 | [CLK_C1CPUX] = &c1cpux_clk.common.hw, |
984 | [CLK_ATB0] = &atb0_clk.common.hw, |
985 | [CLK_AXI0] = &axi0_clk.common.hw, |
986 | [CLK_ATB1] = &atb1_clk.common.hw, |
987 | [CLK_AXI1] = &axi1_clk.common.hw, |
988 | [CLK_GTBUS] = >bus_clk.common.hw, |
989 | [CLK_AHB0] = &ahb0_clk.common.hw, |
990 | [CLK_AHB1] = &ahb1_clk.common.hw, |
991 | [CLK_AHB2] = &ahb2_clk.common.hw, |
992 | [CLK_APB0] = &apb0_clk.common.hw, |
993 | [CLK_APB1] = &apb1_clk.common.hw, |
994 | [CLK_CCI400] = &cci400_clk.common.hw, |
995 | [CLK_ATS] = &ats_clk.common.hw, |
996 | [CLK_TRACE] = &trace_clk.common.hw, |
997 | |
998 | [CLK_OUT_A] = &out_a_clk.common.hw, |
999 | [CLK_OUT_B] = &out_b_clk.common.hw, |
1000 | |
1001 | [CLK_NAND0_0] = &nand0_0_clk.common.hw, |
1002 | [CLK_NAND0_1] = &nand0_1_clk.common.hw, |
1003 | [CLK_NAND1_0] = &nand1_0_clk.common.hw, |
1004 | [CLK_NAND1_1] = &nand1_1_clk.common.hw, |
1005 | [CLK_MMC0] = &mmc0_clk.common.hw, |
1006 | [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, |
1007 | [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, |
1008 | [CLK_MMC1] = &mmc1_clk.common.hw, |
1009 | [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, |
1010 | [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, |
1011 | [CLK_MMC2] = &mmc2_clk.common.hw, |
1012 | [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw, |
1013 | [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw, |
1014 | [CLK_MMC3] = &mmc3_clk.common.hw, |
1015 | [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw, |
1016 | [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw, |
1017 | [CLK_TS] = &ts_clk.common.hw, |
1018 | [CLK_SS] = &ss_clk.common.hw, |
1019 | [CLK_SPI0] = &spi0_clk.common.hw, |
1020 | [CLK_SPI1] = &spi1_clk.common.hw, |
1021 | [CLK_SPI2] = &spi2_clk.common.hw, |
1022 | [CLK_SPI3] = &spi3_clk.common.hw, |
1023 | [CLK_I2S0] = &i2s0_clk.common.hw, |
1024 | [CLK_I2S1] = &i2s1_clk.common.hw, |
1025 | [CLK_SPDIF] = &spdif_clk.common.hw, |
1026 | [CLK_SDRAM] = &sdram_clk.common.hw, |
1027 | [CLK_DE] = &de_clk.common.hw, |
1028 | [CLK_EDP] = &edp_clk.common.hw, |
1029 | [CLK_MP] = &mp_clk.common.hw, |
1030 | [CLK_LCD0] = &lcd0_clk.common.hw, |
1031 | [CLK_LCD1] = &lcd1_clk.common.hw, |
1032 | [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw, |
1033 | [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw, |
1034 | [CLK_HDMI] = &hdmi_clk.common.hw, |
1035 | [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, |
1036 | [CLK_MIPI_CSI] = &mipi_csi_clk.common.hw, |
1037 | [CLK_CSI_ISP] = &csi_isp_clk.common.hw, |
1038 | [CLK_CSI_MISC] = &csi_misc_clk.common.hw, |
1039 | [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, |
1040 | [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, |
1041 | [CLK_FD] = &fd_clk.common.hw, |
1042 | [CLK_VE] = &ve_clk.common.hw, |
1043 | [CLK_AVS] = &avs_clk.common.hw, |
1044 | [CLK_GPU_CORE] = &gpu_core_clk.common.hw, |
1045 | [CLK_GPU_MEMORY] = &gpu_memory_clk.common.hw, |
1046 | [CLK_GPU_AXI] = &gpu_axi_clk.common.hw, |
1047 | [CLK_SATA] = &sata_clk.common.hw, |
1048 | [CLK_AC97] = &ac97_clk.common.hw, |
1049 | [CLK_MIPI_HSI] = &mipi_hsi_clk.common.hw, |
1050 | [CLK_GPADC] = &gpadc_clk.common.hw, |
1051 | [CLK_CIR_TX] = &cir_tx_clk.common.hw, |
1052 | |
1053 | [CLK_BUS_FD] = &bus_fd_clk.common.hw, |
1054 | [CLK_BUS_VE] = &bus_ve_clk.common.hw, |
1055 | [CLK_BUS_GPU_CTRL] = &bus_gpu_ctrl_clk.common.hw, |
1056 | [CLK_BUS_SS] = &bus_ss_clk.common.hw, |
1057 | [CLK_BUS_MMC] = &bus_mmc_clk.common.hw, |
1058 | [CLK_BUS_NAND0] = &bus_nand0_clk.common.hw, |
1059 | [CLK_BUS_NAND1] = &bus_nand1_clk.common.hw, |
1060 | [CLK_BUS_SDRAM] = &bus_sdram_clk.common.hw, |
1061 | [CLK_BUS_MIPI_HSI] = &bus_mipi_hsi_clk.common.hw, |
1062 | [CLK_BUS_SATA] = &bus_sata_clk.common.hw, |
1063 | [CLK_BUS_TS] = &bus_ts_clk.common.hw, |
1064 | [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, |
1065 | [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, |
1066 | [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, |
1067 | [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw, |
1068 | |
1069 | [CLK_BUS_OTG] = &bus_otg_clk.common.hw, |
1070 | [CLK_BUS_USB] = &bus_usb_clk.common.hw, |
1071 | [CLK_BUS_GMAC] = &bus_gmac_clk.common.hw, |
1072 | [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, |
1073 | [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, |
1074 | [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, |
1075 | [CLK_BUS_DMA] = &bus_dma_clk.common.hw, |
1076 | |
1077 | [CLK_BUS_LCD0] = &bus_lcd0_clk.common.hw, |
1078 | [CLK_BUS_LCD1] = &bus_lcd1_clk.common.hw, |
1079 | [CLK_BUS_EDP] = &bus_edp_clk.common.hw, |
1080 | [CLK_BUS_CSI] = &bus_csi_clk.common.hw, |
1081 | [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, |
1082 | [CLK_BUS_DE] = &bus_de_clk.common.hw, |
1083 | [CLK_BUS_MP] = &bus_mp_clk.common.hw, |
1084 | [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, |
1085 | |
1086 | [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, |
1087 | [CLK_BUS_PIO] = &bus_pio_clk.common.hw, |
1088 | [CLK_BUS_AC97] = &bus_ac97_clk.common.hw, |
1089 | [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, |
1090 | [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, |
1091 | [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw, |
1092 | [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw, |
1093 | [CLK_BUS_TWD] = &bus_twd_clk.common.hw, |
1094 | [CLK_BUS_CIR_TX] = &bus_cir_tx_clk.common.hw, |
1095 | |
1096 | [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, |
1097 | [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, |
1098 | [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, |
1099 | [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, |
1100 | [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, |
1101 | [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, |
1102 | [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, |
1103 | [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, |
1104 | [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, |
1105 | [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, |
1106 | [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, |
1107 | }, |
1108 | .num = CLK_NUMBER, |
1109 | }; |
1110 | |
1111 | static struct ccu_reset_map sun9i_a80_ccu_resets[] = { |
1112 | /* AHB0 reset controls */ |
1113 | [RST_BUS_FD] = { 0x5a0, BIT(0) }, |
1114 | [RST_BUS_VE] = { 0x5a0, BIT(1) }, |
1115 | [RST_BUS_GPU_CTRL] = { 0x5a0, BIT(3) }, |
1116 | [RST_BUS_SS] = { 0x5a0, BIT(5) }, |
1117 | [RST_BUS_MMC] = { 0x5a0, BIT(8) }, |
1118 | [RST_BUS_NAND0] = { 0x5a0, BIT(12) }, |
1119 | [RST_BUS_NAND1] = { 0x5a0, BIT(13) }, |
1120 | [RST_BUS_SDRAM] = { 0x5a0, BIT(14) }, |
1121 | [RST_BUS_SATA] = { 0x5a0, BIT(16) }, |
1122 | [RST_BUS_TS] = { 0x5a0, BIT(18) }, |
1123 | [RST_BUS_SPI0] = { 0x5a0, BIT(20) }, |
1124 | [RST_BUS_SPI1] = { 0x5a0, BIT(21) }, |
1125 | [RST_BUS_SPI2] = { 0x5a0, BIT(22) }, |
1126 | [RST_BUS_SPI3] = { 0x5a0, BIT(23) }, |
1127 | |
1128 | /* AHB1 reset controls */ |
1129 | [RST_BUS_OTG] = { 0x5a4, BIT(0) }, |
1130 | [RST_BUS_OTG_PHY] = { 0x5a4, BIT(1) }, |
1131 | [RST_BUS_MIPI_HSI] = { 0x5a4, BIT(9) }, |
1132 | [RST_BUS_GMAC] = { 0x5a4, BIT(17) }, |
1133 | [RST_BUS_MSGBOX] = { 0x5a4, BIT(21) }, |
1134 | [RST_BUS_SPINLOCK] = { 0x5a4, BIT(22) }, |
1135 | [RST_BUS_HSTIMER] = { 0x5a4, BIT(23) }, |
1136 | [RST_BUS_DMA] = { 0x5a4, BIT(24) }, |
1137 | |
1138 | /* AHB2 reset controls */ |
1139 | [RST_BUS_LCD0] = { 0x5a8, BIT(0) }, |
1140 | [RST_BUS_LCD1] = { 0x5a8, BIT(1) }, |
1141 | [RST_BUS_EDP] = { 0x5a8, BIT(2) }, |
1142 | [RST_BUS_LVDS] = { 0x5a8, BIT(3) }, |
1143 | [RST_BUS_CSI] = { 0x5a8, BIT(4) }, |
1144 | [RST_BUS_HDMI0] = { 0x5a8, BIT(5) }, |
1145 | [RST_BUS_HDMI1] = { 0x5a8, BIT(6) }, |
1146 | [RST_BUS_DE] = { 0x5a8, BIT(7) }, |
1147 | [RST_BUS_MP] = { 0x5a8, BIT(8) }, |
1148 | [RST_BUS_GPU] = { 0x5a8, BIT(9) }, |
1149 | [RST_BUS_MIPI_DSI] = { 0x5a8, BIT(11) }, |
1150 | |
1151 | /* APB0 reset controls */ |
1152 | [RST_BUS_SPDIF] = { 0x5b0, BIT(1) }, |
1153 | [RST_BUS_AC97] = { 0x5b0, BIT(11) }, |
1154 | [RST_BUS_I2S0] = { 0x5b0, BIT(12) }, |
1155 | [RST_BUS_I2S1] = { 0x5b0, BIT(13) }, |
1156 | [RST_BUS_LRADC] = { 0x5b0, BIT(15) }, |
1157 | [RST_BUS_GPADC] = { 0x5b0, BIT(17) }, |
1158 | [RST_BUS_CIR_TX] = { 0x5b0, BIT(19) }, |
1159 | |
1160 | /* APB1 reset controls */ |
1161 | [RST_BUS_I2C0] = { 0x5b4, BIT(0) }, |
1162 | [RST_BUS_I2C1] = { 0x5b4, BIT(1) }, |
1163 | [RST_BUS_I2C2] = { 0x5b4, BIT(2) }, |
1164 | [RST_BUS_I2C3] = { 0x5b4, BIT(3) }, |
1165 | [RST_BUS_I2C4] = { 0x5b4, BIT(4) }, |
1166 | [RST_BUS_UART0] = { 0x5b4, BIT(16) }, |
1167 | [RST_BUS_UART1] = { 0x5b4, BIT(17) }, |
1168 | [RST_BUS_UART2] = { 0x5b4, BIT(18) }, |
1169 | [RST_BUS_UART3] = { 0x5b4, BIT(19) }, |
1170 | [RST_BUS_UART4] = { 0x5b4, BIT(20) }, |
1171 | [RST_BUS_UART5] = { 0x5b4, BIT(21) }, |
1172 | }; |
1173 | |
1174 | static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = { |
1175 | .ccu_clks = sun9i_a80_ccu_clks, |
1176 | .num_ccu_clks = ARRAY_SIZE(sun9i_a80_ccu_clks), |
1177 | |
1178 | .hw_clks = &sun9i_a80_hw_clks, |
1179 | |
1180 | .resets = sun9i_a80_ccu_resets, |
1181 | .num_resets = ARRAY_SIZE(sun9i_a80_ccu_resets), |
1182 | }; |
1183 | |
1184 | #define SUN9I_A80_PLL_P_SHIFT 16 |
1185 | #define SUN9I_A80_PLL_N_SHIFT 8 |
1186 | #define SUN9I_A80_PLL_N_WIDTH 8 |
1187 | |
1188 | static void sun9i_a80_cpu_pll_fixup(void __iomem *reg) |
1189 | { |
1190 | u32 val = readl(addr: reg); |
1191 | |
1192 | /* bail out if P divider is not used */ |
1193 | if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT))) |
1194 | return; |
1195 | |
1196 | /* |
1197 | * If P is used, output should be less than 288 MHz. When we |
1198 | * set P to 1, we should also decrease the multiplier so the |
1199 | * output doesn't go out of range, but not too much such that |
1200 | * the multiplier stays above 12, the minimal operation value. |
1201 | * |
1202 | * To keep it simple, set the multiplier to 17, the reset value. |
1203 | */ |
1204 | val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1, |
1205 | SUN9I_A80_PLL_N_SHIFT); |
1206 | val |= 17 << SUN9I_A80_PLL_N_SHIFT; |
1207 | |
1208 | /* And clear P */ |
1209 | val &= ~BIT(SUN9I_A80_PLL_P_SHIFT); |
1210 | |
1211 | writel(val, addr: reg); |
1212 | } |
1213 | |
1214 | static int sun9i_a80_ccu_probe(struct platform_device *pdev) |
1215 | { |
1216 | void __iomem *reg; |
1217 | u32 val; |
1218 | |
1219 | reg = devm_platform_ioremap_resource(pdev, index: 0); |
1220 | if (IS_ERR(ptr: reg)) |
1221 | return PTR_ERR(ptr: reg); |
1222 | |
1223 | /* Enforce d1 = 0, d2 = 0 for Audio PLL */ |
1224 | val = readl(addr: reg + SUN9I_A80_PLL_AUDIO_REG); |
1225 | val &= ~(BIT(16) | BIT(18)); |
1226 | writel(val, addr: reg + SUN9I_A80_PLL_AUDIO_REG); |
1227 | |
1228 | /* Enforce P = 1 for both CPU cluster PLLs */ |
1229 | sun9i_a80_cpu_pll_fixup(reg: reg + SUN9I_A80_PLL_C0CPUX_REG); |
1230 | sun9i_a80_cpu_pll_fixup(reg: reg + SUN9I_A80_PLL_C1CPUX_REG); |
1231 | |
1232 | return devm_sunxi_ccu_probe(dev: &pdev->dev, reg, desc: &sun9i_a80_ccu_desc); |
1233 | } |
1234 | |
1235 | static const struct of_device_id sun9i_a80_ccu_ids[] = { |
1236 | { .compatible = "allwinner,sun9i-a80-ccu" }, |
1237 | { } |
1238 | }; |
1239 | |
1240 | static struct platform_driver sun9i_a80_ccu_driver = { |
1241 | .probe = sun9i_a80_ccu_probe, |
1242 | .driver = { |
1243 | .name = "sun9i-a80-ccu" , |
1244 | .suppress_bind_attrs = true, |
1245 | .of_match_table = sun9i_a80_ccu_ids, |
1246 | }, |
1247 | }; |
1248 | module_platform_driver(sun9i_a80_ccu_driver); |
1249 | |
1250 | MODULE_IMPORT_NS(SUNXI_CCU); |
1251 | MODULE_LICENSE("GPL" ); |
1252 | |