1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2014 MundoReader S.L. 4 * Author: Heiko Stuebner <heiko@sntech.de> 5 * 6 * Copyright (c) 2016 Rockchip Electronics Co. Ltd. 7 * Author: Xing Zheng <zhengxing@rock-chips.com> 8 * 9 * based on 10 * 11 * samsung/clk.c 12 * Copyright (c) 2013 Samsung Electronics Co., Ltd. 13 * Copyright (c) 2013 Linaro Ltd. 14 * Author: Thomas Abraham <thomas.ab@samsung.com> 15 */ 16 17 #include <linux/slab.h> 18 #include <linux/clk.h> 19 #include <linux/clk-provider.h> 20 #include <linux/io.h> 21 #include <linux/mfd/syscon.h> 22 #include <linux/regmap.h> 23 #include <linux/reboot.h> 24 #include <linux/rational.h> 25 26 #include "../clk-fractional-divider.h" 27 #include "clk.h" 28 29 /* 30 * Register a clock branch. 31 * Most clock branches have a form like 32 * 33 * src1 --|--\ 34 * |M |--[GATE]-[DIV]- 35 * src2 --|--/ 36 * 37 * sometimes without one of those components. 38 */ 39 static struct clk *rockchip_clk_register_branch(const char *name, 40 const char *const *parent_names, u8 num_parents, 41 void __iomem *base, 42 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, 43 int div_offset, u8 div_shift, u8 div_width, u8 div_flags, 44 struct clk_div_table *div_table, int gate_offset, 45 u8 gate_shift, u8 gate_flags, unsigned long flags, 46 spinlock_t *lock) 47 { 48 struct clk_hw *hw; 49 struct clk_mux *mux = NULL; 50 struct clk_gate *gate = NULL; 51 struct clk_divider *div = NULL; 52 const struct clk_ops *mux_ops = NULL, *div_ops = NULL, 53 *gate_ops = NULL; 54 int ret; 55 56 if (num_parents > 1) { 57 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 58 if (!mux) 59 return ERR_PTR(-ENOMEM); 60 61 mux->reg = base + muxdiv_offset; 62 mux->shift = mux_shift; 63 mux->mask = BIT(mux_width) - 1; 64 mux->flags = mux_flags; 65 mux->lock = lock; 66 mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops 67 : &clk_mux_ops; 68 } 69 70 if (gate_offset >= 0) { 71 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 72 if (!gate) { 73 ret = -ENOMEM; 74 goto err_gate; 75 } 76 77 gate->flags = gate_flags; 78 gate->reg = base + gate_offset; 79 gate->bit_idx = gate_shift; 80 gate->lock = lock; 81 gate_ops = &clk_gate_ops; 82 } 83 84 if (div_width > 0) { 85 div = kzalloc(sizeof(*div), GFP_KERNEL); 86 if (!div) { 87 ret = -ENOMEM; 88 goto err_div; 89 } 90 91 div->flags = div_flags; 92 if (div_offset) 93 div->reg = base + div_offset; 94 else 95 div->reg = base + muxdiv_offset; 96 div->shift = div_shift; 97 div->width = div_width; 98 div->lock = lock; 99 div->table = div_table; 100 div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) 101 ? &clk_divider_ro_ops 102 : &clk_divider_ops; 103 } 104 105 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 106 mux ? &mux->hw : NULL, mux_ops, 107 div ? &div->hw : NULL, div_ops, 108 gate ? &gate->hw : NULL, gate_ops, 109 flags); 110 if (IS_ERR(hw)) { 111 kfree(div); 112 kfree(gate); 113 return ERR_CAST(hw); 114 } 115 116 return hw->clk; 117 err_div: 118 kfree(gate); 119 err_gate: 120 kfree(mux); 121 return ERR_PTR(ret); 122 } 123 124 struct rockchip_clk_frac { 125 struct notifier_block clk_nb; 126 struct clk_fractional_divider div; 127 struct clk_gate gate; 128 129 struct clk_mux mux; 130 const struct clk_ops *mux_ops; 131 int mux_frac_idx; 132 133 bool rate_change_remuxed; 134 int rate_change_idx; 135 }; 136 137 #define to_rockchip_clk_frac_nb(nb) \ 138 container_of(nb, struct rockchip_clk_frac, clk_nb) 139 140 static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, 141 unsigned long event, void *data) 142 { 143 struct clk_notifier_data *ndata = data; 144 struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb); 145 struct clk_mux *frac_mux = &frac->mux; 146 int ret = 0; 147 148 pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n", 149 __func__, event, ndata->old_rate, ndata->new_rate); 150 if (event == PRE_RATE_CHANGE) { 151 frac->rate_change_idx = 152 frac->mux_ops->get_parent(&frac_mux->hw); 153 if (frac->rate_change_idx != frac->mux_frac_idx) { 154 frac->mux_ops->set_parent(&frac_mux->hw, 155 frac->mux_frac_idx); 156 frac->rate_change_remuxed = 1; 157 } 158 } else if (event == POST_RATE_CHANGE) { 159 /* 160 * The POST_RATE_CHANGE notifier runs directly after the 161 * divider clock is set in clk_change_rate, so we'll have 162 * remuxed back to the original parent before clk_change_rate 163 * reaches the mux itself. 164 */ 165 if (frac->rate_change_remuxed) { 166 frac->mux_ops->set_parent(&frac_mux->hw, 167 frac->rate_change_idx); 168 frac->rate_change_remuxed = 0; 169 } 170 } 171 172 return notifier_from_errno(ret); 173 } 174 175 /* 176 * fractional divider must set that denominator is 20 times larger than 177 * numerator to generate precise clock frequency. 178 */ 179 static void rockchip_fractional_approximation(struct clk_hw *hw, 180 unsigned long rate, unsigned long *parent_rate, 181 unsigned long *m, unsigned long *n) 182 { 183 unsigned long p_rate, p_parent_rate; 184 struct clk_hw *p_parent; 185 186 p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 187 if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { 188 p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); 189 p_parent_rate = clk_hw_get_rate(p_parent); 190 *parent_rate = p_parent_rate; 191 } 192 193 clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n); 194 } 195 196 static struct clk *rockchip_clk_register_frac_branch( 197 struct rockchip_clk_provider *ctx, const char *name, 198 const char *const *parent_names, u8 num_parents, 199 void __iomem *base, int muxdiv_offset, u8 div_flags, 200 int gate_offset, u8 gate_shift, u8 gate_flags, 201 unsigned long flags, struct rockchip_clk_branch *child, 202 spinlock_t *lock) 203 { 204 struct clk_hw *hw; 205 struct rockchip_clk_frac *frac; 206 struct clk_gate *gate = NULL; 207 struct clk_fractional_divider *div = NULL; 208 const struct clk_ops *div_ops = NULL, *gate_ops = NULL; 209 210 if (muxdiv_offset < 0) 211 return ERR_PTR(-EINVAL); 212 213 if (child && child->branch_type != branch_mux) { 214 pr_err("%s: fractional child clock for %s can only be a mux\n", 215 __func__, name); 216 return ERR_PTR(-EINVAL); 217 } 218 219 frac = kzalloc(sizeof(*frac), GFP_KERNEL); 220 if (!frac) 221 return ERR_PTR(-ENOMEM); 222 223 if (gate_offset >= 0) { 224 gate = &frac->gate; 225 gate->flags = gate_flags; 226 gate->reg = base + gate_offset; 227 gate->bit_idx = gate_shift; 228 gate->lock = lock; 229 gate_ops = &clk_gate_ops; 230 } 231 232 div = &frac->div; 233 div->flags = div_flags; 234 div->reg = base + muxdiv_offset; 235 div->mshift = 16; 236 div->mwidth = 16; 237 div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift; 238 div->nshift = 0; 239 div->nwidth = 16; 240 div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; 241 div->lock = lock; 242 div->approximation = rockchip_fractional_approximation; 243 div_ops = &clk_fractional_divider_ops; 244 245 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 246 NULL, NULL, 247 &div->hw, div_ops, 248 gate ? &gate->hw : NULL, gate_ops, 249 flags | CLK_SET_RATE_UNGATE); 250 if (IS_ERR(hw)) { 251 kfree(frac); 252 return ERR_CAST(hw); 253 } 254 255 if (child) { 256 struct clk_mux *frac_mux = &frac->mux; 257 struct clk_init_data init; 258 struct clk *mux_clk; 259 int ret; 260 261 frac->mux_frac_idx = match_string(child->parent_names, 262 child->num_parents, name); 263 frac->mux_ops = &clk_mux_ops; 264 frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb; 265 266 frac_mux->reg = base + child->muxdiv_offset; 267 frac_mux->shift = child->mux_shift; 268 frac_mux->mask = BIT(child->mux_width) - 1; 269 frac_mux->flags = child->mux_flags; 270 frac_mux->lock = lock; 271 frac_mux->hw.init = &init; 272 273 init.name = child->name; 274 init.flags = child->flags | CLK_SET_RATE_PARENT; 275 init.ops = frac->mux_ops; 276 init.parent_names = child->parent_names; 277 init.num_parents = child->num_parents; 278 279 mux_clk = clk_register(NULL, &frac_mux->hw); 280 if (IS_ERR(mux_clk)) { 281 kfree(frac); 282 return mux_clk; 283 } 284 285 rockchip_clk_add_lookup(ctx, mux_clk, child->id); 286 287 /* notifier on the fraction divider to catch rate changes */ 288 if (frac->mux_frac_idx >= 0) { 289 pr_debug("%s: found fractional parent in mux at pos %d\n", 290 __func__, frac->mux_frac_idx); 291 ret = clk_notifier_register(hw->clk, &frac->clk_nb); 292 if (ret) 293 pr_err("%s: failed to register clock notifier for %s\n", 294 __func__, name); 295 } else { 296 pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n", 297 __func__, name, child->name); 298 } 299 } 300 301 return hw->clk; 302 } 303 304 static struct clk *rockchip_clk_register_factor_branch(const char *name, 305 const char *const *parent_names, u8 num_parents, 306 void __iomem *base, unsigned int mult, unsigned int div, 307 int gate_offset, u8 gate_shift, u8 gate_flags, 308 unsigned long flags, spinlock_t *lock) 309 { 310 struct clk_hw *hw; 311 struct clk_gate *gate = NULL; 312 struct clk_fixed_factor *fix = NULL; 313 314 /* without gate, register a simple factor clock */ 315 if (gate_offset == 0) { 316 return clk_register_fixed_factor(NULL, name, 317 parent_names[0], flags, mult, 318 div); 319 } 320 321 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 322 if (!gate) 323 return ERR_PTR(-ENOMEM); 324 325 gate->flags = gate_flags; 326 gate->reg = base + gate_offset; 327 gate->bit_idx = gate_shift; 328 gate->lock = lock; 329 330 fix = kzalloc(sizeof(*fix), GFP_KERNEL); 331 if (!fix) { 332 kfree(gate); 333 return ERR_PTR(-ENOMEM); 334 } 335 336 fix->mult = mult; 337 fix->div = div; 338 339 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, 340 NULL, NULL, 341 &fix->hw, &clk_fixed_factor_ops, 342 &gate->hw, &clk_gate_ops, flags); 343 if (IS_ERR(hw)) { 344 kfree(fix); 345 kfree(gate); 346 return ERR_CAST(hw); 347 } 348 349 return hw->clk; 350 } 351 352 struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, 353 void __iomem *base, 354 unsigned long nr_clks) 355 { 356 struct rockchip_clk_provider *ctx; 357 struct clk **clk_table; 358 int i; 359 360 ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); 361 if (!ctx) 362 return ERR_PTR(-ENOMEM); 363 364 clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); 365 if (!clk_table) 366 goto err_free; 367 368 for (i = 0; i < nr_clks; ++i) 369 clk_table[i] = ERR_PTR(-ENOENT); 370 371 ctx->reg_base = base; 372 ctx->clk_data.clks = clk_table; 373 ctx->clk_data.clk_num = nr_clks; 374 ctx->cru_node = np; 375 spin_lock_init(&ctx->lock); 376 377 ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, 378 "rockchip,grf"); 379 380 return ctx; 381 382 err_free: 383 kfree(ctx); 384 return ERR_PTR(-ENOMEM); 385 } 386 EXPORT_SYMBOL_GPL(rockchip_clk_init); 387 388 void rockchip_clk_of_add_provider(struct device_node *np, 389 struct rockchip_clk_provider *ctx) 390 { 391 if (of_clk_add_provider(np, of_clk_src_onecell_get, 392 &ctx->clk_data)) 393 pr_err("%s: could not register clk provider\n", __func__); 394 } 395 EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider); 396 397 void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, 398 struct clk *clk, unsigned int id) 399 { 400 if (ctx->clk_data.clks && id) 401 ctx->clk_data.clks[id] = clk; 402 } 403 EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup); 404 405 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, 406 struct rockchip_pll_clock *list, 407 unsigned int nr_pll, int grf_lock_offset) 408 { 409 struct clk *clk; 410 int idx; 411 412 for (idx = 0; idx < nr_pll; idx++, list++) { 413 clk = rockchip_clk_register_pll(ctx, list->type, list->name, 414 list->parent_names, list->num_parents, 415 list->con_offset, grf_lock_offset, 416 list->lock_shift, list->mode_offset, 417 list->mode_shift, list->rate_table, 418 list->flags, list->pll_flags); 419 if (IS_ERR(clk)) { 420 pr_err("%s: failed to register clock %s\n", __func__, 421 list->name); 422 continue; 423 } 424 425 rockchip_clk_add_lookup(ctx, clk, list->id); 426 } 427 } 428 EXPORT_SYMBOL_GPL(rockchip_clk_register_plls); 429 430 void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, 431 struct rockchip_clk_branch *list, 432 unsigned int nr_clk) 433 { 434 struct clk *clk = NULL; 435 unsigned int idx; 436 unsigned long flags; 437 438 for (idx = 0; idx < nr_clk; idx++, list++) { 439 flags = list->flags; 440 441 /* catch simple muxes */ 442 switch (list->branch_type) { 443 case branch_mux: 444 clk = clk_register_mux(NULL, list->name, 445 list->parent_names, list->num_parents, 446 flags, ctx->reg_base + list->muxdiv_offset, 447 list->mux_shift, list->mux_width, 448 list->mux_flags, &ctx->lock); 449 break; 450 case branch_muxgrf: 451 clk = rockchip_clk_register_muxgrf(list->name, 452 list->parent_names, list->num_parents, 453 flags, ctx->grf, list->muxdiv_offset, 454 list->mux_shift, list->mux_width, 455 list->mux_flags); 456 break; 457 case branch_divider: 458 if (list->div_table) 459 clk = clk_register_divider_table(NULL, 460 list->name, list->parent_names[0], 461 flags, 462 ctx->reg_base + list->muxdiv_offset, 463 list->div_shift, list->div_width, 464 list->div_flags, list->div_table, 465 &ctx->lock); 466 else 467 clk = clk_register_divider(NULL, list->name, 468 list->parent_names[0], flags, 469 ctx->reg_base + list->muxdiv_offset, 470 list->div_shift, list->div_width, 471 list->div_flags, &ctx->lock); 472 break; 473 case branch_fraction_divider: 474 clk = rockchip_clk_register_frac_branch(ctx, list->name, 475 list->parent_names, list->num_parents, 476 ctx->reg_base, list->muxdiv_offset, 477 list->div_flags, 478 list->gate_offset, list->gate_shift, 479 list->gate_flags, flags, list->child, 480 &ctx->lock); 481 break; 482 case branch_half_divider: 483 clk = rockchip_clk_register_halfdiv(list->name, 484 list->parent_names, list->num_parents, 485 ctx->reg_base, list->muxdiv_offset, 486 list->mux_shift, list->mux_width, 487 list->mux_flags, list->div_shift, 488 list->div_width, list->div_flags, 489 list->gate_offset, list->gate_shift, 490 list->gate_flags, flags, &ctx->lock); 491 break; 492 case branch_gate: 493 flags |= CLK_SET_RATE_PARENT; 494 495 clk = clk_register_gate(NULL, list->name, 496 list->parent_names[0], flags, 497 ctx->reg_base + list->gate_offset, 498 list->gate_shift, list->gate_flags, &ctx->lock); 499 break; 500 case branch_composite: 501 clk = rockchip_clk_register_branch(list->name, 502 list->parent_names, list->num_parents, 503 ctx->reg_base, list->muxdiv_offset, 504 list->mux_shift, 505 list->mux_width, list->mux_flags, 506 list->div_offset, list->div_shift, list->div_width, 507 list->div_flags, list->div_table, 508 list->gate_offset, list->gate_shift, 509 list->gate_flags, flags, &ctx->lock); 510 break; 511 case branch_mmc: 512 clk = rockchip_clk_register_mmc( 513 list->name, 514 list->parent_names, list->num_parents, 515 ctx->reg_base + list->muxdiv_offset, 516 list->div_shift 517 ); 518 break; 519 case branch_inverter: 520 clk = rockchip_clk_register_inverter( 521 list->name, list->parent_names, 522 list->num_parents, 523 ctx->reg_base + list->muxdiv_offset, 524 list->div_shift, list->div_flags, &ctx->lock); 525 break; 526 case branch_factor: 527 clk = rockchip_clk_register_factor_branch( 528 list->name, list->parent_names, 529 list->num_parents, ctx->reg_base, 530 list->div_shift, list->div_width, 531 list->gate_offset, list->gate_shift, 532 list->gate_flags, flags, &ctx->lock); 533 break; 534 case branch_ddrclk: 535 clk = rockchip_clk_register_ddrclk( 536 list->name, list->flags, 537 list->parent_names, list->num_parents, 538 list->muxdiv_offset, list->mux_shift, 539 list->mux_width, list->div_shift, 540 list->div_width, list->div_flags, 541 ctx->reg_base, &ctx->lock); 542 break; 543 } 544 545 /* none of the cases above matched */ 546 if (!clk) { 547 pr_err("%s: unknown clock type %d\n", 548 __func__, list->branch_type); 549 continue; 550 } 551 552 if (IS_ERR(clk)) { 553 pr_err("%s: failed to register clock %s: %ld\n", 554 __func__, list->name, PTR_ERR(clk)); 555 continue; 556 } 557 558 rockchip_clk_add_lookup(ctx, clk, list->id); 559 } 560 } 561 EXPORT_SYMBOL_GPL(rockchip_clk_register_branches); 562 563 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, 564 unsigned int lookup_id, 565 const char *name, const char *const *parent_names, 566 u8 num_parents, 567 const struct rockchip_cpuclk_reg_data *reg_data, 568 const struct rockchip_cpuclk_rate_table *rates, 569 int nrates) 570 { 571 struct clk *clk; 572 573 clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, 574 reg_data, rates, nrates, 575 ctx->reg_base, &ctx->lock); 576 if (IS_ERR(clk)) { 577 pr_err("%s: failed to register clock %s: %ld\n", 578 __func__, name, PTR_ERR(clk)); 579 return; 580 } 581 582 rockchip_clk_add_lookup(ctx, clk, lookup_id); 583 } 584 EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk); 585 586 void rockchip_clk_protect_critical(const char *const clocks[], 587 int nclocks) 588 { 589 int i; 590 591 /* Protect the clocks that needs to stay on */ 592 for (i = 0; i < nclocks; i++) { 593 struct clk *clk = __clk_lookup(clocks[i]); 594 595 clk_prepare_enable(clk); 596 } 597 } 598 EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical); 599 600 static void __iomem *rst_base; 601 static unsigned int reg_restart; 602 static void (*cb_restart)(void); 603 static int rockchip_restart_notify(struct notifier_block *this, 604 unsigned long mode, void *cmd) 605 { 606 if (cb_restart) 607 cb_restart(); 608 609 writel(0xfdb9, rst_base + reg_restart); 610 return NOTIFY_DONE; 611 } 612 613 static struct notifier_block rockchip_restart_handler = { 614 .notifier_call = rockchip_restart_notify, 615 .priority = 128, 616 }; 617 618 void 619 rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, 620 unsigned int reg, 621 void (*cb)(void)) 622 { 623 int ret; 624 625 rst_base = ctx->reg_base; 626 reg_restart = reg; 627 cb_restart = cb; 628 ret = register_restart_handler(&rockchip_restart_handler); 629 if (ret) 630 pr_err("%s: cannot register restart handler, %d\n", 631 __func__, ret); 632 } 633 EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier); 634