1 /* 2 * Copyright (c) 2014 MediaTek Inc. 3 * Author: James Liao <jamesjj.liao@mediatek.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <linux/of.h> 16 #include <linux/of_address.h> 17 #include <linux/err.h> 18 #include <linux/io.h> 19 #include <linux/slab.h> 20 #include <linux/delay.h> 21 #include <linux/clkdev.h> 22 #include <linux/mfd/syscon.h> 23 24 #include "clk-mtk.h" 25 #include "clk-gate.h" 26 27 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) 28 { 29 int i; 30 struct clk_onecell_data *clk_data; 31 32 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); 33 if (!clk_data) 34 return NULL; 35 36 clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL); 37 if (!clk_data->clks) 38 goto err_out; 39 40 clk_data->clk_num = clk_num; 41 42 for (i = 0; i < clk_num; i++) 43 clk_data->clks[i] = ERR_PTR(-ENOENT); 44 45 return clk_data; 46 err_out: 47 kfree(clk_data); 48 49 return NULL; 50 } 51 52 void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, 53 int num, struct clk_onecell_data *clk_data) 54 { 55 int i; 56 struct clk *clk; 57 58 for (i = 0; i < num; i++) { 59 const struct mtk_fixed_clk *rc = &clks[i]; 60 61 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id])) 62 continue; 63 64 clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0, 65 rc->rate); 66 67 if (IS_ERR(clk)) { 68 pr_err("Failed to register clk %s: %ld\n", 69 rc->name, PTR_ERR(clk)); 70 continue; 71 } 72 73 if (clk_data) 74 clk_data->clks[rc->id] = clk; 75 } 76 } 77 78 void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, 79 int num, struct clk_onecell_data *clk_data) 80 { 81 int i; 82 struct clk *clk; 83 84 for (i = 0; i < num; i++) { 85 const struct mtk_fixed_factor *ff = &clks[i]; 86 87 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id])) 88 continue; 89 90 clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, 91 CLK_SET_RATE_PARENT, ff->mult, ff->div); 92 93 if (IS_ERR(clk)) { 94 pr_err("Failed to register clk %s: %ld\n", 95 ff->name, PTR_ERR(clk)); 96 continue; 97 } 98 99 if (clk_data) 100 clk_data->clks[ff->id] = clk; 101 } 102 } 103 104 int mtk_clk_register_gates(struct device_node *node, 105 const struct mtk_gate *clks, 106 int num, struct clk_onecell_data *clk_data) 107 { 108 int i; 109 struct clk *clk; 110 struct regmap *regmap; 111 112 if (!clk_data) 113 return -ENOMEM; 114 115 regmap = syscon_node_to_regmap(node); 116 if (IS_ERR(regmap)) { 117 pr_err("Cannot find regmap for %pOF: %ld\n", node, 118 PTR_ERR(regmap)); 119 return PTR_ERR(regmap); 120 } 121 122 for (i = 0; i < num; i++) { 123 const struct mtk_gate *gate = &clks[i]; 124 125 if (!IS_ERR_OR_NULL(clk_data->clks[gate->id])) 126 continue; 127 128 clk = mtk_clk_register_gate(gate->name, gate->parent_name, 129 regmap, 130 gate->regs->set_ofs, 131 gate->regs->clr_ofs, 132 gate->regs->sta_ofs, 133 gate->shift, gate->ops); 134 135 if (IS_ERR(clk)) { 136 pr_err("Failed to register clk %s: %ld\n", 137 gate->name, PTR_ERR(clk)); 138 continue; 139 } 140 141 clk_data->clks[gate->id] = clk; 142 } 143 144 return 0; 145 } 146 147 struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, 148 void __iomem *base, spinlock_t *lock) 149 { 150 struct clk *clk; 151 struct clk_mux *mux = NULL; 152 struct clk_gate *gate = NULL; 153 struct clk_divider *div = NULL; 154 struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL; 155 const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL; 156 const char * const *parent_names; 157 const char *parent; 158 int num_parents; 159 int ret; 160 161 if (mc->mux_shift >= 0) { 162 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 163 if (!mux) 164 return ERR_PTR(-ENOMEM); 165 166 mux->reg = base + mc->mux_reg; 167 mux->mask = BIT(mc->mux_width) - 1; 168 mux->shift = mc->mux_shift; 169 mux->lock = lock; 170 171 mux_hw = &mux->hw; 172 mux_ops = &clk_mux_ops; 173 174 parent_names = mc->parent_names; 175 num_parents = mc->num_parents; 176 } else { 177 parent = mc->parent; 178 parent_names = &parent; 179 num_parents = 1; 180 } 181 182 if (mc->gate_shift >= 0) { 183 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 184 if (!gate) { 185 ret = -ENOMEM; 186 goto err_out; 187 } 188 189 gate->reg = base + mc->gate_reg; 190 gate->bit_idx = mc->gate_shift; 191 gate->flags = CLK_GATE_SET_TO_DISABLE; 192 gate->lock = lock; 193 194 gate_hw = &gate->hw; 195 gate_ops = &clk_gate_ops; 196 } 197 198 if (mc->divider_shift >= 0) { 199 div = kzalloc(sizeof(*div), GFP_KERNEL); 200 if (!div) { 201 ret = -ENOMEM; 202 goto err_out; 203 } 204 205 div->reg = base + mc->divider_reg; 206 div->shift = mc->divider_shift; 207 div->width = mc->divider_width; 208 div->lock = lock; 209 210 div_hw = &div->hw; 211 div_ops = &clk_divider_ops; 212 } 213 214 clk = clk_register_composite(NULL, mc->name, parent_names, num_parents, 215 mux_hw, mux_ops, 216 div_hw, div_ops, 217 gate_hw, gate_ops, 218 mc->flags); 219 220 if (IS_ERR(clk)) { 221 ret = PTR_ERR(clk); 222 goto err_out; 223 } 224 225 return clk; 226 err_out: 227 kfree(div); 228 kfree(gate); 229 kfree(mux); 230 231 return ERR_PTR(ret); 232 } 233 234 void mtk_clk_register_composites(const struct mtk_composite *mcs, 235 int num, void __iomem *base, spinlock_t *lock, 236 struct clk_onecell_data *clk_data) 237 { 238 struct clk *clk; 239 int i; 240 241 for (i = 0; i < num; i++) { 242 const struct mtk_composite *mc = &mcs[i]; 243 244 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id])) 245 continue; 246 247 clk = mtk_clk_register_composite(mc, base, lock); 248 249 if (IS_ERR(clk)) { 250 pr_err("Failed to register clk %s: %ld\n", 251 mc->name, PTR_ERR(clk)); 252 continue; 253 } 254 255 if (clk_data) 256 clk_data->clks[mc->id] = clk; 257 } 258 } 259 260 void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, 261 int num, void __iomem *base, spinlock_t *lock, 262 struct clk_onecell_data *clk_data) 263 { 264 struct clk *clk; 265 int i; 266 267 for (i = 0; i < num; i++) { 268 const struct mtk_clk_divider *mcd = &mcds[i]; 269 270 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id])) 271 continue; 272 273 clk = clk_register_divider(NULL, mcd->name, mcd->parent_name, 274 mcd->flags, base + mcd->div_reg, mcd->div_shift, 275 mcd->div_width, mcd->clk_divider_flags, lock); 276 277 if (IS_ERR(clk)) { 278 pr_err("Failed to register clk %s: %ld\n", 279 mcd->name, PTR_ERR(clk)); 280 continue; 281 } 282 283 if (clk_data) 284 clk_data->clks[mcd->id] = clk; 285 } 286 } 287