Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: keystone: sci-clk: add support for dynamically probing clocks

Currently, the driver contains a large hints table for clocks that exist
on a device, however, it is possible to probe the clocks from the firmware
also. Add support for this, and drop the clock hints table support from
the driver completely. This causes the driver to send a few extra sci-clk
messages during boot, basically one extra for each device that exists on
the SoC; on K2G this is approx 80.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>

+90 -290
+90 -290
drivers/clk/keystone/sci-clk.c
··· 29 29 #define SCI_CLK_INPUT_TERMINATION BIT(2) 30 30 31 31 /** 32 - * struct sci_clk_data - TI SCI clock data 33 - * @dev: device index 34 - * @num_clks: number of clocks for this device 35 - */ 36 - struct sci_clk_data { 37 - u16 dev; 38 - u16 num_clks; 39 - }; 40 - 41 - /** 42 32 * struct sci_clk_provider - TI SCI clock provider representation 43 33 * @sci: Handle to the System Control Interface protocol handler 44 34 * @ops: Pointer to the SCI ops to be used by the clocks 45 35 * @dev: Device pointer for the clock provider 46 - * @clk_data: Clock data 47 36 * @clocks: Clocks array for this device 48 37 * @num_clocks: Total number of clocks for this provider 49 38 */ ··· 40 51 const struct ti_sci_handle *sci; 41 52 const struct ti_sci_clk_ops *ops; 42 53 struct device *dev; 43 - const struct sci_clk_data *clk_data; 44 - struct clk_hw **clocks; 54 + struct sci_clk **clocks; 45 55 int num_clocks; 46 56 }; 47 57 ··· 49 61 * @hw: Hardware clock cookie for common clock framework 50 62 * @dev_id: Device index 51 63 * @clk_id: Clock index 64 + * @num_parents: Number of parents for this clock 52 65 * @provider: Master clock provider 53 66 * @flags: Flags for the clock 54 67 */ ··· 57 68 struct clk_hw hw; 58 69 u16 dev_id; 59 70 u8 clk_id; 71 + u8 num_parents; 60 72 struct sci_clk_provider *provider; 61 73 u8 flags; 62 74 }; ··· 263 273 /** 264 274 * _sci_clk_get - Gets a handle for an SCI clock 265 275 * @provider: Handle to SCI clock provider 266 - * @dev_id: device ID for the clock to register 267 - * @clk_id: clock ID for the clock to register 276 + * @sci_clk: Handle to the SCI clock to populate 268 277 * 269 278 * Gets a handle to an existing TI SCI hw clock, or builds a new clock 270 279 * entry and registers it with the common clock framework. Called from 271 280 * the common clock framework, when a corresponding of_clk_get call is 272 281 * executed, or recursively from itself when parsing parent clocks. 273 - * Returns a pointer to the hw clock struct, or ERR_PTR value in failure. 282 + * Returns 0 on success, negative error code on failure. 274 283 */ 275 - static struct clk_hw *_sci_clk_build(struct sci_clk_provider *provider, 276 - u16 dev_id, u8 clk_id) 284 + static int _sci_clk_build(struct sci_clk_provider *provider, 285 + struct sci_clk *sci_clk) 277 286 { 278 287 struct clk_init_data init = { NULL }; 279 - struct sci_clk *sci_clk = NULL; 280 288 char *name = NULL; 281 289 char **parent_names = NULL; 282 290 int i; 283 - int ret; 284 - 285 - sci_clk = devm_kzalloc(provider->dev, sizeof(*sci_clk), GFP_KERNEL); 286 - if (!sci_clk) 287 - return ERR_PTR(-ENOMEM); 288 - 289 - sci_clk->dev_id = dev_id; 290 - sci_clk->clk_id = clk_id; 291 - sci_clk->provider = provider; 292 - 293 - ret = provider->ops->get_num_parents(provider->sci, dev_id, 294 - clk_id, 295 - &init.num_parents); 296 - if (ret) 297 - goto err; 291 + int ret = 0; 298 292 299 293 name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev), 300 294 sci_clk->dev_id, sci_clk->clk_id); ··· 291 317 * to have mux functionality. Otherwise it is going to act as a root 292 318 * clock. 293 319 */ 294 - if (init.num_parents < 2) 295 - init.num_parents = 0; 320 + if (sci_clk->num_parents < 2) 321 + sci_clk->num_parents = 0; 296 322 297 - if (init.num_parents) { 298 - parent_names = kcalloc(init.num_parents, sizeof(char *), 323 + if (sci_clk->num_parents) { 324 + parent_names = kcalloc(sci_clk->num_parents, sizeof(char *), 299 325 GFP_KERNEL); 300 326 301 327 if (!parent_names) { ··· 303 329 goto err; 304 330 } 305 331 306 - for (i = 0; i < init.num_parents; i++) { 332 + for (i = 0; i < sci_clk->num_parents; i++) { 307 333 char *parent_name; 308 334 309 335 parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d", ··· 320 346 } 321 347 322 348 init.ops = &sci_clk_ops; 349 + init.num_parents = sci_clk->num_parents; 323 350 sci_clk->hw.init = &init; 324 351 325 352 ret = devm_clk_hw_register(provider->dev, &sci_clk->hw); ··· 329 354 330 355 err: 331 356 if (parent_names) { 332 - for (i = 0; i < init.num_parents; i++) 357 + for (i = 0; i < sci_clk->num_parents; i++) 333 358 kfree(parent_names[i]); 334 359 335 360 kfree(parent_names); ··· 337 362 338 363 kfree(name); 339 364 340 - if (ret) 341 - return ERR_PTR(ret); 342 - 343 - return &sci_clk->hw; 365 + return ret; 344 366 } 345 367 346 368 static int _cmp_sci_clk(const void *a, const void *b) ··· 386 414 387 415 static int ti_sci_init_clocks(struct sci_clk_provider *p) 388 416 { 389 - const struct sci_clk_data *data = p->clk_data; 390 - struct clk_hw *hw; 391 417 int i; 392 - int num_clks = 0; 418 + int ret; 393 419 394 - while (data->num_clks) { 395 - num_clks += data->num_clks; 396 - data++; 397 - } 398 - 399 - p->num_clocks = num_clks; 400 - 401 - p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk), 402 - GFP_KERNEL); 403 - if (!p->clocks) 404 - return -ENOMEM; 405 - 406 - num_clks = 0; 407 - 408 - data = p->clk_data; 409 - 410 - while (data->num_clks) { 411 - for (i = 0; i < data->num_clks; i++) { 412 - hw = _sci_clk_build(p, data->dev, i); 413 - if (!IS_ERR(hw)) { 414 - p->clocks[num_clks++] = hw; 415 - continue; 416 - } 417 - 418 - /* Skip any holes in the clock lists */ 419 - if (PTR_ERR(hw) == -ENODEV) 420 - continue; 421 - 422 - return PTR_ERR(hw); 423 - } 424 - data++; 420 + for (i = 0; i < p->num_clocks; i++) { 421 + ret = _sci_clk_build(p, p->clocks[i]); 422 + if (ret) 423 + return ret; 425 424 } 426 425 427 426 return 0; 428 427 } 429 428 430 - static const struct sci_clk_data k2g_clk_data[] = { 431 - /* pmmc */ 432 - { .dev = 0x0, .num_clks = 4 }, 433 - 434 - /* mlb0 */ 435 - { .dev = 0x1, .num_clks = 5 }, 436 - 437 - /* dss0 */ 438 - { .dev = 0x2, .num_clks = 2 }, 439 - 440 - /* mcbsp0 */ 441 - { .dev = 0x3, .num_clks = 8 }, 442 - 443 - /* mcasp0 */ 444 - { .dev = 0x4, .num_clks = 8 }, 445 - 446 - /* mcasp1 */ 447 - { .dev = 0x5, .num_clks = 8 }, 448 - 449 - /* mcasp2 */ 450 - { .dev = 0x6, .num_clks = 8 }, 451 - 452 - /* dcan0 */ 453 - { .dev = 0x8, .num_clks = 2 }, 454 - 455 - /* dcan1 */ 456 - { .dev = 0x9, .num_clks = 2 }, 457 - 458 - /* emif0 */ 459 - { .dev = 0xa, .num_clks = 6 }, 460 - 461 - /* mmchs0 */ 462 - { .dev = 0xb, .num_clks = 3 }, 463 - 464 - /* mmchs1 */ 465 - { .dev = 0xc, .num_clks = 3 }, 466 - 467 - /* gpmc0 */ 468 - { .dev = 0xd, .num_clks = 1 }, 469 - 470 - /* elm0 */ 471 - { .dev = 0xe, .num_clks = 1 }, 472 - 473 - /* spi0 */ 474 - { .dev = 0x10, .num_clks = 1 }, 475 - 476 - /* spi1 */ 477 - { .dev = 0x11, .num_clks = 1 }, 478 - 479 - /* spi2 */ 480 - { .dev = 0x12, .num_clks = 1 }, 481 - 482 - /* spi3 */ 483 - { .dev = 0x13, .num_clks = 1 }, 484 - 485 - /* icss0 */ 486 - { .dev = 0x14, .num_clks = 6 }, 487 - 488 - /* icss1 */ 489 - { .dev = 0x15, .num_clks = 6 }, 490 - 491 - /* usb0 */ 492 - { .dev = 0x16, .num_clks = 7 }, 493 - 494 - /* usb1 */ 495 - { .dev = 0x17, .num_clks = 7 }, 496 - 497 - /* nss0 */ 498 - { .dev = 0x18, .num_clks = 14 }, 499 - 500 - /* pcie0 */ 501 - { .dev = 0x19, .num_clks = 1 }, 502 - 503 - /* gpio0 */ 504 - { .dev = 0x1b, .num_clks = 1 }, 505 - 506 - /* gpio1 */ 507 - { .dev = 0x1c, .num_clks = 1 }, 508 - 509 - /* timer64_0 */ 510 - { .dev = 0x1d, .num_clks = 9 }, 511 - 512 - /* timer64_1 */ 513 - { .dev = 0x1e, .num_clks = 9 }, 514 - 515 - /* timer64_2 */ 516 - { .dev = 0x1f, .num_clks = 9 }, 517 - 518 - /* timer64_3 */ 519 - { .dev = 0x20, .num_clks = 9 }, 520 - 521 - /* timer64_4 */ 522 - { .dev = 0x21, .num_clks = 9 }, 523 - 524 - /* timer64_5 */ 525 - { .dev = 0x22, .num_clks = 9 }, 526 - 527 - /* timer64_6 */ 528 - { .dev = 0x23, .num_clks = 9 }, 529 - 530 - /* msgmgr0 */ 531 - { .dev = 0x25, .num_clks = 1 }, 532 - 533 - /* bootcfg0 */ 534 - { .dev = 0x26, .num_clks = 1 }, 535 - 536 - /* arm_bootrom0 */ 537 - { .dev = 0x27, .num_clks = 1 }, 538 - 539 - /* dsp_bootrom0 */ 540 - { .dev = 0x29, .num_clks = 1 }, 541 - 542 - /* debugss0 */ 543 - { .dev = 0x2b, .num_clks = 8 }, 544 - 545 - /* uart0 */ 546 - { .dev = 0x2c, .num_clks = 1 }, 547 - 548 - /* uart1 */ 549 - { .dev = 0x2d, .num_clks = 1 }, 550 - 551 - /* uart2 */ 552 - { .dev = 0x2e, .num_clks = 1 }, 553 - 554 - /* ehrpwm0 */ 555 - { .dev = 0x2f, .num_clks = 1 }, 556 - 557 - /* ehrpwm1 */ 558 - { .dev = 0x30, .num_clks = 1 }, 559 - 560 - /* ehrpwm2 */ 561 - { .dev = 0x31, .num_clks = 1 }, 562 - 563 - /* ehrpwm3 */ 564 - { .dev = 0x32, .num_clks = 1 }, 565 - 566 - /* ehrpwm4 */ 567 - { .dev = 0x33, .num_clks = 1 }, 568 - 569 - /* ehrpwm5 */ 570 - { .dev = 0x34, .num_clks = 1 }, 571 - 572 - /* eqep0 */ 573 - { .dev = 0x35, .num_clks = 1 }, 574 - 575 - /* eqep1 */ 576 - { .dev = 0x36, .num_clks = 1 }, 577 - 578 - /* eqep2 */ 579 - { .dev = 0x37, .num_clks = 1 }, 580 - 581 - /* ecap0 */ 582 - { .dev = 0x38, .num_clks = 1 }, 583 - 584 - /* ecap1 */ 585 - { .dev = 0x39, .num_clks = 1 }, 586 - 587 - /* i2c0 */ 588 - { .dev = 0x3a, .num_clks = 1 }, 589 - 590 - /* i2c1 */ 591 - { .dev = 0x3b, .num_clks = 1 }, 592 - 593 - /* i2c2 */ 594 - { .dev = 0x3c, .num_clks = 1 }, 595 - 596 - /* edma0 */ 597 - { .dev = 0x3f, .num_clks = 2 }, 598 - 599 - /* semaphore0 */ 600 - { .dev = 0x40, .num_clks = 1 }, 601 - 602 - /* intc0 */ 603 - { .dev = 0x41, .num_clks = 1 }, 604 - 605 - /* gic0 */ 606 - { .dev = 0x42, .num_clks = 1 }, 607 - 608 - /* qspi0 */ 609 - { .dev = 0x43, .num_clks = 5 }, 610 - 611 - /* arm_64b_counter0 */ 612 - { .dev = 0x44, .num_clks = 2 }, 613 - 614 - /* tetris0 */ 615 - { .dev = 0x45, .num_clks = 2 }, 616 - 617 - /* cgem0 */ 618 - { .dev = 0x46, .num_clks = 2 }, 619 - 620 - /* msmc0 */ 621 - { .dev = 0x47, .num_clks = 1 }, 622 - 623 - /* cbass0 */ 624 - { .dev = 0x49, .num_clks = 1 }, 625 - 626 - /* board0 */ 627 - { .dev = 0x4c, .num_clks = 36 }, 628 - 629 - /* edma1 */ 630 - { .dev = 0x4f, .num_clks = 2 }, 631 - { .num_clks = 0 }, 632 - }; 633 - 634 429 static const struct of_device_id ti_sci_clk_of_match[] = { 635 - { .compatible = "ti,k2g-sci-clk", .data = &k2g_clk_data }, 430 + { .compatible = "ti,k2g-sci-clk" }, 636 431 { /* Sentinel */ }, 637 432 }; 638 433 MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match); ··· 420 681 struct device_node *np = dev->of_node; 421 682 struct sci_clk_provider *provider; 422 683 const struct ti_sci_handle *handle; 423 - const struct sci_clk_data *data; 424 684 int ret; 425 - 426 - data = of_device_get_match_data(dev); 427 - if (!data) 428 - return -EINVAL; 685 + int num_clks = 0; 686 + struct sci_clk **clks = NULL; 687 + struct sci_clk **tmp_clks; 688 + struct sci_clk *sci_clk; 689 + int max_clks = 0; 690 + int clk_id = 0; 691 + int dev_id = 0; 692 + u8 num_parents; 693 + int gap_size = 0; 429 694 430 695 handle = devm_ti_sci_get_handle(dev); 431 696 if (IS_ERR(handle)) ··· 439 696 if (!provider) 440 697 return -ENOMEM; 441 698 442 - provider->clk_data = data; 443 - 444 699 provider->sci = handle; 445 700 provider->ops = &handle->ops.clk_ops; 446 701 provider->dev = dev; 702 + 703 + while (1) { 704 + ret = provider->ops->get_num_parents(provider->sci, dev_id, 705 + clk_id, &num_parents); 706 + if (ret) { 707 + gap_size++; 708 + if (!clk_id) { 709 + if (gap_size >= 5) 710 + break; 711 + dev_id++; 712 + } else { 713 + if (gap_size >= 2) { 714 + dev_id++; 715 + clk_id = 0; 716 + gap_size = 0; 717 + } else { 718 + clk_id++; 719 + } 720 + } 721 + continue; 722 + } 723 + 724 + gap_size = 0; 725 + 726 + if (num_clks == max_clks) { 727 + tmp_clks = devm_kmalloc_array(dev, max_clks + 64, 728 + sizeof(sci_clk), 729 + GFP_KERNEL); 730 + memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk)); 731 + if (max_clks) 732 + devm_kfree(dev, clks); 733 + max_clks += 64; 734 + clks = tmp_clks; 735 + } 736 + 737 + sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL); 738 + if (!sci_clk) 739 + return -ENOMEM; 740 + sci_clk->dev_id = dev_id; 741 + sci_clk->clk_id = clk_id; 742 + sci_clk->provider = provider; 743 + sci_clk->num_parents = num_parents; 744 + 745 + clks[num_clks] = sci_clk; 746 + 747 + clk_id++; 748 + num_clks++; 749 + } 750 + 751 + provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk), 752 + GFP_KERNEL); 753 + if (!provider->clocks) 754 + return -ENOMEM; 755 + 756 + memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk)); 757 + 758 + provider->num_clocks = num_clks; 759 + 760 + devm_kfree(dev, clks); 447 761 448 762 ret = ti_sci_init_clocks(provider); 449 763 if (ret) {