Commit | Line | Data |
---|---|---|
35b97bb9 SH |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Copyright (c) 2020 huangzhenwei@allwinnertech.com | |
4 | * Copyright (C) 2021 Samuel Holland <samuel@sholland.org> | |
5 | */ | |
6 | ||
7 | #include <linux/clk-provider.h> | |
8 | #include <linux/io.h> | |
9 | #include <linux/module.h> | |
10 | #include <linux/platform_device.h> | |
11 | ||
12 | #include "../clk.h" | |
13 | ||
14 | #include "ccu_common.h" | |
15 | #include "ccu_reset.h" | |
16 | ||
17 | #include "ccu_div.h" | |
18 | #include "ccu_gate.h" | |
19 | #include "ccu_mp.h" | |
20 | #include "ccu_mult.h" | |
21 | #include "ccu_nk.h" | |
22 | #include "ccu_nkm.h" | |
23 | #include "ccu_nkmp.h" | |
24 | #include "ccu_nm.h" | |
25 | ||
26 | #include "ccu-sun20i-d1.h" | |
27 | ||
28 | static const struct clk_parent_data osc24M[] = { | |
29 | { .fw_name = "hosc" } | |
30 | }; | |
31 | ||
32 | /* | |
33 | * For the CPU PLL, the output divider is described as "only for testing" | |
34 | * in the user manual. So it's not modelled and forced to 0. | |
35 | */ | |
36 | #define SUN20I_D1_PLL_CPUX_REG 0x000 | |
37 | static struct ccu_mult pll_cpux_clk = { | |
38 | .enable = BIT(27), | |
39 | .lock = BIT(28), | |
40 | .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
41 | .common = { | |
42 | .reg = 0x000, | |
43 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpux", osc24M, | |
44 | &ccu_mult_ops, | |
45 | CLK_SET_RATE_UNGATE), | |
46 | }, | |
47 | }; | |
48 | ||
49 | /* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ | |
50 | #define SUN20I_D1_PLL_DDR0_REG 0x010 | |
51 | static struct ccu_nkmp pll_ddr0_clk = { | |
52 | .enable = BIT(27), | |
53 | .lock = BIT(28), | |
54 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
55 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ | |
56 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ | |
57 | .common = { | |
58 | .reg = 0x010, | |
59 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M, | |
60 | &ccu_nkmp_ops, | |
61 | CLK_SET_RATE_UNGATE), | |
62 | }, | |
63 | }; | |
64 | ||
65 | #define SUN20I_D1_PLL_PERIPH0_REG 0x020 | |
66 | static struct ccu_nm pll_periph0_4x_clk = { | |
67 | .enable = BIT(27), | |
68 | .lock = BIT(28), | |
69 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
70 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ | |
71 | .common = { | |
72 | .reg = 0x020, | |
73 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x", osc24M, | |
74 | &ccu_nm_ops, | |
75 | CLK_SET_RATE_UNGATE), | |
76 | }, | |
77 | }; | |
78 | ||
79 | static const struct clk_hw *pll_periph0_4x_hws[] = { | |
80 | &pll_periph0_4x_clk.common.hw | |
81 | }; | |
82 | static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x", | |
83 | pll_periph0_4x_hws, 0x020, 16, 3, 0); | |
84 | static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M", | |
85 | pll_periph0_4x_hws, 0x020, 20, 3, 0); | |
86 | ||
87 | static const struct clk_hw *pll_periph0_2x_hws[] = { | |
88 | &pll_periph0_2x_clk.common.hw | |
89 | }; | |
90 | static CLK_FIXED_FACTOR_HWS(pll_periph0_clk, "pll-periph0", | |
91 | pll_periph0_2x_hws, 2, 1, 0); | |
92 | ||
93 | static const struct clk_hw *pll_periph0_hws[] = { &pll_periph0_clk.hw }; | |
94 | static CLK_FIXED_FACTOR_HWS(pll_periph0_div3_clk, "pll-periph0-div3", | |
95 | pll_periph0_2x_hws, 6, 1, 0); | |
96 | ||
97 | /* | |
98 | * For Video PLLs, the output divider is described as "only for testing" | |
99 | * in the user manual. So it's not modelled and forced to 0. | |
100 | */ | |
101 | #define SUN20I_D1_PLL_VIDEO0_REG 0x040 | |
102 | static struct ccu_nm pll_video0_4x_clk = { | |
103 | .enable = BIT(27), | |
104 | .lock = BIT(28), | |
105 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
106 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ | |
3930624c SH |
107 | .min_rate = 252000000U, |
108 | .max_rate = 2400000000U, | |
35b97bb9 SH |
109 | .common = { |
110 | .reg = 0x040, | |
111 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video0-4x", osc24M, | |
112 | &ccu_nm_ops, | |
113 | CLK_SET_RATE_UNGATE), | |
114 | }, | |
115 | }; | |
116 | ||
117 | static const struct clk_hw *pll_video0_4x_hws[] = { | |
118 | &pll_video0_4x_clk.common.hw | |
119 | }; | |
120 | static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x", | |
121 | pll_video0_4x_hws, 2, 1, CLK_SET_RATE_PARENT); | |
122 | static CLK_FIXED_FACTOR_HWS(pll_video0_clk, "pll-video0", | |
123 | pll_video0_4x_hws, 4, 1, CLK_SET_RATE_PARENT); | |
124 | ||
125 | #define SUN20I_D1_PLL_VIDEO1_REG 0x048 | |
126 | static struct ccu_nm pll_video1_4x_clk = { | |
127 | .enable = BIT(27), | |
128 | .lock = BIT(28), | |
129 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
130 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ | |
3930624c SH |
131 | .min_rate = 252000000U, |
132 | .max_rate = 2400000000U, | |
35b97bb9 SH |
133 | .common = { |
134 | .reg = 0x048, | |
135 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video1-4x", osc24M, | |
136 | &ccu_nm_ops, | |
137 | CLK_SET_RATE_UNGATE), | |
138 | }, | |
139 | }; | |
140 | ||
141 | static const struct clk_hw *pll_video1_4x_hws[] = { | |
142 | &pll_video1_4x_clk.common.hw | |
143 | }; | |
144 | static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x", | |
145 | pll_video1_4x_hws, 2, 1, CLK_SET_RATE_PARENT); | |
146 | static CLK_FIXED_FACTOR_HWS(pll_video1_clk, "pll-video1", | |
147 | pll_video1_4x_hws, 4, 1, CLK_SET_RATE_PARENT); | |
148 | ||
149 | #define SUN20I_D1_PLL_VE_REG 0x058 | |
150 | static struct ccu_nkmp pll_ve_clk = { | |
151 | .enable = BIT(27), | |
152 | .lock = BIT(28), | |
153 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
154 | .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ | |
155 | .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ | |
156 | .common = { | |
157 | .reg = 0x058, | |
158 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M, | |
159 | &ccu_nkmp_ops, | |
160 | CLK_SET_RATE_UNGATE), | |
161 | }, | |
162 | }; | |
163 | ||
164 | /* | |
165 | * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors. | |
166 | * Since we only need one frequency from this PLL (22.5792 x 4 == 90.3168 MHz), | |
167 | * ignore them for now. Enforce the default for them, which is m1 = 0, m0 = 0. | |
168 | * The M factor must be an even number to produce a 50% duty cycle output. | |
169 | */ | |
170 | #define SUN20I_D1_PLL_AUDIO0_REG 0x078 | |
171 | static struct ccu_sdm_setting pll_audio0_sdm_table[] = { | |
172 | { .rate = 90316800, .pattern = 0xc001288d, .m = 6, .n = 22 }, | |
173 | }; | |
174 | ||
175 | static struct ccu_nm pll_audio0_4x_clk = { | |
176 | .enable = BIT(27), | |
177 | .lock = BIT(28), | |
178 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
179 | .m = _SUNXI_CCU_DIV(16, 6), | |
180 | .sdm = _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24), | |
181 | 0x178, BIT(31)), | |
3930624c SH |
182 | .min_rate = 180000000U, |
183 | .max_rate = 3000000000U, | |
35b97bb9 SH |
184 | .common = { |
185 | .reg = 0x078, | |
186 | .features = CCU_FEATURE_SIGMA_DELTA_MOD, | |
187 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x", osc24M, | |
188 | &ccu_nm_ops, | |
189 | CLK_SET_RATE_UNGATE), | |
190 | }, | |
191 | }; | |
192 | ||
193 | static const struct clk_hw *pll_audio0_4x_hws[] = { | |
194 | &pll_audio0_4x_clk.common.hw | |
195 | }; | |
196 | static CLK_FIXED_FACTOR_HWS(pll_audio0_2x_clk, "pll-audio0-2x", | |
197 | pll_audio0_4x_hws, 2, 1, 0); | |
198 | static CLK_FIXED_FACTOR_HWS(pll_audio0_clk, "pll-audio0", | |
199 | pll_audio0_4x_hws, 4, 1, 0); | |
200 | ||
201 | /* | |
202 | * PLL_AUDIO1 doesn't need Fractional-N. The output is usually 614.4 MHz for | |
203 | * audio. The ADC or DAC should divide the PLL output further to 24.576 MHz. | |
204 | */ | |
205 | #define SUN20I_D1_PLL_AUDIO1_REG 0x080 | |
206 | static struct ccu_nm pll_audio1_clk = { | |
207 | .enable = BIT(27), | |
208 | .lock = BIT(28), | |
209 | .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), | |
210 | .m = _SUNXI_CCU_DIV(1, 1), | |
3930624c SH |
211 | .min_rate = 180000000U, |
212 | .max_rate = 3000000000U, | |
35b97bb9 SH |
213 | .common = { |
214 | .reg = 0x080, | |
215 | .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio1", osc24M, | |
216 | &ccu_nm_ops, | |
217 | CLK_SET_RATE_UNGATE), | |
218 | }, | |
219 | }; | |
220 | ||
221 | static const struct clk_hw *pll_audio1_hws[] = { | |
222 | &pll_audio1_clk.common.hw | |
223 | }; | |
224 | static SUNXI_CCU_M_HWS(pll_audio1_div2_clk, "pll-audio1-div2", | |
225 | pll_audio1_hws, 0x080, 16, 3, 0); | |
226 | static SUNXI_CCU_M_HWS(pll_audio1_div5_clk, "pll-audio1-div5", | |
227 | pll_audio1_hws, 0x080, 20, 3, 0); | |
228 | ||
229 | /* | |
230 | * The CPUX gate is not modelled - it is in a separate register (0x504) | |
231 | * and has a special key field. The clock does not need to be ungated anyway. | |
232 | */ | |
233 | static const struct clk_parent_data cpux_parents[] = { | |
234 | { .fw_name = "hosc" }, | |
235 | { .fw_name = "losc" }, | |
236 | { .fw_name = "iosc" }, | |
237 | { .hw = &pll_cpux_clk.common.hw }, | |
238 | { .hw = &pll_periph0_clk.hw }, | |
239 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
240 | { .hw = &pll_periph0_800M_clk.common.hw }, | |
241 | }; | |
242 | static SUNXI_CCU_MUX_DATA(cpux_clk, "cpux", cpux_parents, | |
6ec1c73f | 243 | 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); |
35b97bb9 SH |
244 | |
245 | static const struct clk_hw *cpux_hws[] = { &cpux_clk.common.hw }; | |
246 | static SUNXI_CCU_M_HWS(cpux_axi_clk, "cpux-axi", | |
247 | cpux_hws, 0x500, 0, 2, 0); | |
248 | static SUNXI_CCU_M_HWS(cpux_apb_clk, "cpux-apb", | |
249 | cpux_hws, 0x500, 8, 2, 0); | |
250 | ||
251 | static const struct clk_parent_data psi_ahb_parents[] = { | |
252 | { .fw_name = "hosc" }, | |
253 | { .fw_name = "losc" }, | |
254 | { .fw_name = "iosc" }, | |
255 | { .hw = &pll_periph0_clk.hw }, | |
256 | }; | |
257 | static SUNXI_CCU_MP_DATA_WITH_MUX(psi_ahb_clk, "psi-ahb", psi_ahb_parents, 0x510, | |
258 | 0, 2, /* M */ | |
259 | 8, 2, /* P */ | |
260 | 24, 2, /* mux */ | |
261 | 0); | |
262 | ||
263 | static const struct clk_parent_data apb0_apb1_parents[] = { | |
264 | { .fw_name = "hosc" }, | |
265 | { .fw_name = "losc" }, | |
266 | { .hw = &psi_ahb_clk.common.hw }, | |
267 | { .hw = &pll_periph0_clk.hw }, | |
268 | }; | |
269 | static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", apb0_apb1_parents, 0x520, | |
270 | 0, 5, /* M */ | |
271 | 8, 2, /* P */ | |
272 | 24, 2, /* mux */ | |
273 | 0); | |
274 | ||
275 | static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", apb0_apb1_parents, 0x524, | |
276 | 0, 5, /* M */ | |
277 | 8, 2, /* P */ | |
278 | 24, 2, /* mux */ | |
279 | 0); | |
280 | ||
281 | static const struct clk_hw *psi_ahb_hws[] = { &psi_ahb_clk.common.hw }; | |
282 | static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw }; | |
283 | static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw }; | |
284 | ||
285 | static const struct clk_hw *de_di_g2d_parents[] = { | |
286 | &pll_periph0_2x_clk.common.hw, | |
287 | &pll_video0_4x_clk.common.hw, | |
288 | &pll_video1_4x_clk.common.hw, | |
289 | &pll_audio1_div2_clk.common.hw, | |
290 | }; | |
291 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_di_g2d_parents, 0x600, | |
292 | 0, 5, /* M */ | |
293 | 24, 3, /* mux */ | |
294 | BIT(31), /* gate */ | |
295 | CLK_SET_RATE_PARENT); | |
296 | ||
297 | static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", psi_ahb_hws, | |
298 | 0x60c, BIT(0), 0); | |
299 | ||
300 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", de_di_g2d_parents, 0x620, | |
301 | 0, 5, /* M */ | |
302 | 24, 3, /* mux */ | |
303 | BIT(31), /* gate */ | |
304 | CLK_SET_RATE_PARENT); | |
305 | ||
306 | static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", psi_ahb_hws, | |
307 | 0x62c, BIT(0), 0); | |
308 | ||
309 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_di_g2d_parents, 0x630, | |
310 | 0, 5, /* M */ | |
311 | 24, 3, /* mux */ | |
312 | BIT(31), /* gate */ | |
313 | 0); | |
314 | ||
315 | static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", psi_ahb_hws, | |
316 | 0x63c, BIT(0), 0); | |
317 | ||
318 | static const struct clk_parent_data ce_parents[] = { | |
319 | { .fw_name = "hosc" }, | |
320 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
321 | { .hw = &pll_periph0_clk.hw }, | |
322 | }; | |
323 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, | |
324 | 0, 4, /* M */ | |
325 | 8, 2, /* P */ | |
326 | 24, 3, /* mux */ | |
327 | BIT(31), /* gate */ | |
328 | 0); | |
329 | ||
330 | static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", psi_ahb_hws, | |
331 | 0x68c, BIT(0), 0); | |
332 | ||
333 | static const struct clk_hw *ve_parents[] = { | |
334 | &pll_ve_clk.common.hw, | |
335 | &pll_periph0_2x_clk.common.hw, | |
336 | }; | |
337 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, | |
338 | 0, 5, /* M */ | |
339 | 24, 1, /* mux */ | |
340 | BIT(31), /* gate */ | |
341 | CLK_SET_RATE_PARENT); | |
342 | ||
343 | static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", psi_ahb_hws, | |
344 | 0x69c, BIT(0), 0); | |
345 | ||
346 | static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", psi_ahb_hws, | |
347 | 0x70c, BIT(0), 0); | |
348 | ||
349 | static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", psi_ahb_hws, | |
350 | 0x71c, BIT(0), 0); | |
351 | static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", psi_ahb_hws, | |
352 | 0x71c, BIT(1), 0); | |
353 | static SUNXI_CCU_GATE_HWS(bus_msgbox2_clk, "bus-msgbox2", psi_ahb_hws, | |
354 | 0x71c, BIT(2), 0); | |
355 | ||
356 | static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", psi_ahb_hws, | |
357 | 0x72c, BIT(0), 0); | |
358 | ||
359 | static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", psi_ahb_hws, | |
360 | 0x73c, BIT(0), 0); | |
361 | ||
362 | static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M, | |
363 | 0x740, BIT(31), 0); | |
364 | ||
365 | static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", psi_ahb_hws, | |
366 | 0x78c, BIT(0), 0); | |
367 | ||
368 | static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws, | |
369 | 0x7ac, BIT(0), 0); | |
370 | ||
371 | static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, | |
372 | 0x7bc, BIT(0), 0); | |
373 | ||
374 | static const struct clk_hw *dram_parents[] = { | |
375 | &pll_ddr0_clk.common.hw, | |
376 | &pll_audio1_div2_clk.common.hw, | |
377 | &pll_periph0_2x_clk.common.hw, | |
378 | &pll_periph0_800M_clk.common.hw, | |
379 | }; | |
380 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800, | |
381 | 0, 2, /* M */ | |
382 | 8, 2, /* P */ | |
383 | 24, 2, /* mux */ | |
384 | BIT(31), CLK_IS_CRITICAL); | |
385 | ||
386 | static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus", | |
387 | &dram_clk.common.hw, 4, 1, 0); | |
388 | ||
389 | static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw }; | |
390 | ||
391 | static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws, | |
392 | 0x804, BIT(0), 0); | |
393 | static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws, | |
394 | 0x804, BIT(1), 0); | |
395 | static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws, | |
396 | 0x804, BIT(2), 0); | |
397 | static SUNXI_CCU_GATE_HWS(mbus_tvin_clk, "mbus-tvin", mbus_hws, | |
398 | 0x804, BIT(7), 0); | |
399 | static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws, | |
400 | 0x804, BIT(8), 0); | |
401 | static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws, | |
402 | 0x804, BIT(10), 0); | |
403 | static SUNXI_CCU_GATE_HWS(mbus_riscv_clk, "mbus-riscv", mbus_hws, | |
404 | 0x804, BIT(11), 0); | |
405 | ||
406 | static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", psi_ahb_hws, | |
407 | 0x80c, BIT(0), CLK_IS_CRITICAL); | |
408 | ||
409 | static const struct clk_parent_data mmc0_mmc1_parents[] = { | |
410 | { .fw_name = "hosc" }, | |
411 | { .hw = &pll_periph0_clk.hw }, | |
412 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
413 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
414 | }; | |
415 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830, | |
416 | 0, 4, /* M */ | |
417 | 8, 2, /* P */ | |
418 | 24, 3, /* mux */ | |
419 | BIT(31), /* gate */ | |
420 | 0); | |
421 | ||
422 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834, | |
423 | 0, 4, /* M */ | |
424 | 8, 2, /* P */ | |
425 | 24, 3, /* mux */ | |
426 | BIT(31), /* gate */ | |
427 | 0); | |
428 | ||
429 | static const struct clk_parent_data mmc2_parents[] = { | |
430 | { .fw_name = "hosc" }, | |
431 | { .hw = &pll_periph0_clk.hw }, | |
432 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
433 | { .hw = &pll_periph0_800M_clk.common.hw }, | |
434 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
435 | }; | |
436 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838, | |
437 | 0, 4, /* M */ | |
438 | 8, 2, /* P */ | |
439 | 24, 3, /* mux */ | |
440 | BIT(31), /* gate */ | |
441 | 0); | |
442 | ||
443 | static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", psi_ahb_hws, | |
444 | 0x84c, BIT(0), 0); | |
445 | static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", psi_ahb_hws, | |
446 | 0x84c, BIT(1), 0); | |
447 | static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", psi_ahb_hws, | |
448 | 0x84c, BIT(2), 0); | |
449 | ||
450 | static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, | |
451 | 0x90c, BIT(0), 0); | |
452 | static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, | |
453 | 0x90c, BIT(1), 0); | |
454 | static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, | |
455 | 0x90c, BIT(2), 0); | |
456 | static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, | |
457 | 0x90c, BIT(3), 0); | |
458 | static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, | |
459 | 0x90c, BIT(4), 0); | |
460 | static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, | |
461 | 0x90c, BIT(5), 0); | |
462 | ||
463 | static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, | |
464 | 0x91c, BIT(0), 0); | |
465 | static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, | |
466 | 0x91c, BIT(1), 0); | |
467 | static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, | |
468 | 0x91c, BIT(2), 0); | |
469 | static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, | |
470 | 0x91c, BIT(3), 0); | |
471 | ||
e6f2ffea FP |
472 | static SUNXI_CCU_GATE_HWS(bus_can0_clk, "bus-can0", apb1_hws, |
473 | 0x92c, BIT(0), 0); | |
474 | static SUNXI_CCU_GATE_HWS(bus_can1_clk, "bus-can1", apb1_hws, | |
475 | 0x92c, BIT(1), 0); | |
476 | ||
35b97bb9 SH |
477 | static const struct clk_parent_data spi_parents[] = { |
478 | { .fw_name = "hosc" }, | |
479 | { .hw = &pll_periph0_clk.hw }, | |
480 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
481 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
482 | { .hw = &pll_audio1_div5_clk.common.hw }, | |
483 | }; | |
484 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940, | |
485 | 0, 4, /* M */ | |
486 | 8, 2, /* P */ | |
487 | 24, 3, /* mux */ | |
488 | BIT(31), /* gate */ | |
489 | 0); | |
490 | ||
491 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944, | |
492 | 0, 4, /* M */ | |
493 | 8, 2, /* P */ | |
494 | 24, 3, /* mux */ | |
495 | BIT(31), /* gate */ | |
496 | 0); | |
497 | ||
498 | static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", psi_ahb_hws, | |
499 | 0x96c, BIT(0), 0); | |
500 | static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", psi_ahb_hws, | |
501 | 0x96c, BIT(1), 0); | |
502 | ||
503 | static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph0_hws, | |
504 | 0x970, BIT(31) | BIT(30), 24, 0); | |
505 | ||
506 | static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", psi_ahb_hws, | |
507 | 0x97c, BIT(0), 0); | |
508 | ||
509 | static const struct clk_parent_data ir_tx_ledc_parents[] = { | |
510 | { .fw_name = "hosc" }, | |
511 | { .hw = &pll_periph0_clk.hw }, | |
512 | }; | |
513 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_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_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, | |
521 | 0x9cc, BIT(0), 0); | |
522 | ||
523 | static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws, | |
524 | 0x9ec, BIT(0), 0); | |
525 | ||
526 | static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, | |
527 | 0x9fc, BIT(0), 0); | |
528 | ||
529 | static const struct clk_hw *i2s_spdif_tx_parents[] = { | |
530 | &pll_audio0_clk.hw, | |
531 | &pll_audio0_4x_clk.common.hw, | |
532 | &pll_audio1_div2_clk.common.hw, | |
533 | &pll_audio1_div5_clk.common.hw, | |
534 | }; | |
535 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", i2s_spdif_tx_parents, 0xa10, | |
536 | 0, 5, /* M */ | |
537 | 8, 2, /* P */ | |
538 | 24, 3, /* mux */ | |
539 | BIT(31), /* gate */ | |
540 | 0); | |
541 | ||
542 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", i2s_spdif_tx_parents, 0xa14, | |
543 | 0, 5, /* M */ | |
544 | 8, 2, /* P */ | |
545 | 24, 3, /* mux */ | |
546 | BIT(31), /* gate */ | |
547 | 0); | |
548 | ||
549 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s2_clk, "i2s2", i2s_spdif_tx_parents, 0xa18, | |
550 | 0, 5, /* M */ | |
551 | 8, 2, /* P */ | |
552 | 24, 3, /* mux */ | |
553 | BIT(31), /* gate */ | |
554 | 0); | |
555 | ||
556 | static const struct clk_hw *i2s2_asrc_parents[] = { | |
557 | &pll_audio0_4x_clk.common.hw, | |
558 | &pll_periph0_clk.hw, | |
559 | &pll_audio1_div2_clk.common.hw, | |
560 | &pll_audio1_div5_clk.common.hw, | |
561 | }; | |
562 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s2_asrc_clk, "i2s2-asrc", i2s2_asrc_parents, 0xa1c, | |
563 | 0, 5, /* M */ | |
564 | 8, 2, /* P */ | |
565 | 24, 3, /* mux */ | |
566 | BIT(31), /* gate */ | |
567 | 0); | |
568 | ||
569 | static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", apb0_hws, | |
570 | 0xa20, BIT(0), 0); | |
571 | static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", apb0_hws, | |
572 | 0xa20, BIT(1), 0); | |
573 | static SUNXI_CCU_GATE_HWS(bus_i2s2_clk, "bus-i2s2", apb0_hws, | |
574 | 0xa20, BIT(2), 0); | |
575 | ||
576 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(spdif_tx_clk, "spdif-tx", i2s_spdif_tx_parents, 0xa24, | |
577 | 0, 5, /* M */ | |
578 | 8, 2, /* P */ | |
579 | 24, 3, /* mux */ | |
580 | BIT(31), /* gate */ | |
581 | 0); | |
582 | ||
583 | static const struct clk_hw *spdif_rx_parents[] = { | |
584 | &pll_periph0_clk.hw, | |
585 | &pll_audio1_div2_clk.common.hw, | |
586 | &pll_audio1_div5_clk.common.hw, | |
587 | }; | |
588 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(spdif_rx_clk, "spdif-rx", spdif_rx_parents, 0xa28, | |
589 | 0, 5, /* M */ | |
590 | 8, 2, /* P */ | |
591 | 24, 3, /* mux */ | |
592 | BIT(31), /* gate */ | |
593 | 0); | |
594 | ||
595 | static SUNXI_CCU_GATE_HWS(bus_spdif_clk, "bus-spdif", apb0_hws, | |
596 | 0xa2c, BIT(0), 0); | |
597 | ||
598 | static const struct clk_hw *dmic_codec_parents[] = { | |
599 | &pll_audio0_clk.hw, | |
600 | &pll_audio1_div2_clk.common.hw, | |
601 | &pll_audio1_div5_clk.common.hw, | |
602 | }; | |
603 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dmic_clk, "dmic", dmic_codec_parents, 0xa40, | |
604 | 0, 5, /* M */ | |
605 | 8, 2, /* P */ | |
606 | 24, 3, /* mux */ | |
607 | BIT(31), /* gate */ | |
608 | 0); | |
609 | ||
610 | static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", apb0_hws, | |
611 | 0xa4c, BIT(0), 0); | |
612 | ||
613 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(audio_dac_clk, "audio-dac", dmic_codec_parents, 0xa50, | |
614 | 0, 5, /* M */ | |
615 | 8, 2, /* P */ | |
616 | 24, 3, /* mux */ | |
617 | BIT(31), /* gate */ | |
618 | 0); | |
619 | ||
620 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(audio_adc_clk, "audio-adc", dmic_codec_parents, 0xa54, | |
621 | 0, 5, /* M */ | |
622 | 8, 2, /* P */ | |
623 | 24, 3, /* mux */ | |
624 | BIT(31), /* gate */ | |
625 | 0); | |
626 | ||
627 | static SUNXI_CCU_GATE_HWS(bus_audio_clk, "bus-audio", apb0_hws, | |
628 | 0xa5c, BIT(0), 0); | |
629 | ||
630 | ||
631 | /* | |
632 | * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is | |
633 | * a 2x multiplier from osc24M synchronized by pll-periph0, and is also used by | |
634 | * the OHCI module. | |
635 | */ | |
636 | static const struct clk_parent_data usb_ohci_parents[] = { | |
637 | { .hw = &pll_periph0_clk.hw }, | |
638 | { .fw_name = "hosc" }, | |
639 | { .fw_name = "losc" }, | |
640 | }; | |
641 | static const struct ccu_mux_fixed_prediv usb_ohci_predivs[] = { | |
642 | { .index = 0, .div = 50 }, | |
643 | { .index = 1, .div = 2 }, | |
644 | }; | |
645 | ||
646 | static struct ccu_mux usb_ohci0_clk = { | |
647 | .enable = BIT(31), | |
648 | .mux = { | |
649 | .shift = 24, | |
650 | .width = 2, | |
651 | .fixed_predivs = usb_ohci_predivs, | |
652 | .n_predivs = ARRAY_SIZE(usb_ohci_predivs), | |
653 | }, | |
654 | .common = { | |
655 | .reg = 0xa70, | |
656 | .features = CCU_FEATURE_FIXED_PREDIV, | |
657 | .hw.init = CLK_HW_INIT_PARENTS_DATA("usb-ohci0", | |
658 | usb_ohci_parents, | |
659 | &ccu_mux_ops, | |
660 | 0), | |
661 | }, | |
662 | }; | |
663 | ||
664 | static struct ccu_mux usb_ohci1_clk = { | |
665 | .enable = BIT(31), | |
666 | .mux = { | |
667 | .shift = 24, | |
668 | .width = 2, | |
669 | .fixed_predivs = usb_ohci_predivs, | |
670 | .n_predivs = ARRAY_SIZE(usb_ohci_predivs), | |
671 | }, | |
672 | .common = { | |
673 | .reg = 0xa74, | |
674 | .features = CCU_FEATURE_FIXED_PREDIV, | |
675 | .hw.init = CLK_HW_INIT_PARENTS_DATA("usb-ohci1", | |
676 | usb_ohci_parents, | |
677 | &ccu_mux_ops, | |
678 | 0), | |
679 | }, | |
680 | }; | |
681 | ||
682 | static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", psi_ahb_hws, | |
683 | 0xa8c, BIT(0), 0); | |
684 | static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", psi_ahb_hws, | |
685 | 0xa8c, BIT(1), 0); | |
686 | static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", psi_ahb_hws, | |
687 | 0xa8c, BIT(4), 0); | |
688 | static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", psi_ahb_hws, | |
689 | 0xa8c, BIT(5), 0); | |
690 | static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", psi_ahb_hws, | |
691 | 0xa8c, BIT(8), 0); | |
692 | ||
693 | static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, | |
694 | 0xa9c, BIT(0), 0); | |
695 | ||
696 | static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", psi_ahb_hws, | |
697 | 0xabc, BIT(0), 0); | |
698 | ||
699 | static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, | |
700 | 0xb04, BIT(31), 0); | |
701 | ||
702 | static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k", | |
703 | pll_periph0_2x_hws, | |
704 | 0xb10, BIT(30), 36621, 0); | |
705 | ||
706 | static const struct clk_parent_data hdmi_cec_parents[] = { | |
707 | { .fw_name = "losc" }, | |
708 | { .hw = &hdmi_cec_32k_clk.common.hw }, | |
709 | }; | |
710 | static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents, 0xb10, | |
711 | 24, 1, /* mux */ | |
712 | BIT(31), /* gate */ | |
713 | 0); | |
714 | ||
715 | static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", psi_ahb_hws, | |
716 | 0xb1c, BIT(0), 0); | |
717 | ||
718 | static const struct clk_parent_data mipi_dsi_parents[] = { | |
719 | { .fw_name = "hosc" }, | |
720 | { .hw = &pll_periph0_clk.hw }, | |
721 | { .hw = &pll_video0_2x_clk.hw }, | |
722 | { .hw = &pll_video1_2x_clk.hw }, | |
723 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
724 | }; | |
725 | static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24, | |
726 | 0, 4, /* M */ | |
727 | 24, 3, /* mux */ | |
728 | BIT(31), /* gate */ | |
729 | CLK_SET_RATE_PARENT); | |
730 | ||
731 | static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", psi_ahb_hws, | |
732 | 0xb4c, BIT(0), 0); | |
733 | ||
734 | static const struct clk_hw *tcon_tve_parents[] = { | |
735 | &pll_video0_clk.hw, | |
736 | &pll_video0_4x_clk.common.hw, | |
737 | &pll_video1_clk.hw, | |
738 | &pll_video1_4x_clk.common.hw, | |
739 | &pll_periph0_2x_clk.common.hw, | |
740 | &pll_audio1_div2_clk.common.hw, | |
741 | }; | |
742 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_tve_parents, 0xb60, | |
743 | 0, 4, /* M */ | |
744 | 8, 2, /* P */ | |
745 | 24, 3, /* mux */ | |
746 | BIT(31), /* gate */ | |
747 | CLK_SET_RATE_PARENT); | |
748 | ||
749 | static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", psi_ahb_hws, | |
750 | 0xb7c, BIT(0), 0); | |
751 | ||
752 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_tv_clk, "tcon-tv", tcon_tve_parents, 0xb80, | |
753 | 0, 4, /* M */ | |
754 | 8, 2, /* P */ | |
755 | 24, 3, /* mux */ | |
756 | BIT(31), /* gate */ | |
757 | CLK_SET_RATE_PARENT); | |
758 | ||
759 | static SUNXI_CCU_GATE_HWS(bus_tcon_tv_clk, "bus-tcon-tv", psi_ahb_hws, | |
760 | 0xb9c, BIT(0), 0); | |
761 | ||
762 | static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tve_clk, "tve", tcon_tve_parents, 0xbb0, | |
763 | 0, 4, /* M */ | |
764 | 8, 2, /* P */ | |
765 | 24, 3, /* mux */ | |
766 | BIT(31), /* gate */ | |
767 | 0); | |
768 | ||
769 | static SUNXI_CCU_GATE_HWS(bus_tve_top_clk, "bus-tve-top", psi_ahb_hws, | |
770 | 0xbbc, BIT(0), 0); | |
771 | static SUNXI_CCU_GATE_HWS(bus_tve_clk, "bus-tve", psi_ahb_hws, | |
772 | 0xbbc, BIT(1), 0); | |
773 | ||
774 | static const struct clk_parent_data tvd_parents[] = { | |
775 | { .fw_name = "hosc" }, | |
776 | { .hw = &pll_video0_clk.hw }, | |
777 | { .hw = &pll_video1_clk.hw }, | |
778 | { .hw = &pll_periph0_clk.hw }, | |
779 | }; | |
780 | static SUNXI_CCU_M_DATA_WITH_MUX_GATE(tvd_clk, "tvd", tvd_parents, 0xbc0, | |
781 | 0, 5, /* M */ | |
782 | 24, 3, /* mux */ | |
783 | BIT(31), /* gate */ | |
784 | 0); | |
785 | ||
786 | static SUNXI_CCU_GATE_HWS(bus_tvd_top_clk, "bus-tvd-top", psi_ahb_hws, | |
787 | 0xbdc, BIT(0), 0); | |
788 | static SUNXI_CCU_GATE_HWS(bus_tvd_clk, "bus-tvd", psi_ahb_hws, | |
789 | 0xbdc, BIT(1), 0); | |
790 | ||
791 | static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents, 0xbf0, | |
792 | 0, 4, /* M */ | |
793 | 8, 2, /* P */ | |
794 | 24, 1, /* mux */ | |
795 | BIT(31), /* gate */ | |
796 | 0); | |
797 | ||
798 | static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", psi_ahb_hws, | |
799 | 0xbfc, BIT(0), 0); | |
800 | ||
801 | static const struct clk_hw *csi_top_parents[] = { | |
802 | &pll_periph0_2x_clk.common.hw, | |
803 | &pll_video0_2x_clk.hw, | |
804 | &pll_video1_2x_clk.hw, | |
805 | }; | |
806 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04, | |
807 | 0, 4, /* M */ | |
808 | 24, 3, /* mux */ | |
809 | BIT(31), /* gate */ | |
810 | 0); | |
811 | ||
812 | static const struct clk_parent_data csi_mclk_parents[] = { | |
813 | { .fw_name = "hosc" }, | |
814 | { .hw = &pll_periph0_clk.hw }, | |
815 | { .hw = &pll_video0_clk.hw }, | |
816 | { .hw = &pll_video1_clk.hw }, | |
817 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
818 | { .hw = &pll_audio1_div5_clk.common.hw }, | |
819 | }; | |
820 | static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, 0xc08, | |
821 | 0, 5, /* M */ | |
822 | 24, 3, /* mux */ | |
823 | BIT(31), /* gate */ | |
824 | 0); | |
825 | ||
826 | static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", psi_ahb_hws, | |
827 | 0xc1c, BIT(0), 0); | |
828 | ||
829 | static const struct clk_parent_data tpadc_parents[] = { | |
830 | { .fw_name = "hosc" }, | |
831 | { .hw = &pll_audio0_clk.hw }, | |
832 | }; | |
833 | static SUNXI_CCU_MUX_DATA_WITH_GATE(tpadc_clk, "tpadc", tpadc_parents, 0xc50, | |
834 | 24, 3, /* mux */ | |
835 | BIT(31), /* gate */ | |
836 | 0); | |
837 | ||
838 | static SUNXI_CCU_GATE_HWS(bus_tpadc_clk, "bus-tpadc", apb0_hws, | |
839 | 0xc5c, BIT(0), 0); | |
840 | ||
841 | static SUNXI_CCU_GATE_HWS(bus_tzma_clk, "bus-tzma", apb0_hws, | |
842 | 0xc6c, BIT(0), 0); | |
843 | ||
844 | static const struct clk_parent_data dsp_parents[] = { | |
845 | { .fw_name = "hosc" }, | |
846 | { .fw_name = "losc" }, | |
847 | { .fw_name = "iosc" }, | |
848 | { .hw = &pll_periph0_2x_clk.common.hw }, | |
849 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
850 | }; | |
851 | static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70, | |
852 | 0, 5, /* M */ | |
853 | 24, 3, /* mux */ | |
854 | BIT(31), /* gate */ | |
855 | 0); | |
856 | ||
857 | static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", psi_ahb_hws, | |
858 | 0xc7c, BIT(1), 0); | |
859 | ||
860 | /* | |
861 | * The RISC-V gate is not modelled - it is in a separate register (0xd04) | |
862 | * and has a special key field. The clock is critical anyway. | |
863 | */ | |
864 | static const struct clk_parent_data riscv_parents[] = { | |
865 | { .fw_name = "hosc" }, | |
866 | { .fw_name = "losc" }, | |
867 | { .fw_name = "iosc" }, | |
868 | { .hw = &pll_periph0_800M_clk.common.hw }, | |
869 | { .hw = &pll_periph0_clk.hw }, | |
870 | { .hw = &pll_cpux_clk.common.hw }, | |
871 | { .hw = &pll_audio1_div2_clk.common.hw }, | |
872 | }; | |
873 | static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv", riscv_parents, 0xd00, | |
874 | 0, 5, /* M */ | |
875 | 24, 3, /* mux */ | |
876 | CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); | |
877 | ||
878 | /* The riscv-axi clk must be divided by at least 2. */ | |
879 | static struct clk_div_table riscv_axi_table[] = { | |
880 | { .val = 1, .div = 2 }, | |
881 | { .val = 2, .div = 3 }, | |
882 | { .val = 3, .div = 4 }, | |
883 | { /* Sentinel */ } | |
884 | }; | |
885 | static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw, | |
886 | 0xd00, 8, 2, riscv_axi_table, 0); | |
887 | ||
888 | static SUNXI_CCU_GATE_HWS(bus_riscv_cfg_clk, "bus-riscv-cfg", psi_ahb_hws, | |
889 | 0xd0c, BIT(0), CLK_IS_CRITICAL); | |
890 | ||
891 | static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M, | |
892 | 0xf30, BIT(0), 0); | |
893 | static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M, | |
894 | 0xf30, BIT(1), 2, 0); | |
895 | static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph0_2x_hws, | |
896 | 0xf30, BIT(2), 75, 0); | |
897 | static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph0_hws, | |
898 | 0xf30, BIT(3), 24, 0); | |
899 | static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_32k_clk, "fanout-32k", pll_periph0_2x_hws, | |
900 | 0xf30, BIT(4), 36621, 0); | |
901 | ||
902 | /* This clock has a second divider that is not modelled and forced to 0. */ | |
903 | #define SUN20I_D1_FANOUT_27M_REG 0xf34 | |
904 | static const struct clk_hw *fanout_27M_parents[] = { | |
905 | &pll_video0_clk.hw, | |
906 | &pll_video1_clk.hw, | |
907 | }; | |
908 | static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34, | |
909 | 0, 5, /* M */ | |
910 | 24, 2, /* mux */ | |
911 | BIT(31), /* gate */ | |
912 | 0); | |
913 | ||
914 | static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38, | |
915 | 0, 5, /* M */ | |
916 | BIT(31), /* gate */ | |
917 | 0); | |
918 | ||
919 | static const struct clk_hw *fanout_parents[] = { | |
920 | &fanout_32k_clk.common.hw, | |
921 | &fanout_12M_clk.common.hw, | |
922 | &fanout_16M_clk.common.hw, | |
923 | &fanout_24M_clk.common.hw, | |
924 | &fanout_25M_clk.common.hw, | |
925 | &fanout_27M_clk.common.hw, | |
926 | &fanout_pclk_clk.common.hw, | |
927 | }; | |
928 | static SUNXI_CCU_MUX_HW_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c, | |
929 | 0, 3, /* mux */ | |
930 | BIT(21), /* gate */ | |
931 | 0); | |
932 | static SUNXI_CCU_MUX_HW_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c, | |
933 | 3, 3, /* mux */ | |
934 | BIT(22), /* gate */ | |
935 | 0); | |
936 | static SUNXI_CCU_MUX_HW_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c, | |
937 | 6, 3, /* mux */ | |
938 | BIT(23), /* gate */ | |
939 | 0); | |
940 | ||
941 | static struct ccu_common *sun20i_d1_ccu_clks[] = { | |
942 | &pll_cpux_clk.common, | |
943 | &pll_ddr0_clk.common, | |
944 | &pll_periph0_4x_clk.common, | |
945 | &pll_periph0_2x_clk.common, | |
946 | &pll_periph0_800M_clk.common, | |
947 | &pll_video0_4x_clk.common, | |
948 | &pll_video1_4x_clk.common, | |
949 | &pll_ve_clk.common, | |
950 | &pll_audio0_4x_clk.common, | |
951 | &pll_audio1_clk.common, | |
952 | &pll_audio1_div2_clk.common, | |
953 | &pll_audio1_div5_clk.common, | |
954 | &cpux_clk.common, | |
955 | &cpux_axi_clk.common, | |
956 | &cpux_apb_clk.common, | |
957 | &psi_ahb_clk.common, | |
958 | &apb0_clk.common, | |
959 | &apb1_clk.common, | |
960 | &de_clk.common, | |
961 | &bus_de_clk.common, | |
962 | &di_clk.common, | |
963 | &bus_di_clk.common, | |
964 | &g2d_clk.common, | |
965 | &bus_g2d_clk.common, | |
966 | &ce_clk.common, | |
967 | &bus_ce_clk.common, | |
968 | &ve_clk.common, | |
969 | &bus_ve_clk.common, | |
970 | &bus_dma_clk.common, | |
971 | &bus_msgbox0_clk.common, | |
972 | &bus_msgbox1_clk.common, | |
973 | &bus_msgbox2_clk.common, | |
974 | &bus_spinlock_clk.common, | |
975 | &bus_hstimer_clk.common, | |
976 | &avs_clk.common, | |
977 | &bus_dbg_clk.common, | |
978 | &bus_pwm_clk.common, | |
979 | &bus_iommu_clk.common, | |
980 | &dram_clk.common, | |
981 | &mbus_dma_clk.common, | |
982 | &mbus_ve_clk.common, | |
983 | &mbus_ce_clk.common, | |
984 | &mbus_tvin_clk.common, | |
985 | &mbus_csi_clk.common, | |
986 | &mbus_g2d_clk.common, | |
987 | &mbus_riscv_clk.common, | |
988 | &bus_dram_clk.common, | |
989 | &mmc0_clk.common, | |
990 | &mmc1_clk.common, | |
991 | &mmc2_clk.common, | |
992 | &bus_mmc0_clk.common, | |
993 | &bus_mmc1_clk.common, | |
994 | &bus_mmc2_clk.common, | |
995 | &bus_uart0_clk.common, | |
996 | &bus_uart1_clk.common, | |
997 | &bus_uart2_clk.common, | |
998 | &bus_uart3_clk.common, | |
999 | &bus_uart4_clk.common, | |
1000 | &bus_uart5_clk.common, | |
1001 | &bus_i2c0_clk.common, | |
1002 | &bus_i2c1_clk.common, | |
1003 | &bus_i2c2_clk.common, | |
1004 | &bus_i2c3_clk.common, | |
e6f2ffea FP |
1005 | &bus_can0_clk.common, |
1006 | &bus_can1_clk.common, | |
35b97bb9 SH |
1007 | &spi0_clk.common, |
1008 | &spi1_clk.common, | |
1009 | &bus_spi0_clk.common, | |
1010 | &bus_spi1_clk.common, | |
1011 | &emac_25M_clk.common, | |
1012 | &bus_emac_clk.common, | |
1013 | &ir_tx_clk.common, | |
1014 | &bus_ir_tx_clk.common, | |
1015 | &bus_gpadc_clk.common, | |
1016 | &bus_ths_clk.common, | |
1017 | &i2s0_clk.common, | |
1018 | &i2s1_clk.common, | |
1019 | &i2s2_clk.common, | |
1020 | &i2s2_asrc_clk.common, | |
1021 | &bus_i2s0_clk.common, | |
1022 | &bus_i2s1_clk.common, | |
1023 | &bus_i2s2_clk.common, | |
1024 | &spdif_tx_clk.common, | |
1025 | &spdif_rx_clk.common, | |
1026 | &bus_spdif_clk.common, | |
1027 | &dmic_clk.common, | |
1028 | &bus_dmic_clk.common, | |
1029 | &audio_dac_clk.common, | |
1030 | &audio_adc_clk.common, | |
1031 | &bus_audio_clk.common, | |
1032 | &usb_ohci0_clk.common, | |
1033 | &usb_ohci1_clk.common, | |
1034 | &bus_ohci0_clk.common, | |
1035 | &bus_ohci1_clk.common, | |
1036 | &bus_ehci0_clk.common, | |
1037 | &bus_ehci1_clk.common, | |
1038 | &bus_otg_clk.common, | |
1039 | &bus_lradc_clk.common, | |
1040 | &bus_dpss_top_clk.common, | |
1041 | &hdmi_24M_clk.common, | |
1042 | &hdmi_cec_32k_clk.common, | |
1043 | &hdmi_cec_clk.common, | |
1044 | &bus_hdmi_clk.common, | |
1045 | &mipi_dsi_clk.common, | |
1046 | &bus_mipi_dsi_clk.common, | |
1047 | &tcon_lcd0_clk.common, | |
1048 | &bus_tcon_lcd0_clk.common, | |
1049 | &tcon_tv_clk.common, | |
1050 | &bus_tcon_tv_clk.common, | |
1051 | &tve_clk.common, | |
1052 | &bus_tve_top_clk.common, | |
1053 | &bus_tve_clk.common, | |
1054 | &tvd_clk.common, | |
1055 | &bus_tvd_top_clk.common, | |
1056 | &bus_tvd_clk.common, | |
1057 | &ledc_clk.common, | |
1058 | &bus_ledc_clk.common, | |
1059 | &csi_top_clk.common, | |
1060 | &csi_mclk_clk.common, | |
1061 | &bus_csi_clk.common, | |
1062 | &tpadc_clk.common, | |
1063 | &bus_tpadc_clk.common, | |
1064 | &bus_tzma_clk.common, | |
1065 | &dsp_clk.common, | |
1066 | &bus_dsp_cfg_clk.common, | |
1067 | &riscv_clk.common, | |
1068 | &riscv_axi_clk.common, | |
1069 | &bus_riscv_cfg_clk.common, | |
1070 | &fanout_24M_clk.common, | |
1071 | &fanout_12M_clk.common, | |
1072 | &fanout_16M_clk.common, | |
1073 | &fanout_25M_clk.common, | |
1074 | &fanout_32k_clk.common, | |
1075 | &fanout_27M_clk.common, | |
1076 | &fanout_pclk_clk.common, | |
1077 | &fanout0_clk.common, | |
1078 | &fanout1_clk.common, | |
1079 | &fanout2_clk.common, | |
1080 | }; | |
1081 | ||
1082 | static struct clk_hw_onecell_data sun20i_d1_hw_clks = { | |
1083 | .num = CLK_NUMBER, | |
1084 | .hws = { | |
1085 | [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, | |
1086 | [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, | |
1087 | [CLK_PLL_PERIPH0_4X] = &pll_periph0_4x_clk.common.hw, | |
1088 | [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.common.hw, | |
1089 | [CLK_PLL_PERIPH0_800M] = &pll_periph0_800M_clk.common.hw, | |
1090 | [CLK_PLL_PERIPH0] = &pll_periph0_clk.hw, | |
1091 | [CLK_PLL_PERIPH0_DIV3] = &pll_periph0_div3_clk.hw, | |
1092 | [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.common.hw, | |
1093 | [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | |
1094 | [CLK_PLL_VIDEO0] = &pll_video0_clk.hw, | |
1095 | [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.common.hw, | |
1096 | [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | |
1097 | [CLK_PLL_VIDEO1] = &pll_video1_clk.hw, | |
1098 | [CLK_PLL_VE] = &pll_ve_clk.common.hw, | |
1099 | [CLK_PLL_AUDIO0_4X] = &pll_audio0_4x_clk.common.hw, | |
1100 | [CLK_PLL_AUDIO0_2X] = &pll_audio0_2x_clk.hw, | |
1101 | [CLK_PLL_AUDIO0] = &pll_audio0_clk.hw, | |
1102 | [CLK_PLL_AUDIO1] = &pll_audio1_clk.common.hw, | |
1103 | [CLK_PLL_AUDIO1_DIV2] = &pll_audio1_div2_clk.common.hw, | |
1104 | [CLK_PLL_AUDIO1_DIV5] = &pll_audio1_div5_clk.common.hw, | |
1105 | [CLK_CPUX] = &cpux_clk.common.hw, | |
1106 | [CLK_CPUX_AXI] = &cpux_axi_clk.common.hw, | |
1107 | [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, | |
1108 | [CLK_PSI_AHB] = &psi_ahb_clk.common.hw, | |
1109 | [CLK_APB0] = &apb0_clk.common.hw, | |
1110 | [CLK_APB1] = &apb1_clk.common.hw, | |
1111 | [CLK_MBUS] = &mbus_clk.hw, | |
1112 | [CLK_DE] = &de_clk.common.hw, | |
1113 | [CLK_BUS_DE] = &bus_de_clk.common.hw, | |
1114 | [CLK_DI] = &di_clk.common.hw, | |
1115 | [CLK_BUS_DI] = &bus_di_clk.common.hw, | |
1116 | [CLK_G2D] = &g2d_clk.common.hw, | |
1117 | [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, | |
1118 | [CLK_CE] = &ce_clk.common.hw, | |
1119 | [CLK_BUS_CE] = &bus_ce_clk.common.hw, | |
1120 | [CLK_VE] = &ve_clk.common.hw, | |
1121 | [CLK_BUS_VE] = &bus_ve_clk.common.hw, | |
1122 | [CLK_BUS_DMA] = &bus_dma_clk.common.hw, | |
1123 | [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw, | |
1124 | [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw, | |
1125 | [CLK_BUS_MSGBOX2] = &bus_msgbox2_clk.common.hw, | |
1126 | [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, | |
1127 | [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, | |
1128 | [CLK_AVS] = &avs_clk.common.hw, | |
1129 | [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, | |
1130 | [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, | |
1131 | [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, | |
1132 | [CLK_DRAM] = &dram_clk.common.hw, | |
1133 | [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, | |
1134 | [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, | |
1135 | [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, | |
1136 | [CLK_MBUS_TVIN] = &mbus_tvin_clk.common.hw, | |
1137 | [CLK_MBUS_CSI] = &mbus_csi_clk.common.hw, | |
1138 | [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, | |
1139 | [CLK_MBUS_RISCV] = &mbus_riscv_clk.common.hw, | |
1140 | [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, | |
1141 | [CLK_MMC0] = &mmc0_clk.common.hw, | |
1142 | [CLK_MMC1] = &mmc1_clk.common.hw, | |
1143 | [CLK_MMC2] = &mmc2_clk.common.hw, | |
1144 | [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, | |
1145 | [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, | |
1146 | [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, | |
1147 | [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, | |
1148 | [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, | |
1149 | [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, | |
1150 | [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, | |
1151 | [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, | |
1152 | [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, | |
1153 | [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, | |
1154 | [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, | |
1155 | [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, | |
1156 | [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, | |
e6f2ffea FP |
1157 | [CLK_BUS_CAN0] = &bus_can0_clk.common.hw, |
1158 | [CLK_BUS_CAN1] = &bus_can1_clk.common.hw, | |
35b97bb9 SH |
1159 | [CLK_SPI0] = &spi0_clk.common.hw, |
1160 | [CLK_SPI1] = &spi1_clk.common.hw, | |
1161 | [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, | |
1162 | [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, | |
1163 | [CLK_EMAC_25M] = &emac_25M_clk.common.hw, | |
1164 | [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, | |
1165 | [CLK_IR_TX] = &ir_tx_clk.common.hw, | |
1166 | [CLK_BUS_IR_TX] = &bus_ir_tx_clk.common.hw, | |
1167 | [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw, | |
1168 | [CLK_BUS_THS] = &bus_ths_clk.common.hw, | |
1169 | [CLK_I2S0] = &i2s0_clk.common.hw, | |
1170 | [CLK_I2S1] = &i2s1_clk.common.hw, | |
1171 | [CLK_I2S2] = &i2s2_clk.common.hw, | |
1172 | [CLK_I2S2_ASRC] = &i2s2_asrc_clk.common.hw, | |
1173 | [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, | |
1174 | [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, | |
1175 | [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, | |
1176 | [CLK_SPDIF_TX] = &spdif_tx_clk.common.hw, | |
1177 | [CLK_SPDIF_RX] = &spdif_rx_clk.common.hw, | |
1178 | [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, | |
1179 | [CLK_DMIC] = &dmic_clk.common.hw, | |
1180 | [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, | |
1181 | [CLK_AUDIO_DAC] = &audio_dac_clk.common.hw, | |
1182 | [CLK_AUDIO_ADC] = &audio_adc_clk.common.hw, | |
1183 | [CLK_BUS_AUDIO] = &bus_audio_clk.common.hw, | |
1184 | [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | |
1185 | [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | |
1186 | [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, | |
1187 | [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, | |
1188 | [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, | |
1189 | [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, | |
1190 | [CLK_BUS_OTG] = &bus_otg_clk.common.hw, | |
1191 | [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw, | |
1192 | [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw, | |
1193 | [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw, | |
1194 | [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw, | |
1195 | [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw, | |
1196 | [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, | |
1197 | [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw, | |
1198 | [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, | |
1199 | [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw, | |
1200 | [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw, | |
1201 | [CLK_TCON_TV] = &tcon_tv_clk.common.hw, | |
1202 | [CLK_BUS_TCON_TV] = &bus_tcon_tv_clk.common.hw, | |
1203 | [CLK_TVE] = &tve_clk.common.hw, | |
1204 | [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, | |
1205 | [CLK_BUS_TVE] = &bus_tve_clk.common.hw, | |
1206 | [CLK_TVD] = &tvd_clk.common.hw, | |
1207 | [CLK_BUS_TVD_TOP] = &bus_tvd_top_clk.common.hw, | |
1208 | [CLK_BUS_TVD] = &bus_tvd_clk.common.hw, | |
1209 | [CLK_LEDC] = &ledc_clk.common.hw, | |
1210 | [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw, | |
1211 | [CLK_CSI_TOP] = &csi_top_clk.common.hw, | |
1212 | [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, | |
1213 | [CLK_BUS_CSI] = &bus_csi_clk.common.hw, | |
1214 | [CLK_TPADC] = &tpadc_clk.common.hw, | |
1215 | [CLK_BUS_TPADC] = &bus_tpadc_clk.common.hw, | |
1216 | [CLK_BUS_TZMA] = &bus_tzma_clk.common.hw, | |
1217 | [CLK_DSP] = &dsp_clk.common.hw, | |
1218 | [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw, | |
1219 | [CLK_RISCV] = &riscv_clk.common.hw, | |
1220 | [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw, | |
1221 | [CLK_BUS_RISCV_CFG] = &bus_riscv_cfg_clk.common.hw, | |
1222 | [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw, | |
1223 | [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw, | |
1224 | [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw, | |
1225 | [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw, | |
1226 | [CLK_FANOUT_32K] = &fanout_32k_clk.common.hw, | |
1227 | [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw, | |
1228 | [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw, | |
1229 | [CLK_FANOUT0] = &fanout0_clk.common.hw, | |
1230 | [CLK_FANOUT1] = &fanout1_clk.common.hw, | |
1231 | [CLK_FANOUT2] = &fanout2_clk.common.hw, | |
1232 | }, | |
1233 | }; | |
1234 | ||
1235 | static struct ccu_reset_map sun20i_d1_ccu_resets[] = { | |
1236 | [RST_MBUS] = { 0x540, BIT(30) }, | |
1237 | [RST_BUS_DE] = { 0x60c, BIT(16) }, | |
1238 | [RST_BUS_DI] = { 0x62c, BIT(16) }, | |
1239 | [RST_BUS_G2D] = { 0x63c, BIT(16) }, | |
1240 | [RST_BUS_CE] = { 0x68c, BIT(16) }, | |
1241 | [RST_BUS_VE] = { 0x69c, BIT(16) }, | |
1242 | [RST_BUS_DMA] = { 0x70c, BIT(16) }, | |
1243 | [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) }, | |
1244 | [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) }, | |
1245 | [RST_BUS_MSGBOX2] = { 0x71c, BIT(18) }, | |
1246 | [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) }, | |
1247 | [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, | |
1248 | [RST_BUS_DBG] = { 0x78c, BIT(16) }, | |
1249 | [RST_BUS_PWM] = { 0x7ac, BIT(16) }, | |
1250 | [RST_BUS_DRAM] = { 0x80c, BIT(16) }, | |
1251 | [RST_BUS_MMC0] = { 0x84c, BIT(16) }, | |
1252 | [RST_BUS_MMC1] = { 0x84c, BIT(17) }, | |
1253 | [RST_BUS_MMC2] = { 0x84c, BIT(18) }, | |
1254 | [RST_BUS_UART0] = { 0x90c, BIT(16) }, | |
1255 | [RST_BUS_UART1] = { 0x90c, BIT(17) }, | |
1256 | [RST_BUS_UART2] = { 0x90c, BIT(18) }, | |
1257 | [RST_BUS_UART3] = { 0x90c, BIT(19) }, | |
1258 | [RST_BUS_UART4] = { 0x90c, BIT(20) }, | |
1259 | [RST_BUS_UART5] = { 0x90c, BIT(21) }, | |
1260 | [RST_BUS_I2C0] = { 0x91c, BIT(16) }, | |
1261 | [RST_BUS_I2C1] = { 0x91c, BIT(17) }, | |
1262 | [RST_BUS_I2C2] = { 0x91c, BIT(18) }, | |
1263 | [RST_BUS_I2C3] = { 0x91c, BIT(19) }, | |
e6f2ffea FP |
1264 | [RST_BUS_CAN0] = { 0x92c, BIT(16) }, |
1265 | [RST_BUS_CAN1] = { 0x92c, BIT(17) }, | |
35b97bb9 SH |
1266 | [RST_BUS_SPI0] = { 0x96c, BIT(16) }, |
1267 | [RST_BUS_SPI1] = { 0x96c, BIT(17) }, | |
1268 | [RST_BUS_EMAC] = { 0x97c, BIT(16) }, | |
1269 | [RST_BUS_IR_TX] = { 0x9cc, BIT(16) }, | |
1270 | [RST_BUS_GPADC] = { 0x9ec, BIT(16) }, | |
1271 | [RST_BUS_THS] = { 0x9fc, BIT(16) }, | |
1272 | [RST_BUS_I2S0] = { 0xa20, BIT(16) }, | |
1273 | [RST_BUS_I2S1] = { 0xa20, BIT(17) }, | |
1274 | [RST_BUS_I2S2] = { 0xa20, BIT(18) }, | |
1275 | [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, | |
1276 | [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, | |
1277 | [RST_BUS_AUDIO] = { 0xa5c, BIT(16) }, | |
1278 | [RST_USB_PHY0] = { 0xa70, BIT(30) }, | |
1279 | [RST_USB_PHY1] = { 0xa74, BIT(30) }, | |
1280 | [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, | |
1281 | [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, | |
1282 | [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, | |
1283 | [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, | |
1284 | [RST_BUS_OTG] = { 0xa8c, BIT(24) }, | |
1285 | [RST_BUS_LRADC] = { 0xa9c, BIT(16) }, | |
1286 | [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) }, | |
1287 | [RST_BUS_HDMI_MAIN] = { 0xb1c, BIT(16) }, | |
1288 | [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) }, | |
1289 | [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) }, | |
1290 | [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) }, | |
1291 | [RST_BUS_TCON_TV] = { 0xb9c, BIT(16) }, | |
1292 | [RST_BUS_LVDS0] = { 0xbac, BIT(16) }, | |
1293 | [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, | |
1294 | [RST_BUS_TVE] = { 0xbbc, BIT(17) }, | |
1295 | [RST_BUS_TVD_TOP] = { 0xbdc, BIT(16) }, | |
1296 | [RST_BUS_TVD] = { 0xbdc, BIT(17) }, | |
1297 | [RST_BUS_LEDC] = { 0xbfc, BIT(16) }, | |
1298 | [RST_BUS_CSI] = { 0xc1c, BIT(16) }, | |
1299 | [RST_BUS_TPADC] = { 0xc5c, BIT(16) }, | |
1300 | [RST_DSP] = { 0xc7c, BIT(16) }, | |
1301 | [RST_BUS_DSP_CFG] = { 0xc7c, BIT(17) }, | |
1302 | [RST_BUS_DSP_DBG] = { 0xc7c, BIT(18) }, | |
1303 | [RST_BUS_RISCV_CFG] = { 0xd0c, BIT(16) }, | |
1304 | }; | |
1305 | ||
1306 | static const struct sunxi_ccu_desc sun20i_d1_ccu_desc = { | |
1307 | .ccu_clks = sun20i_d1_ccu_clks, | |
1308 | .num_ccu_clks = ARRAY_SIZE(sun20i_d1_ccu_clks), | |
1309 | ||
1310 | .hw_clks = &sun20i_d1_hw_clks, | |
1311 | ||
1312 | .resets = sun20i_d1_ccu_resets, | |
1313 | .num_resets = ARRAY_SIZE(sun20i_d1_ccu_resets), | |
1314 | }; | |
1315 | ||
1316 | static const u32 pll_regs[] = { | |
1317 | SUN20I_D1_PLL_CPUX_REG, | |
1318 | SUN20I_D1_PLL_DDR0_REG, | |
1319 | SUN20I_D1_PLL_PERIPH0_REG, | |
1320 | SUN20I_D1_PLL_VIDEO0_REG, | |
1321 | SUN20I_D1_PLL_VIDEO1_REG, | |
1322 | SUN20I_D1_PLL_VE_REG, | |
1323 | SUN20I_D1_PLL_AUDIO0_REG, | |
1324 | SUN20I_D1_PLL_AUDIO1_REG, | |
1325 | }; | |
1326 | ||
1327 | static const u32 pll_video_regs[] = { | |
1328 | SUN20I_D1_PLL_VIDEO0_REG, | |
1329 | SUN20I_D1_PLL_VIDEO1_REG, | |
1330 | }; | |
1331 | ||
1332 | static struct ccu_mux_nb sun20i_d1_riscv_nb = { | |
1333 | .common = &riscv_clk.common, | |
1334 | .cm = &riscv_clk.mux, | |
1335 | .delay_us = 1, | |
1336 | .bypass_index = 4, /* index of pll-periph0 */ | |
1337 | }; | |
1338 | ||
1339 | static int sun20i_d1_ccu_probe(struct platform_device *pdev) | |
1340 | { | |
1341 | void __iomem *reg; | |
1342 | u32 val; | |
1343 | int i, ret; | |
1344 | ||
1345 | reg = devm_platform_ioremap_resource(pdev, 0); | |
1346 | if (IS_ERR(reg)) | |
1347 | return PTR_ERR(reg); | |
1348 | ||
1349 | /* Enable the enable, LDO, and lock bits on all PLLs. */ | |
1350 | for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { | |
1351 | val = readl(reg + pll_regs[i]); | |
1352 | val |= BIT(31) | BIT(30) | BIT(29); | |
1353 | writel(val, reg + pll_regs[i]); | |
1354 | } | |
1355 | ||
1356 | /* Force PLL_CPUX factor M to 0. */ | |
1357 | val = readl(reg + SUN20I_D1_PLL_CPUX_REG); | |
1358 | val &= ~GENMASK(1, 0); | |
1359 | writel(val, reg + SUN20I_D1_PLL_CPUX_REG); | |
1360 | ||
1361 | /* | |
1362 | * Force the output divider of video PLLs to 0. | |
1363 | * | |
1364 | * See the comment before pll-video0 definition for the reason. | |
1365 | */ | |
1366 | for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { | |
1367 | val = readl(reg + pll_video_regs[i]); | |
1368 | val &= ~BIT(0); | |
1369 | writel(val, reg + pll_video_regs[i]); | |
1370 | } | |
1371 | ||
1372 | /* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */ | |
1373 | val = readl(reg + SUN20I_D1_PLL_AUDIO0_REG); | |
1374 | val &= ~BIT(1) | BIT(0); | |
1375 | writel(val, reg + SUN20I_D1_PLL_AUDIO0_REG); | |
1376 | ||
1377 | /* Force fanout-27M factor N to 0. */ | |
1378 | val = readl(reg + SUN20I_D1_FANOUT_27M_REG); | |
1379 | val &= ~GENMASK(9, 8); | |
1380 | writel(val, reg + SUN20I_D1_FANOUT_27M_REG); | |
1381 | ||
1382 | ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun20i_d1_ccu_desc); | |
1383 | if (ret) | |
1384 | return ret; | |
1385 | ||
1386 | /* Reparent CPU during PLL CPUX rate changes */ | |
1387 | ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, | |
1388 | &sun20i_d1_riscv_nb); | |
1389 | ||
1390 | return 0; | |
1391 | } | |
1392 | ||
1393 | static const struct of_device_id sun20i_d1_ccu_ids[] = { | |
1394 | { .compatible = "allwinner,sun20i-d1-ccu" }, | |
1395 | { } | |
1396 | }; | |
1397 | ||
1398 | static struct platform_driver sun20i_d1_ccu_driver = { | |
1399 | .probe = sun20i_d1_ccu_probe, | |
1400 | .driver = { | |
1401 | .name = "sun20i-d1-ccu", | |
1402 | .suppress_bind_attrs = true, | |
1403 | .of_match_table = sun20i_d1_ccu_ids, | |
1404 | }, | |
1405 | }; | |
1406 | module_platform_driver(sun20i_d1_ccu_driver); | |
1407 | ||
1408 | MODULE_IMPORT_NS(SUNXI_CCU); | |
1409 | MODULE_LICENSE("GPL"); |