1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 huangzhenwei@allwinnertech.com
4 * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
7 #include <linux/clk-provider.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
14 #include "ccu_common.h"
15 #include "ccu_reset.h"
26 #include "ccu-sun20i-d1.h"
28 static const struct clk_parent_data osc24M
[] = {
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.
36 #define SUN20I_D1_PLL_CPUX_REG 0x000
37 static struct ccu_mult pll_cpux_clk
= {
40 .mult
= _SUNXI_CCU_MULT_MIN(8, 8, 12),
43 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-cpux", osc24M
,
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
= {
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 */
59 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M
,
65 #define SUN20I_D1_PLL_PERIPH0_REG 0x020
66 static struct ccu_nm pll_periph0_4x_clk
= {
69 .n
= _SUNXI_CCU_MULT_MIN(8, 8, 12),
70 .m
= _SUNXI_CCU_DIV(1, 1), /* input divider */
73 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x", osc24M
,
79 static const struct clk_hw
*pll_periph0_4x_hws
[] = {
80 &pll_periph0_4x_clk
.common
.hw
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);
87 static const struct clk_hw
*pll_periph0_2x_hws
[] = {
88 &pll_periph0_2x_clk
.common
.hw
90 static CLK_FIXED_FACTOR_HWS(pll_periph0_clk
, "pll-periph0",
91 pll_periph0_2x_hws
, 2, 1, 0);
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);
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.
101 #define SUN20I_D1_PLL_VIDEO0_REG 0x040
102 static struct ccu_nm pll_video0_4x_clk
= {
105 .n
= _SUNXI_CCU_MULT_MIN(8, 8, 12),
106 .m
= _SUNXI_CCU_DIV(1, 1), /* input divider */
107 .min_rate
= 252000000U,
108 .max_rate
= 2400000000U,
111 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-video0-4x", osc24M
,
113 CLK_SET_RATE_UNGATE
),
117 static const struct clk_hw
*pll_video0_4x_hws
[] = {
118 &pll_video0_4x_clk
.common
.hw
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
);
125 #define SUN20I_D1_PLL_VIDEO1_REG 0x048
126 static struct ccu_nm pll_video1_4x_clk
= {
129 .n
= _SUNXI_CCU_MULT_MIN(8, 8, 12),
130 .m
= _SUNXI_CCU_DIV(1, 1), /* input divider */
131 .min_rate
= 252000000U,
132 .max_rate
= 2400000000U,
135 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-video1-4x", osc24M
,
137 CLK_SET_RATE_UNGATE
),
141 static const struct clk_hw
*pll_video1_4x_hws
[] = {
142 &pll_video1_4x_clk
.common
.hw
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
);
149 #define SUN20I_D1_PLL_VE_REG 0x058
150 static struct ccu_nkmp pll_ve_clk
= {
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 */
158 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M
,
160 CLK_SET_RATE_UNGATE
),
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.
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 },
175 static struct ccu_nm pll_audio0_4x_clk
= {
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),
182 .min_rate
= 180000000U,
183 .max_rate
= 3000000000U,
186 .features
= CCU_FEATURE_SIGMA_DELTA_MOD
,
187 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x", osc24M
,
189 CLK_SET_RATE_UNGATE
),
193 static const struct clk_hw
*pll_audio0_4x_hws
[] = {
194 &pll_audio0_4x_clk
.common
.hw
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);
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.
205 #define SUN20I_D1_PLL_AUDIO1_REG 0x080
206 static struct ccu_nm pll_audio1_clk
= {
209 .n
= _SUNXI_CCU_MULT_MIN(8, 8, 12),
210 .m
= _SUNXI_CCU_DIV(1, 1),
211 .min_rate
= 180000000U,
212 .max_rate
= 3000000000U,
215 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("pll-audio1", osc24M
,
217 CLK_SET_RATE_UNGATE
),
221 static const struct clk_hw
*pll_audio1_hws
[] = {
222 &pll_audio1_clk
.common
.hw
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);
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.
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
},
242 static SUNXI_CCU_MUX_DATA(cpux_clk
, "cpux", cpux_parents
,
243 0x500, 24, 3, CLK_SET_RATE_PARENT
| CLK_IS_CRITICAL
);
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);
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
},
257 static SUNXI_CCU_MP_DATA_WITH_MUX(psi_ahb_clk
, "psi-ahb", psi_ahb_parents
, 0x510,
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
},
269 static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk
, "apb0", apb0_apb1_parents
, 0x520,
275 static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk
, "apb1", apb0_apb1_parents
, 0x524,
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
};
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
,
291 static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk
, "de", de_di_g2d_parents
, 0x600,
295 CLK_SET_RATE_PARENT
);
297 static SUNXI_CCU_GATE_HWS(bus_de_clk
, "bus-de", psi_ahb_hws
,
300 static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk
, "di", de_di_g2d_parents
, 0x620,
304 CLK_SET_RATE_PARENT
);
306 static SUNXI_CCU_GATE_HWS(bus_di_clk
, "bus-di", psi_ahb_hws
,
309 static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk
, "g2d", de_di_g2d_parents
, 0x630,
315 static SUNXI_CCU_GATE_HWS(bus_g2d_clk
, "bus-g2d", psi_ahb_hws
,
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
},
323 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ce_clk
, "ce", ce_parents
, 0x680,
330 static SUNXI_CCU_GATE_HWS(bus_ce_clk
, "bus-ce", psi_ahb_hws
,
333 static const struct clk_hw
*ve_parents
[] = {
334 &pll_ve_clk
.common
.hw
,
335 &pll_periph0_2x_clk
.common
.hw
,
337 static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk
, "ve", ve_parents
, 0x690,
341 CLK_SET_RATE_PARENT
);
343 static SUNXI_CCU_GATE_HWS(bus_ve_clk
, "bus-ve", psi_ahb_hws
,
346 static SUNXI_CCU_GATE_HWS(bus_dma_clk
, "bus-dma", psi_ahb_hws
,
349 static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk
, "bus-msgbox0", psi_ahb_hws
,
351 static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk
, "bus-msgbox1", psi_ahb_hws
,
353 static SUNXI_CCU_GATE_HWS(bus_msgbox2_clk
, "bus-msgbox2", psi_ahb_hws
,
356 static SUNXI_CCU_GATE_HWS(bus_spinlock_clk
, "bus-spinlock", psi_ahb_hws
,
359 static SUNXI_CCU_GATE_HWS(bus_hstimer_clk
, "bus-hstimer", psi_ahb_hws
,
362 static SUNXI_CCU_GATE_DATA(avs_clk
, "avs", osc24M
,
365 static SUNXI_CCU_GATE_HWS(bus_dbg_clk
, "bus-dbg", psi_ahb_hws
,
368 static SUNXI_CCU_GATE_HWS(bus_pwm_clk
, "bus-pwm", apb0_hws
,
371 static SUNXI_CCU_GATE_HWS(bus_iommu_clk
, "bus-iommu", apb0_hws
,
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
,
380 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk
, "dram", dram_parents
, 0x800,
384 BIT(31), CLK_IS_CRITICAL
);
386 static CLK_FIXED_FACTOR_HW(mbus_clk
, "mbus",
387 &dram_clk
.common
.hw
, 4, 1, 0);
389 static const struct clk_hw
*mbus_hws
[] = { &mbus_clk
.hw
};
391 static SUNXI_CCU_GATE_HWS(mbus_dma_clk
, "mbus-dma", mbus_hws
,
393 static SUNXI_CCU_GATE_HWS(mbus_ve_clk
, "mbus-ve", mbus_hws
,
395 static SUNXI_CCU_GATE_HWS(mbus_ce_clk
, "mbus-ce", mbus_hws
,
397 static SUNXI_CCU_GATE_HWS(mbus_tvin_clk
, "mbus-tvin", mbus_hws
,
399 static SUNXI_CCU_GATE_HWS(mbus_csi_clk
, "mbus-csi", mbus_hws
,
401 static SUNXI_CCU_GATE_HWS(mbus_g2d_clk
, "mbus-g2d", mbus_hws
,
403 static SUNXI_CCU_GATE_HWS(mbus_riscv_clk
, "mbus-riscv", mbus_hws
,
406 static SUNXI_CCU_GATE_HWS(bus_dram_clk
, "bus-dram", psi_ahb_hws
,
407 0x80c, BIT(0), CLK_IS_CRITICAL
);
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
},
415 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk
, "mmc0", mmc0_mmc1_parents
, 0x830,
422 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk
, "mmc1", mmc0_mmc1_parents
, 0x834,
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
},
436 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk
, "mmc2", mmc2_parents
, 0x838,
443 static SUNXI_CCU_GATE_HWS(bus_mmc0_clk
, "bus-mmc0", psi_ahb_hws
,
445 static SUNXI_CCU_GATE_HWS(bus_mmc1_clk
, "bus-mmc1", psi_ahb_hws
,
447 static SUNXI_CCU_GATE_HWS(bus_mmc2_clk
, "bus-mmc2", psi_ahb_hws
,
450 static SUNXI_CCU_GATE_HWS(bus_uart0_clk
, "bus-uart0", apb1_hws
,
452 static SUNXI_CCU_GATE_HWS(bus_uart1_clk
, "bus-uart1", apb1_hws
,
454 static SUNXI_CCU_GATE_HWS(bus_uart2_clk
, "bus-uart2", apb1_hws
,
456 static SUNXI_CCU_GATE_HWS(bus_uart3_clk
, "bus-uart3", apb1_hws
,
458 static SUNXI_CCU_GATE_HWS(bus_uart4_clk
, "bus-uart4", apb1_hws
,
460 static SUNXI_CCU_GATE_HWS(bus_uart5_clk
, "bus-uart5", apb1_hws
,
463 static SUNXI_CCU_GATE_HWS(bus_i2c0_clk
, "bus-i2c0", apb1_hws
,
465 static SUNXI_CCU_GATE_HWS(bus_i2c1_clk
, "bus-i2c1", apb1_hws
,
467 static SUNXI_CCU_GATE_HWS(bus_i2c2_clk
, "bus-i2c2", apb1_hws
,
469 static SUNXI_CCU_GATE_HWS(bus_i2c3_clk
, "bus-i2c3", apb1_hws
,
472 static SUNXI_CCU_GATE_HWS(bus_can0_clk
, "bus-can0", apb1_hws
,
474 static SUNXI_CCU_GATE_HWS(bus_can1_clk
, "bus-can1", apb1_hws
,
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
},
484 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk
, "spi0", spi_parents
, 0x940,
491 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk
, "spi1", spi_parents
, 0x944,
498 static SUNXI_CCU_GATE_HWS(bus_spi0_clk
, "bus-spi0", psi_ahb_hws
,
500 static SUNXI_CCU_GATE_HWS(bus_spi1_clk
, "bus-spi1", psi_ahb_hws
,
503 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk
, "emac-25M", pll_periph0_hws
,
504 0x970, BIT(31) | BIT(30), 24, 0);
506 static SUNXI_CCU_GATE_HWS(bus_emac_clk
, "bus-emac", psi_ahb_hws
,
509 static const struct clk_parent_data ir_tx_ledc_parents
[] = {
510 { .fw_name
= "hosc" },
511 { .hw
= &pll_periph0_clk
.hw
},
513 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ir_tx_clk
, "ir-tx", ir_tx_ledc_parents
, 0x9c0,
520 static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk
, "bus-ir-tx", apb0_hws
,
523 static SUNXI_CCU_GATE_HWS(bus_gpadc_clk
, "bus-gpadc", apb0_hws
,
526 static SUNXI_CCU_GATE_HWS(bus_ths_clk
, "bus-ths", apb0_hws
,
529 static const struct clk_hw
*i2s_spdif_tx_parents
[] = {
531 &pll_audio0_4x_clk
.common
.hw
,
532 &pll_audio1_div2_clk
.common
.hw
,
533 &pll_audio1_div5_clk
.common
.hw
,
535 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s0_clk
, "i2s0", i2s_spdif_tx_parents
, 0xa10,
542 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s1_clk
, "i2s1", i2s_spdif_tx_parents
, 0xa14,
549 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s2_clk
, "i2s2", i2s_spdif_tx_parents
, 0xa18,
556 static const struct clk_hw
*i2s2_asrc_parents
[] = {
557 &pll_audio0_4x_clk
.common
.hw
,
559 &pll_audio1_div2_clk
.common
.hw
,
560 &pll_audio1_div5_clk
.common
.hw
,
562 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(i2s2_asrc_clk
, "i2s2-asrc", i2s2_asrc_parents
, 0xa1c,
569 static SUNXI_CCU_GATE_HWS(bus_i2s0_clk
, "bus-i2s0", apb0_hws
,
571 static SUNXI_CCU_GATE_HWS(bus_i2s1_clk
, "bus-i2s1", apb0_hws
,
573 static SUNXI_CCU_GATE_HWS(bus_i2s2_clk
, "bus-i2s2", apb0_hws
,
576 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(spdif_tx_clk
, "spdif-tx", i2s_spdif_tx_parents
, 0xa24,
583 static const struct clk_hw
*spdif_rx_parents
[] = {
585 &pll_audio1_div2_clk
.common
.hw
,
586 &pll_audio1_div5_clk
.common
.hw
,
588 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(spdif_rx_clk
, "spdif-rx", spdif_rx_parents
, 0xa28,
595 static SUNXI_CCU_GATE_HWS(bus_spdif_clk
, "bus-spdif", apb0_hws
,
598 static const struct clk_hw
*dmic_codec_parents
[] = {
600 &pll_audio1_div2_clk
.common
.hw
,
601 &pll_audio1_div5_clk
.common
.hw
,
603 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dmic_clk
, "dmic", dmic_codec_parents
, 0xa40,
610 static SUNXI_CCU_GATE_HWS(bus_dmic_clk
, "bus-dmic", apb0_hws
,
613 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(audio_dac_clk
, "audio-dac", dmic_codec_parents
, 0xa50,
620 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(audio_adc_clk
, "audio-adc", dmic_codec_parents
, 0xa54,
627 static SUNXI_CCU_GATE_HWS(bus_audio_clk
, "bus-audio", apb0_hws
,
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
636 static const struct clk_parent_data usb_ohci_parents
[] = {
637 { .hw
= &pll_periph0_clk
.hw
},
638 { .fw_name
= "hosc" },
639 { .fw_name
= "losc" },
641 static const struct ccu_mux_fixed_prediv usb_ohci_predivs
[] = {
642 { .index
= 0, .div
= 50 },
643 { .index
= 1, .div
= 2 },
646 static struct ccu_mux usb_ohci0_clk
= {
651 .fixed_predivs
= usb_ohci_predivs
,
652 .n_predivs
= ARRAY_SIZE(usb_ohci_predivs
),
656 .features
= CCU_FEATURE_FIXED_PREDIV
,
657 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("usb-ohci0",
664 static struct ccu_mux usb_ohci1_clk
= {
669 .fixed_predivs
= usb_ohci_predivs
,
670 .n_predivs
= ARRAY_SIZE(usb_ohci_predivs
),
674 .features
= CCU_FEATURE_FIXED_PREDIV
,
675 .hw
.init
= CLK_HW_INIT_PARENTS_DATA("usb-ohci1",
682 static SUNXI_CCU_GATE_HWS(bus_ohci0_clk
, "bus-ohci0", psi_ahb_hws
,
684 static SUNXI_CCU_GATE_HWS(bus_ohci1_clk
, "bus-ohci1", psi_ahb_hws
,
686 static SUNXI_CCU_GATE_HWS(bus_ehci0_clk
, "bus-ehci0", psi_ahb_hws
,
688 static SUNXI_CCU_GATE_HWS(bus_ehci1_clk
, "bus-ehci1", psi_ahb_hws
,
690 static SUNXI_CCU_GATE_HWS(bus_otg_clk
, "bus-otg", psi_ahb_hws
,
693 static SUNXI_CCU_GATE_HWS(bus_lradc_clk
, "bus-lradc", apb0_hws
,
696 static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk
, "bus-dpss-top", psi_ahb_hws
,
699 static SUNXI_CCU_GATE_DATA(hdmi_24M_clk
, "hdmi-24M", osc24M
,
702 static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk
, "hdmi-cec-32k",
704 0xb10, BIT(30), 36621, 0);
706 static const struct clk_parent_data hdmi_cec_parents
[] = {
707 { .fw_name
= "losc" },
708 { .hw
= &hdmi_cec_32k_clk
.common
.hw
},
710 static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk
, "hdmi-cec", hdmi_cec_parents
, 0xb10,
715 static SUNXI_CCU_GATE_HWS(bus_hdmi_clk
, "bus-hdmi", psi_ahb_hws
,
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
},
725 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk
, "mipi-dsi", mipi_dsi_parents
, 0xb24,
729 CLK_SET_RATE_PARENT
);
731 static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk
, "bus-mipi-dsi", psi_ahb_hws
,
734 static const struct clk_hw
*tcon_tve_parents
[] = {
736 &pll_video0_4x_clk
.common
.hw
,
738 &pll_video1_4x_clk
.common
.hw
,
739 &pll_periph0_2x_clk
.common
.hw
,
740 &pll_audio1_div2_clk
.common
.hw
,
742 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd0_clk
, "tcon-lcd0", tcon_tve_parents
, 0xb60,
747 CLK_SET_RATE_PARENT
);
749 static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk
, "bus-tcon-lcd0", psi_ahb_hws
,
752 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_tv_clk
, "tcon-tv", tcon_tve_parents
, 0xb80,
757 CLK_SET_RATE_PARENT
);
759 static SUNXI_CCU_GATE_HWS(bus_tcon_tv_clk
, "bus-tcon-tv", psi_ahb_hws
,
762 static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tve_clk
, "tve", tcon_tve_parents
, 0xbb0,
769 static SUNXI_CCU_GATE_HWS(bus_tve_top_clk
, "bus-tve-top", psi_ahb_hws
,
771 static SUNXI_CCU_GATE_HWS(bus_tve_clk
, "bus-tve", psi_ahb_hws
,
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
},
780 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(tvd_clk
, "tvd", tvd_parents
, 0xbc0,
786 static SUNXI_CCU_GATE_HWS(bus_tvd_top_clk
, "bus-tvd-top", psi_ahb_hws
,
788 static SUNXI_CCU_GATE_HWS(bus_tvd_clk
, "bus-tvd", psi_ahb_hws
,
791 static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(ledc_clk
, "ledc", ir_tx_ledc_parents
, 0xbf0,
798 static SUNXI_CCU_GATE_HWS(bus_ledc_clk
, "bus-ledc", psi_ahb_hws
,
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
,
806 static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk
, "csi-top", csi_top_parents
, 0xc04,
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
},
820 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk_clk
, "csi-mclk", csi_mclk_parents
, 0xc08,
826 static SUNXI_CCU_GATE_HWS(bus_csi_clk
, "bus-csi", psi_ahb_hws
,
829 static const struct clk_parent_data tpadc_parents
[] = {
830 { .fw_name
= "hosc" },
831 { .hw
= &pll_audio0_clk
.hw
},
833 static SUNXI_CCU_MUX_DATA_WITH_GATE(tpadc_clk
, "tpadc", tpadc_parents
, 0xc50,
838 static SUNXI_CCU_GATE_HWS(bus_tpadc_clk
, "bus-tpadc", apb0_hws
,
841 static SUNXI_CCU_GATE_HWS(bus_tzma_clk
, "bus-tzma", apb0_hws
,
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
},
851 static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk
, "dsp", dsp_parents
, 0xc70,
857 static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk
, "bus-dsp-cfg", psi_ahb_hws
,
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.
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
},
873 static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk
, "riscv", riscv_parents
, 0xd00,
876 CLK_SET_RATE_PARENT
| CLK_IS_CRITICAL
);
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 },
885 static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk
, "riscv-axi", &riscv_clk
.common
.hw
,
886 0xd00, 8, 2, riscv_axi_table
, 0);
888 static SUNXI_CCU_GATE_HWS(bus_riscv_cfg_clk
, "bus-riscv-cfg", psi_ahb_hws
,
889 0xd0c, BIT(0), CLK_IS_CRITICAL
);
891 static SUNXI_CCU_GATE_DATA(fanout_24M_clk
, "fanout-24M", osc24M
,
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);
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
[] = {
908 static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk
, "fanout-27M", fanout_27M_parents
, 0xf34,
914 static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk
, "fanout-pclk", apb0_hws
, 0xf38,
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
,
928 static SUNXI_CCU_MUX_HW_WITH_GATE(fanout0_clk
, "fanout0", fanout_parents
, 0xf3c,
932 static SUNXI_CCU_MUX_HW_WITH_GATE(fanout1_clk
, "fanout1", fanout_parents
, 0xf3c,
936 static SUNXI_CCU_MUX_HW_WITH_GATE(fanout2_clk
, "fanout2", fanout_parents
, 0xf3c,
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
,
950 &pll_audio0_4x_clk
.common
,
951 &pll_audio1_clk
.common
,
952 &pll_audio1_div2_clk
.common
,
953 &pll_audio1_div5_clk
.common
,
955 &cpux_axi_clk
.common
,
956 &cpux_apb_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
,
979 &bus_iommu_clk
.common
,
981 &mbus_dma_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
,
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
,
1005 &bus_can0_clk
.common
,
1006 &bus_can1_clk
.common
,
1009 &bus_spi0_clk
.common
,
1010 &bus_spi1_clk
.common
,
1011 &emac_25M_clk
.common
,
1012 &bus_emac_clk
.common
,
1014 &bus_ir_tx_clk
.common
,
1015 &bus_gpadc_clk
.common
,
1016 &bus_ths_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
,
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
,
1052 &bus_tve_top_clk
.common
,
1053 &bus_tve_clk
.common
,
1055 &bus_tvd_top_clk
.common
,
1056 &bus_tvd_clk
.common
,
1058 &bus_ledc_clk
.common
,
1059 &csi_top_clk
.common
,
1060 &csi_mclk_clk
.common
,
1061 &bus_csi_clk
.common
,
1063 &bus_tpadc_clk
.common
,
1064 &bus_tzma_clk
.common
,
1066 &bus_dsp_cfg_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
,
1082 static struct clk_hw_onecell_data sun20i_d1_hw_clks
= {
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
,
1157 [CLK_BUS_CAN0
] = &bus_can0_clk
.common
.hw
,
1158 [CLK_BUS_CAN1
] = &bus_can1_clk
.common
.hw
,
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
,
1235 static const 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) },
1264 [RST_BUS_CAN0
] = { 0x92c, BIT(16) },
1265 [RST_BUS_CAN1
] = { 0x92c, BIT(17) },
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) },
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
),
1310 .hw_clks
= &sun20i_d1_hw_clks
,
1312 .resets
= sun20i_d1_ccu_resets
,
1313 .num_resets
= ARRAY_SIZE(sun20i_d1_ccu_resets
),
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
,
1327 static const u32 pll_video_regs
[] = {
1328 SUN20I_D1_PLL_VIDEO0_REG
,
1329 SUN20I_D1_PLL_VIDEO1_REG
,
1332 static struct ccu_mux_nb sun20i_d1_riscv_nb
= {
1333 .common
= &riscv_clk
.common
,
1334 .cm
= &riscv_clk
.mux
,
1336 .bypass_index
= 4, /* index of pll-periph0 */
1339 static int sun20i_d1_ccu_probe(struct platform_device
*pdev
)
1345 reg
= devm_platform_ioremap_resource(pdev
, 0);
1347 return PTR_ERR(reg
);
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
]);
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
);
1362 * Force the output divider of video PLLs to 0.
1364 * See the comment before pll-video0 definition for the reason.
1366 for (i
= 0; i
< ARRAY_SIZE(pll_video_regs
); i
++) {
1367 val
= readl(reg
+ pll_video_regs
[i
]);
1369 writel(val
, reg
+ pll_video_regs
[i
]);
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
);
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
);
1382 ret
= devm_sunxi_ccu_probe(&pdev
->dev
, reg
, &sun20i_d1_ccu_desc
);
1386 /* Reparent CPU during PLL CPUX rate changes */
1387 ccu_mux_notifier_register(pll_cpux_clk
.common
.hw
.clk
,
1388 &sun20i_d1_riscv_nb
);
1393 static const struct of_device_id sun20i_d1_ccu_ids
[] = {
1394 { .compatible
= "allwinner,sun20i-d1-ccu" },
1397 MODULE_DEVICE_TABLE(of
, sun20i_d1_ccu_ids
);
1399 static struct platform_driver sun20i_d1_ccu_driver
= {
1400 .probe
= sun20i_d1_ccu_probe
,
1402 .name
= "sun20i-d1-ccu",
1403 .suppress_bind_attrs
= true,
1404 .of_match_table
= sun20i_d1_ccu_ids
,
1407 module_platform_driver(sun20i_d1_ccu_driver
);
1409 MODULE_IMPORT_NS("SUNXI_CCU");
1410 MODULE_DESCRIPTION("Support for the Allwinner D1/R528/T113 CCU");
1411 MODULE_LICENSE("GPL");