Commit | Line | Data |
---|---|---|
3bb16560 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
c7bb4fc1 JJ |
2 | /* |
3 | * MOXA ART SoCs clock driver. | |
4 | * | |
5 | * Copyright (C) 2013 Jonas Jensen | |
6 | * | |
7 | * Jonas Jensen <jonas.jensen@gmail.com> | |
c7bb4fc1 JJ |
8 | */ |
9 | ||
67bb5408 | 10 | #include <linux/clk.h> |
c7bb4fc1 JJ |
11 | #include <linux/clk-provider.h> |
12 | #include <linux/io.h> | |
13 | #include <linux/of_address.h> | |
14 | #include <linux/clkdev.h> | |
15 | ||
61ad23a1 | 16 | static void __init moxart_of_pll_clk_init(struct device_node *node) |
c7bb4fc1 | 17 | { |
c8108cf2 | 18 | void __iomem *base; |
5a962d2e SB |
19 | struct clk_hw *hw; |
20 | struct clk *ref_clk; | |
c7bb4fc1 JJ |
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) { | |
16673931 | 30 | pr_err("%pOF: of_iomap failed\n", node); |
c7bb4fc1 JJ |
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)) { | |
16673931 | 39 | pr_err("%pOF: of_clk_get failed\n", node); |
c7bb4fc1 JJ |
40 | return; |
41 | } | |
42 | ||
5a962d2e SB |
43 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); |
44 | if (IS_ERR(hw)) { | |
16673931 | 45 | pr_err("%pOF: failed to register clock\n", node); |
c7bb4fc1 JJ |
46 | return; |
47 | } | |
48 | ||
5a962d2e SB |
49 | clk_hw_register_clkdev(hw, NULL, name); |
50 | of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); | |
c7bb4fc1 JJ |
51 | } |
52 | CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", | |
53 | moxart_of_pll_clk_init); | |
54 | ||
61ad23a1 | 55 | static void __init moxart_of_apb_clk_init(struct device_node *node) |
c7bb4fc1 | 56 | { |
c8108cf2 | 57 | void __iomem *base; |
5a962d2e SB |
58 | struct clk_hw *hw; |
59 | struct clk *pll_clk; | |
c7bb4fc1 JJ |
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) { | |
16673931 | 70 | pr_err("%pOF: of_iomap failed\n", node); |
c7bb4fc1 JJ |
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)) { | |
16673931 | 83 | pr_err("%pOF: of_clk_get failed\n", node); |
c7bb4fc1 JJ |
84 | return; |
85 | } | |
86 | ||
5a962d2e SB |
87 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div); |
88 | if (IS_ERR(hw)) { | |
16673931 | 89 | pr_err("%pOF: failed to register clock\n", node); |
c7bb4fc1 JJ |
90 | return; |
91 | } | |
92 | ||
5a962d2e SB |
93 | clk_hw_register_clkdev(hw, NULL, name); |
94 | of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); | |
c7bb4fc1 JJ |
95 | } |
96 | CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", | |
97 | moxart_of_apb_clk_init); |