1*0aa0c95fSHaojian Zhuang /* 2*0aa0c95fSHaojian Zhuang * Hisilicon clock driver 3*0aa0c95fSHaojian Zhuang * 4*0aa0c95fSHaojian Zhuang * Copyright (c) 2012-2013 Hisilicon Limited. 5*0aa0c95fSHaojian Zhuang * Copyright (c) 2012-2013 Linaro Limited. 6*0aa0c95fSHaojian Zhuang * 7*0aa0c95fSHaojian Zhuang * Author: Haojian Zhuang <haojian.zhuang@linaro.org> 8*0aa0c95fSHaojian Zhuang * Xin Li <li.xin@linaro.org> 9*0aa0c95fSHaojian Zhuang * 10*0aa0c95fSHaojian Zhuang * This program is free software; you can redistribute it and/or modify 11*0aa0c95fSHaojian Zhuang * it under the terms of the GNU General Public License as published by 12*0aa0c95fSHaojian Zhuang * the Free Software Foundation; either version 2 of the License, or 13*0aa0c95fSHaojian Zhuang * (at your option) any later version. 14*0aa0c95fSHaojian Zhuang * 15*0aa0c95fSHaojian Zhuang * This program is distributed in the hope that it will be useful, 16*0aa0c95fSHaojian Zhuang * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*0aa0c95fSHaojian Zhuang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*0aa0c95fSHaojian Zhuang * GNU General Public License for more details. 19*0aa0c95fSHaojian Zhuang * 20*0aa0c95fSHaojian Zhuang * You should have received a copy of the GNU General Public License along 21*0aa0c95fSHaojian Zhuang * with this program; if not, write to the Free Software Foundation, Inc., 22*0aa0c95fSHaojian Zhuang * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23*0aa0c95fSHaojian Zhuang * 24*0aa0c95fSHaojian Zhuang */ 25*0aa0c95fSHaojian Zhuang 26*0aa0c95fSHaojian Zhuang #include <linux/kernel.h> 27*0aa0c95fSHaojian Zhuang #include <linux/clk-provider.h> 28*0aa0c95fSHaojian Zhuang #include <linux/clkdev.h> 29*0aa0c95fSHaojian Zhuang #include <linux/delay.h> 30*0aa0c95fSHaojian Zhuang #include <linux/io.h> 31*0aa0c95fSHaojian Zhuang #include <linux/of.h> 32*0aa0c95fSHaojian Zhuang #include <linux/of_address.h> 33*0aa0c95fSHaojian Zhuang #include <linux/of_device.h> 34*0aa0c95fSHaojian Zhuang #include <linux/slab.h> 35*0aa0c95fSHaojian Zhuang #include <linux/clk.h> 36*0aa0c95fSHaojian Zhuang 37*0aa0c95fSHaojian Zhuang #include "clk.h" 38*0aa0c95fSHaojian Zhuang 39*0aa0c95fSHaojian Zhuang static DEFINE_SPINLOCK(hisi_clk_lock); 40*0aa0c95fSHaojian Zhuang static struct clk **clk_table; 41*0aa0c95fSHaojian Zhuang static struct clk_onecell_data clk_data; 42*0aa0c95fSHaojian Zhuang 43*0aa0c95fSHaojian Zhuang void __init hisi_clk_init(struct device_node *np, int nr_clks) 44*0aa0c95fSHaojian Zhuang { 45*0aa0c95fSHaojian Zhuang clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); 46*0aa0c95fSHaojian Zhuang if (!clk_table) { 47*0aa0c95fSHaojian Zhuang pr_err("%s: could not allocate clock lookup table\n", __func__); 48*0aa0c95fSHaojian Zhuang return; 49*0aa0c95fSHaojian Zhuang } 50*0aa0c95fSHaojian Zhuang clk_data.clks = clk_table; 51*0aa0c95fSHaojian Zhuang clk_data.clk_num = nr_clks; 52*0aa0c95fSHaojian Zhuang of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 53*0aa0c95fSHaojian Zhuang } 54*0aa0c95fSHaojian Zhuang 55*0aa0c95fSHaojian Zhuang void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks, 56*0aa0c95fSHaojian Zhuang int nums, void __iomem *base) 57*0aa0c95fSHaojian Zhuang { 58*0aa0c95fSHaojian Zhuang struct clk *clk; 59*0aa0c95fSHaojian Zhuang int i; 60*0aa0c95fSHaojian Zhuang 61*0aa0c95fSHaojian Zhuang for (i = 0; i < nums; i++) { 62*0aa0c95fSHaojian Zhuang clk = clk_register_fixed_rate(NULL, clks[i].name, 63*0aa0c95fSHaojian Zhuang clks[i].parent_name, 64*0aa0c95fSHaojian Zhuang clks[i].flags, 65*0aa0c95fSHaojian Zhuang clks[i].fixed_rate); 66*0aa0c95fSHaojian Zhuang if (IS_ERR(clk)) { 67*0aa0c95fSHaojian Zhuang pr_err("%s: failed to register clock %s\n", 68*0aa0c95fSHaojian Zhuang __func__, clks[i].name); 69*0aa0c95fSHaojian Zhuang continue; 70*0aa0c95fSHaojian Zhuang } 71*0aa0c95fSHaojian Zhuang } 72*0aa0c95fSHaojian Zhuang } 73*0aa0c95fSHaojian Zhuang 74*0aa0c95fSHaojian Zhuang void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks, 75*0aa0c95fSHaojian Zhuang int nums, void __iomem *base) 76*0aa0c95fSHaojian Zhuang { 77*0aa0c95fSHaojian Zhuang struct clk *clk; 78*0aa0c95fSHaojian Zhuang int i; 79*0aa0c95fSHaojian Zhuang 80*0aa0c95fSHaojian Zhuang for (i = 0; i < nums; i++) { 81*0aa0c95fSHaojian Zhuang clk = clk_register_fixed_factor(NULL, clks[i].name, 82*0aa0c95fSHaojian Zhuang clks[i].parent_name, 83*0aa0c95fSHaojian Zhuang clks[i].flags, clks[i].mult, 84*0aa0c95fSHaojian Zhuang clks[i].div); 85*0aa0c95fSHaojian Zhuang if (IS_ERR(clk)) { 86*0aa0c95fSHaojian Zhuang pr_err("%s: failed to register clock %s\n", 87*0aa0c95fSHaojian Zhuang __func__, clks[i].name); 88*0aa0c95fSHaojian Zhuang continue; 89*0aa0c95fSHaojian Zhuang } 90*0aa0c95fSHaojian Zhuang } 91*0aa0c95fSHaojian Zhuang } 92*0aa0c95fSHaojian Zhuang 93*0aa0c95fSHaojian Zhuang void __init hisi_clk_register_mux(struct hisi_mux_clock *clks, 94*0aa0c95fSHaojian Zhuang int nums, void __iomem *base) 95*0aa0c95fSHaojian Zhuang { 96*0aa0c95fSHaojian Zhuang struct clk *clk; 97*0aa0c95fSHaojian Zhuang int i; 98*0aa0c95fSHaojian Zhuang 99*0aa0c95fSHaojian Zhuang for (i = 0; i < nums; i++) { 100*0aa0c95fSHaojian Zhuang clk = clk_register_mux(NULL, clks[i].name, clks[i].parent_names, 101*0aa0c95fSHaojian Zhuang clks[i].num_parents, clks[i].flags, 102*0aa0c95fSHaojian Zhuang base + clks[i].offset, clks[i].shift, 103*0aa0c95fSHaojian Zhuang clks[i].width, clks[i].mux_flags, 104*0aa0c95fSHaojian Zhuang &hisi_clk_lock); 105*0aa0c95fSHaojian Zhuang if (IS_ERR(clk)) { 106*0aa0c95fSHaojian Zhuang pr_err("%s: failed to register clock %s\n", 107*0aa0c95fSHaojian Zhuang __func__, clks[i].name); 108*0aa0c95fSHaojian Zhuang continue; 109*0aa0c95fSHaojian Zhuang } 110*0aa0c95fSHaojian Zhuang 111*0aa0c95fSHaojian Zhuang if (clks[i].alias) 112*0aa0c95fSHaojian Zhuang clk_register_clkdev(clk, clks[i].alias, NULL); 113*0aa0c95fSHaojian Zhuang 114*0aa0c95fSHaojian Zhuang clk_table[clks[i].id] = clk; 115*0aa0c95fSHaojian Zhuang } 116*0aa0c95fSHaojian Zhuang } 117*0aa0c95fSHaojian Zhuang 118*0aa0c95fSHaojian Zhuang void __init hisi_clk_register_divider(struct hisi_divider_clock *clks, 119*0aa0c95fSHaojian Zhuang int nums, void __iomem *base) 120*0aa0c95fSHaojian Zhuang { 121*0aa0c95fSHaojian Zhuang struct clk *clk; 122*0aa0c95fSHaojian Zhuang int i; 123*0aa0c95fSHaojian Zhuang 124*0aa0c95fSHaojian Zhuang for (i = 0; i < nums; i++) { 125*0aa0c95fSHaojian Zhuang clk = clk_register_divider_table(NULL, clks[i].name, 126*0aa0c95fSHaojian Zhuang clks[i].parent_name, 127*0aa0c95fSHaojian Zhuang clks[i].flags, 128*0aa0c95fSHaojian Zhuang base + clks[i].offset, 129*0aa0c95fSHaojian Zhuang clks[i].shift, clks[i].width, 130*0aa0c95fSHaojian Zhuang clks[i].div_flags, 131*0aa0c95fSHaojian Zhuang clks[i].table, 132*0aa0c95fSHaojian Zhuang &hisi_clk_lock); 133*0aa0c95fSHaojian Zhuang if (IS_ERR(clk)) { 134*0aa0c95fSHaojian Zhuang pr_err("%s: failed to register clock %s\n", 135*0aa0c95fSHaojian Zhuang __func__, clks[i].name); 136*0aa0c95fSHaojian Zhuang continue; 137*0aa0c95fSHaojian Zhuang } 138*0aa0c95fSHaojian Zhuang 139*0aa0c95fSHaojian Zhuang if (clks[i].alias) 140*0aa0c95fSHaojian Zhuang clk_register_clkdev(clk, clks[i].alias, NULL); 141*0aa0c95fSHaojian Zhuang 142*0aa0c95fSHaojian Zhuang clk_table[clks[i].id] = clk; 143*0aa0c95fSHaojian Zhuang } 144*0aa0c95fSHaojian Zhuang } 145*0aa0c95fSHaojian Zhuang 146*0aa0c95fSHaojian Zhuang void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, 147*0aa0c95fSHaojian Zhuang int nums, void __iomem *base) 148*0aa0c95fSHaojian Zhuang { 149*0aa0c95fSHaojian Zhuang struct clk *clk; 150*0aa0c95fSHaojian Zhuang int i; 151*0aa0c95fSHaojian Zhuang 152*0aa0c95fSHaojian Zhuang for (i = 0; i < nums; i++) { 153*0aa0c95fSHaojian Zhuang clk = hisi_register_clkgate_sep(NULL, clks[i].name, 154*0aa0c95fSHaojian Zhuang clks[i].parent_name, 155*0aa0c95fSHaojian Zhuang clks[i].flags, 156*0aa0c95fSHaojian Zhuang base + clks[i].offset, 157*0aa0c95fSHaojian Zhuang clks[i].bit_idx, 158*0aa0c95fSHaojian Zhuang clks[i].gate_flags, 159*0aa0c95fSHaojian Zhuang &hisi_clk_lock); 160*0aa0c95fSHaojian Zhuang if (IS_ERR(clk)) { 161*0aa0c95fSHaojian Zhuang pr_err("%s: failed to register clock %s\n", 162*0aa0c95fSHaojian Zhuang __func__, clks[i].name); 163*0aa0c95fSHaojian Zhuang continue; 164*0aa0c95fSHaojian Zhuang } 165*0aa0c95fSHaojian Zhuang 166*0aa0c95fSHaojian Zhuang if (clks[i].alias) 167*0aa0c95fSHaojian Zhuang clk_register_clkdev(clk, clks[i].alias, NULL); 168*0aa0c95fSHaojian Zhuang 169*0aa0c95fSHaojian Zhuang clk_table[clks[i].id] = clk; 170*0aa0c95fSHaojian Zhuang } 171*0aa0c95fSHaojian Zhuang } 172