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