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 struct clk *ref_clk; 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) { 30 pr_err("%pOF: of_iomap failed\n", node); 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)) { 39 pr_err("%pOF: of_clk_get failed\n", node); 40 return; 41 } 42 43 hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); 44 if (IS_ERR(hw)) { 45 pr_err("%pOF: failed to register clock\n", node); 46 return; 47 } 48 49 clk_hw_register_clkdev(hw, NULL, name); 50 of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); 51 } 52 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", 53 moxart_of_pll_clk_init); 54 55 static void __init moxart_of_apb_clk_init(struct device_node *node) 56 { 57 void __iomem *base; 58 struct clk_hw *hw; 59 struct 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("%pOF: of_iomap failed\n", node); 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("%pOF: of_clk_get failed\n", node); 84 return; 85 } 86 87 hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div); 88 if (IS_ERR(hw)) { 89 pr_err("%pOF: failed to register clock\n", node); 90 return; 91 } 92 93 clk_hw_register_clkdev(hw, NULL, name); 94 of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); 95 } 96 CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", 97 moxart_of_apb_clk_init); 98