Commit | Line | Data |
---|---|---|
9c92ab61 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
cdb8b80b IZ |
2 | /* |
3 | * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz> | |
cdb8b80b IZ |
4 | */ |
5 | ||
6 | #include <linux/clk-provider.h> | |
7 | #include <linux/of_address.h> | |
8 | #include <linux/platform_device.h> | |
9 | ||
10 | #include "ccu_common.h" | |
11 | #include "ccu_reset.h" | |
12 | ||
13 | #include "ccu_div.h" | |
14 | #include "ccu_gate.h" | |
15 | #include "ccu_mp.h" | |
16 | #include "ccu_nm.h" | |
17 | ||
18 | #include "ccu-sun8i-r.h" | |
19 | ||
20 | static const char * const ar100_parents[] = { "osc32k", "osc24M", | |
21 | "pll-periph0", "iosc" }; | |
5a90c14c CYT |
22 | static const char * const a83t_ar100_parents[] = { "osc16M-d512", "osc24M", |
23 | "pll-periph0", "iosc" }; | |
13e0dde8 CYT |
24 | static const struct ccu_mux_var_prediv ar100_predivs[] = { |
25 | { .index = 2, .shift = 8, .width = 5 }, | |
26 | }; | |
cdb8b80b IZ |
27 | |
28 | static struct ccu_div ar100_clk = { | |
29 | .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | |
30 | ||
31 | .mux = { | |
32 | .shift = 16, | |
33 | .width = 2, | |
34 | ||
13e0dde8 CYT |
35 | .var_predivs = ar100_predivs, |
36 | .n_var_predivs = ARRAY_SIZE(ar100_predivs), | |
cdb8b80b IZ |
37 | }, |
38 | ||
39 | .common = { | |
40 | .reg = 0x00, | |
41 | .features = CCU_FEATURE_VARIABLE_PREDIV, | |
42 | .hw.init = CLK_HW_INIT_PARENTS("ar100", | |
43 | ar100_parents, | |
44 | &ccu_div_ops, | |
45 | 0), | |
46 | }, | |
47 | }; | |
48 | ||
5a90c14c CYT |
49 | static struct ccu_div a83t_ar100_clk = { |
50 | .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | |
51 | ||
52 | .mux = { | |
53 | .shift = 16, | |
54 | .width = 2, | |
55 | ||
56 | .var_predivs = ar100_predivs, | |
57 | .n_var_predivs = ARRAY_SIZE(ar100_predivs), | |
58 | }, | |
59 | ||
60 | .common = { | |
61 | .reg = 0x00, | |
62 | .features = CCU_FEATURE_VARIABLE_PREDIV, | |
63 | .hw.init = CLK_HW_INIT_PARENTS("ar100", | |
64 | a83t_ar100_parents, | |
65 | &ccu_div_ops, | |
66 | 0), | |
67 | }, | |
68 | }; | |
69 | ||
cdb8b80b IZ |
70 | static CLK_FIXED_FACTOR(ahb0_clk, "ahb0", "ar100", 1, 1, 0); |
71 | ||
72 | static struct ccu_div apb0_clk = { | |
73 | .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), | |
74 | ||
75 | .common = { | |
76 | .reg = 0x0c, | |
77 | .hw.init = CLK_HW_INIT("apb0", | |
78 | "ahb0", | |
79 | &ccu_div_ops, | |
80 | 0), | |
81 | }, | |
82 | }; | |
83 | ||
5a90c14c CYT |
84 | static SUNXI_CCU_M(a83t_apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0); |
85 | ||
cdb8b80b IZ |
86 | static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0", |
87 | 0x28, BIT(0), 0); | |
88 | static SUNXI_CCU_GATE(apb0_ir_clk, "apb0-ir", "apb0", | |
89 | 0x28, BIT(1), 0); | |
90 | static SUNXI_CCU_GATE(apb0_timer_clk, "apb0-timer", "apb0", | |
91 | 0x28, BIT(2), 0); | |
92 | static SUNXI_CCU_GATE(apb0_rsb_clk, "apb0-rsb", "apb0", | |
93 | 0x28, BIT(3), 0); | |
94 | static SUNXI_CCU_GATE(apb0_uart_clk, "apb0-uart", "apb0", | |
95 | 0x28, BIT(4), 0); | |
96 | static SUNXI_CCU_GATE(apb0_i2c_clk, "apb0-i2c", "apb0", | |
97 | 0x28, BIT(6), 0); | |
98 | static SUNXI_CCU_GATE(apb0_twd_clk, "apb0-twd", "apb0", | |
99 | 0x28, BIT(7), 0); | |
100 | ||
37cabc74 | 101 | static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" }; |
cdb8b80b IZ |
102 | static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir", |
103 | r_mod0_default_parents, 0x54, | |
104 | 0, 4, /* M */ | |
105 | 16, 2, /* P */ | |
106 | 24, 2, /* mux */ | |
107 | BIT(31), /* gate */ | |
108 | 0); | |
109 | ||
5a90c14c CYT |
110 | static const char *const a83t_r_mod0_parents[] = { "osc16M", "osc24M" }; |
111 | static const struct ccu_mux_fixed_prediv a83t_ir_predivs[] = { | |
112 | { .index = 0, .div = 16 }, | |
113 | }; | |
114 | static struct ccu_mp a83t_ir_clk = { | |
115 | .enable = BIT(31), | |
116 | ||
117 | .m = _SUNXI_CCU_DIV(0, 4), | |
118 | .p = _SUNXI_CCU_DIV(16, 2), | |
119 | ||
120 | .mux = { | |
121 | .shift = 24, | |
122 | .width = 2, | |
123 | .fixed_predivs = a83t_ir_predivs, | |
124 | .n_predivs = ARRAY_SIZE(a83t_ir_predivs), | |
125 | }, | |
126 | ||
127 | .common = { | |
128 | .reg = 0x54, | |
129 | .features = CCU_FEATURE_VARIABLE_PREDIV, | |
130 | .hw.init = CLK_HW_INIT_PARENTS("ir", | |
131 | a83t_r_mod0_parents, | |
132 | &ccu_mp_ops, | |
133 | 0), | |
134 | }, | |
135 | }; | |
136 | ||
137 | static struct ccu_common *sun8i_a83t_r_ccu_clks[] = { | |
138 | &a83t_ar100_clk.common, | |
139 | &a83t_apb0_clk.common, | |
140 | &apb0_pio_clk.common, | |
141 | &apb0_ir_clk.common, | |
142 | &apb0_timer_clk.common, | |
143 | &apb0_rsb_clk.common, | |
144 | &apb0_uart_clk.common, | |
145 | &apb0_i2c_clk.common, | |
146 | &apb0_twd_clk.common, | |
147 | &a83t_ir_clk.common, | |
148 | }; | |
149 | ||
cdb8b80b IZ |
150 | static struct ccu_common *sun8i_h3_r_ccu_clks[] = { |
151 | &ar100_clk.common, | |
152 | &apb0_clk.common, | |
153 | &apb0_pio_clk.common, | |
154 | &apb0_ir_clk.common, | |
155 | &apb0_timer_clk.common, | |
156 | &apb0_uart_clk.common, | |
157 | &apb0_i2c_clk.common, | |
158 | &apb0_twd_clk.common, | |
159 | &ir_clk.common, | |
160 | }; | |
161 | ||
162 | static struct ccu_common *sun50i_a64_r_ccu_clks[] = { | |
163 | &ar100_clk.common, | |
164 | &apb0_clk.common, | |
165 | &apb0_pio_clk.common, | |
166 | &apb0_ir_clk.common, | |
167 | &apb0_timer_clk.common, | |
168 | &apb0_rsb_clk.common, | |
169 | &apb0_uart_clk.common, | |
170 | &apb0_i2c_clk.common, | |
171 | &apb0_twd_clk.common, | |
172 | &ir_clk.common, | |
173 | }; | |
174 | ||
5a90c14c CYT |
175 | static struct clk_hw_onecell_data sun8i_a83t_r_hw_clks = { |
176 | .hws = { | |
177 | [CLK_AR100] = &a83t_ar100_clk.common.hw, | |
178 | [CLK_AHB0] = &ahb0_clk.hw, | |
179 | [CLK_APB0] = &a83t_apb0_clk.common.hw, | |
180 | [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | |
181 | [CLK_APB0_IR] = &apb0_ir_clk.common.hw, | |
182 | [CLK_APB0_TIMER] = &apb0_timer_clk.common.hw, | |
183 | [CLK_APB0_RSB] = &apb0_rsb_clk.common.hw, | |
184 | [CLK_APB0_UART] = &apb0_uart_clk.common.hw, | |
185 | [CLK_APB0_I2C] = &apb0_i2c_clk.common.hw, | |
186 | [CLK_APB0_TWD] = &apb0_twd_clk.common.hw, | |
187 | [CLK_IR] = &a83t_ir_clk.common.hw, | |
188 | }, | |
189 | .num = CLK_NUMBER, | |
190 | }; | |
191 | ||
cdb8b80b IZ |
192 | static struct clk_hw_onecell_data sun8i_h3_r_hw_clks = { |
193 | .hws = { | |
194 | [CLK_AR100] = &ar100_clk.common.hw, | |
195 | [CLK_AHB0] = &ahb0_clk.hw, | |
196 | [CLK_APB0] = &apb0_clk.common.hw, | |
197 | [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | |
198 | [CLK_APB0_IR] = &apb0_ir_clk.common.hw, | |
199 | [CLK_APB0_TIMER] = &apb0_timer_clk.common.hw, | |
200 | [CLK_APB0_UART] = &apb0_uart_clk.common.hw, | |
201 | [CLK_APB0_I2C] = &apb0_i2c_clk.common.hw, | |
202 | [CLK_APB0_TWD] = &apb0_twd_clk.common.hw, | |
203 | [CLK_IR] = &ir_clk.common.hw, | |
204 | }, | |
205 | .num = CLK_NUMBER, | |
206 | }; | |
207 | ||
208 | static struct clk_hw_onecell_data sun50i_a64_r_hw_clks = { | |
209 | .hws = { | |
210 | [CLK_AR100] = &ar100_clk.common.hw, | |
211 | [CLK_AHB0] = &ahb0_clk.hw, | |
212 | [CLK_APB0] = &apb0_clk.common.hw, | |
213 | [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | |
214 | [CLK_APB0_IR] = &apb0_ir_clk.common.hw, | |
215 | [CLK_APB0_TIMER] = &apb0_timer_clk.common.hw, | |
216 | [CLK_APB0_RSB] = &apb0_rsb_clk.common.hw, | |
217 | [CLK_APB0_UART] = &apb0_uart_clk.common.hw, | |
218 | [CLK_APB0_I2C] = &apb0_i2c_clk.common.hw, | |
219 | [CLK_APB0_TWD] = &apb0_twd_clk.common.hw, | |
220 | [CLK_IR] = &ir_clk.common.hw, | |
221 | }, | |
222 | .num = CLK_NUMBER, | |
223 | }; | |
224 | ||
5a90c14c CYT |
225 | static struct ccu_reset_map sun8i_a83t_r_ccu_resets[] = { |
226 | [RST_APB0_IR] = { 0xb0, BIT(1) }, | |
227 | [RST_APB0_TIMER] = { 0xb0, BIT(2) }, | |
228 | [RST_APB0_RSB] = { 0xb0, BIT(3) }, | |
229 | [RST_APB0_UART] = { 0xb0, BIT(4) }, | |
230 | [RST_APB0_I2C] = { 0xb0, BIT(6) }, | |
231 | }; | |
232 | ||
cdb8b80b IZ |
233 | static struct ccu_reset_map sun8i_h3_r_ccu_resets[] = { |
234 | [RST_APB0_IR] = { 0xb0, BIT(1) }, | |
235 | [RST_APB0_TIMER] = { 0xb0, BIT(2) }, | |
236 | [RST_APB0_UART] = { 0xb0, BIT(4) }, | |
237 | [RST_APB0_I2C] = { 0xb0, BIT(6) }, | |
238 | }; | |
239 | ||
240 | static struct ccu_reset_map sun50i_a64_r_ccu_resets[] = { | |
241 | [RST_APB0_IR] = { 0xb0, BIT(1) }, | |
242 | [RST_APB0_TIMER] = { 0xb0, BIT(2) }, | |
243 | [RST_APB0_RSB] = { 0xb0, BIT(3) }, | |
244 | [RST_APB0_UART] = { 0xb0, BIT(4) }, | |
245 | [RST_APB0_I2C] = { 0xb0, BIT(6) }, | |
246 | }; | |
247 | ||
5a90c14c CYT |
248 | static const struct sunxi_ccu_desc sun8i_a83t_r_ccu_desc = { |
249 | .ccu_clks = sun8i_a83t_r_ccu_clks, | |
250 | .num_ccu_clks = ARRAY_SIZE(sun8i_a83t_r_ccu_clks), | |
251 | ||
252 | .hw_clks = &sun8i_a83t_r_hw_clks, | |
253 | ||
254 | .resets = sun8i_a83t_r_ccu_resets, | |
255 | .num_resets = ARRAY_SIZE(sun8i_a83t_r_ccu_resets), | |
256 | }; | |
257 | ||
cdb8b80b IZ |
258 | static const struct sunxi_ccu_desc sun8i_h3_r_ccu_desc = { |
259 | .ccu_clks = sun8i_h3_r_ccu_clks, | |
260 | .num_ccu_clks = ARRAY_SIZE(sun8i_h3_r_ccu_clks), | |
261 | ||
262 | .hw_clks = &sun8i_h3_r_hw_clks, | |
263 | ||
264 | .resets = sun8i_h3_r_ccu_resets, | |
265 | .num_resets = ARRAY_SIZE(sun8i_h3_r_ccu_resets), | |
266 | }; | |
267 | ||
268 | static const struct sunxi_ccu_desc sun50i_a64_r_ccu_desc = { | |
269 | .ccu_clks = sun50i_a64_r_ccu_clks, | |
270 | .num_ccu_clks = ARRAY_SIZE(sun50i_a64_r_ccu_clks), | |
271 | ||
272 | .hw_clks = &sun50i_a64_r_hw_clks, | |
273 | ||
274 | .resets = sun50i_a64_r_ccu_resets, | |
275 | .num_resets = ARRAY_SIZE(sun50i_a64_r_ccu_resets), | |
276 | }; | |
277 | ||
278 | static void __init sunxi_r_ccu_init(struct device_node *node, | |
279 | const struct sunxi_ccu_desc *desc) | |
280 | { | |
281 | void __iomem *reg; | |
282 | ||
283 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | |
284 | if (IS_ERR(reg)) { | |
16673931 | 285 | pr_err("%pOF: Could not map the clock registers\n", node); |
cdb8b80b IZ |
286 | return; |
287 | } | |
288 | ||
289 | sunxi_ccu_probe(node, reg, desc); | |
290 | } | |
291 | ||
5a90c14c CYT |
292 | static void __init sun8i_a83t_r_ccu_setup(struct device_node *node) |
293 | { | |
294 | sunxi_r_ccu_init(node, &sun8i_a83t_r_ccu_desc); | |
295 | } | |
296 | CLK_OF_DECLARE(sun8i_a83t_r_ccu, "allwinner,sun8i-a83t-r-ccu", | |
297 | sun8i_a83t_r_ccu_setup); | |
298 | ||
cdb8b80b IZ |
299 | static void __init sun8i_h3_r_ccu_setup(struct device_node *node) |
300 | { | |
301 | sunxi_r_ccu_init(node, &sun8i_h3_r_ccu_desc); | |
302 | } | |
303 | CLK_OF_DECLARE(sun8i_h3_r_ccu, "allwinner,sun8i-h3-r-ccu", | |
304 | sun8i_h3_r_ccu_setup); | |
305 | ||
306 | static void __init sun50i_a64_r_ccu_setup(struct device_node *node) | |
307 | { | |
308 | sunxi_r_ccu_init(node, &sun50i_a64_r_ccu_desc); | |
309 | } | |
310 | CLK_OF_DECLARE(sun50i_a64_r_ccu, "allwinner,sun50i-a64-r-ccu", | |
311 | sun50i_a64_r_ccu_setup); |