xref: /linux/drivers/clk/clk-moxart.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
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 	unsigned int mul;
21 	const char *name = node->name;
22 	const char *parent_name;
23 
24 	of_property_read_string(node, "clock-output-names", &name);
25 	parent_name = of_clk_get_parent_name(node, 0);
26 
27 	base = of_iomap(node, 0);
28 	if (!base) {
29 		pr_err("%pOF: of_iomap failed\n", node);
30 		return;
31 	}
32 
33 	mul = readl(base + 0x30) >> 3 & 0x3f;
34 	iounmap(base);
35 
36 	hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
37 	if (IS_ERR(hw)) {
38 		pr_err("%pOF: failed to register clock\n", node);
39 		return;
40 	}
41 
42 	clk_hw_register_clkdev(hw, NULL, name);
43 	of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
44 }
45 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
46 	       moxart_of_pll_clk_init);
47 
48 static void __init moxart_of_apb_clk_init(struct device_node *node)
49 {
50 	void __iomem *base;
51 	struct clk_hw *hw;
52 	unsigned int div, val;
53 	unsigned int div_idx[] = { 2, 3, 4, 6, 8};
54 	const char *name = node->name;
55 	const char *parent_name;
56 
57 	of_property_read_string(node, "clock-output-names", &name);
58 	parent_name = of_clk_get_parent_name(node, 0);
59 
60 	base = of_iomap(node, 0);
61 	if (!base) {
62 		pr_err("%pOF: of_iomap failed\n", node);
63 		return;
64 	}
65 
66 	val = readl(base + 0xc) >> 4 & 0x7;
67 	iounmap(base);
68 
69 	if (val > 4)
70 		val = 0;
71 	div = div_idx[val] * 2;
72 
73 	hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
74 	if (IS_ERR(hw)) {
75 		pr_err("%pOF: failed to register clock\n", node);
76 		return;
77 	}
78 
79 	clk_hw_register_clkdev(hw, NULL, name);
80 	of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
81 }
82 CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock",
83 	       moxart_of_apb_clk_init);
84