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 18void __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} 53CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", 54 moxart_of_pll_clk_init); 55 56void __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} 96CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock", 97 moxart_of_apb_clk_init); 98