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