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.h> 14 #include <linux/clk-provider.h> 15 #include <linux/io.h> 16 #include <linux/of_address.h> 17 #include <linux/clkdev.h> 18 19 static void __init moxart_of_pll_clk_init(struct device_node *node) 20 { 21 static void __iomem *base; 22 struct clk *clk, *ref_clk; 23 unsigned int mul; 24 const char *name = node->name; 25 const char *parent_name; 26 27 of_property_read_string(node, "clock-output-names", &name); 28 parent_name = of_clk_get_parent_name(node, 0); 29 30 base = of_iomap(node, 0); 31 if (!base) { 32 pr_err("%s: of_iomap failed\n", node->full_name); 33 return; 34 } 35 36 mul = readl(base + 0x30) >> 3 & 0x3f; 37 iounmap(base); 38 39 ref_clk = of_clk_get(node, 0); 40 if (IS_ERR(ref_clk)) { 41 pr_err("%s: of_clk_get failed\n", node->full_name); 42 return; 43 } 44 45 clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); 46 if (IS_ERR(clk)) { 47 pr_err("%s: failed to register clock\n", node->full_name); 48 return; 49 } 50 51 clk_register_clkdev(clk, NULL, name); 52 of_clk_add_provider(node, of_clk_src_simple_get, clk); 53 } 54 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", 55 moxart_of_pll_clk_init); 56 57 static void __init moxart_of_apb_clk_init(struct device_node *node) 58 { 59 static void __iomem *base; 60 struct clk *clk, *pll_clk; 61 unsigned int div, val; 62 unsigned int div_idx[] = { 2, 3, 4, 6, 8}; 63 const char *name = node->name; 64 const char *parent_name; 65 66 of_property_read_string(node, "clock-output-names", &name); 67 parent_name = of_clk_get_parent_name(node, 0); 68 69 base = of_iomap(node, 0); 70 if (!base) { 71 pr_err("%s: of_iomap failed\n", node->full_name); 72 return; 73 } 74 75 val = readl(base + 0xc) >> 4 & 0x7; 76 iounmap(base); 77 78 if (val > 4) 79 val = 0; 80 div = div_idx[val] * 2; 81 82 pll_clk = of_clk_get(node, 0); 83 if (IS_ERR(pll_clk)) { 84 pr_err("%s: of_clk_get failed\n", node->full_name); 85 return; 86 } 87 88 clk = clk_register_fixed_factor(NULL, name, parent_name, 0, 1, div); 89 if (IS_ERR(clk)) { 90 pr_err("%s: failed to register clock\n", node->full_name); 91 return; 92 } 93 94 clk_register_clkdev(clk, NULL, name); 95 of_clk_add_provider(node, of_clk_src_simple_get, clk); 96 } 97 CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", 98 moxart_of_apb_clk_init); 99