xref: /linux/drivers/clk/clk-moxart.c (revision c0e297dc61f8d4453e07afbea1fa8d0e67cd4a34)
1 /*
2  * MOXA ART SoCs clock driver.
3  *
4  * Copyright (C) 2013 Jonas Jensen
5  *
6  * Jonas Jensen <jonas.jensen@gmail.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2.  This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12 
13 #include <linux/clk-provider.h>
14 #include <linux/io.h>
15 #include <linux/of_address.h>
16 #include <linux/clkdev.h>
17 
18 static void __init moxart_of_pll_clk_init(struct device_node *node)
19 {
20 	static void __iomem *base;
21 	struct clk *clk, *ref_clk;
22 	unsigned int mul;
23 	const char *name = node->name;
24 	const char *parent_name;
25 
26 	of_property_read_string(node, "clock-output-names", &name);
27 	parent_name = of_clk_get_parent_name(node, 0);
28 
29 	base = of_iomap(node, 0);
30 	if (!base) {
31 		pr_err("%s: of_iomap failed\n", node->full_name);
32 		return;
33 	}
34 
35 	mul = readl(base + 0x30) >> 3 & 0x3f;
36 	iounmap(base);
37 
38 	ref_clk = of_clk_get(node, 0);
39 	if (IS_ERR(ref_clk)) {
40 		pr_err("%s: of_clk_get failed\n", node->full_name);
41 		return;
42 	}
43 
44 	clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
45 	if (IS_ERR(clk)) {
46 		pr_err("%s: failed to register clock\n", node->full_name);
47 		return;
48 	}
49 
50 	clk_register_clkdev(clk, NULL, name);
51 	of_clk_add_provider(node, of_clk_src_simple_get, clk);
52 }
53 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
54 	       moxart_of_pll_clk_init);
55 
56 static void __init moxart_of_apb_clk_init(struct device_node *node)
57 {
58 	static void __iomem *base;
59 	struct clk *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("%s: of_iomap failed\n", node->full_name);
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("%s: of_clk_get failed\n", node->full_name);
84 		return;
85 	}
86 
87 	clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
88 	if (IS_ERR(clk)) {
89 		pr_err("%s: failed to register clock\n", node->full_name);
90 		return;
91 	}
92 
93 	clk_register_clkdev(clk, NULL, name);
94 	of_clk_add_provider(node, of_clk_src_simple_get, clk);
95 }
96 CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock",
97 	       moxart_of_apb_clk_init);
98