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/bitops.h> 8 #include <linux/clk-provider.h> 9 #include <linux/err.h> 10 #include <linux/io.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/of_address.h> 15 #include <linux/platform_device.h> 16 #include <linux/slab.h> 17 18 #include "clk-mtk.h" 19 #include "clk-gate.h" 20 #include "clk-mux.h" 21 22 const struct mtk_gate_regs cg_regs_dummy = { 0, 0, 0 }; 23 EXPORT_SYMBOL_GPL(cg_regs_dummy); 24 25 static int mtk_clk_dummy_enable(struct clk_hw *hw) 26 { 27 return 0; 28 } 29 30 static void mtk_clk_dummy_disable(struct clk_hw *hw) { } 31 32 const struct clk_ops mtk_clk_dummy_ops = { 33 .enable = mtk_clk_dummy_enable, 34 .disable = mtk_clk_dummy_disable, 35 }; 36 EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops); 37 38 static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data, 39 unsigned int clk_num) 40 { 41 int i; 42 43 clk_data->num = clk_num; 44 45 for (i = 0; i < clk_num; i++) 46 clk_data->hws[i] = ERR_PTR(-ENOENT); 47 } 48 49 struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev, 50 unsigned int clk_num) 51 { 52 struct clk_hw_onecell_data *clk_data; 53 54 clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, clk_num), 55 GFP_KERNEL); 56 if (!clk_data) 57 return NULL; 58 59 mtk_init_clk_data(clk_data, clk_num); 60 61 return clk_data; 62 } 63 EXPORT_SYMBOL_GPL(mtk_devm_alloc_clk_data); 64 65 struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) 66 { 67 struct clk_hw_onecell_data *clk_data; 68 69 clk_data = kzalloc(struct_size(clk_data, hws, clk_num), GFP_KERNEL); 70 if (!clk_data) 71 return NULL; 72 73 mtk_init_clk_data(clk_data, clk_num); 74 75 return clk_data; 76 } 77 EXPORT_SYMBOL_GPL(mtk_alloc_clk_data); 78 79 void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data) 80 { 81 kfree(clk_data); 82 } 83 EXPORT_SYMBOL_GPL(mtk_free_clk_data); 84 85 int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, 86 struct clk_hw_onecell_data *clk_data) 87 { 88 int i; 89 struct clk_hw *hw; 90 91 if (!clk_data) 92 return -ENOMEM; 93 94 for (i = 0; i < num; i++) { 95 const struct mtk_fixed_clk *rc = &clks[i]; 96 97 if (!IS_ERR_OR_NULL(clk_data->hws[rc->id])) { 98 pr_warn("Trying to register duplicate clock ID: %d\n", rc->id); 99 continue; 100 } 101 102 hw = clk_hw_register_fixed_rate(NULL, rc->name, rc->parent, 0, 103 rc->rate); 104 105 if (IS_ERR(hw)) { 106 pr_err("Failed to register clk %s: %pe\n", rc->name, 107 hw); 108 goto err; 109 } 110 111 clk_data->hws[rc->id] = hw; 112 } 113 114 return 0; 115 116 err: 117 while (--i >= 0) { 118 const struct mtk_fixed_clk *rc = &clks[i]; 119 120 if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) 121 continue; 122 123 clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); 124 clk_data->hws[rc->id] = ERR_PTR(-ENOENT); 125 } 126 127 return PTR_ERR(hw); 128 } 129 EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks); 130 131 void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, 132 struct clk_hw_onecell_data *clk_data) 133 { 134 int i; 135 136 if (!clk_data) 137 return; 138 139 for (i = num; i > 0; i--) { 140 const struct mtk_fixed_clk *rc = &clks[i - 1]; 141 142 if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) 143 continue; 144 145 clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); 146 clk_data->hws[rc->id] = ERR_PTR(-ENOENT); 147 } 148 } 149 EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks); 150 151 int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, 152 struct clk_hw_onecell_data *clk_data) 153 { 154 int i; 155 struct clk_hw *hw; 156 157 if (!clk_data) 158 return -ENOMEM; 159 160 for (i = 0; i < num; i++) { 161 const struct mtk_fixed_factor *ff = &clks[i]; 162 163 if (!IS_ERR_OR_NULL(clk_data->hws[ff->id])) { 164 pr_warn("Trying to register duplicate clock ID: %d\n", ff->id); 165 continue; 166 } 167 168 hw = clk_hw_register_fixed_factor(NULL, ff->name, ff->parent_name, 169 ff->flags, ff->mult, ff->div); 170 171 if (IS_ERR(hw)) { 172 pr_err("Failed to register clk %s: %pe\n", ff->name, 173 hw); 174 goto err; 175 } 176 177 clk_data->hws[ff->id] = hw; 178 } 179 180 return 0; 181 182 err: 183 while (--i >= 0) { 184 const struct mtk_fixed_factor *ff = &clks[i]; 185 186 if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) 187 continue; 188 189 clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); 190 clk_data->hws[ff->id] = ERR_PTR(-ENOENT); 191 } 192 193 return PTR_ERR(hw); 194 } 195 EXPORT_SYMBOL_GPL(mtk_clk_register_factors); 196 197 void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, 198 struct clk_hw_onecell_data *clk_data) 199 { 200 int i; 201 202 if (!clk_data) 203 return; 204 205 for (i = num; i > 0; i--) { 206 const struct mtk_fixed_factor *ff = &clks[i - 1]; 207 208 if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) 209 continue; 210 211 clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); 212 clk_data->hws[ff->id] = ERR_PTR(-ENOENT); 213 } 214 } 215 EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); 216 217 static struct clk_hw *mtk_clk_register_composite(struct device *dev, 218 const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) 219 { 220 struct clk_hw *hw; 221 struct clk_mux *mux = NULL; 222 struct clk_gate *gate = NULL; 223 struct clk_divider *div = NULL; 224 struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL; 225 const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL; 226 const char * const *parent_names; 227 const char *parent; 228 int num_parents; 229 int ret; 230 231 if (mc->mux_shift >= 0) { 232 mux = kzalloc(sizeof(*mux), GFP_KERNEL); 233 if (!mux) 234 return ERR_PTR(-ENOMEM); 235 236 mux->reg = base + mc->mux_reg; 237 mux->mask = BIT(mc->mux_width) - 1; 238 mux->shift = mc->mux_shift; 239 mux->lock = lock; 240 mux->flags = mc->mux_flags; 241 mux_hw = &mux->hw; 242 mux_ops = &clk_mux_ops; 243 244 parent_names = mc->parent_names; 245 num_parents = mc->num_parents; 246 } else { 247 parent = mc->parent; 248 parent_names = &parent; 249 num_parents = 1; 250 } 251 252 if (mc->gate_shift >= 0) { 253 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 254 if (!gate) { 255 ret = -ENOMEM; 256 goto err_out; 257 } 258 259 gate->reg = base + mc->gate_reg; 260 gate->bit_idx = mc->gate_shift; 261 gate->flags = CLK_GATE_SET_TO_DISABLE; 262 gate->lock = lock; 263 264 gate_hw = &gate->hw; 265 gate_ops = &clk_gate_ops; 266 } 267 268 if (mc->divider_shift >= 0) { 269 div = kzalloc(sizeof(*div), GFP_KERNEL); 270 if (!div) { 271 ret = -ENOMEM; 272 goto err_out; 273 } 274 275 div->reg = base + mc->divider_reg; 276 div->shift = mc->divider_shift; 277 div->width = mc->divider_width; 278 div->lock = lock; 279 280 div_hw = &div->hw; 281 div_ops = &clk_divider_ops; 282 } 283 284 hw = clk_hw_register_composite(dev, mc->name, parent_names, num_parents, 285 mux_hw, mux_ops, 286 div_hw, div_ops, 287 gate_hw, gate_ops, 288 mc->flags); 289 290 if (IS_ERR(hw)) { 291 ret = PTR_ERR(hw); 292 goto err_out; 293 } 294 295 return hw; 296 err_out: 297 kfree(div); 298 kfree(gate); 299 kfree(mux); 300 301 return ERR_PTR(ret); 302 } 303 304 static void mtk_clk_unregister_composite(struct clk_hw *hw) 305 { 306 struct clk_composite *composite; 307 struct clk_mux *mux = NULL; 308 struct clk_gate *gate = NULL; 309 struct clk_divider *div = NULL; 310 311 if (!hw) 312 return; 313 314 composite = to_clk_composite(hw); 315 if (composite->mux_hw) 316 mux = to_clk_mux(composite->mux_hw); 317 if (composite->gate_hw) 318 gate = to_clk_gate(composite->gate_hw); 319 if (composite->rate_hw) 320 div = to_clk_divider(composite->rate_hw); 321 322 clk_hw_unregister_composite(hw); 323 kfree(div); 324 kfree(gate); 325 kfree(mux); 326 } 327 328 int mtk_clk_register_composites(struct device *dev, 329 const struct mtk_composite *mcs, int num, 330 void __iomem *base, spinlock_t *lock, 331 struct clk_hw_onecell_data *clk_data) 332 { 333 struct clk_hw *hw; 334 int i; 335 336 if (!clk_data) 337 return -ENOMEM; 338 339 for (i = 0; i < num; i++) { 340 const struct mtk_composite *mc = &mcs[i]; 341 342 if (!IS_ERR_OR_NULL(clk_data->hws[mc->id])) { 343 pr_warn("Trying to register duplicate clock ID: %d\n", 344 mc->id); 345 continue; 346 } 347 348 hw = mtk_clk_register_composite(dev, mc, base, lock); 349 350 if (IS_ERR(hw)) { 351 pr_err("Failed to register clk %s: %pe\n", mc->name, 352 hw); 353 goto err; 354 } 355 356 clk_data->hws[mc->id] = hw; 357 } 358 359 return 0; 360 361 err: 362 while (--i >= 0) { 363 const struct mtk_composite *mc = &mcs[i]; 364 365 if (IS_ERR_OR_NULL(clk_data->hws[mcs->id])) 366 continue; 367 368 mtk_clk_unregister_composite(clk_data->hws[mc->id]); 369 clk_data->hws[mc->id] = ERR_PTR(-ENOENT); 370 } 371 372 return PTR_ERR(hw); 373 } 374 EXPORT_SYMBOL_GPL(mtk_clk_register_composites); 375 376 void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, 377 struct clk_hw_onecell_data *clk_data) 378 { 379 int i; 380 381 if (!clk_data) 382 return; 383 384 for (i = num; i > 0; i--) { 385 const struct mtk_composite *mc = &mcs[i - 1]; 386 387 if (IS_ERR_OR_NULL(clk_data->hws[mc->id])) 388 continue; 389 390 mtk_clk_unregister_composite(clk_data->hws[mc->id]); 391 clk_data->hws[mc->id] = ERR_PTR(-ENOENT); 392 } 393 } 394 EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites); 395 396 int mtk_clk_register_dividers(struct device *dev, 397 const struct mtk_clk_divider *mcds, int num, 398 void __iomem *base, spinlock_t *lock, 399 struct clk_hw_onecell_data *clk_data) 400 { 401 struct clk_hw *hw; 402 int i; 403 404 if (!clk_data) 405 return -ENOMEM; 406 407 for (i = 0; i < num; i++) { 408 const struct mtk_clk_divider *mcd = &mcds[i]; 409 410 if (!IS_ERR_OR_NULL(clk_data->hws[mcd->id])) { 411 pr_warn("Trying to register duplicate clock ID: %d\n", 412 mcd->id); 413 continue; 414 } 415 416 hw = clk_hw_register_divider(dev, mcd->name, mcd->parent_name, 417 mcd->flags, base + mcd->div_reg, mcd->div_shift, 418 mcd->div_width, mcd->clk_divider_flags, lock); 419 420 if (IS_ERR(hw)) { 421 pr_err("Failed to register clk %s: %pe\n", mcd->name, 422 hw); 423 goto err; 424 } 425 426 clk_data->hws[mcd->id] = hw; 427 } 428 429 return 0; 430 431 err: 432 while (--i >= 0) { 433 const struct mtk_clk_divider *mcd = &mcds[i]; 434 435 if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) 436 continue; 437 438 clk_hw_unregister_divider(clk_data->hws[mcd->id]); 439 clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); 440 } 441 442 return PTR_ERR(hw); 443 } 444 EXPORT_SYMBOL_GPL(mtk_clk_register_dividers); 445 446 void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, 447 struct clk_hw_onecell_data *clk_data) 448 { 449 int i; 450 451 if (!clk_data) 452 return; 453 454 for (i = num; i > 0; i--) { 455 const struct mtk_clk_divider *mcd = &mcds[i - 1]; 456 457 if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) 458 continue; 459 460 clk_hw_unregister_divider(clk_data->hws[mcd->id]); 461 clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); 462 } 463 } 464 EXPORT_SYMBOL_GPL(mtk_clk_unregister_dividers); 465 466 static int __mtk_clk_simple_probe(struct platform_device *pdev, 467 struct device_node *node) 468 { 469 const struct platform_device_id *id; 470 const struct mtk_clk_desc *mcd; 471 struct clk_hw_onecell_data *clk_data; 472 void __iomem *base; 473 int num_clks, r; 474 475 mcd = device_get_match_data(&pdev->dev); 476 if (!mcd) { 477 /* Clock driver wasn't registered from devicetree */ 478 id = platform_get_device_id(pdev); 479 if (id) 480 mcd = (const struct mtk_clk_desc *)id->driver_data; 481 482 if (!mcd) 483 return -EINVAL; 484 } 485 486 /* Composite clocks needs us to pass iomem pointer */ 487 if (mcd->composite_clks) { 488 if (!mcd->shared_io) 489 base = devm_platform_ioremap_resource(pdev, 0); 490 else 491 base = of_iomap(node, 0); 492 493 if (IS_ERR_OR_NULL(base)) 494 return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM; 495 } 496 497 /* Calculate how many clk_hw_onecell_data entries to allocate */ 498 num_clks = mcd->num_clks + mcd->num_composite_clks; 499 num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; 500 num_clks += mcd->num_mux_clks + mcd->num_divider_clks; 501 502 clk_data = mtk_alloc_clk_data(num_clks); 503 if (!clk_data) 504 return -ENOMEM; 505 506 if (mcd->fixed_clks) { 507 r = mtk_clk_register_fixed_clks(mcd->fixed_clks, 508 mcd->num_fixed_clks, clk_data); 509 if (r) 510 goto free_data; 511 } 512 513 if (mcd->factor_clks) { 514 r = mtk_clk_register_factors(mcd->factor_clks, 515 mcd->num_factor_clks, clk_data); 516 if (r) 517 goto unregister_fixed_clks; 518 } 519 520 if (mcd->mux_clks) { 521 r = mtk_clk_register_muxes(&pdev->dev, mcd->mux_clks, 522 mcd->num_mux_clks, node, 523 mcd->clk_lock, clk_data); 524 if (r) 525 goto unregister_factors; 526 } 527 528 if (mcd->composite_clks) { 529 /* We don't check composite_lock because it's optional */ 530 r = mtk_clk_register_composites(&pdev->dev, 531 mcd->composite_clks, 532 mcd->num_composite_clks, 533 base, mcd->clk_lock, clk_data); 534 if (r) 535 goto unregister_muxes; 536 } 537 538 if (mcd->divider_clks) { 539 r = mtk_clk_register_dividers(&pdev->dev, 540 mcd->divider_clks, 541 mcd->num_divider_clks, 542 base, mcd->clk_lock, clk_data); 543 if (r) 544 goto unregister_composites; 545 } 546 547 if (mcd->clks) { 548 r = mtk_clk_register_gates(&pdev->dev, node, mcd->clks, 549 mcd->num_clks, clk_data); 550 if (r) 551 goto unregister_dividers; 552 } 553 554 if (mcd->clk_notifier_func) { 555 struct clk *mfg_mux = clk_data->hws[mcd->mfg_clk_idx]->clk; 556 557 r = mcd->clk_notifier_func(&pdev->dev, mfg_mux); 558 if (r) 559 goto unregister_clks; 560 } 561 562 r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 563 if (r) 564 goto unregister_clks; 565 566 platform_set_drvdata(pdev, clk_data); 567 568 if (mcd->rst_desc) { 569 r = mtk_register_reset_controller_with_dev(&pdev->dev, 570 mcd->rst_desc); 571 if (r) 572 goto unregister_clks; 573 } 574 575 return r; 576 577 unregister_clks: 578 if (mcd->clks) 579 mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); 580 unregister_dividers: 581 if (mcd->divider_clks) 582 mtk_clk_unregister_dividers(mcd->divider_clks, 583 mcd->num_divider_clks, clk_data); 584 unregister_composites: 585 if (mcd->composite_clks) 586 mtk_clk_unregister_composites(mcd->composite_clks, 587 mcd->num_composite_clks, clk_data); 588 unregister_muxes: 589 if (mcd->mux_clks) 590 mtk_clk_unregister_muxes(mcd->mux_clks, 591 mcd->num_mux_clks, clk_data); 592 unregister_factors: 593 if (mcd->factor_clks) 594 mtk_clk_unregister_factors(mcd->factor_clks, 595 mcd->num_factor_clks, clk_data); 596 unregister_fixed_clks: 597 if (mcd->fixed_clks) 598 mtk_clk_unregister_fixed_clks(mcd->fixed_clks, 599 mcd->num_fixed_clks, clk_data); 600 free_data: 601 mtk_free_clk_data(clk_data); 602 if (mcd->shared_io && base) 603 iounmap(base); 604 return r; 605 } 606 607 static int __mtk_clk_simple_remove(struct platform_device *pdev, 608 struct device_node *node) 609 { 610 struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); 611 const struct mtk_clk_desc *mcd = device_get_match_data(&pdev->dev); 612 613 of_clk_del_provider(node); 614 if (mcd->clks) 615 mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); 616 if (mcd->divider_clks) 617 mtk_clk_unregister_dividers(mcd->divider_clks, 618 mcd->num_divider_clks, clk_data); 619 if (mcd->composite_clks) 620 mtk_clk_unregister_composites(mcd->composite_clks, 621 mcd->num_composite_clks, clk_data); 622 if (mcd->mux_clks) 623 mtk_clk_unregister_muxes(mcd->mux_clks, 624 mcd->num_mux_clks, clk_data); 625 if (mcd->factor_clks) 626 mtk_clk_unregister_factors(mcd->factor_clks, 627 mcd->num_factor_clks, clk_data); 628 if (mcd->fixed_clks) 629 mtk_clk_unregister_fixed_clks(mcd->fixed_clks, 630 mcd->num_fixed_clks, clk_data); 631 mtk_free_clk_data(clk_data); 632 633 return 0; 634 } 635 636 int mtk_clk_pdev_probe(struct platform_device *pdev) 637 { 638 struct device *dev = &pdev->dev; 639 struct device_node *node = dev->parent->of_node; 640 641 return __mtk_clk_simple_probe(pdev, node); 642 } 643 EXPORT_SYMBOL_GPL(mtk_clk_pdev_probe); 644 645 int mtk_clk_simple_probe(struct platform_device *pdev) 646 { 647 struct device_node *node = pdev->dev.of_node; 648 649 return __mtk_clk_simple_probe(pdev, node); 650 } 651 EXPORT_SYMBOL_GPL(mtk_clk_simple_probe); 652 653 int mtk_clk_pdev_remove(struct platform_device *pdev) 654 { 655 struct device *dev = &pdev->dev; 656 struct device_node *node = dev->parent->of_node; 657 658 return __mtk_clk_simple_remove(pdev, node); 659 } 660 EXPORT_SYMBOL_GPL(mtk_clk_pdev_remove); 661 662 int mtk_clk_simple_remove(struct platform_device *pdev) 663 { 664 return __mtk_clk_simple_remove(pdev, pdev->dev.of_node); 665 } 666 EXPORT_SYMBOL_GPL(mtk_clk_simple_remove); 667 668 MODULE_LICENSE("GPL"); 669