Merge tag 'dt-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / clk / clk-axm5516.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * drivers/clk/clk-axm5516.c
4  *
5  * Provides clock implementations for three different types of clock devices on
6  * the Axxia device: PLL clock, a clock divider and a clock mux.
7  *
8  * Copyright (C) 2014 LSI Corporation
9  */
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/platform_device.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/clk-provider.h>
17 #include <linux/regmap.h>
18 #include <dt-bindings/clock/lsi,axm5516-clks.h>
19
20
21 /**
22  * struct axxia_clk - Common struct to all Axxia clocks.
23  * @hw: clk_hw for the common clk framework
24  * @regmap: Regmap for the clock control registers
25  */
26 struct axxia_clk {
27         struct clk_hw hw;
28         struct regmap *regmap;
29 };
30 #define to_axxia_clk(_hw) container_of(_hw, struct axxia_clk, hw)
31
32 /**
33  * struct axxia_pllclk - Axxia PLL generated clock.
34  * @aclk: Common struct
35  * @reg: Offset into regmap for PLL control register
36  */
37 struct axxia_pllclk {
38         struct axxia_clk aclk;
39         u32 reg;
40 };
41 #define to_axxia_pllclk(_aclk) container_of(_aclk, struct axxia_pllclk, aclk)
42
43 /**
44  * axxia_pllclk_recalc - Calculate the PLL generated clock rate given the
45  * parent clock rate.
46  */
47 static unsigned long
48 axxia_pllclk_recalc(struct clk_hw *hw, unsigned long parent_rate)
49 {
50         struct axxia_clk *aclk = to_axxia_clk(hw);
51         struct axxia_pllclk *pll = to_axxia_pllclk(aclk);
52         unsigned long rate, fbdiv, refdiv, postdiv;
53         u32 control;
54
55         regmap_read(aclk->regmap, pll->reg, &control);
56         postdiv = ((control >> 0) & 0xf) + 1;
57         fbdiv   = ((control >> 4) & 0xfff) + 3;
58         refdiv  = ((control >> 16) & 0x1f) + 1;
59         rate = (parent_rate / (refdiv * postdiv)) * fbdiv;
60
61         return rate;
62 }
63
64 static const struct clk_ops axxia_pllclk_ops = {
65         .recalc_rate = axxia_pllclk_recalc,
66 };
67
68 /**
69  * struct axxia_divclk - Axxia clock divider
70  * @aclk: Common struct
71  * @reg: Offset into regmap for PLL control register
72  * @shift: Bit position for divider value
73  * @width: Number of bits in divider value
74  */
75 struct axxia_divclk {
76         struct axxia_clk aclk;
77         u32 reg;
78         u32 shift;
79         u32 width;
80 };
81 #define to_axxia_divclk(_aclk) container_of(_aclk, struct axxia_divclk, aclk)
82
83 /**
84  * axxia_divclk_recalc_rate - Calculate clock divider output rage
85  */
86 static unsigned long
87 axxia_divclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
88 {
89         struct axxia_clk *aclk = to_axxia_clk(hw);
90         struct axxia_divclk *divclk = to_axxia_divclk(aclk);
91         u32 ctrl, div;
92
93         regmap_read(aclk->regmap, divclk->reg, &ctrl);
94         div = 1 + ((ctrl >> divclk->shift) & ((1 << divclk->width)-1));
95
96         return parent_rate / div;
97 }
98
99 static const struct clk_ops axxia_divclk_ops = {
100         .recalc_rate = axxia_divclk_recalc_rate,
101 };
102
103 /**
104  * struct axxia_clkmux - Axxia clock mux
105  * @aclk: Common struct
106  * @reg: Offset into regmap for PLL control register
107  * @shift: Bit position for selection value
108  * @width: Number of bits in selection value
109  */
110 struct axxia_clkmux {
111         struct axxia_clk aclk;
112         u32 reg;
113         u32 shift;
114         u32 width;
115 };
116 #define to_axxia_clkmux(_aclk) container_of(_aclk, struct axxia_clkmux, aclk)
117
118 /**
119  * axxia_clkmux_get_parent - Return the index of selected parent clock
120  */
121 static u8 axxia_clkmux_get_parent(struct clk_hw *hw)
122 {
123         struct axxia_clk *aclk = to_axxia_clk(hw);
124         struct axxia_clkmux *mux = to_axxia_clkmux(aclk);
125         u32 ctrl, parent;
126
127         regmap_read(aclk->regmap, mux->reg, &ctrl);
128         parent = (ctrl >> mux->shift) & ((1 << mux->width) - 1);
129
130         return (u8) parent;
131 }
132
133 static const struct clk_ops axxia_clkmux_ops = {
134         .get_parent = axxia_clkmux_get_parent,
135 };
136
137
138 /*
139  * PLLs
140  */
141
142 static struct axxia_pllclk clk_fab_pll = {
143         .aclk.hw.init = &(struct clk_init_data){
144                 .name = "clk_fab_pll",
145                 .parent_names = (const char *[]){
146                         "clk_ref0"
147                 },
148                 .num_parents = 1,
149                 .ops = &axxia_pllclk_ops,
150         },
151         .reg   = 0x01800,
152 };
153
154 static struct axxia_pllclk clk_cpu_pll = {
155         .aclk.hw.init = &(struct clk_init_data){
156                 .name = "clk_cpu_pll",
157                 .parent_names = (const char *[]){
158                         "clk_ref0"
159                 },
160                 .num_parents = 1,
161                 .ops = &axxia_pllclk_ops,
162         },
163         .reg   = 0x02000,
164 };
165
166 static struct axxia_pllclk clk_sys_pll = {
167         .aclk.hw.init = &(struct clk_init_data){
168                 .name = "clk_sys_pll",
169                 .parent_names = (const char *[]){
170                         "clk_ref0"
171                 },
172                 .num_parents = 1,
173                 .ops = &axxia_pllclk_ops,
174         },
175         .reg   = 0x02800,
176 };
177
178 static struct axxia_pllclk clk_sm0_pll = {
179         .aclk.hw.init = &(struct clk_init_data){
180                 .name = "clk_sm0_pll",
181                 .parent_names = (const char *[]){
182                         "clk_ref2"
183                 },
184                 .num_parents = 1,
185                 .ops = &axxia_pllclk_ops,
186         },
187         .reg   = 0x03000,
188 };
189
190 static struct axxia_pllclk clk_sm1_pll = {
191         .aclk.hw.init = &(struct clk_init_data){
192                 .name = "clk_sm1_pll",
193                 .parent_names = (const char *[]){
194                         "clk_ref1"
195                 },
196                 .num_parents = 1,
197                 .ops = &axxia_pllclk_ops,
198         },
199         .reg   = 0x03800,
200 };
201
202 /*
203  * Clock dividers
204  */
205
206 static struct axxia_divclk clk_cpu0_div = {
207         .aclk.hw.init = &(struct clk_init_data){
208                 .name = "clk_cpu0_div",
209                 .parent_names = (const char *[]){
210                         "clk_cpu_pll"
211                 },
212                 .num_parents = 1,
213                 .ops = &axxia_divclk_ops,
214         },
215         .reg   = 0x10008,
216         .shift = 0,
217         .width = 4,
218 };
219
220 static struct axxia_divclk clk_cpu1_div = {
221         .aclk.hw.init = &(struct clk_init_data){
222                 .name = "clk_cpu1_div",
223                 .parent_names = (const char *[]){
224                         "clk_cpu_pll"
225                 },
226                 .num_parents = 1,
227                 .ops = &axxia_divclk_ops,
228         },
229         .reg   = 0x10008,
230         .shift = 4,
231         .width = 4,
232 };
233
234 static struct axxia_divclk clk_cpu2_div = {
235         .aclk.hw.init = &(struct clk_init_data){
236                 .name = "clk_cpu2_div",
237                 .parent_names = (const char *[]){
238                         "clk_cpu_pll"
239                 },
240                 .num_parents = 1,
241                 .ops = &axxia_divclk_ops,
242         },
243         .reg   = 0x10008,
244         .shift = 8,
245         .width = 4,
246 };
247
248 static struct axxia_divclk clk_cpu3_div = {
249         .aclk.hw.init = &(struct clk_init_data){
250                 .name = "clk_cpu3_div",
251                 .parent_names = (const char *[]){
252                         "clk_cpu_pll"
253                 },
254                 .num_parents = 1,
255                 .ops = &axxia_divclk_ops,
256         },
257         .reg   = 0x10008,
258         .shift = 12,
259         .width = 4,
260 };
261
262 static struct axxia_divclk clk_nrcp_div = {
263         .aclk.hw.init = &(struct clk_init_data){
264                 .name = "clk_nrcp_div",
265                 .parent_names = (const char *[]){
266                         "clk_sys_pll"
267                 },
268                 .num_parents = 1,
269                 .ops = &axxia_divclk_ops,
270         },
271         .reg   = 0x1000c,
272         .shift = 0,
273         .width = 4,
274 };
275
276 static struct axxia_divclk clk_sys_div = {
277         .aclk.hw.init = &(struct clk_init_data){
278                 .name = "clk_sys_div",
279                 .parent_names = (const char *[]){
280                         "clk_sys_pll"
281                 },
282                 .num_parents = 1,
283                 .ops = &axxia_divclk_ops,
284         },
285         .reg   = 0x1000c,
286         .shift = 4,
287         .width = 4,
288 };
289
290 static struct axxia_divclk clk_fab_div = {
291         .aclk.hw.init = &(struct clk_init_data){
292                 .name = "clk_fab_div",
293                 .parent_names = (const char *[]){
294                         "clk_fab_pll"
295                 },
296                 .num_parents = 1,
297                 .ops = &axxia_divclk_ops,
298         },
299         .reg   = 0x1000c,
300         .shift = 8,
301         .width = 4,
302 };
303
304 static struct axxia_divclk clk_per_div = {
305         .aclk.hw.init = &(struct clk_init_data){
306                 .name = "clk_per_div",
307                 .parent_names = (const char *[]){
308                         "clk_sm1_pll"
309                 },
310                 .num_parents = 1,
311                 .ops = &axxia_divclk_ops,
312         },
313         .reg   = 0x1000c,
314         .shift = 12,
315         .width = 4,
316 };
317
318 static struct axxia_divclk clk_mmc_div = {
319         .aclk.hw.init = &(struct clk_init_data){
320                 .name = "clk_mmc_div",
321                 .parent_names = (const char *[]){
322                         "clk_sm1_pll"
323                 },
324                 .num_parents = 1,
325                 .ops = &axxia_divclk_ops,
326         },
327         .reg   = 0x1000c,
328         .shift = 16,
329         .width = 4,
330 };
331
332 /*
333  * Clock MUXes
334  */
335
336 static struct axxia_clkmux clk_cpu0_mux = {
337         .aclk.hw.init = &(struct clk_init_data){
338                 .name = "clk_cpu0",
339                 .parent_names = (const char *[]){
340                         "clk_ref0",
341                         "clk_cpu_pll",
342                         "clk_cpu0_div",
343                         "clk_cpu0_div"
344                 },
345                 .num_parents = 4,
346                 .ops = &axxia_clkmux_ops,
347         },
348         .reg   = 0x10000,
349         .shift = 0,
350         .width = 2,
351 };
352
353 static struct axxia_clkmux clk_cpu1_mux = {
354         .aclk.hw.init = &(struct clk_init_data){
355                 .name = "clk_cpu1",
356                 .parent_names = (const char *[]){
357                         "clk_ref0",
358                         "clk_cpu_pll",
359                         "clk_cpu1_div",
360                         "clk_cpu1_div"
361                 },
362                 .num_parents = 4,
363                 .ops = &axxia_clkmux_ops,
364         },
365         .reg   = 0x10000,
366         .shift = 2,
367         .width = 2,
368 };
369
370 static struct axxia_clkmux clk_cpu2_mux = {
371         .aclk.hw.init = &(struct clk_init_data){
372                 .name = "clk_cpu2",
373                 .parent_names = (const char *[]){
374                         "clk_ref0",
375                         "clk_cpu_pll",
376                         "clk_cpu2_div",
377                         "clk_cpu2_div"
378                 },
379                 .num_parents = 4,
380                 .ops = &axxia_clkmux_ops,
381         },
382         .reg   = 0x10000,
383         .shift = 4,
384         .width = 2,
385 };
386
387 static struct axxia_clkmux clk_cpu3_mux = {
388         .aclk.hw.init = &(struct clk_init_data){
389                 .name = "clk_cpu3",
390                 .parent_names = (const char *[]){
391                         "clk_ref0",
392                         "clk_cpu_pll",
393                         "clk_cpu3_div",
394                         "clk_cpu3_div"
395                 },
396                 .num_parents = 4,
397                 .ops = &axxia_clkmux_ops,
398         },
399         .reg   = 0x10000,
400         .shift = 6,
401         .width = 2,
402 };
403
404 static struct axxia_clkmux clk_nrcp_mux = {
405         .aclk.hw.init = &(struct clk_init_data){
406                 .name = "clk_nrcp",
407                 .parent_names = (const char *[]){
408                         "clk_ref0",
409                         "clk_sys_pll",
410                         "clk_nrcp_div",
411                         "clk_nrcp_div"
412                 },
413                 .num_parents = 4,
414                 .ops = &axxia_clkmux_ops,
415         },
416         .reg   = 0x10004,
417         .shift = 0,
418         .width = 2,
419 };
420
421 static struct axxia_clkmux clk_sys_mux = {
422         .aclk.hw.init = &(struct clk_init_data){
423                 .name = "clk_sys",
424                 .parent_names = (const char *[]){
425                         "clk_ref0",
426                         "clk_sys_pll",
427                         "clk_sys_div",
428                         "clk_sys_div"
429                 },
430                 .num_parents = 4,
431                 .ops = &axxia_clkmux_ops,
432         },
433         .reg   = 0x10004,
434         .shift = 2,
435         .width = 2,
436 };
437
438 static struct axxia_clkmux clk_fab_mux = {
439         .aclk.hw.init = &(struct clk_init_data){
440                 .name = "clk_fab",
441                 .parent_names = (const char *[]){
442                         "clk_ref0",
443                         "clk_fab_pll",
444                         "clk_fab_div",
445                         "clk_fab_div"
446                 },
447                 .num_parents = 4,
448                 .ops = &axxia_clkmux_ops,
449         },
450         .reg   = 0x10004,
451         .shift = 4,
452         .width = 2,
453 };
454
455 static struct axxia_clkmux clk_per_mux = {
456         .aclk.hw.init = &(struct clk_init_data){
457                 .name = "clk_per",
458                 .parent_names = (const char *[]){
459                         "clk_ref1",
460                         "clk_per_div"
461                 },
462                 .num_parents = 2,
463                 .ops = &axxia_clkmux_ops,
464         },
465         .reg   = 0x10004,
466         .shift = 6,
467         .width = 1,
468 };
469
470 static struct axxia_clkmux clk_mmc_mux = {
471         .aclk.hw.init = &(struct clk_init_data){
472                 .name = "clk_mmc",
473                 .parent_names = (const char *[]){
474                         "clk_ref1",
475                         "clk_mmc_div"
476                 },
477                 .num_parents = 2,
478                 .ops = &axxia_clkmux_ops,
479         },
480         .reg   = 0x10004,
481         .shift = 9,
482         .width = 1,
483 };
484
485 /* Table of all supported clocks indexed by the clock identifiers from the
486  * device tree binding
487  */
488 static struct axxia_clk *axmclk_clocks[] = {
489         [AXXIA_CLK_FAB_PLL]  = &clk_fab_pll.aclk,
490         [AXXIA_CLK_CPU_PLL]  = &clk_cpu_pll.aclk,
491         [AXXIA_CLK_SYS_PLL]  = &clk_sys_pll.aclk,
492         [AXXIA_CLK_SM0_PLL]  = &clk_sm0_pll.aclk,
493         [AXXIA_CLK_SM1_PLL]  = &clk_sm1_pll.aclk,
494         [AXXIA_CLK_FAB_DIV]  = &clk_fab_div.aclk,
495         [AXXIA_CLK_SYS_DIV]  = &clk_sys_div.aclk,
496         [AXXIA_CLK_NRCP_DIV] = &clk_nrcp_div.aclk,
497         [AXXIA_CLK_CPU0_DIV] = &clk_cpu0_div.aclk,
498         [AXXIA_CLK_CPU1_DIV] = &clk_cpu1_div.aclk,
499         [AXXIA_CLK_CPU2_DIV] = &clk_cpu2_div.aclk,
500         [AXXIA_CLK_CPU3_DIV] = &clk_cpu3_div.aclk,
501         [AXXIA_CLK_PER_DIV]  = &clk_per_div.aclk,
502         [AXXIA_CLK_MMC_DIV]  = &clk_mmc_div.aclk,
503         [AXXIA_CLK_FAB]      = &clk_fab_mux.aclk,
504         [AXXIA_CLK_SYS]      = &clk_sys_mux.aclk,
505         [AXXIA_CLK_NRCP]     = &clk_nrcp_mux.aclk,
506         [AXXIA_CLK_CPU0]     = &clk_cpu0_mux.aclk,
507         [AXXIA_CLK_CPU1]     = &clk_cpu1_mux.aclk,
508         [AXXIA_CLK_CPU2]     = &clk_cpu2_mux.aclk,
509         [AXXIA_CLK_CPU3]     = &clk_cpu3_mux.aclk,
510         [AXXIA_CLK_PER]      = &clk_per_mux.aclk,
511         [AXXIA_CLK_MMC]      = &clk_mmc_mux.aclk,
512 };
513
514 static struct clk_hw *
515 of_clk_axmclk_get(struct of_phandle_args *clkspec, void *unused)
516 {
517         unsigned int idx = clkspec->args[0];
518
519         if (idx >= ARRAY_SIZE(axmclk_clocks)) {
520                 pr_err("%s: invalid index %u\n", __func__, idx);
521                 return ERR_PTR(-EINVAL);
522         }
523
524         return &axmclk_clocks[idx]->hw;
525 }
526
527 static const struct regmap_config axmclk_regmap_config = {
528         .reg_bits       = 32,
529         .reg_stride     = 4,
530         .val_bits       = 32,
531         .max_register   = 0x1fffc,
532         .fast_io        = true,
533 };
534
535 static const struct of_device_id axmclk_match_table[] = {
536         { .compatible = "lsi,axm5516-clks" },
537         { }
538 };
539 MODULE_DEVICE_TABLE(of, axmclk_match_table);
540
541 static int axmclk_probe(struct platform_device *pdev)
542 {
543         void __iomem *base;
544         struct resource *res;
545         int i, ret;
546         struct device *dev = &pdev->dev;
547         struct regmap *regmap;
548         size_t num_clks;
549
550         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
551         base = devm_ioremap_resource(dev, res);
552         if (IS_ERR(base))
553                 return PTR_ERR(base);
554
555         regmap = devm_regmap_init_mmio(dev, base, &axmclk_regmap_config);
556         if (IS_ERR(regmap))
557                 return PTR_ERR(regmap);
558
559         num_clks = ARRAY_SIZE(axmclk_clocks);
560         pr_info("axmclk: supporting %zu clocks\n", num_clks);
561
562         /* Update each entry with the allocated regmap and register the clock
563          * with the common clock framework
564          */
565         for (i = 0; i < num_clks; i++) {
566                 axmclk_clocks[i]->regmap = regmap;
567                 ret = devm_clk_hw_register(dev, &axmclk_clocks[i]->hw);
568                 if (ret)
569                         return ret;
570         }
571
572         return of_clk_add_hw_provider(dev->of_node, of_clk_axmclk_get, NULL);
573 }
574
575 static int axmclk_remove(struct platform_device *pdev)
576 {
577         of_clk_del_provider(pdev->dev.of_node);
578         return 0;
579 }
580
581 static struct platform_driver axmclk_driver = {
582         .probe          = axmclk_probe,
583         .remove         = axmclk_remove,
584         .driver         = {
585                 .name   = "clk-axm5516",
586                 .of_match_table = axmclk_match_table,
587         },
588 };
589
590 static int __init axmclk_init(void)
591 {
592         return platform_driver_register(&axmclk_driver);
593 }
594 core_initcall(axmclk_init);
595
596 static void __exit axmclk_exit(void)
597 {
598         platform_driver_unregister(&axmclk_driver);
599 }
600 module_exit(axmclk_exit);
601
602 MODULE_DESCRIPTION("AXM5516 clock driver");
603 MODULE_LICENSE("GPL v2");
604 MODULE_ALIAS("platform:clk-axm5516");