Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: sunxi-ng: add support for the Allwinner A100 CCU

Add support for a100 in the sunxi-ng CCU framework.

Signed-off-by: Yangtao Li <frank@allwinnertech.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/1eb41bf6c966a0e54820200650d27a5d4f2ac160.1595572867.git.frank@allwinnertech.com

authored by

Yangtao Li and committed by
Maxime Ripard
fb038ce4 2f704c29

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