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