Merge tag 'for-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power...
[linux-block.git] / drivers / clk / clk-moxart.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * MOXA ART SoCs clock driver.
4  *
5  * Copyright (C) 2013 Jonas Jensen
6  *
7  * Jonas Jensen <jonas.jensen@gmail.com>
8  */
9
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/io.h>
13 #include <linux/of_address.h>
14 #include <linux/clkdev.h>
15
16 static void __init moxart_of_pll_clk_init(struct device_node *node)
17 {
18         void __iomem *base;
19         struct clk_hw *hw;
20         struct clk *ref_clk;
21         unsigned int mul;
22         const char *name = node->name;
23         const char *parent_name;
24
25         of_property_read_string(node, "clock-output-names", &name);
26         parent_name = of_clk_get_parent_name(node, 0);
27
28         base = of_iomap(node, 0);
29         if (!base) {
30                 pr_err("%pOF: of_iomap failed\n", node);
31                 return;
32         }
33
34         mul = readl(base + 0x30) >> 3 & 0x3f;
35         iounmap(base);
36
37         ref_clk = of_clk_get(node, 0);
38         if (IS_ERR(ref_clk)) {
39                 pr_err("%pOF: of_clk_get failed\n", node);
40                 return;
41         }
42
43         hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
44         if (IS_ERR(hw)) {
45                 pr_err("%pOF: failed to register clock\n", node);
46                 return;
47         }
48
49         clk_hw_register_clkdev(hw, NULL, name);
50         of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
51 }
52 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
53                moxart_of_pll_clk_init);
54
55 static void __init moxart_of_apb_clk_init(struct device_node *node)
56 {
57         void __iomem *base;
58         struct clk_hw *hw;
59         struct clk *pll_clk;
60         unsigned int div, val;
61         unsigned int div_idx[] = { 2, 3, 4, 6, 8};
62         const char *name = node->name;
63         const char *parent_name;
64
65         of_property_read_string(node, "clock-output-names", &name);
66         parent_name = of_clk_get_parent_name(node, 0);
67
68         base = of_iomap(node, 0);
69         if (!base) {
70                 pr_err("%pOF: of_iomap failed\n", node);
71                 return;
72         }
73
74         val = readl(base + 0xc) >> 4 & 0x7;
75         iounmap(base);
76
77         if (val > 4)
78                 val = 0;
79         div = div_idx[val] * 2;
80
81         pll_clk = of_clk_get(node, 0);
82         if (IS_ERR(pll_clk)) {
83                 pr_err("%pOF: of_clk_get failed\n", node);
84                 return;
85         }
86
87         hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
88         if (IS_ERR(hw)) {
89                 pr_err("%pOF: failed to register clock\n", node);
90                 return;
91         }
92
93         clk_hw_register_clkdev(hw, NULL, name);
94         of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
95 }
96 CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock",
97                moxart_of_apb_clk_init);