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