1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2020 Arm Ltd. |
4 | * Based on the H6 CCU driver, which is: |
5 | * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> |
6 | */ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/io.h> |
10 | #include <linux/module.h> |
11 | #include <linux/platform_device.h> |
12 | |
13 | #include "ccu_common.h" |
14 | #include "ccu_reset.h" |
15 | |
16 | #include "ccu_div.h" |
17 | #include "ccu_gate.h" |
18 | #include "ccu_mp.h" |
19 | #include "ccu_mult.h" |
20 | #include "ccu_nk.h" |
21 | #include "ccu_nkm.h" |
22 | #include "ccu_nkmp.h" |
23 | #include "ccu_nm.h" |
24 | |
25 | #include "ccu-sun50i-h616.h" |
26 | |
27 | /* |
28 | * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However |
29 | * P should only be used for output frequencies lower than 288 MHz. |
30 | * |
31 | * For now we can just model it as a multiplier clock, and force P to /1. |
32 | * |
33 | * The M factor is present in the register's description, but not in the |
34 | * frequency formula, and it's documented as "M is only used for backdoor |
35 | * testing", so it's not modelled and then force to 0. |
36 | */ |
37 | #define SUN50I_H616_PLL_CPUX_REG 0x000 |
38 | static struct ccu_mult pll_cpux_clk = { |
39 | .enable = BIT(31), |
40 | .lock = BIT(28), |
41 | .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
42 | .common = { |
43 | .reg = 0x000, |
44 | .hw.init = CLK_HW_INIT("pll-cpux" , "osc24M" , |
45 | &ccu_mult_ops, |
46 | CLK_SET_RATE_UNGATE), |
47 | }, |
48 | }; |
49 | |
50 | /* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ |
51 | #define SUN50I_H616_PLL_DDR0_REG 0x010 |
52 | static struct ccu_nkmp pll_ddr0_clk = { |
53 | .enable = BIT(31), |
54 | .lock = BIT(28), |
55 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
56 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
57 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
58 | .common = { |
59 | .reg = 0x010, |
60 | .hw.init = CLK_HW_INIT("pll-ddr0" , "osc24M" , |
61 | &ccu_nkmp_ops, |
62 | CLK_SET_RATE_UNGATE), |
63 | }, |
64 | }; |
65 | |
66 | #define SUN50I_H616_PLL_DDR1_REG 0x018 |
67 | static struct ccu_nkmp pll_ddr1_clk = { |
68 | .enable = BIT(31), |
69 | .lock = BIT(28), |
70 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
71 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
72 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
73 | .common = { |
74 | .reg = 0x018, |
75 | .hw.init = CLK_HW_INIT("pll-ddr1" , "osc24M" , |
76 | &ccu_nkmp_ops, |
77 | CLK_SET_RATE_UNGATE), |
78 | }, |
79 | }; |
80 | |
81 | #define SUN50I_H616_PLL_PERIPH0_REG 0x020 |
82 | static struct ccu_nkmp pll_periph0_clk = { |
83 | .enable = BIT(31), |
84 | .lock = BIT(28), |
85 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
86 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
87 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
88 | .fixed_post_div = 2, |
89 | .common = { |
90 | .reg = 0x020, |
91 | .features = CCU_FEATURE_FIXED_POSTDIV, |
92 | .hw.init = CLK_HW_INIT("pll-periph0" , "osc24M" , |
93 | &ccu_nkmp_ops, |
94 | CLK_SET_RATE_UNGATE), |
95 | }, |
96 | }; |
97 | |
98 | #define SUN50I_H616_PLL_PERIPH1_REG 0x028 |
99 | static struct ccu_nkmp pll_periph1_clk = { |
100 | .enable = BIT(31), |
101 | .lock = BIT(28), |
102 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
103 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
104 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
105 | .fixed_post_div = 2, |
106 | .common = { |
107 | .reg = 0x028, |
108 | .features = CCU_FEATURE_FIXED_POSTDIV, |
109 | .hw.init = CLK_HW_INIT("pll-periph1" , "osc24M" , |
110 | &ccu_nkmp_ops, |
111 | CLK_SET_RATE_UNGATE), |
112 | }, |
113 | }; |
114 | |
115 | #define SUN50I_H616_PLL_GPU_REG 0x030 |
116 | static struct ccu_nkmp pll_gpu_clk = { |
117 | .enable = BIT(31), |
118 | .lock = BIT(28), |
119 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
120 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
121 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
122 | .common = { |
123 | .reg = 0x030, |
124 | .hw.init = CLK_HW_INIT("pll-gpu" , "osc24M" , |
125 | &ccu_nkmp_ops, |
126 | CLK_SET_RATE_UNGATE), |
127 | }, |
128 | }; |
129 | |
130 | /* |
131 | * For Video PLLs, the output divider is described as "used for testing" |
132 | * in the user manual. So it's not modelled and forced to 0. |
133 | */ |
134 | #define SUN50I_H616_PLL_VIDEO0_REG 0x040 |
135 | static struct ccu_nm pll_video0_clk = { |
136 | .enable = BIT(31), |
137 | .lock = BIT(28), |
138 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
139 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
140 | .fixed_post_div = 4, |
141 | .min_rate = 288000000, |
142 | .max_rate = 2400000000UL, |
143 | .common = { |
144 | .reg = 0x040, |
145 | .features = CCU_FEATURE_FIXED_POSTDIV, |
146 | .hw.init = CLK_HW_INIT("pll-video0" , "osc24M" , |
147 | &ccu_nm_ops, |
148 | CLK_SET_RATE_UNGATE), |
149 | }, |
150 | }; |
151 | |
152 | #define SUN50I_H616_PLL_VIDEO1_REG 0x048 |
153 | static struct ccu_nm pll_video1_clk = { |
154 | .enable = BIT(31), |
155 | .lock = BIT(28), |
156 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
157 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
158 | .fixed_post_div = 4, |
159 | .min_rate = 288000000, |
160 | .max_rate = 2400000000UL, |
161 | .common = { |
162 | .reg = 0x048, |
163 | .features = CCU_FEATURE_FIXED_POSTDIV, |
164 | .hw.init = CLK_HW_INIT("pll-video1" , "osc24M" , |
165 | &ccu_nm_ops, |
166 | CLK_SET_RATE_UNGATE), |
167 | }, |
168 | }; |
169 | |
170 | #define SUN50I_H616_PLL_VIDEO2_REG 0x050 |
171 | static struct ccu_nm pll_video2_clk = { |
172 | .enable = BIT(31), |
173 | .lock = BIT(28), |
174 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
175 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
176 | .fixed_post_div = 4, |
177 | .min_rate = 288000000, |
178 | .max_rate = 2400000000UL, |
179 | .common = { |
180 | .reg = 0x050, |
181 | .features = CCU_FEATURE_FIXED_POSTDIV, |
182 | .hw.init = CLK_HW_INIT("pll-video2" , "osc24M" , |
183 | &ccu_nm_ops, |
184 | CLK_SET_RATE_UNGATE), |
185 | }, |
186 | }; |
187 | |
188 | #define SUN50I_H616_PLL_VE_REG 0x058 |
189 | static struct ccu_nkmp pll_ve_clk = { |
190 | .enable = BIT(31), |
191 | .lock = BIT(28), |
192 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
193 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
194 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
195 | .common = { |
196 | .reg = 0x058, |
197 | .hw.init = CLK_HW_INIT("pll-ve" , "osc24M" , |
198 | &ccu_nkmp_ops, |
199 | CLK_SET_RATE_UNGATE), |
200 | }, |
201 | }; |
202 | |
203 | #define SUN50I_H616_PLL_DE_REG 0x060 |
204 | static struct ccu_nkmp pll_de_clk = { |
205 | .enable = BIT(31), |
206 | .lock = BIT(28), |
207 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
208 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
209 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
210 | .common = { |
211 | .reg = 0x060, |
212 | .hw.init = CLK_HW_INIT("pll-de" , "osc24M" , |
213 | &ccu_nkmp_ops, |
214 | CLK_SET_RATE_UNGATE), |
215 | }, |
216 | }; |
217 | |
218 | /* |
219 | * TODO: Determine SDM settings for the audio PLL. The manual suggests |
220 | * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b |
221 | * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2, |
222 | * pattern=0xe001288c for 22.5792 MHz. |
223 | * This clashes with our fixed PLL_POST_DIV_P. |
224 | */ |
225 | #define SUN50I_H616_PLL_AUDIO_REG 0x078 |
226 | static struct ccu_nm pll_audio_hs_clk = { |
227 | .enable = BIT(31), |
228 | .lock = BIT(28), |
229 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
230 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
231 | .common = { |
232 | .reg = 0x078, |
233 | .hw.init = CLK_HW_INIT("pll-audio-hs" , "osc24M" , |
234 | &ccu_nm_ops, |
235 | CLK_SET_RATE_UNGATE), |
236 | }, |
237 | }; |
238 | |
239 | static const char * const cpux_parents[] = { "osc24M" , "osc32k" , |
240 | "iosc" , "pll-cpux" , "pll-periph0" }; |
241 | static SUNXI_CCU_MUX(cpux_clk, "cpux" , cpux_parents, |
242 | 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); |
243 | static SUNXI_CCU_M(axi_clk, "axi" , "cpux" , 0x500, 0, 2, 0); |
244 | static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb" , "cpux" , 0x500, 8, 2, 0); |
245 | |
246 | static const char * const psi_ahb1_ahb2_parents[] = { "osc24M" , "osc32k" , |
247 | "iosc" , "pll-periph0" }; |
248 | static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2" , |
249 | psi_ahb1_ahb2_parents, |
250 | 0x510, |
251 | 0, 2, /* M */ |
252 | 8, 2, /* P */ |
253 | 24, 2, /* mux */ |
254 | 0); |
255 | |
256 | static const char * const ahb3_apb1_apb2_parents[] = { "osc24M" , "osc32k" , |
257 | "psi-ahb1-ahb2" , |
258 | "pll-periph0" }; |
259 | static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3" , ahb3_apb1_apb2_parents, 0x51c, |
260 | 0, 2, /* M */ |
261 | 8, 2, /* P */ |
262 | 24, 2, /* mux */ |
263 | 0); |
264 | |
265 | static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1" , ahb3_apb1_apb2_parents, 0x520, |
266 | 0, 2, /* M */ |
267 | 8, 2, /* P */ |
268 | 24, 2, /* mux */ |
269 | 0); |
270 | |
271 | static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2" , ahb3_apb1_apb2_parents, 0x524, |
272 | 0, 2, /* M */ |
273 | 8, 2, /* P */ |
274 | 24, 2, /* mux */ |
275 | 0); |
276 | |
277 | static const char * const mbus_parents[] = { "osc24M" , "pll-periph0-2x" , |
278 | "pll-ddr0" , "pll-ddr1" }; |
279 | static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus" , mbus_parents, 0x540, |
280 | 0, 3, /* M */ |
281 | 24, 2, /* mux */ |
282 | BIT(31), /* gate */ |
283 | CLK_IS_CRITICAL); |
284 | |
285 | static const char * const de_parents[] = { "pll-de" , "pll-periph0-2x" }; |
286 | static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de" , de_parents, 0x600, |
287 | 0, 4, /* M */ |
288 | 24, 1, /* mux */ |
289 | BIT(31), /* gate */ |
290 | CLK_SET_RATE_PARENT); |
291 | |
292 | static SUNXI_CCU_GATE(bus_de_clk, "bus-de" , "psi-ahb1-ahb2" , |
293 | 0x60c, BIT(0), 0); |
294 | |
295 | static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace" , |
296 | de_parents, |
297 | 0x620, |
298 | 0, 4, /* M */ |
299 | 24, 1, /* mux */ |
300 | BIT(31), /* gate */ |
301 | 0); |
302 | |
303 | static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace" , "psi-ahb1-ahb2" , |
304 | 0x62c, BIT(0), 0); |
305 | |
306 | static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d" , de_parents, 0x630, |
307 | 0, 4, /* M */ |
308 | 24, 1, /* mux */ |
309 | BIT(31), /* gate */ |
310 | 0); |
311 | |
312 | static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d" , "psi-ahb1-ahb2" , |
313 | 0x63c, BIT(0), 0); |
314 | |
315 | static const char * const gpu0_parents[] = { "pll-gpu" , "gpu1" }; |
316 | static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0" , gpu0_parents, 0x670, |
317 | 0, 2, /* M */ |
318 | 24, 1, /* mux */ |
319 | BIT(31), /* gate */ |
320 | CLK_SET_RATE_PARENT); |
321 | static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1" , "pll-periph0-2x" , 0x674, |
322 | 0, 2, /* M */ |
323 | BIT(31),/* gate */ |
324 | 0); |
325 | |
326 | static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu" , "psi-ahb1-ahb2" , |
327 | 0x67c, BIT(0), 0); |
328 | |
329 | static const char * const ce_parents[] = { "osc24M" , "pll-periph0-2x" }; |
330 | static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce" , ce_parents, 0x680, |
331 | 0, 4, /* M */ |
332 | 8, 2, /* N */ |
333 | 24, 1, /* mux */ |
334 | BIT(31),/* gate */ |
335 | 0); |
336 | |
337 | static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce" , "psi-ahb1-ahb2" , |
338 | 0x68c, BIT(0), 0); |
339 | |
340 | static const char * const ve_parents[] = { "pll-ve" }; |
341 | static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve" , ve_parents, 0x690, |
342 | 0, 3, /* M */ |
343 | 24, 1, /* mux */ |
344 | BIT(31), /* gate */ |
345 | CLK_SET_RATE_PARENT); |
346 | |
347 | static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve" , "psi-ahb1-ahb2" , |
348 | 0x69c, BIT(0), 0); |
349 | |
350 | static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma" , "psi-ahb1-ahb2" , |
351 | 0x70c, BIT(0), 0); |
352 | |
353 | static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer" , "psi-ahb1-ahb2" , |
354 | 0x73c, BIT(0), 0); |
355 | |
356 | static SUNXI_CCU_GATE(avs_clk, "avs" , "osc24M" , 0x740, BIT(31), 0); |
357 | |
358 | static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg" , "psi-ahb1-ahb2" , |
359 | 0x78c, BIT(0), 0); |
360 | |
361 | static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi" , "psi-ahb1-ahb2" , |
362 | 0x79c, BIT(0), 0); |
363 | |
364 | static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm" , "apb1" , 0x7ac, BIT(0), 0); |
365 | |
366 | static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu" , "apb1" , 0x7bc, BIT(0), 0); |
367 | |
368 | static const char * const dram_parents[] = { "pll-ddr0" , "pll-ddr1" }; |
369 | static struct ccu_div dram_clk = { |
370 | .div = _SUNXI_CCU_DIV(0, 2), |
371 | .mux = _SUNXI_CCU_MUX(24, 2), |
372 | .common = { |
373 | .reg = 0x800, |
374 | .hw.init = CLK_HW_INIT_PARENTS("dram" , |
375 | dram_parents, |
376 | &ccu_div_ops, |
377 | CLK_IS_CRITICAL), |
378 | }, |
379 | }; |
380 | |
381 | static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma" , "mbus" , |
382 | 0x804, BIT(0), 0); |
383 | static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve" , "mbus" , |
384 | 0x804, BIT(1), 0); |
385 | static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce" , "mbus" , |
386 | 0x804, BIT(2), 0); |
387 | static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts" , "mbus" , |
388 | 0x804, BIT(3), 0); |
389 | static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand" , "mbus" , |
390 | 0x804, BIT(5), 0); |
391 | static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d" , "mbus" , |
392 | 0x804, BIT(10), 0); |
393 | |
394 | static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram" , "psi-ahb1-ahb2" , |
395 | 0x80c, BIT(0), CLK_IS_CRITICAL); |
396 | |
397 | static const char * const nand_spi_parents[] = { "osc24M" , "pll-periph0" , |
398 | "pll-periph1" , "pll-periph0-2x" , |
399 | "pll-periph1-2x" }; |
400 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0" , nand_spi_parents, 0x810, |
401 | 0, 4, /* M */ |
402 | 8, 2, /* N */ |
403 | 24, 3, /* mux */ |
404 | BIT(31),/* gate */ |
405 | 0); |
406 | |
407 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1" , nand_spi_parents, 0x814, |
408 | 0, 4, /* M */ |
409 | 8, 2, /* N */ |
410 | 24, 3, /* mux */ |
411 | BIT(31),/* gate */ |
412 | 0); |
413 | |
414 | static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand" , "ahb3" , 0x82c, BIT(0), 0); |
415 | |
416 | static const char * const mmc_parents[] = { "osc24M" , "pll-periph0-2x" , |
417 | "pll-periph1-2x" }; |
418 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0" , mmc_parents, 0x830, |
419 | 0, 4, /* M */ |
420 | 8, 2, /* N */ |
421 | 24, 2, /* mux */ |
422 | BIT(31), /* gate */ |
423 | 2, /* post-div */ |
424 | 0); |
425 | |
426 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1" , mmc_parents, 0x834, |
427 | 0, 4, /* M */ |
428 | 8, 2, /* N */ |
429 | 24, 2, /* mux */ |
430 | BIT(31), /* gate */ |
431 | 2, /* post-div */ |
432 | 0); |
433 | |
434 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2" , mmc_parents, 0x838, |
435 | 0, 4, /* M */ |
436 | 8, 2, /* N */ |
437 | 24, 2, /* mux */ |
438 | BIT(31), /* gate */ |
439 | 2, /* post-div */ |
440 | 0); |
441 | |
442 | static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0" , "ahb3" , 0x84c, BIT(0), 0); |
443 | static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1" , "ahb3" , 0x84c, BIT(1), 0); |
444 | static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2" , "ahb3" , 0x84c, BIT(2), 0); |
445 | |
446 | static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0" , "apb2" , 0x90c, BIT(0), 0); |
447 | static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1" , "apb2" , 0x90c, BIT(1), 0); |
448 | static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2" , "apb2" , 0x90c, BIT(2), 0); |
449 | static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3" , "apb2" , 0x90c, BIT(3), 0); |
450 | static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4" , "apb2" , 0x90c, BIT(4), 0); |
451 | static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5" , "apb2" , 0x90c, BIT(5), 0); |
452 | |
453 | static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0" , "apb2" , 0x91c, BIT(0), 0); |
454 | static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1" , "apb2" , 0x91c, BIT(1), 0); |
455 | static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2" , "apb2" , 0x91c, BIT(2), 0); |
456 | static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3" , "apb2" , 0x91c, BIT(3), 0); |
457 | static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4" , "apb2" , 0x91c, BIT(4), 0); |
458 | |
459 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0" , nand_spi_parents, 0x940, |
460 | 0, 4, /* M */ |
461 | 8, 2, /* N */ |
462 | 24, 3, /* mux */ |
463 | BIT(31),/* gate */ |
464 | 0); |
465 | |
466 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1" , nand_spi_parents, 0x944, |
467 | 0, 4, /* M */ |
468 | 8, 2, /* N */ |
469 | 24, 3, /* mux */ |
470 | BIT(31),/* gate */ |
471 | 0); |
472 | |
473 | static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0" , "ahb3" , 0x96c, BIT(0), 0); |
474 | static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1" , "ahb3" , 0x96c, BIT(1), 0); |
475 | |
476 | static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m" , "ahb3" , 0x970, |
477 | BIT(31) | BIT(30), 0); |
478 | |
479 | static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0" , "ahb3" , 0x97c, BIT(0), 0); |
480 | static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1" , "ahb3" , 0x97c, BIT(1), 0); |
481 | |
482 | static const char * const ts_parents[] = { "osc24M" , "pll-periph0" }; |
483 | static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts" , ts_parents, 0x9b0, |
484 | 0, 4, /* M */ |
485 | 8, 2, /* N */ |
486 | 24, 1, /* mux */ |
487 | BIT(31),/* gate */ |
488 | 0); |
489 | |
490 | static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts" , "ahb3" , 0x9bc, BIT(0), 0); |
491 | |
492 | static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths" , "apb1" , 0x9fc, BIT(0), 0); |
493 | |
494 | static const char * const audio_parents[] = { "pll-audio-1x" , "pll-audio-2x" , |
495 | "pll-audio-4x" , "pll-audio-hs" }; |
496 | static struct ccu_div spdif_clk = { |
497 | .enable = BIT(31), |
498 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
499 | .mux = _SUNXI_CCU_MUX(24, 2), |
500 | .common = { |
501 | .reg = 0xa20, |
502 | .hw.init = CLK_HW_INIT_PARENTS("spdif" , |
503 | audio_parents, |
504 | &ccu_div_ops, |
505 | 0), |
506 | }, |
507 | }; |
508 | |
509 | static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif" , "apb1" , 0xa2c, BIT(0), 0); |
510 | |
511 | static struct ccu_div dmic_clk = { |
512 | .enable = BIT(31), |
513 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
514 | .mux = _SUNXI_CCU_MUX(24, 2), |
515 | .common = { |
516 | .reg = 0xa40, |
517 | .hw.init = CLK_HW_INIT_PARENTS("dmic" , |
518 | audio_parents, |
519 | &ccu_div_ops, |
520 | 0), |
521 | }, |
522 | }; |
523 | |
524 | static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic" , "apb1" , 0xa4c, BIT(0), 0); |
525 | |
526 | static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x" , |
527 | audio_parents, 0xa50, |
528 | 0, 4, /* M */ |
529 | 24, 2, /* mux */ |
530 | BIT(31), /* gate */ |
531 | CLK_SET_RATE_PARENT); |
532 | static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x" , |
533 | audio_parents, 0xa54, |
534 | 0, 4, /* M */ |
535 | 24, 2, /* mux */ |
536 | BIT(31), /* gate */ |
537 | CLK_SET_RATE_PARENT); |
538 | |
539 | static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec" , "apb1" , 0xa5c, |
540 | BIT(0), 0); |
541 | |
542 | static struct ccu_div audio_hub_clk = { |
543 | .enable = BIT(31), |
544 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
545 | .mux = _SUNXI_CCU_MUX(24, 2), |
546 | .common = { |
547 | .reg = 0xa60, |
548 | .hw.init = CLK_HW_INIT_PARENTS("audio-hub" , |
549 | audio_parents, |
550 | &ccu_div_ops, |
551 | 0), |
552 | }, |
553 | }; |
554 | |
555 | static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub" , "apb1" , 0xa6c, BIT(0), 0); |
556 | |
557 | /* |
558 | * There are OHCI 12M clock source selection bits for the four USB 2.0 ports. |
559 | * We will force them to 0 (12M divided from 48M). |
560 | */ |
561 | #define SUN50I_H616_USB0_CLK_REG 0xa70 |
562 | #define SUN50I_H616_USB1_CLK_REG 0xa74 |
563 | #define SUN50I_H616_USB2_CLK_REG 0xa78 |
564 | #define SUN50I_H616_USB3_CLK_REG 0xa7c |
565 | |
566 | static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0" , "osc12M" , 0xa70, BIT(31), 0); |
567 | static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0" , "osc24M" , 0xa70, BIT(29), 0); |
568 | |
569 | static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1" , "osc12M" , 0xa74, BIT(31), 0); |
570 | static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1" , "osc24M" , 0xa74, BIT(29), 0); |
571 | |
572 | static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2" , "osc12M" , 0xa78, BIT(31), 0); |
573 | static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2" , "osc24M" , 0xa78, BIT(29), 0); |
574 | |
575 | static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3" , "osc12M" , 0xa7c, BIT(31), 0); |
576 | static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3" , "osc24M" , 0xa7c, BIT(29), 0); |
577 | |
578 | static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0" , "ahb3" , 0xa8c, BIT(0), 0); |
579 | static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1" , "ahb3" , 0xa8c, BIT(1), 0); |
580 | static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2" , "ahb3" , 0xa8c, BIT(2), 0); |
581 | static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3" , "ahb3" , 0xa8c, BIT(3), 0); |
582 | static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0" , "ahb3" , 0xa8c, BIT(4), 0); |
583 | static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1" , "ahb3" , 0xa8c, BIT(5), 0); |
584 | static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2" , "ahb3" , 0xa8c, BIT(6), 0); |
585 | static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3" , "ahb3" , 0xa8c, BIT(7), 0); |
586 | static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg" , "ahb3" , 0xa8c, BIT(8), 0); |
587 | |
588 | static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc" , "apb1" , 0xa9c, BIT(0), 0); |
589 | |
590 | static const char * const hdmi_parents[] = { "pll-video0" , "pll-video0-4x" , |
591 | "pll-video2" , "pll-video2-4x" }; |
592 | static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi" , hdmi_parents, 0xb00, |
593 | 0, 4, /* M */ |
594 | 24, 2, /* mux */ |
595 | BIT(31), /* gate */ |
596 | 0); |
597 | |
598 | static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow" , "osc24M" , 0xb04, BIT(31), 0); |
599 | |
600 | static const char * const hdmi_cec_parents[] = { "osc32k" , "pll-periph0-2x" }; |
601 | static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = { |
602 | { .index = 1, .div = 36621 }, |
603 | }; |
604 | |
605 | #define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10 |
606 | static struct ccu_mux hdmi_cec_clk = { |
607 | .enable = BIT(31) | BIT(30), |
608 | |
609 | .mux = { |
610 | .shift = 24, |
611 | .width = 2, |
612 | |
613 | .fixed_predivs = hdmi_cec_predivs, |
614 | .n_predivs = ARRAY_SIZE(hdmi_cec_predivs), |
615 | }, |
616 | |
617 | .common = { |
618 | .reg = 0xb10, |
619 | .features = CCU_FEATURE_FIXED_PREDIV, |
620 | .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec" , |
621 | hdmi_cec_parents, |
622 | &ccu_mux_ops, |
623 | 0), |
624 | }, |
625 | }; |
626 | |
627 | static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi" , "ahb3" , 0xb1c, BIT(0), 0); |
628 | |
629 | static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top" , "ahb3" , |
630 | 0xb5c, BIT(0), 0); |
631 | |
632 | static const char * const tcon_tv_parents[] = { "pll-video0" , |
633 | "pll-video0-4x" , |
634 | "pll-video1" , |
635 | "pll-video1-4x" }; |
636 | static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0" , |
637 | tcon_tv_parents, 0xb80, |
638 | 0, 4, /* M */ |
639 | 8, 2, /* P */ |
640 | 24, 3, /* mux */ |
641 | BIT(31), /* gate */ |
642 | CLK_SET_RATE_PARENT); |
643 | static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1" , |
644 | tcon_tv_parents, 0xb84, |
645 | 0, 4, /* M */ |
646 | 8, 2, /* P */ |
647 | 24, 3, /* mux */ |
648 | BIT(31), /* gate */ |
649 | CLK_SET_RATE_PARENT); |
650 | |
651 | static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0" , "ahb3" , |
652 | 0xb9c, BIT(0), 0); |
653 | static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1" , "ahb3" , |
654 | 0xb9c, BIT(1), 0); |
655 | |
656 | static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0" , |
657 | tcon_tv_parents, 0xbb0, |
658 | 0, 4, /* M */ |
659 | 8, 2, /* P */ |
660 | 24, 3, /* mux */ |
661 | BIT(31), /* gate */ |
662 | CLK_SET_RATE_PARENT); |
663 | |
664 | static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top" , "ahb3" , |
665 | 0xbbc, BIT(0), 0); |
666 | static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0" , "ahb3" , |
667 | 0xbbc, BIT(1), 0); |
668 | |
669 | static const char * const hdcp_parents[] = { "pll-periph0" , "pll-periph1" }; |
670 | static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp" , hdcp_parents, 0xc40, |
671 | 0, 4, /* M */ |
672 | 24, 2, /* mux */ |
673 | BIT(31), /* gate */ |
674 | 0); |
675 | |
676 | static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp" , "ahb3" , 0xc4c, BIT(0), 0); |
677 | |
678 | /* Fixed factor clocks */ |
679 | static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M" , "hosc" , 2, 1, 0); |
680 | |
681 | static const struct clk_hw *clk_parent_pll_audio[] = { |
682 | &pll_audio_hs_clk.common.hw |
683 | }; |
684 | |
685 | /* |
686 | * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200 |
687 | * rates can be set exactly in conjunction with sigma-delta modulation. |
688 | */ |
689 | static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x" , |
690 | clk_parent_pll_audio, |
691 | 96, 1, CLK_SET_RATE_PARENT); |
692 | static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x" , |
693 | clk_parent_pll_audio, |
694 | 48, 1, CLK_SET_RATE_PARENT); |
695 | static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x" , |
696 | clk_parent_pll_audio, |
697 | 24, 1, CLK_SET_RATE_PARENT); |
698 | |
699 | static const struct clk_hw *pll_periph0_parents[] = { |
700 | &pll_periph0_clk.common.hw |
701 | }; |
702 | |
703 | static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x" , |
704 | pll_periph0_parents, |
705 | 1, 2, 0); |
706 | |
707 | static const struct clk_hw *pll_periph0_2x_hws[] = { |
708 | &pll_periph0_2x_clk.hw |
709 | }; |
710 | |
711 | static CLK_FIXED_FACTOR_HWS(pll_system_32k_clk, "pll-system-32k" , |
712 | pll_periph0_2x_hws, 36621, 1, 0); |
713 | |
714 | static const struct clk_hw *pll_periph1_parents[] = { |
715 | &pll_periph1_clk.common.hw |
716 | }; |
717 | |
718 | static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x" , |
719 | pll_periph1_parents, |
720 | 1, 2, 0); |
721 | |
722 | static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x" , |
723 | &pll_video0_clk.common.hw, |
724 | 1, 4, CLK_SET_RATE_PARENT); |
725 | static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x" , |
726 | &pll_video1_clk.common.hw, |
727 | 1, 4, CLK_SET_RATE_PARENT); |
728 | static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x" , |
729 | &pll_video2_clk.common.hw, |
730 | 1, 4, CLK_SET_RATE_PARENT); |
731 | |
732 | static struct ccu_common *sun50i_h616_ccu_clks[] = { |
733 | &pll_cpux_clk.common, |
734 | &pll_ddr0_clk.common, |
735 | &pll_ddr1_clk.common, |
736 | &pll_periph0_clk.common, |
737 | &pll_periph1_clk.common, |
738 | &pll_gpu_clk.common, |
739 | &pll_video0_clk.common, |
740 | &pll_video1_clk.common, |
741 | &pll_video2_clk.common, |
742 | &pll_ve_clk.common, |
743 | &pll_de_clk.common, |
744 | &pll_audio_hs_clk.common, |
745 | &cpux_clk.common, |
746 | &axi_clk.common, |
747 | &cpux_apb_clk.common, |
748 | &psi_ahb1_ahb2_clk.common, |
749 | &ahb3_clk.common, |
750 | &apb1_clk.common, |
751 | &apb2_clk.common, |
752 | &mbus_clk.common, |
753 | &de_clk.common, |
754 | &bus_de_clk.common, |
755 | &deinterlace_clk.common, |
756 | &bus_deinterlace_clk.common, |
757 | &g2d_clk.common, |
758 | &bus_g2d_clk.common, |
759 | &gpu0_clk.common, |
760 | &bus_gpu_clk.common, |
761 | &gpu1_clk.common, |
762 | &ce_clk.common, |
763 | &bus_ce_clk.common, |
764 | &ve_clk.common, |
765 | &bus_ve_clk.common, |
766 | &bus_dma_clk.common, |
767 | &bus_hstimer_clk.common, |
768 | &avs_clk.common, |
769 | &bus_dbg_clk.common, |
770 | &bus_psi_clk.common, |
771 | &bus_pwm_clk.common, |
772 | &bus_iommu_clk.common, |
773 | &dram_clk.common, |
774 | &mbus_dma_clk.common, |
775 | &mbus_ve_clk.common, |
776 | &mbus_ce_clk.common, |
777 | &mbus_ts_clk.common, |
778 | &mbus_nand_clk.common, |
779 | &mbus_g2d_clk.common, |
780 | &bus_dram_clk.common, |
781 | &nand0_clk.common, |
782 | &nand1_clk.common, |
783 | &bus_nand_clk.common, |
784 | &mmc0_clk.common, |
785 | &mmc1_clk.common, |
786 | &mmc2_clk.common, |
787 | &bus_mmc0_clk.common, |
788 | &bus_mmc1_clk.common, |
789 | &bus_mmc2_clk.common, |
790 | &bus_uart0_clk.common, |
791 | &bus_uart1_clk.common, |
792 | &bus_uart2_clk.common, |
793 | &bus_uart3_clk.common, |
794 | &bus_uart4_clk.common, |
795 | &bus_uart5_clk.common, |
796 | &bus_i2c0_clk.common, |
797 | &bus_i2c1_clk.common, |
798 | &bus_i2c2_clk.common, |
799 | &bus_i2c3_clk.common, |
800 | &bus_i2c4_clk.common, |
801 | &spi0_clk.common, |
802 | &spi1_clk.common, |
803 | &bus_spi0_clk.common, |
804 | &bus_spi1_clk.common, |
805 | &emac_25m_clk.common, |
806 | &bus_emac0_clk.common, |
807 | &bus_emac1_clk.common, |
808 | &ts_clk.common, |
809 | &bus_ts_clk.common, |
810 | &bus_ths_clk.common, |
811 | &spdif_clk.common, |
812 | &bus_spdif_clk.common, |
813 | &dmic_clk.common, |
814 | &bus_dmic_clk.common, |
815 | &audio_codec_1x_clk.common, |
816 | &audio_codec_4x_clk.common, |
817 | &bus_audio_codec_clk.common, |
818 | &audio_hub_clk.common, |
819 | &bus_audio_hub_clk.common, |
820 | &usb_ohci0_clk.common, |
821 | &usb_phy0_clk.common, |
822 | &usb_ohci1_clk.common, |
823 | &usb_phy1_clk.common, |
824 | &usb_ohci2_clk.common, |
825 | &usb_phy2_clk.common, |
826 | &usb_ohci3_clk.common, |
827 | &usb_phy3_clk.common, |
828 | &bus_ohci0_clk.common, |
829 | &bus_ohci1_clk.common, |
830 | &bus_ohci2_clk.common, |
831 | &bus_ohci3_clk.common, |
832 | &bus_ehci0_clk.common, |
833 | &bus_ehci1_clk.common, |
834 | &bus_ehci2_clk.common, |
835 | &bus_ehci3_clk.common, |
836 | &bus_otg_clk.common, |
837 | &bus_keyadc_clk.common, |
838 | &hdmi_clk.common, |
839 | &hdmi_slow_clk.common, |
840 | &hdmi_cec_clk.common, |
841 | &bus_hdmi_clk.common, |
842 | &bus_tcon_top_clk.common, |
843 | &tcon_tv0_clk.common, |
844 | &tcon_tv1_clk.common, |
845 | &bus_tcon_tv0_clk.common, |
846 | &bus_tcon_tv1_clk.common, |
847 | &tve0_clk.common, |
848 | &bus_tve_top_clk.common, |
849 | &bus_tve0_clk.common, |
850 | &hdcp_clk.common, |
851 | &bus_hdcp_clk.common, |
852 | }; |
853 | |
854 | static struct clk_hw_onecell_data sun50i_h616_hw_clks = { |
855 | .hws = { |
856 | [CLK_OSC12M] = &osc12M_clk.hw, |
857 | [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, |
858 | [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, |
859 | [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, |
860 | [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, |
861 | [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, |
862 | [CLK_PLL_SYSTEM_32K] = &pll_system_32k_clk.hw, |
863 | [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, |
864 | [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, |
865 | [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, |
866 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, |
867 | [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw, |
868 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, |
869 | [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw, |
870 | [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw, |
871 | [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw, |
872 | [CLK_PLL_VE] = &pll_ve_clk.common.hw, |
873 | [CLK_PLL_DE] = &pll_de_clk.common.hw, |
874 | [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw, |
875 | [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw, |
876 | [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, |
877 | [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, |
878 | [CLK_CPUX] = &cpux_clk.common.hw, |
879 | [CLK_AXI] = &axi_clk.common.hw, |
880 | [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, |
881 | [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw, |
882 | [CLK_AHB3] = &ahb3_clk.common.hw, |
883 | [CLK_APB1] = &apb1_clk.common.hw, |
884 | [CLK_APB2] = &apb2_clk.common.hw, |
885 | [CLK_MBUS] = &mbus_clk.common.hw, |
886 | [CLK_DE] = &de_clk.common.hw, |
887 | [CLK_BUS_DE] = &bus_de_clk.common.hw, |
888 | [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, |
889 | [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, |
890 | [CLK_G2D] = &g2d_clk.common.hw, |
891 | [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, |
892 | [CLK_GPU0] = &gpu0_clk.common.hw, |
893 | [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, |
894 | [CLK_GPU1] = &gpu1_clk.common.hw, |
895 | [CLK_CE] = &ce_clk.common.hw, |
896 | [CLK_BUS_CE] = &bus_ce_clk.common.hw, |
897 | [CLK_VE] = &ve_clk.common.hw, |
898 | [CLK_BUS_VE] = &bus_ve_clk.common.hw, |
899 | [CLK_BUS_DMA] = &bus_dma_clk.common.hw, |
900 | [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, |
901 | [CLK_AVS] = &avs_clk.common.hw, |
902 | [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, |
903 | [CLK_BUS_PSI] = &bus_psi_clk.common.hw, |
904 | [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, |
905 | [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, |
906 | [CLK_DRAM] = &dram_clk.common.hw, |
907 | [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, |
908 | [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, |
909 | [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, |
910 | [CLK_MBUS_TS] = &mbus_ts_clk.common.hw, |
911 | [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw, |
912 | [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, |
913 | [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, |
914 | [CLK_NAND0] = &nand0_clk.common.hw, |
915 | [CLK_NAND1] = &nand1_clk.common.hw, |
916 | [CLK_BUS_NAND] = &bus_nand_clk.common.hw, |
917 | [CLK_MMC0] = &mmc0_clk.common.hw, |
918 | [CLK_MMC1] = &mmc1_clk.common.hw, |
919 | [CLK_MMC2] = &mmc2_clk.common.hw, |
920 | [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, |
921 | [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, |
922 | [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, |
923 | [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, |
924 | [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, |
925 | [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, |
926 | [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, |
927 | [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, |
928 | [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, |
929 | [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, |
930 | [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, |
931 | [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, |
932 | [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, |
933 | [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, |
934 | [CLK_SPI0] = &spi0_clk.common.hw, |
935 | [CLK_SPI1] = &spi1_clk.common.hw, |
936 | [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, |
937 | [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, |
938 | [CLK_EMAC_25M] = &emac_25m_clk.common.hw, |
939 | [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw, |
940 | [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw, |
941 | [CLK_TS] = &ts_clk.common.hw, |
942 | [CLK_BUS_TS] = &bus_ts_clk.common.hw, |
943 | [CLK_BUS_THS] = &bus_ths_clk.common.hw, |
944 | [CLK_SPDIF] = &spdif_clk.common.hw, |
945 | [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, |
946 | [CLK_DMIC] = &dmic_clk.common.hw, |
947 | [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, |
948 | [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw, |
949 | [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw, |
950 | [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw, |
951 | [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw, |
952 | [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw, |
953 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, |
954 | [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, |
955 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, |
956 | [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, |
957 | [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, |
958 | [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, |
959 | [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw, |
960 | [CLK_USB_PHY3] = &usb_phy3_clk.common.hw, |
961 | [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, |
962 | [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, |
963 | [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, |
964 | [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw, |
965 | [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, |
966 | [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, |
967 | [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, |
968 | [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw, |
969 | [CLK_BUS_OTG] = &bus_otg_clk.common.hw, |
970 | [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw, |
971 | [CLK_HDMI] = &hdmi_clk.common.hw, |
972 | [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, |
973 | [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw, |
974 | [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, |
975 | [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, |
976 | [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, |
977 | [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, |
978 | [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, |
979 | [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, |
980 | [CLK_TVE0] = &tve0_clk.common.hw, |
981 | [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, |
982 | [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, |
983 | [CLK_HDCP] = &hdcp_clk.common.hw, |
984 | [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw, |
985 | }, |
986 | .num = CLK_NUMBER, |
987 | }; |
988 | |
989 | static struct ccu_reset_map sun50i_h616_ccu_resets[] = { |
990 | [RST_MBUS] = { 0x540, BIT(30) }, |
991 | |
992 | [RST_BUS_DE] = { 0x60c, BIT(16) }, |
993 | [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) }, |
994 | [RST_BUS_GPU] = { 0x67c, BIT(16) }, |
995 | [RST_BUS_CE] = { 0x68c, BIT(16) }, |
996 | [RST_BUS_VE] = { 0x69c, BIT(16) }, |
997 | [RST_BUS_DMA] = { 0x70c, BIT(16) }, |
998 | [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, |
999 | [RST_BUS_DBG] = { 0x78c, BIT(16) }, |
1000 | [RST_BUS_PSI] = { 0x79c, BIT(16) }, |
1001 | [RST_BUS_PWM] = { 0x7ac, BIT(16) }, |
1002 | [RST_BUS_IOMMU] = { 0x7bc, BIT(16) }, |
1003 | [RST_BUS_DRAM] = { 0x80c, BIT(16) }, |
1004 | [RST_BUS_NAND] = { 0x82c, BIT(16) }, |
1005 | [RST_BUS_MMC0] = { 0x84c, BIT(16) }, |
1006 | [RST_BUS_MMC1] = { 0x84c, BIT(17) }, |
1007 | [RST_BUS_MMC2] = { 0x84c, BIT(18) }, |
1008 | [RST_BUS_UART0] = { 0x90c, BIT(16) }, |
1009 | [RST_BUS_UART1] = { 0x90c, BIT(17) }, |
1010 | [RST_BUS_UART2] = { 0x90c, BIT(18) }, |
1011 | [RST_BUS_UART3] = { 0x90c, BIT(19) }, |
1012 | [RST_BUS_UART4] = { 0x90c, BIT(20) }, |
1013 | [RST_BUS_UART5] = { 0x90c, BIT(21) }, |
1014 | [RST_BUS_I2C0] = { 0x91c, BIT(16) }, |
1015 | [RST_BUS_I2C1] = { 0x91c, BIT(17) }, |
1016 | [RST_BUS_I2C2] = { 0x91c, BIT(18) }, |
1017 | [RST_BUS_I2C3] = { 0x91c, BIT(19) }, |
1018 | [RST_BUS_I2C4] = { 0x91c, BIT(20) }, |
1019 | [RST_BUS_SPI0] = { 0x96c, BIT(16) }, |
1020 | [RST_BUS_SPI1] = { 0x96c, BIT(17) }, |
1021 | [RST_BUS_EMAC0] = { 0x97c, BIT(16) }, |
1022 | [RST_BUS_EMAC1] = { 0x97c, BIT(17) }, |
1023 | [RST_BUS_TS] = { 0x9bc, BIT(16) }, |
1024 | [RST_BUS_THS] = { 0x9fc, BIT(16) }, |
1025 | [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, |
1026 | [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, |
1027 | [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) }, |
1028 | [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) }, |
1029 | |
1030 | [RST_USB_PHY0] = { 0xa70, BIT(30) }, |
1031 | [RST_USB_PHY1] = { 0xa74, BIT(30) }, |
1032 | [RST_USB_PHY2] = { 0xa78, BIT(30) }, |
1033 | [RST_USB_PHY3] = { 0xa7c, BIT(30) }, |
1034 | [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, |
1035 | [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, |
1036 | [RST_BUS_OHCI2] = { 0xa8c, BIT(18) }, |
1037 | [RST_BUS_OHCI3] = { 0xa8c, BIT(19) }, |
1038 | [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, |
1039 | [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, |
1040 | [RST_BUS_EHCI2] = { 0xa8c, BIT(22) }, |
1041 | [RST_BUS_EHCI3] = { 0xa8c, BIT(23) }, |
1042 | [RST_BUS_OTG] = { 0xa8c, BIT(24) }, |
1043 | [RST_BUS_KEYADC] = { 0xa9c, BIT(16) }, |
1044 | |
1045 | [RST_BUS_HDMI] = { 0xb1c, BIT(16) }, |
1046 | [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) }, |
1047 | [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) }, |
1048 | [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) }, |
1049 | [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) }, |
1050 | [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, |
1051 | [RST_BUS_TVE0] = { 0xbbc, BIT(17) }, |
1052 | [RST_BUS_HDCP] = { 0xc4c, BIT(16) }, |
1053 | }; |
1054 | |
1055 | static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = { |
1056 | .ccu_clks = sun50i_h616_ccu_clks, |
1057 | .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks), |
1058 | |
1059 | .hw_clks = &sun50i_h616_hw_clks, |
1060 | |
1061 | .resets = sun50i_h616_ccu_resets, |
1062 | .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets), |
1063 | }; |
1064 | |
1065 | static const u32 pll_regs[] = { |
1066 | SUN50I_H616_PLL_CPUX_REG, |
1067 | SUN50I_H616_PLL_DDR0_REG, |
1068 | SUN50I_H616_PLL_DDR1_REG, |
1069 | SUN50I_H616_PLL_PERIPH0_REG, |
1070 | SUN50I_H616_PLL_PERIPH1_REG, |
1071 | SUN50I_H616_PLL_GPU_REG, |
1072 | SUN50I_H616_PLL_VIDEO0_REG, |
1073 | SUN50I_H616_PLL_VIDEO1_REG, |
1074 | SUN50I_H616_PLL_VIDEO2_REG, |
1075 | SUN50I_H616_PLL_VE_REG, |
1076 | SUN50I_H616_PLL_DE_REG, |
1077 | SUN50I_H616_PLL_AUDIO_REG, |
1078 | }; |
1079 | |
1080 | static const u32 pll_video_regs[] = { |
1081 | SUN50I_H616_PLL_VIDEO0_REG, |
1082 | SUN50I_H616_PLL_VIDEO1_REG, |
1083 | SUN50I_H616_PLL_VIDEO2_REG, |
1084 | }; |
1085 | |
1086 | static const u32 usb2_clk_regs[] = { |
1087 | SUN50I_H616_USB0_CLK_REG, |
1088 | SUN50I_H616_USB1_CLK_REG, |
1089 | SUN50I_H616_USB2_CLK_REG, |
1090 | SUN50I_H616_USB3_CLK_REG, |
1091 | }; |
1092 | |
1093 | static int sun50i_h616_ccu_probe(struct platform_device *pdev) |
1094 | { |
1095 | void __iomem *reg; |
1096 | u32 val; |
1097 | int i; |
1098 | |
1099 | reg = devm_platform_ioremap_resource(pdev, index: 0); |
1100 | if (IS_ERR(ptr: reg)) |
1101 | return PTR_ERR(ptr: reg); |
1102 | |
1103 | /* Enable the lock bits and the output enable bits on all PLLs */ |
1104 | for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { |
1105 | val = readl(addr: reg + pll_regs[i]); |
1106 | val |= BIT(29) | BIT(27); |
1107 | writel(val, addr: reg + pll_regs[i]); |
1108 | } |
1109 | |
1110 | /* |
1111 | * Force the output divider of video PLLs to 0. |
1112 | * |
1113 | * See the comment before pll-video0 definition for the reason. |
1114 | */ |
1115 | for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { |
1116 | val = readl(addr: reg + pll_video_regs[i]); |
1117 | val &= ~BIT(0); |
1118 | writel(val, addr: reg + pll_video_regs[i]); |
1119 | } |
1120 | |
1121 | /* |
1122 | * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) |
1123 | * |
1124 | * This clock mux is still mysterious, and the code just enforces |
1125 | * it to have a valid clock parent. |
1126 | */ |
1127 | for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) { |
1128 | val = readl(addr: reg + usb2_clk_regs[i]); |
1129 | val &= ~GENMASK(25, 24); |
1130 | writel(val, addr: reg + usb2_clk_regs[i]); |
1131 | } |
1132 | |
1133 | /* |
1134 | * Force the post-divider of pll-audio to 12 and the output divider |
1135 | * of it to 2, so 24576000 and 22579200 rates can be set exactly. |
1136 | */ |
1137 | val = readl(addr: reg + SUN50I_H616_PLL_AUDIO_REG); |
1138 | val &= ~(GENMASK(21, 16) | BIT(0)); |
1139 | writel(val: val | (11 << 16) | BIT(0), addr: reg + SUN50I_H616_PLL_AUDIO_REG); |
1140 | |
1141 | /* |
1142 | * First clock parent (osc32K) is unusable for CEC. But since there |
1143 | * is no good way to force parent switch (both run with same frequency), |
1144 | * just set second clock parent here. |
1145 | */ |
1146 | val = readl(addr: reg + SUN50I_H616_HDMI_CEC_CLK_REG); |
1147 | val |= BIT(24); |
1148 | writel(val, addr: reg + SUN50I_H616_HDMI_CEC_CLK_REG); |
1149 | |
1150 | return devm_sunxi_ccu_probe(dev: &pdev->dev, reg, desc: &sun50i_h616_ccu_desc); |
1151 | } |
1152 | |
1153 | static const struct of_device_id sun50i_h616_ccu_ids[] = { |
1154 | { .compatible = "allwinner,sun50i-h616-ccu" }, |
1155 | { } |
1156 | }; |
1157 | |
1158 | static struct platform_driver sun50i_h616_ccu_driver = { |
1159 | .probe = sun50i_h616_ccu_probe, |
1160 | .driver = { |
1161 | .name = "sun50i-h616-ccu" , |
1162 | .suppress_bind_attrs = true, |
1163 | .of_match_table = sun50i_h616_ccu_ids, |
1164 | }, |
1165 | }; |
1166 | module_platform_driver(sun50i_h616_ccu_driver); |
1167 | |
1168 | MODULE_IMPORT_NS(SUNXI_CCU); |
1169 | MODULE_LICENSE("GPL" ); |
1170 | |