1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> |
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_mult.h" |
18 | #include "ccu_nk.h" |
19 | #include "ccu_nkm.h" |
20 | #include "ccu_nkmp.h" |
21 | #include "ccu_nm.h" |
22 | |
23 | #include "ccu-sun50i-a100.h" |
24 | |
25 | #define SUN50I_A100_PLL_SDM_ENABLE BIT(24) |
26 | #define SUN50I_A100_PLL_OUTPUT_ENABLE BIT(27) |
27 | #define SUN50I_A100_PLL_LOCK BIT(28) |
28 | #define SUN50I_A100_PLL_LOCK_ENABLE BIT(29) |
29 | #define SUN50I_A100_PLL_ENABLE BIT(31) |
30 | |
31 | #define SUN50I_A100_PLL_PERIPH1_PATTERN0 0xd1303333 |
32 | |
33 | /* |
34 | * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However |
35 | * P should only be used for output frequencies lower than 288 MHz. |
36 | * |
37 | * For now we can just model it as a multiplier clock, and force P to /1. |
38 | * |
39 | * The M factor is present in the register's description, but not in the |
40 | * frequency formula, and it's documented as "M is only used for backdoor |
41 | * testing", so it's not modelled and then force to 0. |
42 | */ |
43 | #define SUN50I_A100_PLL_CPUX_REG 0x000 |
44 | static struct ccu_mult pll_cpux_clk = { |
45 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
46 | .lock = SUN50I_A100_PLL_LOCK, |
47 | .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
48 | .common = { |
49 | .reg = 0x000, |
50 | .hw.init = CLK_HW_INIT("pll-cpux" , "dcxo24M" , |
51 | &ccu_mult_ops, |
52 | CLK_SET_RATE_UNGATE), |
53 | }, |
54 | }; |
55 | |
56 | /* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ |
57 | #define SUN50I_A100_PLL_DDR0_REG 0x010 |
58 | static struct ccu_nkmp pll_ddr0_clk = { |
59 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
60 | .lock = SUN50I_A100_PLL_LOCK, |
61 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
62 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
63 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
64 | .common = { |
65 | .reg = 0x010, |
66 | .hw.init = CLK_HW_INIT("pll-ddr0" , "dcxo24M" , |
67 | &ccu_nkmp_ops, |
68 | CLK_SET_RATE_UNGATE | |
69 | CLK_IS_CRITICAL), |
70 | }, |
71 | }; |
72 | |
73 | #define SUN50I_A100_PLL_PERIPH0_REG 0x020 |
74 | static struct ccu_nkmp pll_periph0_clk = { |
75 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
76 | .lock = SUN50I_A100_PLL_LOCK, |
77 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
78 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
79 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
80 | .fixed_post_div = 2, |
81 | .common = { |
82 | .reg = 0x020, |
83 | .features = CCU_FEATURE_FIXED_POSTDIV, |
84 | .hw.init = CLK_HW_INIT("pll-periph0" , "dcxo24M" , |
85 | &ccu_nkmp_ops, |
86 | CLK_SET_RATE_UNGATE), |
87 | }, |
88 | }; |
89 | |
90 | #define SUN50I_A100_PLL_PERIPH1_REG 0x028 |
91 | static struct ccu_nkmp pll_periph1_clk = { |
92 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
93 | .lock = SUN50I_A100_PLL_LOCK, |
94 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
95 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
96 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
97 | .fixed_post_div = 2, |
98 | .common = { |
99 | .reg = 0x028, |
100 | .features = CCU_FEATURE_FIXED_POSTDIV, |
101 | .hw.init = CLK_HW_INIT("pll-periph1" , "dcxo24M" , |
102 | &ccu_nkmp_ops, |
103 | CLK_SET_RATE_UNGATE), |
104 | }, |
105 | }; |
106 | #define SUN50I_A100_PLL_PERIPH1_PATTERN0_REG 0x128 |
107 | |
108 | #define SUN50I_A100_PLL_GPU_REG 0x030 |
109 | static struct ccu_nkmp pll_gpu_clk = { |
110 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
111 | .lock = SUN50I_A100_PLL_LOCK, |
112 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
113 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
114 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
115 | .common = { |
116 | .reg = 0x030, |
117 | .hw.init = CLK_HW_INIT("pll-gpu" , "dcxo24M" , |
118 | &ccu_nkmp_ops, |
119 | CLK_SET_RATE_UNGATE), |
120 | }, |
121 | }; |
122 | |
123 | /* |
124 | * For Video PLLs, the output divider is described as "used for testing" |
125 | * in the user manual. So it's not modelled and forced to 0. |
126 | */ |
127 | #define SUN50I_A100_PLL_VIDEO0_REG 0x040 |
128 | static struct ccu_nm pll_video0_clk = { |
129 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
130 | .lock = SUN50I_A100_PLL_LOCK, |
131 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
132 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
133 | .fixed_post_div = 4, |
134 | .common = { |
135 | .reg = 0x040, |
136 | .features = CCU_FEATURE_FIXED_POSTDIV, |
137 | .hw.init = CLK_HW_INIT("pll-video0" , "dcxo24M" , |
138 | &ccu_nm_ops, |
139 | CLK_SET_RATE_UNGATE), |
140 | }, |
141 | }; |
142 | |
143 | #define SUN50I_A100_PLL_VIDEO1_REG 0x048 |
144 | static struct ccu_nm pll_video1_clk = { |
145 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
146 | .lock = SUN50I_A100_PLL_LOCK, |
147 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
148 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
149 | .fixed_post_div = 4, |
150 | .common = { |
151 | .reg = 0x048, |
152 | .features = CCU_FEATURE_FIXED_POSTDIV, |
153 | .hw.init = CLK_HW_INIT("pll-video1" , "dcxo24M" , |
154 | &ccu_nm_ops, |
155 | CLK_SET_RATE_UNGATE), |
156 | }, |
157 | }; |
158 | |
159 | #define SUN50I_A100_PLL_VIDEO2_REG 0x050 |
160 | static struct ccu_nm pll_video2_clk = { |
161 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
162 | .lock = SUN50I_A100_PLL_LOCK, |
163 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
164 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
165 | .fixed_post_div = 4, |
166 | .common = { |
167 | .reg = 0x050, |
168 | .features = CCU_FEATURE_FIXED_POSTDIV, |
169 | .hw.init = CLK_HW_INIT("pll-video2" , "dcxo24M" , |
170 | &ccu_nm_ops, |
171 | CLK_SET_RATE_UNGATE), |
172 | }, |
173 | }; |
174 | |
175 | #define SUN50I_A100_PLL_VE_REG 0x058 |
176 | static struct ccu_nkmp pll_ve_clk = { |
177 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
178 | .lock = SUN50I_A100_PLL_LOCK, |
179 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
180 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
181 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ |
182 | .common = { |
183 | .reg = 0x058, |
184 | .hw.init = CLK_HW_INIT("pll-ve" , "dcxo24M" , |
185 | &ccu_nkmp_ops, |
186 | CLK_SET_RATE_UNGATE), |
187 | }, |
188 | }; |
189 | |
190 | /* |
191 | * The COM PLL has m0 dividers in addition to the usual N, M |
192 | * factors. Since we only need 1 frequencies from this PLL: 45.1584 MHz, |
193 | * ignore it for now. |
194 | */ |
195 | #define SUN50I_A100_PLL_COM_REG 0x060 |
196 | static struct ccu_sdm_setting pll_com_sdm_table[] = { |
197 | { .rate = 451584000, .pattern = 0xc0014396, .m = 2, .n = 37 }, |
198 | }; |
199 | |
200 | static struct ccu_nm pll_com_clk = { |
201 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
202 | .lock = SUN50I_A100_PLL_LOCK, |
203 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
204 | .m = _SUNXI_CCU_DIV(0, 1), |
205 | .sdm = _SUNXI_CCU_SDM(pll_com_sdm_table, BIT(24), |
206 | 0x160, BIT(31)), |
207 | .common = { |
208 | .reg = 0x060, |
209 | .features = CCU_FEATURE_SIGMA_DELTA_MOD, |
210 | .hw.init = CLK_HW_INIT("pll-com" , "dcxo24M" , |
211 | &ccu_nm_ops, |
212 | CLK_SET_RATE_UNGATE), |
213 | }, |
214 | }; |
215 | |
216 | #define SUN50I_A100_PLL_VIDEO3_REG 0x068 |
217 | static struct ccu_nm pll_video3_clk = { |
218 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
219 | .lock = SUN50I_A100_PLL_LOCK, |
220 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
221 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ |
222 | .fixed_post_div = 4, |
223 | .common = { |
224 | .reg = 0x068, |
225 | .features = CCU_FEATURE_FIXED_POSTDIV, |
226 | .hw.init = CLK_HW_INIT("pll-video3" , "dcxo24M" , |
227 | &ccu_nm_ops, |
228 | CLK_SET_RATE_UNGATE), |
229 | }, |
230 | }; |
231 | |
232 | /* |
233 | * The Audio PLL has m0, m1 dividers in addition to the usual N, M |
234 | * factors. Since we only need 4 frequencies from this PLL: 22.5792 MHz, |
235 | * 24.576 MHz, 90.3168MHz and 98.304MHz ignore them for now. |
236 | * Enforce the default for them, which is m0 = 1, m1 = 0. |
237 | */ |
238 | #define SUN50I_A100_PLL_AUDIO_REG 0x078 |
239 | static struct ccu_sdm_setting pll_audio_sdm_table[] = { |
240 | { .rate = 45158400, .pattern = 0xc001bcd3, .m = 18, .n = 33 }, |
241 | { .rate = 49152000, .pattern = 0xc001eb85, .m = 20, .n = 40 }, |
242 | { .rate = 180633600, .pattern = 0xc001288d, .m = 3, .n = 22 }, |
243 | { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, |
244 | }; |
245 | |
246 | static struct ccu_nm pll_audio_clk = { |
247 | .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, |
248 | .lock = SUN50I_A100_PLL_LOCK, |
249 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), |
250 | .m = _SUNXI_CCU_DIV(16, 6), |
251 | .fixed_post_div = 2, |
252 | .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24), |
253 | 0x178, BIT(31)), |
254 | .common = { |
255 | .reg = 0x078, |
256 | .features = CCU_FEATURE_FIXED_POSTDIV | |
257 | CCU_FEATURE_SIGMA_DELTA_MOD, |
258 | .hw.init = CLK_HW_INIT("pll-audio" , "dcxo24M" , |
259 | &ccu_nm_ops, |
260 | CLK_SET_RATE_UNGATE), |
261 | }, |
262 | }; |
263 | |
264 | static const char * const cpux_parents[] = { "dcxo24M" , "osc32k" , |
265 | "iosc" , "pll-cpux" , |
266 | "pll-periph0" }; |
267 | static SUNXI_CCU_MUX(cpux_clk, "cpux" , cpux_parents, |
268 | 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); |
269 | static SUNXI_CCU_M(axi_clk, "axi" , "cpux" , 0x500, 0, 2, 0); |
270 | static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb" , "cpux" , 0x500, 8, 2, 0); |
271 | |
272 | static const char * const psi_ahb1_ahb2_parents[] = { "dcxo24M" , "osc32k" , |
273 | "iosc" , "pll-periph0" , |
274 | "pll-periph0-2x" }; |
275 | static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2" , |
276 | psi_ahb1_ahb2_parents, 0x510, |
277 | 0, 2, /* M */ |
278 | 8, 2, /* P */ |
279 | 24, 3, /* mux */ |
280 | 0); |
281 | |
282 | static const char * const ahb3_apb1_apb2_parents[] = { "dcxo24M" , "osc32k" , |
283 | "psi-ahb1-ahb2" , |
284 | "pll-periph0" , |
285 | "pll-periph0-2x" }; |
286 | static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3" , ahb3_apb1_apb2_parents, 0x51c, |
287 | 0, 2, /* M */ |
288 | 8, 2, /* P */ |
289 | 24, 3, /* mux */ |
290 | 0); |
291 | |
292 | static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1" , ahb3_apb1_apb2_parents, 0x520, |
293 | 0, 2, /* M */ |
294 | 8, 2, /* P */ |
295 | 24, 3, /* mux */ |
296 | 0); |
297 | |
298 | static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2" , ahb3_apb1_apb2_parents, 0x524, |
299 | 0, 2, /* M */ |
300 | 8, 2, /* P */ |
301 | 24, 3, /* mux */ |
302 | 0); |
303 | |
304 | static const char * const mbus_parents[] = { "dcxo24M" , "pll-ddr0" , |
305 | "pll-periph0" , |
306 | "pll-periph0-2x" }; |
307 | static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus" , mbus_parents, 0x540, |
308 | 0, 3, /* M */ |
309 | 24, 2, /* mux */ |
310 | BIT(31), /* gate */ |
311 | CLK_IS_CRITICAL); |
312 | |
313 | static const char * const de_parents[] = { "pll-com" , "pll-periph0-2x" }; |
314 | static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de0" , de_parents, 0x600, |
315 | 0, 4, /* M */ |
316 | 24, 1, /* mux */ |
317 | BIT(31), /* gate */ |
318 | CLK_SET_RATE_PARENT); |
319 | |
320 | static SUNXI_CCU_GATE(bus_de_clk, "bus-de" , "psi-ahb1-ahb2" , |
321 | 0x60c, BIT(0), 0); |
322 | |
323 | static const char * const g2d_parents[] = { "pll-com" , "pll-periph0-2x" , |
324 | "pll-video0-2x" , "pll-video1-2x" , |
325 | "pll-video2-2x" }; |
326 | static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d" , |
327 | g2d_parents, |
328 | 0x630, |
329 | 0, 4, /* M */ |
330 | 24, 3, /* mux */ |
331 | BIT(31), /* gate */ |
332 | 0); |
333 | |
334 | static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d" , "psi-ahb1-ahb2" , |
335 | 0x63c, BIT(0), 0); |
336 | |
337 | static const char * const gpu_parents[] = { "pll-gpu" }; |
338 | static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu" , gpu_parents, 0x670, |
339 | 0, 2, /* M */ |
340 | 24, 1, /* mux */ |
341 | BIT(31), /* gate */ |
342 | 0); |
343 | |
344 | static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu" , "psi-ahb1-ahb2" , |
345 | 0x67c, BIT(0), 0); |
346 | |
347 | static const char * const ce_parents[] = { "dcxo24M" , "pll-periph0-2x" }; |
348 | static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce" , ce_parents, 0x680, |
349 | 0, 4, /* M */ |
350 | 8, 2, /* P */ |
351 | 24, 1, /* mux */ |
352 | BIT(31), /* gate */ |
353 | 0); |
354 | |
355 | static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce" , "psi-ahb1-ahb2" , |
356 | 0x68c, BIT(0), 0); |
357 | |
358 | static const char * const ve_parents[] = { "pll-ve" }; |
359 | static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve" , ve_parents, 0x690, |
360 | 0, 3, /* M */ |
361 | 24, 1, /* mux */ |
362 | BIT(31), /* gate */ |
363 | CLK_SET_RATE_PARENT); |
364 | |
365 | static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve" , "psi-ahb1-ahb2" , |
366 | 0x69c, BIT(0), 0); |
367 | |
368 | static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma" , "psi-ahb1-ahb2" , |
369 | 0x70c, BIT(0), 0); |
370 | |
371 | static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox" , "psi-ahb1-ahb2" , |
372 | 0x71c, BIT(0), 0); |
373 | |
374 | static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock" , "psi-ahb1-ahb2" , |
375 | 0x72c, BIT(0), 0); |
376 | |
377 | static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer" , "psi-ahb1-ahb2" , |
378 | 0x73c, BIT(0), 0); |
379 | |
380 | static SUNXI_CCU_GATE(avs_clk, "avs" , "dcxo24M" , 0x740, BIT(31), 0); |
381 | |
382 | static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg" , "psi-ahb1-ahb2" , |
383 | 0x78c, BIT(0), 0); |
384 | |
385 | static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi" , "psi-ahb1-ahb2" , |
386 | 0x79c, BIT(0), 0); |
387 | |
388 | static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm" , "apb1" , 0x7ac, BIT(0), 0); |
389 | |
390 | static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu" , "apb1" , 0x7bc, BIT(0), 0); |
391 | |
392 | static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma" , "mbus" , |
393 | 0x804, BIT(0), 0); |
394 | static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve" , "mbus" , |
395 | 0x804, BIT(1), 0); |
396 | static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce" , "mbus" , |
397 | 0x804, BIT(2), 0); |
398 | static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand" , "mbus" , |
399 | 0x804, BIT(5), 0); |
400 | static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi" , "mbus" , |
401 | 0x804, BIT(8), 0); |
402 | static SUNXI_CCU_GATE(mbus_isp_clk, "mbus-isp" , "mbus" , |
403 | 0x804, BIT(9), 0); |
404 | static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d" , "mbus" , |
405 | 0x804, BIT(10), 0); |
406 | |
407 | static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram" , "psi-ahb1-ahb2" , |
408 | 0x80c, BIT(0), CLK_IS_CRITICAL); |
409 | |
410 | static const char * const nand_spi_parents[] = { "dcxo24M" , |
411 | "pll-periph0" , |
412 | "pll-periph1" , |
413 | "pll-periph0-2x" , |
414 | "pll-periph1-2x" }; |
415 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0" , nand_spi_parents, 0x810, |
416 | 0, 4, /* M */ |
417 | 8, 2, /* P */ |
418 | 24, 3, /* mux */ |
419 | BIT(31), /* gate */ |
420 | 0); |
421 | |
422 | static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1" , nand_spi_parents, 0x814, |
423 | 0, 4, /* M */ |
424 | 8, 2, /* P */ |
425 | 24, 3, /* mux */ |
426 | BIT(31), /* gate */ |
427 | 0); |
428 | |
429 | static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand" , "ahb3" , 0x82c, BIT(0), 0); |
430 | |
431 | static const char * const mmc_parents[] = { "dcxo24M" , "pll-periph0-2x" , |
432 | "pll-periph1-2x" }; |
433 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0" , mmc_parents, 0x830, |
434 | 0, 4, /* M */ |
435 | 8, 2, /* P */ |
436 | 24, 2, /* mux */ |
437 | BIT(31), /* gate */ |
438 | 2, /* post-div */ |
439 | CLK_SET_RATE_NO_REPARENT); |
440 | |
441 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1" , mmc_parents, 0x834, |
442 | 0, 4, /* M */ |
443 | 8, 2, /* P */ |
444 | 24, 2, /* mux */ |
445 | BIT(31), /* gate */ |
446 | 2, /* post-div */ |
447 | CLK_SET_RATE_NO_REPARENT); |
448 | |
449 | static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2" , mmc_parents, 0x838, |
450 | 0, 4, /* M */ |
451 | 8, 2, /* P */ |
452 | 24, 2, /* mux */ |
453 | BIT(31), /* gate */ |
454 | 2, /* post-div */ |
455 | CLK_SET_RATE_NO_REPARENT); |
456 | |
457 | static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0" , "ahb3" , 0x84c, BIT(0), 0); |
458 | static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1" , "ahb3" , 0x84c, BIT(1), 0); |
459 | static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2" , "ahb3" , 0x84c, BIT(2), 0); |
460 | |
461 | static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0" , "apb2" , 0x90c, BIT(0), 0); |
462 | static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1" , "apb2" , 0x90c, BIT(1), 0); |
463 | static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2" , "apb2" , 0x90c, BIT(2), 0); |
464 | static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3" , "apb2" , 0x90c, BIT(3), 0); |
465 | static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4" , "apb2" , 0x90c, BIT(4), 0); |
466 | |
467 | static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0" , "apb2" , 0x91c, BIT(0), 0); |
468 | static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1" , "apb2" , 0x91c, BIT(1), 0); |
469 | static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2" , "apb2" , 0x91c, BIT(2), 0); |
470 | static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3" , "apb2" , 0x91c, BIT(3), 0); |
471 | |
472 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0" , nand_spi_parents, 0x940, |
473 | 0, 4, /* M */ |
474 | 8, 2, /* P */ |
475 | 24, 3, /* mux */ |
476 | BIT(31), /* gate */ |
477 | 0); |
478 | |
479 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1" , nand_spi_parents, 0x944, |
480 | 0, 4, /* M */ |
481 | 8, 2, /* P */ |
482 | 24, 3, /* mux */ |
483 | BIT(31), /* gate */ |
484 | 0); |
485 | |
486 | static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2" , nand_spi_parents, 0x948, |
487 | 0, 4, /* M */ |
488 | 8, 2, /* P */ |
489 | 24, 3, /* mux */ |
490 | BIT(31), /* gate */ |
491 | 0); |
492 | |
493 | static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0" , "ahb3" , 0x96c, BIT(0), 0); |
494 | static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1" , "ahb3" , 0x96c, BIT(1), 0); |
495 | static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2" , "ahb3" , 0x96c, BIT(2), 0); |
496 | |
497 | static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m" , "ahb3" , 0x970, |
498 | BIT(31) | BIT(30), 0); |
499 | |
500 | static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac" , "ahb3" , 0x97c, BIT(0), 0); |
501 | |
502 | static const char * const ir_parents[] = { "osc32k" , "iosc" , |
503 | "pll-periph0" , "pll-periph1" }; |
504 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx" , ir_parents, 0x990, |
505 | 0, 4, /* M */ |
506 | 8, 2, /* P */ |
507 | 24, 3, /* mux */ |
508 | BIT(31), /* gate */ |
509 | 0); |
510 | |
511 | static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx" , "ahb3" , 0x99c, BIT(0), 0); |
512 | |
513 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx" , ir_parents, 0x9c0, |
514 | 0, 4, /* M */ |
515 | 8, 2, /* P */ |
516 | 24, 3, /* mux */ |
517 | BIT(31), /* gate */ |
518 | 0); |
519 | |
520 | static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx" , "apb1" , 0x9cc, BIT(0), 0); |
521 | |
522 | static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc" , "apb1" , 0x9ec, BIT(0), 0); |
523 | |
524 | static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths" , "apb1" , 0x9fc, BIT(0), 0); |
525 | |
526 | static const char * const audio_parents[] = { "pll-audio" , "pll-com-audio" }; |
527 | static struct ccu_div i2s0_clk = { |
528 | .enable = BIT(31), |
529 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
530 | .mux = _SUNXI_CCU_MUX(24, 2), |
531 | .common = { |
532 | .reg = 0xa10, |
533 | .hw.init = CLK_HW_INIT_PARENTS("i2s0" , |
534 | audio_parents, |
535 | &ccu_div_ops, |
536 | CLK_SET_RATE_PARENT), |
537 | }, |
538 | }; |
539 | |
540 | static struct ccu_div i2s1_clk = { |
541 | .enable = BIT(31), |
542 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
543 | .mux = _SUNXI_CCU_MUX(24, 2), |
544 | .common = { |
545 | .reg = 0xa14, |
546 | .hw.init = CLK_HW_INIT_PARENTS("i2s1" , |
547 | audio_parents, |
548 | &ccu_div_ops, |
549 | CLK_SET_RATE_PARENT), |
550 | }, |
551 | }; |
552 | |
553 | static struct ccu_div i2s2_clk = { |
554 | .enable = BIT(31), |
555 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
556 | .mux = _SUNXI_CCU_MUX(24, 2), |
557 | .common = { |
558 | .reg = 0xa18, |
559 | .hw.init = CLK_HW_INIT_PARENTS("i2s2" , |
560 | audio_parents, |
561 | &ccu_div_ops, |
562 | CLK_SET_RATE_PARENT), |
563 | }, |
564 | }; |
565 | |
566 | static struct ccu_div i2s3_clk = { |
567 | .enable = BIT(31), |
568 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
569 | .mux = _SUNXI_CCU_MUX(24, 2), |
570 | .common = { |
571 | .reg = 0xa1c, |
572 | .hw.init = CLK_HW_INIT_PARENTS("i2s3" , |
573 | audio_parents, |
574 | &ccu_div_ops, |
575 | CLK_SET_RATE_PARENT), |
576 | }, |
577 | }; |
578 | |
579 | static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0" , "apb1" , 0xa20, BIT(0), 0); |
580 | static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1" , "apb1" , 0xa20, BIT(1), 0); |
581 | static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2" , "apb1" , 0xa20, BIT(2), 0); |
582 | static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3" , "apb1" , 0xa20, BIT(3), 0); |
583 | |
584 | static struct ccu_div spdif_clk = { |
585 | .enable = BIT(31), |
586 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
587 | .mux = _SUNXI_CCU_MUX(24, 2), |
588 | .common = { |
589 | .reg = 0xa24, |
590 | .hw.init = CLK_HW_INIT_PARENTS("spdif" , |
591 | audio_parents, |
592 | &ccu_div_ops, |
593 | 0), |
594 | }, |
595 | }; |
596 | |
597 | static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif" , "apb1" , 0xa2c, BIT(0), 0); |
598 | |
599 | static struct ccu_div dmic_clk = { |
600 | .enable = BIT(31), |
601 | .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), |
602 | .mux = _SUNXI_CCU_MUX(24, 2), |
603 | .common = { |
604 | .reg = 0xa40, |
605 | .hw.init = CLK_HW_INIT_PARENTS("dmic" , |
606 | audio_parents, |
607 | &ccu_div_ops, |
608 | 0), |
609 | }, |
610 | }; |
611 | |
612 | static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic" , "apb1" , 0xa4c, BIT(0), 0); |
613 | |
614 | static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac" , |
615 | audio_parents, 0xa50, |
616 | 0, 4, /* M */ |
617 | 24, 2, /* mux */ |
618 | BIT(31), /* gate */ |
619 | 0); |
620 | |
621 | static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc" , |
622 | audio_parents, 0xa54, |
623 | 0, 4, /* M */ |
624 | 24, 2, /* mux */ |
625 | BIT(31), /* gate */ |
626 | 0); |
627 | |
628 | static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x" , |
629 | audio_parents, 0xa58, |
630 | 0, 4, /* M */ |
631 | 24, 2, /* mux */ |
632 | BIT(31), /* gate */ |
633 | 0); |
634 | |
635 | static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec" , "apb1" , 0xa5c, |
636 | BIT(0), 0); |
637 | |
638 | /* |
639 | * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports. |
640 | * We will force them to 0 (12M divided from 48M). |
641 | */ |
642 | #define SUN50I_A100_USB0_CLK_REG 0xa70 |
643 | #define SUN50I_A100_USB1_CLK_REG 0xa74 |
644 | |
645 | static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0" , "osc12M" , 0xa70, BIT(31), 0); |
646 | static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0" , "dcxo24M" , 0xa70, BIT(29), 0); |
647 | |
648 | static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1" , "osc12M" , 0xa74, BIT(31), 0); |
649 | static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1" , "dcxo24M" , 0xa74, BIT(29), 0); |
650 | |
651 | static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0" , "ahb3" , 0xa8c, BIT(0), 0); |
652 | static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1" , "ahb3" , 0xa8c, BIT(1), 0); |
653 | static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0" , "ahb3" , 0xa8c, BIT(4), 0); |
654 | static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1" , "ahb3" , 0xa8c, BIT(5), 0); |
655 | static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg" , "ahb3" , 0xa8c, BIT(8), 0); |
656 | |
657 | static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc" , "ahb3" , 0xa9c, BIT(0), 0); |
658 | |
659 | static SUNXI_CCU_GATE(bus_dpss_top0_clk, "bus-dpss-top0" , "ahb3" , |
660 | 0xabc, BIT(0), 0); |
661 | |
662 | static SUNXI_CCU_GATE(bus_dpss_top1_clk, "bus-dpss-top1" , "ahb3" , |
663 | 0xacc, BIT(0), 0); |
664 | |
665 | static const char * const mipi_dsi_parents[] = { "dcxo24M" , "pll-periph0-2x" , |
666 | "pll-periph0" }; |
667 | static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi" , |
668 | mipi_dsi_parents, |
669 | 0xb24, |
670 | 0, 4, /* M */ |
671 | 24, 2, /* mux */ |
672 | BIT(31), /* gate */ |
673 | 0); |
674 | |
675 | static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi" , "ahb3" , |
676 | 0xb4c, BIT(0), 0); |
677 | |
678 | static const char * const tcon_lcd_parents[] = { "pll-video0-4x" , |
679 | "pll-video1-4x" , |
680 | "pll-video2-4x" , |
681 | "pll-video3-4x" , |
682 | "pll-periph0-2x" }; |
683 | static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd0" , |
684 | tcon_lcd_parents, 0xb60, |
685 | 0, 4, /* M */ |
686 | 8, 2, /* P */ |
687 | 24, 3, /* mux */ |
688 | BIT(31), /* gate */ |
689 | 0); |
690 | |
691 | static SUNXI_CCU_GATE(bus_tcon_lcd_clk, "bus-tcon-lcd0" , "ahb3" , |
692 | 0xb7c, BIT(0), 0); |
693 | |
694 | static const char * const ledc_parents[] = { "dcxo24M" , |
695 | "pll-periph0" }; |
696 | static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc" , |
697 | ledc_parents, 0xbf0, |
698 | 0, 4, /* M */ |
699 | 8, 2, /* P */ |
700 | 24, 3, /* mux */ |
701 | BIT(31), /* gate */ |
702 | 0); |
703 | |
704 | static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc" , "ahb3" , 0xbfc, BIT(0), 0); |
705 | |
706 | static const char * const csi_top_parents[] = { "pll-periph0-2x" , |
707 | "pll-video0-2x" , |
708 | "pll-video1-2x" , |
709 | "pll-video2-2x" , |
710 | "pll-video3-2x" }; |
711 | static SUNXI_CCU_M_WITH_MUX_GATE(csi_top_clk, "csi-top" , |
712 | csi_top_parents, 0xc04, |
713 | 0, 4, /* M */ |
714 | 24, 3, /* mux */ |
715 | BIT(31), /* gate */ |
716 | 0); |
717 | |
718 | static const char * const csi0_mclk_parents[] = { "dcxo24M" , "pll-video2" , |
719 | "pll-video3" , "pll-video0" , |
720 | "pll-video1" }; |
721 | static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk" , |
722 | csi0_mclk_parents, 0xc08, |
723 | 0, 5, /* M */ |
724 | 24, 3, /* mux */ |
725 | BIT(31), /* gate */ |
726 | 0); |
727 | |
728 | static const char * const csi1_mclk_parents[] = { "dcxo24M" , "pll-video3" , |
729 | "pll-video0" , "pll-video1" , |
730 | "pll-video2" }; |
731 | static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk" , |
732 | csi1_mclk_parents, 0xc0c, |
733 | 0, 5, /* M */ |
734 | 24, 3, /* mux */ |
735 | BIT(31), /* gate */ |
736 | 0); |
737 | |
738 | static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi" , "ahb3" , 0xc1c, BIT(0), 0); |
739 | |
740 | static const char * const csi_isp_parents[] = { "pll-periph0-2x" , |
741 | "pll-video0-2x" , |
742 | "pll-video1-2x" , |
743 | "pll-video2-2x" , |
744 | "pll-video3-2x" }; |
745 | static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp" , |
746 | csi_isp_parents, 0xc20, |
747 | 0, 5, /* M */ |
748 | 24, 3, /* mux */ |
749 | BIT(31), /* gate */ |
750 | 0); |
751 | |
752 | /* Fixed factor clocks */ |
753 | static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M" , "hosc" , 2, 1, 0); |
754 | |
755 | static CLK_FIXED_FACTOR_HW(pll_com_audio_clk, "pll-com-audio" , |
756 | &pll_com_clk.common.hw, |
757 | 5, 1, CLK_SET_RATE_PARENT); |
758 | |
759 | static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x" , |
760 | &pll_periph0_clk.common.hw, |
761 | 1, 2, 0); |
762 | |
763 | static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x" , |
764 | &pll_periph1_clk.common.hw, |
765 | 1, 2, 0); |
766 | |
767 | static const struct clk_hw *pll_video0_parents[] = { |
768 | &pll_video0_clk.common.hw |
769 | }; |
770 | static CLK_FIXED_FACTOR_HWS(pll_video0_4x_clk, "pll-video0-4x" , |
771 | pll_video0_parents, |
772 | 1, 4, CLK_SET_RATE_PARENT); |
773 | static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x" , |
774 | pll_video0_parents, |
775 | 1, 2, CLK_SET_RATE_PARENT); |
776 | |
777 | static const struct clk_hw *pll_video1_parents[] = { |
778 | &pll_video1_clk.common.hw |
779 | }; |
780 | static CLK_FIXED_FACTOR_HWS(pll_video1_4x_clk, "pll-video1-4x" , |
781 | pll_video1_parents, |
782 | 1, 4, CLK_SET_RATE_PARENT); |
783 | static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x" , |
784 | pll_video1_parents, |
785 | 1, 2, CLK_SET_RATE_PARENT); |
786 | |
787 | static const struct clk_hw *pll_video2_parents[] = { |
788 | &pll_video2_clk.common.hw |
789 | }; |
790 | static CLK_FIXED_FACTOR_HWS(pll_video2_4x_clk, "pll-video2-4x" , |
791 | pll_video2_parents, |
792 | 1, 4, CLK_SET_RATE_PARENT); |
793 | static CLK_FIXED_FACTOR_HWS(pll_video2_2x_clk, "pll-video2-2x" , |
794 | pll_video2_parents, |
795 | 1, 2, CLK_SET_RATE_PARENT); |
796 | |
797 | static const struct clk_hw *pll_video3_parents[] = { |
798 | &pll_video3_clk.common.hw |
799 | }; |
800 | static CLK_FIXED_FACTOR_HWS(pll_video3_4x_clk, "pll-video3-4x" , |
801 | pll_video3_parents, |
802 | 1, 4, CLK_SET_RATE_PARENT); |
803 | static CLK_FIXED_FACTOR_HWS(pll_video3_2x_clk, "pll-video3-2x" , |
804 | pll_video3_parents, |
805 | 1, 2, CLK_SET_RATE_PARENT); |
806 | |
807 | static struct ccu_common *sun50i_a100_ccu_clks[] = { |
808 | &pll_cpux_clk.common, |
809 | &pll_ddr0_clk.common, |
810 | &pll_periph0_clk.common, |
811 | &pll_periph1_clk.common, |
812 | &pll_gpu_clk.common, |
813 | &pll_video0_clk.common, |
814 | &pll_video1_clk.common, |
815 | &pll_video2_clk.common, |
816 | &pll_video3_clk.common, |
817 | &pll_ve_clk.common, |
818 | &pll_com_clk.common, |
819 | &pll_audio_clk.common, |
820 | &cpux_clk.common, |
821 | &axi_clk.common, |
822 | &cpux_apb_clk.common, |
823 | &psi_ahb1_ahb2_clk.common, |
824 | &ahb3_clk.common, |
825 | &apb1_clk.common, |
826 | &apb2_clk.common, |
827 | &mbus_clk.common, |
828 | &de_clk.common, |
829 | &bus_de_clk.common, |
830 | &g2d_clk.common, |
831 | &bus_g2d_clk.common, |
832 | &gpu_clk.common, |
833 | &bus_gpu_clk.common, |
834 | &ce_clk.common, |
835 | &bus_ce_clk.common, |
836 | &ve_clk.common, |
837 | &bus_ve_clk.common, |
838 | &bus_dma_clk.common, |
839 | &bus_msgbox_clk.common, |
840 | &bus_spinlock_clk.common, |
841 | &bus_hstimer_clk.common, |
842 | &avs_clk.common, |
843 | &bus_dbg_clk.common, |
844 | &bus_psi_clk.common, |
845 | &bus_pwm_clk.common, |
846 | &bus_iommu_clk.common, |
847 | &mbus_dma_clk.common, |
848 | &mbus_ve_clk.common, |
849 | &mbus_ce_clk.common, |
850 | &mbus_nand_clk.common, |
851 | &mbus_csi_clk.common, |
852 | &mbus_isp_clk.common, |
853 | &mbus_g2d_clk.common, |
854 | &bus_dram_clk.common, |
855 | &nand0_clk.common, |
856 | &nand1_clk.common, |
857 | &bus_nand_clk.common, |
858 | &mmc0_clk.common, |
859 | &mmc1_clk.common, |
860 | &mmc2_clk.common, |
861 | &bus_mmc0_clk.common, |
862 | &bus_mmc1_clk.common, |
863 | &bus_mmc2_clk.common, |
864 | &bus_uart0_clk.common, |
865 | &bus_uart1_clk.common, |
866 | &bus_uart2_clk.common, |
867 | &bus_uart3_clk.common, |
868 | &bus_uart4_clk.common, |
869 | &bus_i2c0_clk.common, |
870 | &bus_i2c1_clk.common, |
871 | &bus_i2c2_clk.common, |
872 | &bus_i2c3_clk.common, |
873 | &spi0_clk.common, |
874 | &spi1_clk.common, |
875 | &spi2_clk.common, |
876 | &bus_spi0_clk.common, |
877 | &bus_spi1_clk.common, |
878 | &bus_spi2_clk.common, |
879 | &emac_25m_clk.common, |
880 | &bus_emac_clk.common, |
881 | &ir_rx_clk.common, |
882 | &bus_ir_rx_clk.common, |
883 | &ir_tx_clk.common, |
884 | &bus_ir_tx_clk.common, |
885 | &bus_gpadc_clk.common, |
886 | &bus_ths_clk.common, |
887 | &i2s0_clk.common, |
888 | &i2s1_clk.common, |
889 | &i2s2_clk.common, |
890 | &i2s3_clk.common, |
891 | &bus_i2s0_clk.common, |
892 | &bus_i2s1_clk.common, |
893 | &bus_i2s2_clk.common, |
894 | &bus_i2s3_clk.common, |
895 | &spdif_clk.common, |
896 | &bus_spdif_clk.common, |
897 | &dmic_clk.common, |
898 | &bus_dmic_clk.common, |
899 | &audio_codec_dac_clk.common, |
900 | &audio_codec_adc_clk.common, |
901 | &audio_codec_4x_clk.common, |
902 | &bus_audio_codec_clk.common, |
903 | &usb_ohci0_clk.common, |
904 | &usb_phy0_clk.common, |
905 | &usb_ohci1_clk.common, |
906 | &usb_phy1_clk.common, |
907 | &bus_ohci0_clk.common, |
908 | &bus_ohci1_clk.common, |
909 | &bus_ehci0_clk.common, |
910 | &bus_ehci1_clk.common, |
911 | &bus_otg_clk.common, |
912 | &bus_lradc_clk.common, |
913 | &bus_dpss_top0_clk.common, |
914 | &bus_dpss_top1_clk.common, |
915 | &mipi_dsi_clk.common, |
916 | &bus_mipi_dsi_clk.common, |
917 | &tcon_lcd_clk.common, |
918 | &bus_tcon_lcd_clk.common, |
919 | &ledc_clk.common, |
920 | &bus_ledc_clk.common, |
921 | &csi_top_clk.common, |
922 | &csi0_mclk_clk.common, |
923 | &csi1_mclk_clk.common, |
924 | &bus_csi_clk.common, |
925 | &csi_isp_clk.common, |
926 | }; |
927 | |
928 | static struct clk_hw_onecell_data sun50i_a100_hw_clks = { |
929 | .hws = { |
930 | [CLK_OSC12M] = &osc12M_clk.hw, |
931 | [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, |
932 | [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, |
933 | [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, |
934 | [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, |
935 | [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, |
936 | [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, |
937 | [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, |
938 | [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, |
939 | [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, |
940 | [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw, |
941 | [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, |
942 | [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, |
943 | [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw, |
944 | [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw, |
945 | [CLK_PLL_VIDEO2_2X] = &pll_video2_2x_clk.hw, |
946 | [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw, |
947 | [CLK_PLL_VIDEO3] = &pll_video3_clk.common.hw, |
948 | [CLK_PLL_VIDEO3_2X] = &pll_video3_2x_clk.hw, |
949 | [CLK_PLL_VIDEO3_4X] = &pll_video3_4x_clk.hw, |
950 | [CLK_PLL_VE] = &pll_ve_clk.common.hw, |
951 | [CLK_PLL_COM] = &pll_com_clk.common.hw, |
952 | [CLK_PLL_COM_AUDIO] = &pll_com_audio_clk.hw, |
953 | [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw, |
954 | [CLK_CPUX] = &cpux_clk.common.hw, |
955 | [CLK_AXI] = &axi_clk.common.hw, |
956 | [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, |
957 | [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw, |
958 | [CLK_AHB3] = &ahb3_clk.common.hw, |
959 | [CLK_APB1] = &apb1_clk.common.hw, |
960 | [CLK_APB2] = &apb2_clk.common.hw, |
961 | [CLK_MBUS] = &mbus_clk.common.hw, |
962 | [CLK_DE] = &de_clk.common.hw, |
963 | [CLK_BUS_DE] = &bus_de_clk.common.hw, |
964 | [CLK_G2D] = &g2d_clk.common.hw, |
965 | [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, |
966 | [CLK_GPU] = &gpu_clk.common.hw, |
967 | [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, |
968 | [CLK_CE] = &ce_clk.common.hw, |
969 | [CLK_BUS_CE] = &bus_ce_clk.common.hw, |
970 | [CLK_VE] = &ve_clk.common.hw, |
971 | [CLK_BUS_VE] = &bus_ve_clk.common.hw, |
972 | [CLK_BUS_DMA] = &bus_dma_clk.common.hw, |
973 | [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, |
974 | [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, |
975 | [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, |
976 | [CLK_AVS] = &avs_clk.common.hw, |
977 | [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, |
978 | [CLK_BUS_PSI] = &bus_psi_clk.common.hw, |
979 | [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, |
980 | [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, |
981 | [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, |
982 | [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, |
983 | [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, |
984 | [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw, |
985 | [CLK_MBUS_CSI] = &mbus_csi_clk.common.hw, |
986 | [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw, |
987 | [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, |
988 | [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, |
989 | [CLK_NAND0] = &nand0_clk.common.hw, |
990 | [CLK_NAND1] = &nand1_clk.common.hw, |
991 | [CLK_BUS_NAND] = &bus_nand_clk.common.hw, |
992 | [CLK_MMC0] = &mmc0_clk.common.hw, |
993 | [CLK_MMC1] = &mmc1_clk.common.hw, |
994 | [CLK_MMC2] = &mmc2_clk.common.hw, |
995 | [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, |
996 | [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, |
997 | [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, |
998 | [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, |
999 | [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, |
1000 | [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, |
1001 | [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, |
1002 | [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, |
1003 | [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, |
1004 | [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, |
1005 | [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, |
1006 | [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, |
1007 | [CLK_SPI0] = &spi0_clk.common.hw, |
1008 | [CLK_SPI1] = &spi1_clk.common.hw, |
1009 | [CLK_SPI2] = &spi2_clk.common.hw, |
1010 | [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, |
1011 | [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, |
1012 | [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, |
1013 | [CLK_EMAC_25M] = &emac_25m_clk.common.hw, |
1014 | [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, |
1015 | [CLK_IR_RX] = &ir_rx_clk.common.hw, |
1016 | [CLK_BUS_IR_RX] = &bus_ir_rx_clk.common.hw, |
1017 | [CLK_IR_TX] = &ir_tx_clk.common.hw, |
1018 | [CLK_BUS_IR_TX] = &bus_ir_tx_clk.common.hw, |
1019 | [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw, |
1020 | [CLK_BUS_THS] = &bus_ths_clk.common.hw, |
1021 | [CLK_I2S0] = &i2s0_clk.common.hw, |
1022 | [CLK_I2S1] = &i2s1_clk.common.hw, |
1023 | [CLK_I2S2] = &i2s2_clk.common.hw, |
1024 | [CLK_I2S3] = &i2s3_clk.common.hw, |
1025 | [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, |
1026 | [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, |
1027 | [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, |
1028 | [CLK_BUS_I2S3] = &bus_i2s3_clk.common.hw, |
1029 | [CLK_SPDIF] = &spdif_clk.common.hw, |
1030 | [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, |
1031 | [CLK_DMIC] = &dmic_clk.common.hw, |
1032 | [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, |
1033 | [CLK_AUDIO_DAC] = &audio_codec_dac_clk.common.hw, |
1034 | [CLK_AUDIO_ADC] = &audio_codec_adc_clk.common.hw, |
1035 | [CLK_AUDIO_4X] = &audio_codec_4x_clk.common.hw, |
1036 | [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw, |
1037 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, |
1038 | [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, |
1039 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, |
1040 | [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, |
1041 | [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, |
1042 | [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, |
1043 | [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, |
1044 | [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, |
1045 | [CLK_BUS_OTG] = &bus_otg_clk.common.hw, |
1046 | [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw, |
1047 | [CLK_BUS_DPSS_TOP0] = &bus_dpss_top0_clk.common.hw, |
1048 | [CLK_BUS_DPSS_TOP1] = &bus_dpss_top1_clk.common.hw, |
1049 | [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw, |
1050 | [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, |
1051 | [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw, |
1052 | [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw, |
1053 | [CLK_LEDC] = &ledc_clk.common.hw, |
1054 | [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw, |
1055 | [CLK_CSI_TOP] = &csi_top_clk.common.hw, |
1056 | [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, |
1057 | [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, |
1058 | [CLK_BUS_CSI] = &bus_csi_clk.common.hw, |
1059 | [CLK_CSI_ISP] = &csi_isp_clk.common.hw, |
1060 | }, |
1061 | .num = CLK_NUMBER, |
1062 | }; |
1063 | |
1064 | static struct ccu_reset_map sun50i_a100_ccu_resets[] = { |
1065 | [RST_MBUS] = { 0x540, BIT(30) }, |
1066 | |
1067 | [RST_BUS_DE] = { 0x60c, BIT(16) }, |
1068 | [RST_BUS_G2D] = { 0x63c, BIT(16) }, |
1069 | [RST_BUS_GPU] = { 0x67c, BIT(16) }, |
1070 | [RST_BUS_CE] = { 0x68c, BIT(16) }, |
1071 | [RST_BUS_VE] = { 0x69c, BIT(16) }, |
1072 | [RST_BUS_DMA] = { 0x70c, BIT(16) }, |
1073 | [RST_BUS_MSGBOX] = { 0x71c, BIT(16) }, |
1074 | [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) }, |
1075 | [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, |
1076 | [RST_BUS_DBG] = { 0x78c, BIT(16) }, |
1077 | [RST_BUS_PSI] = { 0x79c, BIT(16) }, |
1078 | [RST_BUS_PWM] = { 0x7ac, BIT(16) }, |
1079 | [RST_BUS_DRAM] = { 0x80c, BIT(16) }, |
1080 | [RST_BUS_NAND] = { 0x82c, BIT(16) }, |
1081 | [RST_BUS_MMC0] = { 0x84c, BIT(16) }, |
1082 | [RST_BUS_MMC1] = { 0x84c, BIT(17) }, |
1083 | [RST_BUS_MMC2] = { 0x84c, BIT(18) }, |
1084 | [RST_BUS_UART0] = { 0x90c, BIT(16) }, |
1085 | [RST_BUS_UART1] = { 0x90c, BIT(17) }, |
1086 | [RST_BUS_UART2] = { 0x90c, BIT(18) }, |
1087 | [RST_BUS_UART3] = { 0x90c, BIT(19) }, |
1088 | [RST_BUS_UART4] = { 0x90c, BIT(20) }, |
1089 | [RST_BUS_I2C0] = { 0x91c, BIT(16) }, |
1090 | [RST_BUS_I2C1] = { 0x91c, BIT(17) }, |
1091 | [RST_BUS_I2C2] = { 0x91c, BIT(18) }, |
1092 | [RST_BUS_I2C3] = { 0x91c, BIT(19) }, |
1093 | [RST_BUS_SPI0] = { 0x96c, BIT(16) }, |
1094 | [RST_BUS_SPI1] = { 0x96c, BIT(17) }, |
1095 | [RST_BUS_SPI2] = { 0x96c, BIT(18) }, |
1096 | [RST_BUS_EMAC] = { 0x97c, BIT(16) }, |
1097 | [RST_BUS_IR_RX] = { 0x99c, BIT(16) }, |
1098 | [RST_BUS_IR_TX] = { 0x9cc, BIT(16) }, |
1099 | [RST_BUS_GPADC] = { 0x9ec, BIT(16) }, |
1100 | [RST_BUS_THS] = { 0x9fc, BIT(16) }, |
1101 | [RST_BUS_I2S0] = { 0xa20, BIT(16) }, |
1102 | [RST_BUS_I2S1] = { 0xa20, BIT(17) }, |
1103 | [RST_BUS_I2S2] = { 0xa20, BIT(18) }, |
1104 | [RST_BUS_I2S3] = { 0xa20, BIT(19) }, |
1105 | [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, |
1106 | [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, |
1107 | [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) }, |
1108 | |
1109 | [RST_USB_PHY0] = { 0xa70, BIT(30) }, |
1110 | [RST_USB_PHY1] = { 0xa74, BIT(30) }, |
1111 | |
1112 | [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, |
1113 | [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, |
1114 | [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, |
1115 | [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, |
1116 | [RST_BUS_OTG] = { 0xa8c, BIT(24) }, |
1117 | |
1118 | [RST_BUS_LRADC] = { 0xa9c, BIT(16) }, |
1119 | [RST_BUS_DPSS_TOP0] = { 0xabc, BIT(16) }, |
1120 | [RST_BUS_DPSS_TOP1] = { 0xacc, BIT(16) }, |
1121 | [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) }, |
1122 | [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) }, |
1123 | [RST_BUS_LVDS] = { 0xbac, BIT(16) }, |
1124 | [RST_BUS_LEDC] = { 0xbfc, BIT(16) }, |
1125 | [RST_BUS_CSI] = { 0xc1c, BIT(16) }, |
1126 | [RST_BUS_CSI_ISP] = { 0xc2c, BIT(16) }, |
1127 | }; |
1128 | |
1129 | static const struct sunxi_ccu_desc sun50i_a100_ccu_desc = { |
1130 | .ccu_clks = sun50i_a100_ccu_clks, |
1131 | .num_ccu_clks = ARRAY_SIZE(sun50i_a100_ccu_clks), |
1132 | |
1133 | .hw_clks = &sun50i_a100_hw_clks, |
1134 | |
1135 | .resets = sun50i_a100_ccu_resets, |
1136 | .num_resets = ARRAY_SIZE(sun50i_a100_ccu_resets), |
1137 | }; |
1138 | |
1139 | static const u32 sun50i_a100_pll_regs[] = { |
1140 | SUN50I_A100_PLL_CPUX_REG, |
1141 | SUN50I_A100_PLL_DDR0_REG, |
1142 | SUN50I_A100_PLL_PERIPH0_REG, |
1143 | SUN50I_A100_PLL_PERIPH1_REG, |
1144 | SUN50I_A100_PLL_GPU_REG, |
1145 | SUN50I_A100_PLL_VIDEO0_REG, |
1146 | SUN50I_A100_PLL_VIDEO1_REG, |
1147 | SUN50I_A100_PLL_VIDEO2_REG, |
1148 | SUN50I_A100_PLL_VIDEO3_REG, |
1149 | SUN50I_A100_PLL_VE_REG, |
1150 | SUN50I_A100_PLL_COM_REG, |
1151 | SUN50I_A100_PLL_AUDIO_REG, |
1152 | }; |
1153 | |
1154 | static const u32 sun50i_a100_pll_video_regs[] = { |
1155 | SUN50I_A100_PLL_VIDEO0_REG, |
1156 | SUN50I_A100_PLL_VIDEO1_REG, |
1157 | SUN50I_A100_PLL_VIDEO2_REG, |
1158 | SUN50I_A100_PLL_VIDEO3_REG, |
1159 | }; |
1160 | |
1161 | static const u32 sun50i_a100_usb2_clk_regs[] = { |
1162 | SUN50I_A100_USB0_CLK_REG, |
1163 | SUN50I_A100_USB1_CLK_REG, |
1164 | }; |
1165 | |
1166 | static struct ccu_pll_nb sun50i_a100_pll_cpu_nb = { |
1167 | .common = &pll_cpux_clk.common, |
1168 | /* copy from pll_cpux_clk */ |
1169 | .enable = BIT(27), |
1170 | .lock = BIT(28), |
1171 | }; |
1172 | |
1173 | static struct ccu_mux_nb sun50i_a100_cpu_nb = { |
1174 | .common = &cpux_clk.common, |
1175 | .cm = &cpux_clk.mux, |
1176 | .delay_us = 1, |
1177 | .bypass_index = 4, /* index of pll periph0 */ |
1178 | }; |
1179 | |
1180 | static int sun50i_a100_ccu_probe(struct platform_device *pdev) |
1181 | { |
1182 | void __iomem *reg; |
1183 | u32 val; |
1184 | int i, ret; |
1185 | |
1186 | reg = devm_platform_ioremap_resource(pdev, index: 0); |
1187 | if (IS_ERR(ptr: reg)) |
1188 | return PTR_ERR(ptr: reg); |
1189 | |
1190 | /* |
1191 | * Enable lock and enable bits on all PLLs. |
1192 | * |
1193 | * Due to the current design, multiple PLLs share one power switch, |
1194 | * so switching PLL is easy to cause stability problems. |
1195 | * When initializing, we enable them by default. When disable, |
1196 | * we only turn off the output of PLL. |
1197 | */ |
1198 | for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_regs); i++) { |
1199 | val = readl(addr: reg + sun50i_a100_pll_regs[i]); |
1200 | val |= SUN50I_A100_PLL_LOCK_ENABLE | SUN50I_A100_PLL_ENABLE; |
1201 | writel(val, addr: reg + sun50i_a100_pll_regs[i]); |
1202 | } |
1203 | |
1204 | /* |
1205 | * In order to pass the EMI certification, the SDM function of |
1206 | * the peripheral 1 bus is enabled, and the frequency is still |
1207 | * calculated using the previous division factor. |
1208 | */ |
1209 | writel(SUN50I_A100_PLL_PERIPH1_PATTERN0, |
1210 | addr: reg + SUN50I_A100_PLL_PERIPH1_PATTERN0_REG); |
1211 | |
1212 | val = readl(addr: reg + SUN50I_A100_PLL_PERIPH1_REG); |
1213 | val |= SUN50I_A100_PLL_SDM_ENABLE; |
1214 | writel(val, addr: reg + SUN50I_A100_PLL_PERIPH1_REG); |
1215 | |
1216 | /* |
1217 | * Force the output divider of video PLLs to 0. |
1218 | * |
1219 | * See the comment before pll-video0 definition for the reason. |
1220 | */ |
1221 | for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_video_regs); i++) { |
1222 | val = readl(addr: reg + sun50i_a100_pll_video_regs[i]); |
1223 | val &= ~BIT(0); |
1224 | writel(val, addr: reg + sun50i_a100_pll_video_regs[i]); |
1225 | } |
1226 | |
1227 | /* |
1228 | * Enforce m1 = 0, m0 = 1 for Audio PLL |
1229 | * |
1230 | * See the comment before pll-audio definition for the reason. |
1231 | */ |
1232 | val = readl(addr: reg + SUN50I_A100_PLL_AUDIO_REG); |
1233 | val &= ~BIT(1); |
1234 | val |= BIT(0); |
1235 | writel(val, addr: reg + SUN50I_A100_PLL_AUDIO_REG); |
1236 | |
1237 | /* |
1238 | * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) |
1239 | * |
1240 | * This clock mux is still mysterious, and the code just enforces |
1241 | * it to have a valid clock parent. |
1242 | */ |
1243 | for (i = 0; i < ARRAY_SIZE(sun50i_a100_usb2_clk_regs); i++) { |
1244 | val = readl(addr: reg + sun50i_a100_usb2_clk_regs[i]); |
1245 | val &= ~GENMASK(25, 24); |
1246 | writel(val, addr: reg + sun50i_a100_usb2_clk_regs[i]); |
1247 | } |
1248 | |
1249 | ret = devm_sunxi_ccu_probe(dev: &pdev->dev, reg, desc: &sun50i_a100_ccu_desc); |
1250 | if (ret) |
1251 | return ret; |
1252 | |
1253 | /* Gate then ungate PLL CPU after any rate changes */ |
1254 | ccu_pll_notifier_register(pll_nb: &sun50i_a100_pll_cpu_nb); |
1255 | |
1256 | /* Reparent CPU during PLL CPU rate changes */ |
1257 | ccu_mux_notifier_register(clk: pll_cpux_clk.common.hw.clk, |
1258 | mux_nb: &sun50i_a100_cpu_nb); |
1259 | |
1260 | return 0; |
1261 | } |
1262 | |
1263 | static const struct of_device_id sun50i_a100_ccu_ids[] = { |
1264 | { .compatible = "allwinner,sun50i-a100-ccu" }, |
1265 | { } |
1266 | }; |
1267 | |
1268 | static struct platform_driver sun50i_a100_ccu_driver = { |
1269 | .probe = sun50i_a100_ccu_probe, |
1270 | .driver = { |
1271 | .name = "sun50i-a100-ccu" , |
1272 | .suppress_bind_attrs = true, |
1273 | .of_match_table = sun50i_a100_ccu_ids, |
1274 | }, |
1275 | }; |
1276 | module_platform_driver(sun50i_a100_ccu_driver); |
1277 | |
1278 | MODULE_IMPORT_NS(SUNXI_CCU); |
1279 | MODULE_LICENSE("GPL" ); |
1280 | |