1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * MTMIPS SoCs Clock Driver |
4 | * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com> |
5 | */ |
6 | |
7 | #include <linux/bitops.h> |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/mfd/syscon.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/regmap.h> |
12 | #include <linux/reset-controller.h> |
13 | #include <linux/slab.h> |
14 | |
15 | /* Configuration registers */ |
16 | #define SYSC_REG_SYSTEM_CONFIG 0x10 |
17 | #define SYSC_REG_CLKCFG0 0x2c |
18 | #define SYSC_REG_RESET_CTRL 0x34 |
19 | #define SYSC_REG_CPU_SYS_CLKCFG 0x3c |
20 | #define SYSC_REG_CPLL_CONFIG0 0x54 |
21 | #define SYSC_REG_CPLL_CONFIG1 0x58 |
22 | |
23 | /* RT2880 SoC */ |
24 | #define RT2880_CONFIG_CPUCLK_SHIFT 20 |
25 | #define RT2880_CONFIG_CPUCLK_MASK 0x3 |
26 | #define RT2880_CONFIG_CPUCLK_250 0x0 |
27 | #define RT2880_CONFIG_CPUCLK_266 0x1 |
28 | #define RT2880_CONFIG_CPUCLK_280 0x2 |
29 | #define RT2880_CONFIG_CPUCLK_300 0x3 |
30 | |
31 | /* RT305X SoC */ |
32 | #define RT305X_SYSCFG_CPUCLK_SHIFT 18 |
33 | #define RT305X_SYSCFG_CPUCLK_MASK 0x1 |
34 | #define RT305X_SYSCFG_CPUCLK_LOW 0x0 |
35 | #define RT305X_SYSCFG_CPUCLK_HIGH 0x1 |
36 | |
37 | /* RT3352 SoC */ |
38 | #define RT3352_SYSCFG0_CPUCLK_SHIFT 8 |
39 | #define RT3352_SYSCFG0_CPUCLK_MASK 0x1 |
40 | #define RT3352_SYSCFG0_CPUCLK_LOW 0x0 |
41 | #define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 |
42 | |
43 | /* RT3383 SoC */ |
44 | #define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) |
45 | #define RT3883_SYSCFG0_CPUCLK_SHIFT 8 |
46 | #define RT3883_SYSCFG0_CPUCLK_MASK 0x3 |
47 | #define RT3883_SYSCFG0_CPUCLK_250 0x0 |
48 | #define RT3883_SYSCFG0_CPUCLK_384 0x1 |
49 | #define RT3883_SYSCFG0_CPUCLK_480 0x2 |
50 | #define RT3883_SYSCFG0_CPUCLK_500 0x3 |
51 | |
52 | /* RT5350 SoC */ |
53 | #define RT5350_CLKCFG0_XTAL_SEL BIT(20) |
54 | #define RT5350_SYSCFG0_CPUCLK_SHIFT 8 |
55 | #define RT5350_SYSCFG0_CPUCLK_MASK 0x3 |
56 | #define RT5350_SYSCFG0_CPUCLK_360 0x0 |
57 | #define RT5350_SYSCFG0_CPUCLK_320 0x2 |
58 | #define RT5350_SYSCFG0_CPUCLK_300 0x3 |
59 | |
60 | /* MT7620 and MT76x8 SoCs */ |
61 | #define MT7620_XTAL_FREQ_SEL BIT(6) |
62 | #define CPLL_CFG0_SW_CFG BIT(31) |
63 | #define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 |
64 | #define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 |
65 | #define CPLL_CFG0_LC_CURFCK BIT(15) |
66 | #define CPLL_CFG0_BYPASS_REF_CLK BIT(14) |
67 | #define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 |
68 | #define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 |
69 | #define CPLL_CFG1_CPU_AUX1 BIT(25) |
70 | #define CPLL_CFG1_CPU_AUX0 BIT(24) |
71 | #define CLKCFG0_PERI_CLK_SEL BIT(4) |
72 | #define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 |
73 | #define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf |
74 | #define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ |
75 | #define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ |
76 | #define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ |
77 | #define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ |
78 | #define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ |
79 | #define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ |
80 | #define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ |
81 | #define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ |
82 | #define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ |
83 | #define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 |
84 | #define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f |
85 | #define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 |
86 | #define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f |
87 | |
88 | /* clock scaling */ |
89 | #define CLKCFG_FDIV_MASK 0x1f00 |
90 | #define CLKCFG_FDIV_USB_VAL 0x0300 |
91 | #define CLKCFG_FFRAC_MASK 0x001f |
92 | #define CLKCFG_FFRAC_USB_VAL 0x0003 |
93 | |
94 | struct mtmips_clk; |
95 | struct mtmips_clk_fixed; |
96 | struct mtmips_clk_factor; |
97 | |
98 | struct mtmips_clk_data { |
99 | struct mtmips_clk *clk_base; |
100 | size_t num_clk_base; |
101 | struct mtmips_clk_fixed *clk_fixed; |
102 | size_t num_clk_fixed; |
103 | struct mtmips_clk_factor *clk_factor; |
104 | size_t num_clk_factor; |
105 | struct mtmips_clk *clk_periph; |
106 | size_t num_clk_periph; |
107 | }; |
108 | |
109 | struct mtmips_clk_priv { |
110 | struct regmap *sysc; |
111 | const struct mtmips_clk_data *data; |
112 | }; |
113 | |
114 | struct mtmips_clk { |
115 | struct clk_hw hw; |
116 | struct mtmips_clk_priv *priv; |
117 | }; |
118 | |
119 | struct mtmips_clk_fixed { |
120 | const char *name; |
121 | const char *parent; |
122 | unsigned long rate; |
123 | struct clk_hw *hw; |
124 | }; |
125 | |
126 | struct mtmips_clk_factor { |
127 | const char *name; |
128 | const char *parent; |
129 | int mult; |
130 | int div; |
131 | unsigned long flags; |
132 | struct clk_hw *hw; |
133 | }; |
134 | |
135 | static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw, |
136 | unsigned long parent_rate) |
137 | { |
138 | return parent_rate; |
139 | } |
140 | |
141 | static const struct clk_ops mtmips_periph_clk_ops = { |
142 | .recalc_rate = mtmips_pherip_clk_rate, |
143 | }; |
144 | |
145 | #define CLK_PERIPH(_name, _parent) { \ |
146 | .init = &(const struct clk_init_data) { \ |
147 | .name = _name, \ |
148 | .ops = &mtmips_periph_clk_ops, \ |
149 | .parent_data = &(const struct clk_parent_data) {\ |
150 | .name = _parent, \ |
151 | .fw_name = _parent \ |
152 | }, \ |
153 | .num_parents = 1, \ |
154 | /* \ |
155 | * There are drivers for these SoCs that are \ |
156 | * older than clock driver and are not prepared \ |
157 | * for the clock. We don't want the kernel to \ |
158 | * disable anything so we add CLK_IS_CRITICAL \ |
159 | * flag here. \ |
160 | */ \ |
161 | .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \ |
162 | }, \ |
163 | } |
164 | |
165 | static struct mtmips_clk rt2880_pherip_clks[] = { |
166 | { CLK_PERIPH("300100.timer" , "bus" ) }, |
167 | { CLK_PERIPH("300120.watchdog" , "bus" ) }, |
168 | { CLK_PERIPH("300500.uart" , "bus" ) }, |
169 | { CLK_PERIPH("300900.i2c" , "bus" ) }, |
170 | { CLK_PERIPH("300c00.uartlite" , "bus" ) }, |
171 | { CLK_PERIPH("400000.ethernet" , "bus" ) }, |
172 | { CLK_PERIPH("480000.wmac" , "xtal" ) } |
173 | }; |
174 | |
175 | static struct mtmips_clk rt305x_pherip_clks[] = { |
176 | { CLK_PERIPH("10000100.timer" , "bus" ) }, |
177 | { CLK_PERIPH("10000120.watchdog" , "bus" ) }, |
178 | { CLK_PERIPH("10000500.uart" , "bus" ) }, |
179 | { CLK_PERIPH("10000900.i2c" , "bus" ) }, |
180 | { CLK_PERIPH("10000a00.i2s" , "bus" ) }, |
181 | { CLK_PERIPH("10000b00.spi" , "bus" ) }, |
182 | { CLK_PERIPH("10000b40.spi" , "bus" ) }, |
183 | { CLK_PERIPH("10000c00.uartlite" , "bus" ) }, |
184 | { CLK_PERIPH("10100000.ethernet" , "bus" ) }, |
185 | { CLK_PERIPH("10180000.wmac" , "xtal" ) } |
186 | }; |
187 | |
188 | static struct mtmips_clk rt5350_pherip_clks[] = { |
189 | { CLK_PERIPH("10000100.timer" , "bus" ) }, |
190 | { CLK_PERIPH("10000120.watchdog" , "bus" ) }, |
191 | { CLK_PERIPH("10000500.uart" , "periph" ) }, |
192 | { CLK_PERIPH("10000900.i2c" , "periph" ) }, |
193 | { CLK_PERIPH("10000a00.i2s" , "periph" ) }, |
194 | { CLK_PERIPH("10000b00.spi" , "bus" ) }, |
195 | { CLK_PERIPH("10000b40.spi" , "bus" ) }, |
196 | { CLK_PERIPH("10000c00.uartlite" , "periph" ) }, |
197 | { CLK_PERIPH("10100000.ethernet" , "bus" ) }, |
198 | { CLK_PERIPH("10180000.wmac" , "xtal" ) } |
199 | }; |
200 | |
201 | static struct mtmips_clk mt7620_pherip_clks[] = { |
202 | { CLK_PERIPH("10000100.timer" , "periph" ) }, |
203 | { CLK_PERIPH("10000120.watchdog" , "periph" ) }, |
204 | { CLK_PERIPH("10000500.uart" , "periph" ) }, |
205 | { CLK_PERIPH("10000900.i2c" , "periph" ) }, |
206 | { CLK_PERIPH("10000a00.i2s" , "periph" ) }, |
207 | { CLK_PERIPH("10000b00.spi" , "bus" ) }, |
208 | { CLK_PERIPH("10000b40.spi" , "bus" ) }, |
209 | { CLK_PERIPH("10000c00.uartlite" , "periph" ) }, |
210 | { CLK_PERIPH("10180000.wmac" , "xtal" ) } |
211 | }; |
212 | |
213 | static struct mtmips_clk mt76x8_pherip_clks[] = { |
214 | { CLK_PERIPH("10000100.timer" , "periph" ) }, |
215 | { CLK_PERIPH("10000120.watchdog" , "periph" ) }, |
216 | { CLK_PERIPH("10000900.i2c" , "periph" ) }, |
217 | { CLK_PERIPH("10000a00.i2s" , "pcmi2s" ) }, |
218 | { CLK_PERIPH("10000b00.spi" , "bus" ) }, |
219 | { CLK_PERIPH("10000b40.spi" , "bus" ) }, |
220 | { CLK_PERIPH("10000c00.uart0" , "periph" ) }, |
221 | { CLK_PERIPH("10000d00.uart1" , "periph" ) }, |
222 | { CLK_PERIPH("10000e00.uart2" , "periph" ) }, |
223 | { CLK_PERIPH("10300000.wmac" , "xtal" ) } |
224 | }; |
225 | |
226 | static int mtmips_register_pherip_clocks(struct device_node *np, |
227 | struct clk_hw_onecell_data *clk_data, |
228 | struct mtmips_clk_priv *priv) |
229 | { |
230 | struct clk_hw **hws = clk_data->hws; |
231 | struct mtmips_clk *sclk; |
232 | size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed + |
233 | priv->data->num_clk_factor; |
234 | int ret, i; |
235 | |
236 | for (i = 0; i < priv->data->num_clk_periph; i++) { |
237 | int idx = idx_start + i; |
238 | |
239 | sclk = &priv->data->clk_periph[i]; |
240 | ret = of_clk_hw_register(node: np, hw: &sclk->hw); |
241 | if (ret) { |
242 | pr_err("Couldn't register peripheral clock %d\n" , idx); |
243 | goto err_clk_unreg; |
244 | } |
245 | |
246 | hws[idx] = &sclk->hw; |
247 | } |
248 | |
249 | return 0; |
250 | |
251 | err_clk_unreg: |
252 | while (--i >= 0) { |
253 | sclk = &priv->data->clk_periph[i]; |
254 | clk_hw_unregister(hw: &sclk->hw); |
255 | } |
256 | return ret; |
257 | } |
258 | |
259 | #define CLK_FIXED(_name, _parent, _rate) \ |
260 | { \ |
261 | .name = _name, \ |
262 | .parent = _parent, \ |
263 | .rate = _rate \ |
264 | } |
265 | |
266 | static struct mtmips_clk_fixed rt305x_fixed_clocks[] = { |
267 | CLK_FIXED("xtal" , NULL, 40000000) |
268 | }; |
269 | |
270 | static struct mtmips_clk_fixed rt3352_fixed_clocks[] = { |
271 | CLK_FIXED("periph" , "xtal" , 40000000) |
272 | }; |
273 | |
274 | static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = { |
275 | CLK_FIXED("pcmi2s" , "xtal" , 480000000), |
276 | CLK_FIXED("periph" , "xtal" , 40000000) |
277 | }; |
278 | |
279 | static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data, |
280 | struct mtmips_clk_priv *priv) |
281 | { |
282 | struct clk_hw **hws = clk_data->hws; |
283 | struct mtmips_clk_fixed *sclk; |
284 | size_t idx_start = priv->data->num_clk_base; |
285 | int ret, i; |
286 | |
287 | for (i = 0; i < priv->data->num_clk_fixed; i++) { |
288 | int idx = idx_start + i; |
289 | |
290 | sclk = &priv->data->clk_fixed[i]; |
291 | sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name, |
292 | sclk->parent, 0, |
293 | sclk->rate); |
294 | if (IS_ERR(ptr: sclk->hw)) { |
295 | ret = PTR_ERR(ptr: sclk->hw); |
296 | pr_err("Couldn't register fixed clock %d\n" , idx); |
297 | goto err_clk_unreg; |
298 | } |
299 | |
300 | hws[idx] = sclk->hw; |
301 | } |
302 | |
303 | return 0; |
304 | |
305 | err_clk_unreg: |
306 | while (--i >= 0) { |
307 | sclk = &priv->data->clk_fixed[i]; |
308 | clk_hw_unregister_fixed_rate(hw: sclk->hw); |
309 | } |
310 | return ret; |
311 | } |
312 | |
313 | #define CLK_FACTOR(_name, _parent, _mult, _div) \ |
314 | { \ |
315 | .name = _name, \ |
316 | .parent = _parent, \ |
317 | .mult = _mult, \ |
318 | .div = _div, \ |
319 | .flags = CLK_SET_RATE_PARENT \ |
320 | } |
321 | |
322 | static struct mtmips_clk_factor rt2880_factor_clocks[] = { |
323 | CLK_FACTOR("bus" , "cpu" , 1, 2) |
324 | }; |
325 | |
326 | static struct mtmips_clk_factor rt305x_factor_clocks[] = { |
327 | CLK_FACTOR("bus" , "cpu" , 1, 3) |
328 | }; |
329 | |
330 | static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data, |
331 | struct mtmips_clk_priv *priv) |
332 | { |
333 | struct clk_hw **hws = clk_data->hws; |
334 | struct mtmips_clk_factor *sclk; |
335 | size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed; |
336 | int ret, i; |
337 | |
338 | for (i = 0; i < priv->data->num_clk_factor; i++) { |
339 | int idx = idx_start + i; |
340 | |
341 | sclk = &priv->data->clk_factor[i]; |
342 | sclk->hw = clk_hw_register_fixed_factor(NULL, name: sclk->name, |
343 | parent_name: sclk->parent, flags: sclk->flags, |
344 | mult: sclk->mult, div: sclk->div); |
345 | if (IS_ERR(ptr: sclk->hw)) { |
346 | ret = PTR_ERR(ptr: sclk->hw); |
347 | pr_err("Couldn't register factor clock %d\n" , idx); |
348 | goto err_clk_unreg; |
349 | } |
350 | |
351 | hws[idx] = sclk->hw; |
352 | } |
353 | |
354 | return 0; |
355 | |
356 | err_clk_unreg: |
357 | while (--i >= 0) { |
358 | sclk = &priv->data->clk_factor[i]; |
359 | clk_hw_unregister_fixed_factor(hw: sclk->hw); |
360 | } |
361 | return ret; |
362 | } |
363 | |
364 | static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw) |
365 | { |
366 | return container_of(hw, struct mtmips_clk, hw); |
367 | } |
368 | |
369 | static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw, |
370 | unsigned long parent_rate) |
371 | { |
372 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
373 | struct regmap *sysc = clk->priv->sysc; |
374 | u32 val; |
375 | |
376 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &val); |
377 | if (!(val & RT5350_CLKCFG0_XTAL_SEL)) |
378 | return 20000000; |
379 | |
380 | return 40000000; |
381 | } |
382 | |
383 | static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw, |
384 | unsigned long xtal_clk) |
385 | { |
386 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
387 | struct regmap *sysc = clk->priv->sysc; |
388 | u32 t; |
389 | |
390 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
391 | t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK; |
392 | |
393 | switch (t) { |
394 | case RT5350_SYSCFG0_CPUCLK_360: |
395 | return 360000000; |
396 | case RT5350_SYSCFG0_CPUCLK_320: |
397 | return 320000000; |
398 | case RT5350_SYSCFG0_CPUCLK_300: |
399 | return 300000000; |
400 | default: |
401 | BUG(); |
402 | } |
403 | } |
404 | |
405 | static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw, |
406 | unsigned long parent_rate) |
407 | { |
408 | if (parent_rate == 320000000) |
409 | return parent_rate / 4; |
410 | |
411 | return parent_rate / 3; |
412 | } |
413 | |
414 | static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw, |
415 | unsigned long xtal_clk) |
416 | { |
417 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
418 | struct regmap *sysc = clk->priv->sysc; |
419 | u32 t; |
420 | |
421 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
422 | t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK; |
423 | |
424 | switch (t) { |
425 | case RT3352_SYSCFG0_CPUCLK_LOW: |
426 | return 384000000; |
427 | case RT3352_SYSCFG0_CPUCLK_HIGH: |
428 | return 400000000; |
429 | default: |
430 | BUG(); |
431 | } |
432 | } |
433 | |
434 | static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw, |
435 | unsigned long xtal_clk) |
436 | { |
437 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
438 | struct regmap *sysc = clk->priv->sysc; |
439 | u32 t; |
440 | |
441 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
442 | t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK; |
443 | |
444 | switch (t) { |
445 | case RT305X_SYSCFG_CPUCLK_LOW: |
446 | return 320000000; |
447 | case RT305X_SYSCFG_CPUCLK_HIGH: |
448 | return 384000000; |
449 | default: |
450 | BUG(); |
451 | } |
452 | } |
453 | |
454 | static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw, |
455 | unsigned long xtal_clk) |
456 | { |
457 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
458 | struct regmap *sysc = clk->priv->sysc; |
459 | u32 t; |
460 | |
461 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
462 | t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK; |
463 | |
464 | switch (t) { |
465 | case RT3883_SYSCFG0_CPUCLK_250: |
466 | return 250000000; |
467 | case RT3883_SYSCFG0_CPUCLK_384: |
468 | return 384000000; |
469 | case RT3883_SYSCFG0_CPUCLK_480: |
470 | return 480000000; |
471 | case RT3883_SYSCFG0_CPUCLK_500: |
472 | return 500000000; |
473 | default: |
474 | BUG(); |
475 | } |
476 | } |
477 | |
478 | static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw, |
479 | unsigned long parent_rate) |
480 | { |
481 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
482 | struct regmap *sysc = clk->priv->sysc; |
483 | u32 ddr2; |
484 | u32 t; |
485 | |
486 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
487 | ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2; |
488 | |
489 | switch (parent_rate) { |
490 | case 250000000: |
491 | return (ddr2) ? 125000000 : 83000000; |
492 | case 384000000: |
493 | return (ddr2) ? 128000000 : 96000000; |
494 | case 480000000: |
495 | return (ddr2) ? 160000000 : 120000000; |
496 | case 500000000: |
497 | return (ddr2) ? 166000000 : 125000000; |
498 | default: |
499 | WARN_ON_ONCE(parent_rate == 0); |
500 | return parent_rate / 4; |
501 | } |
502 | } |
503 | |
504 | static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw, |
505 | unsigned long xtal_clk) |
506 | { |
507 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
508 | struct regmap *sysc = clk->priv->sysc; |
509 | u32 t; |
510 | |
511 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
512 | t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK; |
513 | |
514 | switch (t) { |
515 | case RT2880_CONFIG_CPUCLK_250: |
516 | return 250000000; |
517 | case RT2880_CONFIG_CPUCLK_266: |
518 | return 266000000; |
519 | case RT2880_CONFIG_CPUCLK_280: |
520 | return 280000000; |
521 | case RT2880_CONFIG_CPUCLK_300: |
522 | return 300000000; |
523 | default: |
524 | BUG(); |
525 | } |
526 | } |
527 | |
528 | static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) |
529 | { |
530 | u64 t; |
531 | |
532 | t = ref_rate; |
533 | t *= mul; |
534 | t = div_u64(dividend: t, divisor: div); |
535 | |
536 | return t; |
537 | } |
538 | |
539 | static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw, |
540 | unsigned long parent_rate) |
541 | { |
542 | static const u32 clk_divider[] = { 2, 3, 4, 8 }; |
543 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
544 | struct regmap *sysc = clk->priv->sysc; |
545 | unsigned long cpu_pll; |
546 | u32 t; |
547 | u32 mul; |
548 | u32 div; |
549 | |
550 | regmap_read(map: sysc, SYSC_REG_CPLL_CONFIG0, val: &t); |
551 | if (t & CPLL_CFG0_BYPASS_REF_CLK) { |
552 | cpu_pll = parent_rate; |
553 | } else if ((t & CPLL_CFG0_SW_CFG) == 0) { |
554 | cpu_pll = 600000000; |
555 | } else { |
556 | mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & |
557 | CPLL_CFG0_PLL_MULT_RATIO_MASK; |
558 | mul += 24; |
559 | if (t & CPLL_CFG0_LC_CURFCK) |
560 | mul *= 2; |
561 | |
562 | div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & |
563 | CPLL_CFG0_PLL_DIV_RATIO_MASK; |
564 | |
565 | WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider)); |
566 | |
567 | cpu_pll = mt7620_calc_rate(ref_rate: parent_rate, mul, div: clk_divider[div]); |
568 | } |
569 | |
570 | regmap_read(map: sysc, SYSC_REG_CPLL_CONFIG1, val: &t); |
571 | if (t & CPLL_CFG1_CPU_AUX1) |
572 | return parent_rate; |
573 | |
574 | if (t & CPLL_CFG1_CPU_AUX0) |
575 | return 480000000; |
576 | |
577 | return cpu_pll; |
578 | } |
579 | |
580 | static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw, |
581 | unsigned long parent_rate) |
582 | { |
583 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
584 | struct regmap *sysc = clk->priv->sysc; |
585 | u32 t; |
586 | u32 mul; |
587 | u32 div; |
588 | |
589 | regmap_read(map: sysc, SYSC_REG_CPU_SYS_CLKCFG, val: &t); |
590 | mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; |
591 | div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & |
592 | CPU_SYS_CLKCFG_CPU_FDIV_MASK; |
593 | |
594 | return mt7620_calc_rate(ref_rate: parent_rate, mul, div); |
595 | } |
596 | |
597 | static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw, |
598 | unsigned long parent_rate) |
599 | { |
600 | static const u32 ocp_dividers[16] = { |
601 | [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, |
602 | [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, |
603 | [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, |
604 | [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, |
605 | [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, |
606 | }; |
607 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
608 | struct regmap *sysc = clk->priv->sysc; |
609 | u32 t; |
610 | u32 ocp_ratio; |
611 | u32 div; |
612 | |
613 | regmap_read(map: sysc, SYSC_REG_CPU_SYS_CLKCFG, val: &t); |
614 | ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & |
615 | CPU_SYS_CLKCFG_OCP_RATIO_MASK; |
616 | |
617 | if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers))) |
618 | return parent_rate; |
619 | |
620 | div = ocp_dividers[ocp_ratio]; |
621 | |
622 | if (WARN(!div, "invalid divider for OCP ratio %u" , ocp_ratio)) |
623 | return parent_rate; |
624 | |
625 | return parent_rate / div; |
626 | } |
627 | |
628 | static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw, |
629 | unsigned long parent_rate) |
630 | { |
631 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
632 | struct regmap *sysc = clk->priv->sysc; |
633 | u32 t; |
634 | |
635 | regmap_read(map: sysc, SYSC_REG_CLKCFG0, val: &t); |
636 | if (t & CLKCFG0_PERI_CLK_SEL) |
637 | return parent_rate; |
638 | |
639 | return 40000000; |
640 | } |
641 | |
642 | static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw, |
643 | unsigned long parent_rate) |
644 | { |
645 | struct mtmips_clk *clk = to_mtmips_clk(hw); |
646 | struct regmap *sysc = clk->priv->sysc; |
647 | u32 t; |
648 | |
649 | regmap_read(map: sysc, SYSC_REG_SYSTEM_CONFIG, val: &t); |
650 | if (t & MT7620_XTAL_FREQ_SEL) |
651 | return 40000000; |
652 | |
653 | return 20000000; |
654 | } |
655 | |
656 | static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw, |
657 | unsigned long xtal_clk) |
658 | { |
659 | if (xtal_clk == 40000000) |
660 | return 580000000; |
661 | |
662 | return 575000000; |
663 | } |
664 | |
665 | #define CLK_BASE(_name, _parent, _recalc) { \ |
666 | .init = &(const struct clk_init_data) { \ |
667 | .name = _name, \ |
668 | .ops = &(const struct clk_ops) { \ |
669 | .recalc_rate = _recalc, \ |
670 | }, \ |
671 | .parent_data = &(const struct clk_parent_data) { \ |
672 | .name = _parent, \ |
673 | .fw_name = _parent \ |
674 | }, \ |
675 | .num_parents = _parent ? 1 : 0 \ |
676 | }, \ |
677 | } |
678 | |
679 | static struct mtmips_clk rt2880_clks_base[] = { |
680 | { CLK_BASE("cpu" , "xtal" , rt2880_cpu_recalc_rate) } |
681 | }; |
682 | |
683 | static struct mtmips_clk rt305x_clks_base[] = { |
684 | { CLK_BASE("cpu" , "xtal" , rt305x_cpu_recalc_rate) } |
685 | }; |
686 | |
687 | static struct mtmips_clk rt3352_clks_base[] = { |
688 | { CLK_BASE("xtal" , NULL, rt5350_xtal_recalc_rate) }, |
689 | { CLK_BASE("cpu" , "xtal" , rt3352_cpu_recalc_rate) } |
690 | }; |
691 | |
692 | static struct mtmips_clk rt3883_clks_base[] = { |
693 | { CLK_BASE("cpu" , "xtal" , rt3883_cpu_recalc_rate) }, |
694 | { CLK_BASE("bus" , "cpu" , rt3883_bus_recalc_rate) } |
695 | }; |
696 | |
697 | static struct mtmips_clk rt5350_clks_base[] = { |
698 | { CLK_BASE("xtal" , NULL, rt5350_xtal_recalc_rate) }, |
699 | { CLK_BASE("cpu" , "xtal" , rt5350_cpu_recalc_rate) }, |
700 | { CLK_BASE("bus" , "cpu" , rt5350_bus_recalc_rate) } |
701 | }; |
702 | |
703 | static struct mtmips_clk mt7620_clks_base[] = { |
704 | { CLK_BASE("xtal" , NULL, mt76x8_xtal_recalc_rate) }, |
705 | { CLK_BASE("pll" , "xtal" , mt7620_pll_recalc_rate) }, |
706 | { CLK_BASE("cpu" , "pll" , mt7620_cpu_recalc_rate) }, |
707 | { CLK_BASE("periph" , "xtal" , mt7620_periph_recalc_rate) }, |
708 | { CLK_BASE("bus" , "cpu" , mt7620_bus_recalc_rate) } |
709 | }; |
710 | |
711 | static struct mtmips_clk mt76x8_clks_base[] = { |
712 | { CLK_BASE("xtal" , NULL, mt76x8_xtal_recalc_rate) }, |
713 | { CLK_BASE("cpu" , "xtal" , mt76x8_cpu_recalc_rate) } |
714 | }; |
715 | |
716 | static int mtmips_register_clocks(struct device_node *np, |
717 | struct clk_hw_onecell_data *clk_data, |
718 | struct mtmips_clk_priv *priv) |
719 | { |
720 | struct clk_hw **hws = clk_data->hws; |
721 | struct mtmips_clk *sclk; |
722 | int ret, i; |
723 | |
724 | for (i = 0; i < priv->data->num_clk_base; i++) { |
725 | sclk = &priv->data->clk_base[i]; |
726 | sclk->priv = priv; |
727 | ret = of_clk_hw_register(node: np, hw: &sclk->hw); |
728 | if (ret) { |
729 | pr_err("Couldn't register top clock %i\n" , i); |
730 | goto err_clk_unreg; |
731 | } |
732 | |
733 | hws[i] = &sclk->hw; |
734 | } |
735 | |
736 | return 0; |
737 | |
738 | err_clk_unreg: |
739 | while (--i >= 0) { |
740 | sclk = &priv->data->clk_base[i]; |
741 | clk_hw_unregister(hw: &sclk->hw); |
742 | } |
743 | return ret; |
744 | } |
745 | |
746 | static const struct mtmips_clk_data rt2880_clk_data = { |
747 | .clk_base = rt2880_clks_base, |
748 | .num_clk_base = ARRAY_SIZE(rt2880_clks_base), |
749 | .clk_fixed = rt305x_fixed_clocks, |
750 | .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), |
751 | .clk_factor = rt2880_factor_clocks, |
752 | .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks), |
753 | .clk_periph = rt2880_pherip_clks, |
754 | .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks), |
755 | }; |
756 | |
757 | static const struct mtmips_clk_data rt305x_clk_data = { |
758 | .clk_base = rt305x_clks_base, |
759 | .num_clk_base = ARRAY_SIZE(rt305x_clks_base), |
760 | .clk_fixed = rt305x_fixed_clocks, |
761 | .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), |
762 | .clk_factor = rt305x_factor_clocks, |
763 | .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), |
764 | .clk_periph = rt305x_pherip_clks, |
765 | .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks), |
766 | }; |
767 | |
768 | static const struct mtmips_clk_data rt3352_clk_data = { |
769 | .clk_base = rt3352_clks_base, |
770 | .num_clk_base = ARRAY_SIZE(rt3352_clks_base), |
771 | .clk_fixed = rt3352_fixed_clocks, |
772 | .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), |
773 | .clk_factor = rt305x_factor_clocks, |
774 | .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), |
775 | .clk_periph = rt5350_pherip_clks, |
776 | .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), |
777 | }; |
778 | |
779 | static const struct mtmips_clk_data rt3883_clk_data = { |
780 | .clk_base = rt3883_clks_base, |
781 | .num_clk_base = ARRAY_SIZE(rt3883_clks_base), |
782 | .clk_fixed = rt305x_fixed_clocks, |
783 | .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), |
784 | .clk_factor = NULL, |
785 | .num_clk_factor = 0, |
786 | .clk_periph = rt5350_pherip_clks, |
787 | .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), |
788 | }; |
789 | |
790 | static const struct mtmips_clk_data rt5350_clk_data = { |
791 | .clk_base = rt5350_clks_base, |
792 | .num_clk_base = ARRAY_SIZE(rt5350_clks_base), |
793 | .clk_fixed = rt3352_fixed_clocks, |
794 | .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), |
795 | .clk_factor = NULL, |
796 | .num_clk_factor = 0, |
797 | .clk_periph = rt5350_pherip_clks, |
798 | .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), |
799 | }; |
800 | |
801 | static const struct mtmips_clk_data mt7620_clk_data = { |
802 | .clk_base = mt7620_clks_base, |
803 | .num_clk_base = ARRAY_SIZE(mt7620_clks_base), |
804 | .clk_fixed = NULL, |
805 | .num_clk_fixed = 0, |
806 | .clk_factor = NULL, |
807 | .num_clk_factor = 0, |
808 | .clk_periph = mt7620_pherip_clks, |
809 | .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks), |
810 | }; |
811 | |
812 | static const struct mtmips_clk_data mt76x8_clk_data = { |
813 | .clk_base = mt76x8_clks_base, |
814 | .num_clk_base = ARRAY_SIZE(mt76x8_clks_base), |
815 | .clk_fixed = mt76x8_fixed_clocks, |
816 | .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks), |
817 | .clk_factor = rt305x_factor_clocks, |
818 | .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), |
819 | .clk_periph = mt76x8_pherip_clks, |
820 | .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks), |
821 | }; |
822 | |
823 | static const struct of_device_id mtmips_of_match[] = { |
824 | { |
825 | .compatible = "ralink,rt2880-reset" , |
826 | .data = NULL, |
827 | }, |
828 | { |
829 | .compatible = "ralink,rt2880-sysc" , |
830 | .data = &rt2880_clk_data, |
831 | }, |
832 | { |
833 | .compatible = "ralink,rt3050-sysc" , |
834 | .data = &rt305x_clk_data, |
835 | }, |
836 | { |
837 | .compatible = "ralink,rt3052-sysc" , |
838 | .data = &rt305x_clk_data, |
839 | }, |
840 | { |
841 | .compatible = "ralink,rt3352-sysc" , |
842 | .data = &rt3352_clk_data, |
843 | }, |
844 | { |
845 | .compatible = "ralink,rt3883-sysc" , |
846 | .data = &rt3883_clk_data, |
847 | }, |
848 | { |
849 | .compatible = "ralink,rt5350-sysc" , |
850 | .data = &rt5350_clk_data, |
851 | }, |
852 | { |
853 | .compatible = "ralink,mt7620-sysc" , |
854 | .data = &mt7620_clk_data, |
855 | }, |
856 | { |
857 | .compatible = "ralink,mt7628-sysc" , |
858 | .data = &mt76x8_clk_data, |
859 | }, |
860 | { |
861 | .compatible = "ralink,mt7688-sysc" , |
862 | .data = &mt76x8_clk_data, |
863 | }, |
864 | {} |
865 | }; |
866 | |
867 | static void __init mtmips_clk_regs_init(struct device_node *node, |
868 | struct mtmips_clk_priv *priv) |
869 | { |
870 | u32 t; |
871 | |
872 | if (!of_device_is_compatible(device: node, "ralink,mt7620-sysc" )) |
873 | return; |
874 | |
875 | /* |
876 | * When the CPU goes into sleep mode, the BUS |
877 | * clock will be too low for USB to function properly. |
878 | * Adjust the busses fractional divider to fix this |
879 | */ |
880 | regmap_read(map: priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, val: &t); |
881 | t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); |
882 | t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; |
883 | regmap_write(map: priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, val: t); |
884 | } |
885 | |
886 | static void __init mtmips_clk_init(struct device_node *node) |
887 | { |
888 | const struct of_device_id *match; |
889 | const struct mtmips_clk_data *data; |
890 | struct mtmips_clk_priv *priv; |
891 | struct clk_hw_onecell_data *clk_data; |
892 | int ret, i, count; |
893 | |
894 | priv = kzalloc(size: sizeof(*priv), GFP_KERNEL); |
895 | if (!priv) |
896 | return; |
897 | |
898 | priv->sysc = syscon_node_to_regmap(np: node); |
899 | if (IS_ERR(ptr: priv->sysc)) { |
900 | pr_err("Could not get sysc syscon regmap\n" ); |
901 | goto free_clk_priv; |
902 | } |
903 | |
904 | mtmips_clk_regs_init(node, priv); |
905 | |
906 | match = of_match_node(matches: mtmips_of_match, node); |
907 | if (WARN_ON(!match)) |
908 | return; |
909 | |
910 | data = match->data; |
911 | priv->data = data; |
912 | count = priv->data->num_clk_base + priv->data->num_clk_fixed + |
913 | priv->data->num_clk_factor + priv->data->num_clk_periph; |
914 | clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL); |
915 | if (!clk_data) |
916 | goto free_clk_priv; |
917 | |
918 | ret = mtmips_register_clocks(np: node, clk_data, priv); |
919 | if (ret) { |
920 | pr_err("Couldn't register top clocks\n" ); |
921 | goto free_clk_data; |
922 | } |
923 | |
924 | ret = mtmips_register_fixed_clocks(clk_data, priv); |
925 | if (ret) { |
926 | pr_err("Couldn't register fixed clocks\n" ); |
927 | goto unreg_clk_top; |
928 | } |
929 | |
930 | ret = mtmips_register_factor_clocks(clk_data, priv); |
931 | if (ret) { |
932 | pr_err("Couldn't register factor clocks\n" ); |
933 | goto unreg_clk_fixed; |
934 | } |
935 | |
936 | ret = mtmips_register_pherip_clocks(np: node, clk_data, priv); |
937 | if (ret) { |
938 | pr_err("Couldn't register peripheral clocks\n" ); |
939 | goto unreg_clk_factor; |
940 | } |
941 | |
942 | clk_data->num = count; |
943 | |
944 | ret = of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data); |
945 | if (ret) { |
946 | pr_err("Couldn't add clk hw provider\n" ); |
947 | goto unreg_clk_periph; |
948 | } |
949 | |
950 | return; |
951 | |
952 | unreg_clk_periph: |
953 | for (i = 0; i < priv->data->num_clk_periph; i++) { |
954 | struct mtmips_clk *sclk = &priv->data->clk_periph[i]; |
955 | |
956 | clk_hw_unregister(hw: &sclk->hw); |
957 | } |
958 | |
959 | unreg_clk_factor: |
960 | for (i = 0; i < priv->data->num_clk_factor; i++) { |
961 | struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i]; |
962 | |
963 | clk_hw_unregister_fixed_factor(hw: sclk->hw); |
964 | } |
965 | |
966 | unreg_clk_fixed: |
967 | for (i = 0; i < priv->data->num_clk_fixed; i++) { |
968 | struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i]; |
969 | |
970 | clk_hw_unregister_fixed_rate(hw: sclk->hw); |
971 | } |
972 | |
973 | unreg_clk_top: |
974 | for (i = 0; i < priv->data->num_clk_base; i++) { |
975 | struct mtmips_clk *sclk = &priv->data->clk_base[i]; |
976 | |
977 | clk_hw_unregister(hw: &sclk->hw); |
978 | } |
979 | |
980 | free_clk_data: |
981 | kfree(objp: clk_data); |
982 | |
983 | free_clk_priv: |
984 | kfree(objp: priv); |
985 | } |
986 | CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc" , mtmips_clk_init); |
987 | CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc" , mtmips_clk_init); |
988 | CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc" , mtmips_clk_init); |
989 | CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc" , mtmips_clk_init); |
990 | CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc" , mtmips_clk_init); |
991 | CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc" , mtmips_clk_init); |
992 | CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc" , mtmips_clk_init); |
993 | CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc" , mtmips_clk_init); |
994 | CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc" , mtmips_clk_init); |
995 | |
996 | struct mtmips_rst { |
997 | struct reset_controller_dev rcdev; |
998 | struct regmap *sysc; |
999 | }; |
1000 | |
1001 | static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev) |
1002 | { |
1003 | return container_of(dev, struct mtmips_rst, rcdev); |
1004 | } |
1005 | |
1006 | static int mtmips_assert_device(struct reset_controller_dev *rcdev, |
1007 | unsigned long id) |
1008 | { |
1009 | struct mtmips_rst *data = to_mtmips_rst(dev: rcdev); |
1010 | struct regmap *sysc = data->sysc; |
1011 | |
1012 | return regmap_update_bits(map: sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); |
1013 | } |
1014 | |
1015 | static int mtmips_deassert_device(struct reset_controller_dev *rcdev, |
1016 | unsigned long id) |
1017 | { |
1018 | struct mtmips_rst *data = to_mtmips_rst(dev: rcdev); |
1019 | struct regmap *sysc = data->sysc; |
1020 | |
1021 | return regmap_update_bits(map: sysc, SYSC_REG_RESET_CTRL, BIT(id), val: 0); |
1022 | } |
1023 | |
1024 | static int mtmips_reset_device(struct reset_controller_dev *rcdev, |
1025 | unsigned long id) |
1026 | { |
1027 | int ret; |
1028 | |
1029 | ret = mtmips_assert_device(rcdev, id); |
1030 | if (ret < 0) |
1031 | return ret; |
1032 | |
1033 | return mtmips_deassert_device(rcdev, id); |
1034 | } |
1035 | |
1036 | static int mtmips_rst_xlate(struct reset_controller_dev *rcdev, |
1037 | const struct of_phandle_args *reset_spec) |
1038 | { |
1039 | unsigned long id = reset_spec->args[0]; |
1040 | |
1041 | if (id == 0 || id >= rcdev->nr_resets) |
1042 | return -EINVAL; |
1043 | |
1044 | return id; |
1045 | } |
1046 | |
1047 | static const struct reset_control_ops reset_ops = { |
1048 | .reset = mtmips_reset_device, |
1049 | .assert = mtmips_assert_device, |
1050 | .deassert = mtmips_deassert_device |
1051 | }; |
1052 | |
1053 | static int mtmips_reset_init(struct device *dev, struct regmap *sysc) |
1054 | { |
1055 | struct mtmips_rst *rst_data; |
1056 | |
1057 | rst_data = devm_kzalloc(dev, size: sizeof(*rst_data), GFP_KERNEL); |
1058 | if (!rst_data) |
1059 | return -ENOMEM; |
1060 | |
1061 | rst_data->sysc = sysc; |
1062 | rst_data->rcdev.ops = &reset_ops; |
1063 | rst_data->rcdev.owner = THIS_MODULE; |
1064 | rst_data->rcdev.nr_resets = 32; |
1065 | rst_data->rcdev.of_reset_n_cells = 1; |
1066 | rst_data->rcdev.of_xlate = mtmips_rst_xlate; |
1067 | rst_data->rcdev.of_node = dev_of_node(dev); |
1068 | |
1069 | return devm_reset_controller_register(dev, rcdev: &rst_data->rcdev); |
1070 | } |
1071 | |
1072 | static int mtmips_clk_probe(struct platform_device *pdev) |
1073 | { |
1074 | struct device_node *np = pdev->dev.of_node; |
1075 | struct device *dev = &pdev->dev; |
1076 | struct mtmips_clk_priv *priv; |
1077 | int ret; |
1078 | |
1079 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
1080 | if (!priv) |
1081 | return -ENOMEM; |
1082 | |
1083 | priv->sysc = syscon_node_to_regmap(np); |
1084 | if (IS_ERR(ptr: priv->sysc)) |
1085 | return dev_err_probe(dev, err: PTR_ERR(ptr: priv->sysc), |
1086 | fmt: "Could not get sysc syscon regmap\n" ); |
1087 | |
1088 | ret = mtmips_reset_init(dev, sysc: priv->sysc); |
1089 | if (ret) |
1090 | return dev_err_probe(dev, err: ret, fmt: "Could not init reset controller\n" ); |
1091 | |
1092 | return 0; |
1093 | } |
1094 | |
1095 | static struct platform_driver mtmips_clk_driver = { |
1096 | .probe = mtmips_clk_probe, |
1097 | .driver = { |
1098 | .name = "mtmips-clk" , |
1099 | .of_match_table = mtmips_of_match, |
1100 | }, |
1101 | }; |
1102 | |
1103 | static int __init mtmips_clk_reset_init(void) |
1104 | { |
1105 | return platform_driver_register(&mtmips_clk_driver); |
1106 | } |
1107 | arch_initcall(mtmips_clk_reset_init); |
1108 | |