1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/export.h> 7 #include <linux/module.h> 8 #include <linux/regmap.h> 9 #include <linux/platform_device.h> 10 #include <linux/clk-provider.h> 11 #include <linux/interconnect-clk.h> 12 #include <linux/pm_runtime.h> 13 #include <linux/reset-controller.h> 14 #include <linux/of.h> 15 16 #include "common.h" 17 #include "clk-alpha-pll.h" 18 #include "clk-branch.h" 19 #include "clk-rcg.h" 20 #include "clk-regmap.h" 21 #include "reset.h" 22 #include "gdsc.h" 23 24 struct qcom_cc { 25 struct qcom_reset_controller reset; 26 struct clk_regmap **rclks; 27 size_t num_rclks; 28 struct dev_pm_domain_list *pd_list; 29 }; 30 31 const 32 struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) 33 { 34 if (!f) 35 return NULL; 36 37 if (!f->freq) 38 return f; 39 40 for (; f->freq; f++) 41 if (rate <= f->freq) 42 return f; 43 44 /* Default to our fastest rate */ 45 return f - 1; 46 } 47 EXPORT_SYMBOL_GPL(qcom_find_freq); 48 49 const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f, 50 unsigned long rate) 51 { 52 if (!f) 53 return NULL; 54 55 if (!f->freq) 56 return f; 57 58 for (; f->freq; f++) 59 if (rate <= f->freq) 60 return f; 61 62 /* Default to our fastest rate */ 63 return f - 1; 64 } 65 EXPORT_SYMBOL_GPL(qcom_find_freq_multi); 66 67 const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, 68 unsigned long rate) 69 { 70 const struct freq_tbl *best = NULL; 71 72 for ( ; f->freq; f++) { 73 if (rate >= f->freq) 74 best = f; 75 else 76 break; 77 } 78 79 return best; 80 } 81 EXPORT_SYMBOL_GPL(qcom_find_freq_floor); 82 83 int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) 84 { 85 int i, num_parents = clk_hw_get_num_parents(hw); 86 87 for (i = 0; i < num_parents; i++) 88 if (src == map[i].src) 89 return i; 90 91 return -ENOENT; 92 } 93 EXPORT_SYMBOL_GPL(qcom_find_src_index); 94 95 int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg) 96 { 97 int i, num_parents = clk_hw_get_num_parents(hw); 98 99 for (i = 0; i < num_parents; i++) 100 if (cfg == map[i].cfg) 101 return i; 102 103 return -ENOENT; 104 } 105 EXPORT_SYMBOL_GPL(qcom_find_cfg_index); 106 107 struct regmap * 108 qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) 109 { 110 void __iomem *base; 111 struct device *dev = &pdev->dev; 112 113 base = devm_platform_ioremap_resource(pdev, 0); 114 if (IS_ERR(base)) 115 return ERR_CAST(base); 116 117 return devm_regmap_init_mmio(dev, base, desc->config); 118 } 119 EXPORT_SYMBOL_GPL(qcom_cc_map); 120 121 void 122 qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count) 123 { 124 u32 val; 125 u32 mask; 126 127 /* De-assert reset to FSM */ 128 regmap_update_bits(map, reg, PLL_VOTE_FSM_RESET, 0); 129 130 /* Program bias count and lock count */ 131 val = bias_count << PLL_BIAS_COUNT_SHIFT | 132 lock_count << PLL_LOCK_COUNT_SHIFT; 133 mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT; 134 mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT; 135 regmap_update_bits(map, reg, mask, val); 136 137 /* Enable PLL FSM voting */ 138 regmap_update_bits(map, reg, PLL_VOTE_FSM_ENA, PLL_VOTE_FSM_ENA); 139 } 140 EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode); 141 142 static void qcom_cc_gdsc_unregister(void *data) 143 { 144 gdsc_unregister(data); 145 } 146 147 /* 148 * Backwards compatibility with old DTs. Register a pass-through factor 1/1 149 * clock to translate 'path' clk into 'name' clk and register the 'path' 150 * clk as a fixed rate clock if it isn't present. 151 */ 152 static int _qcom_cc_register_board_clk(struct device *dev, const char *path, 153 const char *name, unsigned long rate, 154 bool add_factor) 155 { 156 struct device_node *node = NULL; 157 struct device_node *clocks_node; 158 struct clk_fixed_factor *factor; 159 struct clk_fixed_rate *fixed; 160 struct clk_init_data init_data = { }; 161 int ret; 162 163 clocks_node = of_find_node_by_path("/clocks"); 164 if (clocks_node) { 165 node = of_get_child_by_name(clocks_node, path); 166 of_node_put(clocks_node); 167 } 168 169 if (!node) { 170 fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL); 171 if (!fixed) 172 return -EINVAL; 173 174 fixed->fixed_rate = rate; 175 fixed->hw.init = &init_data; 176 177 init_data.name = path; 178 init_data.ops = &clk_fixed_rate_ops; 179 180 ret = devm_clk_hw_register(dev, &fixed->hw); 181 if (ret) 182 return ret; 183 } 184 of_node_put(node); 185 186 if (add_factor) { 187 factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL); 188 if (!factor) 189 return -EINVAL; 190 191 factor->mult = factor->div = 1; 192 factor->hw.init = &init_data; 193 194 init_data.name = name; 195 init_data.parent_names = &path; 196 init_data.num_parents = 1; 197 init_data.flags = 0; 198 init_data.ops = &clk_fixed_factor_ops; 199 200 ret = devm_clk_hw_register(dev, &factor->hw); 201 if (ret) 202 return ret; 203 } 204 205 return 0; 206 } 207 208 int qcom_cc_register_board_clk(struct device *dev, const char *path, 209 const char *name, unsigned long rate) 210 { 211 bool add_factor = true; 212 213 /* 214 * TODO: The RPM clock driver currently does not support the xo clock. 215 * When xo is added to the RPM clock driver, we should change this 216 * function to skip registration of xo factor clocks. 217 */ 218 219 return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor); 220 } 221 EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk); 222 223 int qcom_cc_register_sleep_clk(struct device *dev) 224 { 225 return _qcom_cc_register_board_clk(dev, "sleep_clk", "sleep_clk_src", 226 32768, true); 227 } 228 EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk); 229 230 /* Drop 'protected-clocks' from the list of clocks to register */ 231 static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc) 232 { 233 struct device_node *np = dev->of_node; 234 u32 i; 235 236 of_property_for_each_u32(np, "protected-clocks", i) { 237 if (i >= cc->num_rclks) 238 continue; 239 240 cc->rclks[i] = NULL; 241 } 242 } 243 244 static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, 245 void *data) 246 { 247 struct qcom_cc *cc = data; 248 unsigned int idx = clkspec->args[0]; 249 250 if (idx >= cc->num_rclks) { 251 pr_err("%s: invalid index %u\n", __func__, idx); 252 return ERR_PTR(-EINVAL); 253 } 254 255 return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL; 256 } 257 258 static int qcom_cc_icc_register(struct device *dev, 259 const struct qcom_cc_desc *desc) 260 { 261 struct icc_clk_data *icd; 262 struct clk_hw *hws; 263 int i; 264 265 if (!IS_ENABLED(CONFIG_INTERCONNECT_CLK)) 266 return 0; 267 268 if (!desc->icc_hws) 269 return 0; 270 271 icd = devm_kcalloc(dev, desc->num_icc_hws, sizeof(*icd), GFP_KERNEL); 272 if (!icd) 273 return -ENOMEM; 274 275 for (i = 0; i < desc->num_icc_hws; i++) { 276 icd[i].master_id = desc->icc_hws[i].master_id; 277 icd[i].slave_id = desc->icc_hws[i].slave_id; 278 hws = &desc->clks[desc->icc_hws[i].clk_id]->hw; 279 icd[i].clk = devm_clk_hw_get_clk(dev, hws, "icc"); 280 if (!icd[i].clk) 281 return dev_err_probe(dev, -ENOENT, 282 "(%d) clock entry is null\n", i); 283 icd[i].name = clk_hw_get_name(hws); 284 } 285 286 return devm_icc_clk_register(dev, desc->icc_first_node_id, 287 desc->num_icc_hws, icd); 288 } 289 290 static int qcom_cc_clk_pll_configure(const struct qcom_cc_driver_data *data, 291 struct regmap *regmap) 292 { 293 const struct clk_init_data *init; 294 struct clk_alpha_pll *pll; 295 int i; 296 297 for (i = 0; i < data->num_alpha_plls; i++) { 298 pll = data->alpha_plls[i]; 299 init = pll->clkr.hw.init; 300 301 if (!pll->config || !pll->regs) { 302 pr_err("%s: missing pll config or regs\n", init->name); 303 return -EINVAL; 304 } 305 306 qcom_clk_alpha_pll_configure(pll, regmap); 307 } 308 309 return 0; 310 } 311 312 static void qcom_cc_clk_regs_configure(struct device *dev, const struct qcom_cc_driver_data *data, 313 struct regmap *regmap) 314 { 315 int i; 316 317 for (i = 0; i < data->num_clk_cbcrs; i++) 318 qcom_branch_set_clk_en(regmap, data->clk_cbcrs[i]); 319 320 if (data->clk_regs_configure) 321 data->clk_regs_configure(dev, regmap); 322 } 323 324 int qcom_cc_really_probe(struct device *dev, 325 const struct qcom_cc_desc *desc, struct regmap *regmap) 326 { 327 int i, ret; 328 struct qcom_reset_controller *reset; 329 struct qcom_cc *cc; 330 struct gdsc_desc *scd; 331 size_t num_clks = desc->num_clks; 332 struct clk_regmap **rclks = desc->clks; 333 size_t num_clk_hws = desc->num_clk_hws; 334 struct clk_hw **clk_hws = desc->clk_hws; 335 336 cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); 337 if (!cc) 338 return -ENOMEM; 339 340 ret = devm_pm_domain_attach_list(dev, NULL, &cc->pd_list); 341 if (ret < 0 && ret != -EEXIST) 342 return ret; 343 344 if (desc->use_rpm) { 345 ret = devm_pm_runtime_enable(dev); 346 if (ret) 347 return ret; 348 349 ret = pm_runtime_resume_and_get(dev); 350 if (ret) 351 return ret; 352 } 353 354 if (desc->driver_data) { 355 ret = qcom_cc_clk_pll_configure(desc->driver_data, regmap); 356 if (ret) 357 goto put_rpm; 358 359 qcom_cc_clk_regs_configure(dev, desc->driver_data, regmap); 360 } 361 362 reset = &cc->reset; 363 reset->rcdev.of_node = dev->of_node; 364 reset->rcdev.ops = &qcom_reset_ops; 365 reset->rcdev.owner = dev->driver->owner; 366 reset->rcdev.nr_resets = desc->num_resets; 367 reset->regmap = regmap; 368 reset->reset_map = desc->resets; 369 370 ret = devm_reset_controller_register(dev, &reset->rcdev); 371 if (ret) 372 goto put_rpm; 373 374 if (desc->gdscs && desc->num_gdscs) { 375 scd = devm_kzalloc(dev, sizeof(*scd), GFP_KERNEL); 376 if (!scd) { 377 ret = -ENOMEM; 378 goto put_rpm; 379 } 380 scd->dev = dev; 381 scd->scs = desc->gdscs; 382 scd->num = desc->num_gdscs; 383 scd->pd_list = cc->pd_list; 384 ret = gdsc_register(scd, &reset->rcdev, regmap); 385 if (ret) 386 goto put_rpm; 387 ret = devm_add_action_or_reset(dev, qcom_cc_gdsc_unregister, 388 scd); 389 if (ret) 390 goto put_rpm; 391 } 392 393 if (desc->driver_data && 394 desc->driver_data->dfs_rcgs && 395 desc->driver_data->num_dfs_rcgs) { 396 ret = qcom_cc_register_rcg_dfs(regmap, 397 desc->driver_data->dfs_rcgs, 398 desc->driver_data->num_dfs_rcgs); 399 if (ret) 400 goto put_rpm; 401 } 402 403 cc->rclks = rclks; 404 cc->num_rclks = num_clks; 405 406 qcom_cc_drop_protected(dev, cc); 407 408 for (i = 0; i < num_clk_hws; i++) { 409 ret = devm_clk_hw_register(dev, clk_hws[i]); 410 if (ret) 411 goto put_rpm; 412 } 413 414 for (i = 0; i < num_clks; i++) { 415 if (!rclks[i]) 416 continue; 417 418 ret = devm_clk_register_regmap(dev, rclks[i]); 419 if (ret) 420 goto put_rpm; 421 } 422 423 ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc); 424 if (ret) 425 goto put_rpm; 426 427 ret = qcom_cc_icc_register(dev, desc); 428 429 put_rpm: 430 if (desc->use_rpm) 431 pm_runtime_put(dev); 432 433 return ret; 434 } 435 EXPORT_SYMBOL_GPL(qcom_cc_really_probe); 436 437 int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) 438 { 439 struct regmap *regmap; 440 441 regmap = qcom_cc_map(pdev, desc); 442 if (IS_ERR(regmap)) 443 return PTR_ERR(regmap); 444 445 return qcom_cc_really_probe(&pdev->dev, desc, regmap); 446 } 447 EXPORT_SYMBOL_GPL(qcom_cc_probe); 448 449 int qcom_cc_probe_by_index(struct platform_device *pdev, int index, 450 const struct qcom_cc_desc *desc) 451 { 452 struct regmap *regmap; 453 void __iomem *base; 454 455 base = devm_platform_ioremap_resource(pdev, index); 456 if (IS_ERR(base)) 457 return -ENOMEM; 458 459 regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config); 460 if (IS_ERR(regmap)) 461 return PTR_ERR(regmap); 462 463 return qcom_cc_really_probe(&pdev->dev, desc, regmap); 464 } 465 EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index); 466 467 MODULE_LICENSE("GPL v2"); 468 MODULE_DESCRIPTION("QTI Common Clock module"); 469