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

clk: qcom: Allow clk_set_parent() to work on display clocks

Sometimes the display driver may want to change the parent PLL of
the display clocks (byte and pixel clocks) depending on the
use-case. Currently the parent is fixed by means of having a
frequency table with one entry that chooses a particular parent.
Remove this restriction and use the parent the clock is
configured for in the hardware during clk_set_rate(). This
requires consumers to rely on the default parent or to configure
the parent with clk_set_parent()/assigned-clock-parents on the
clocks before calling clk_set_rate().

Tested-by: Archit Taneja <architt@codeaurora.org>
Cc: Hai Li <hali@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

+89 -46
+1
drivers/clk/qcom/clk-rcg.h
··· 171 171 extern const struct clk_ops clk_rcg2_ops; 172 172 extern const struct clk_ops clk_edp_pixel_ops; 173 173 extern const struct clk_ops clk_byte_ops; 174 + extern const struct clk_ops clk_byte2_ops; 174 175 extern const struct clk_ops clk_pixel_ops; 175 176 176 177 #endif
+83 -8
drivers/clk/qcom/clk-rcg2.c
··· 485 485 }; 486 486 EXPORT_SYMBOL_GPL(clk_byte_ops); 487 487 488 + static int clk_byte2_determine_rate(struct clk_hw *hw, 489 + struct clk_rate_request *req) 490 + { 491 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 492 + unsigned long parent_rate, div; 493 + u32 mask = BIT(rcg->hid_width) - 1; 494 + struct clk_hw *p; 495 + unsigned long rate = req->rate; 496 + 497 + if (rate == 0) 498 + return -EINVAL; 499 + 500 + p = req->best_parent_hw; 501 + req->best_parent_rate = parent_rate = clk_hw_round_rate(p, rate); 502 + 503 + div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; 504 + div = min_t(u32, div, mask); 505 + 506 + req->rate = calc_rate(parent_rate, 0, 0, 0, div); 507 + 508 + return 0; 509 + } 510 + 511 + static int clk_byte2_set_rate(struct clk_hw *hw, unsigned long rate, 512 + unsigned long parent_rate) 513 + { 514 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 515 + struct freq_tbl f = { 0 }; 516 + unsigned long div; 517 + int i, num_parents = clk_hw_get_num_parents(hw); 518 + u32 mask = BIT(rcg->hid_width) - 1; 519 + u32 cfg; 520 + 521 + div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; 522 + div = min_t(u32, div, mask); 523 + 524 + f.pre_div = div; 525 + 526 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); 527 + cfg &= CFG_SRC_SEL_MASK; 528 + cfg >>= CFG_SRC_SEL_SHIFT; 529 + 530 + for (i = 0; i < num_parents; i++) { 531 + if (cfg == rcg->parent_map[i].cfg) { 532 + f.src = rcg->parent_map[i].src; 533 + return clk_rcg2_configure(rcg, &f); 534 + } 535 + } 536 + 537 + return -EINVAL; 538 + } 539 + 540 + static int clk_byte2_set_rate_and_parent(struct clk_hw *hw, 541 + unsigned long rate, unsigned long parent_rate, u8 index) 542 + { 543 + /* Read the hardware to determine parent during set_rate */ 544 + return clk_byte2_set_rate(hw, rate, parent_rate); 545 + } 546 + 547 + const struct clk_ops clk_byte2_ops = { 548 + .is_enabled = clk_rcg2_is_enabled, 549 + .get_parent = clk_rcg2_get_parent, 550 + .set_parent = clk_rcg2_set_parent, 551 + .recalc_rate = clk_rcg2_recalc_rate, 552 + .set_rate = clk_byte2_set_rate, 553 + .set_rate_and_parent = clk_byte2_set_rate_and_parent, 554 + .determine_rate = clk_byte2_determine_rate, 555 + }; 556 + EXPORT_SYMBOL_GPL(clk_byte2_ops); 557 + 488 558 static const struct frac_entry frac_table_pixel[] = { 489 559 { 3, 8 }, 490 560 { 2, 9 }, ··· 566 496 static int clk_pixel_determine_rate(struct clk_hw *hw, 567 497 struct clk_rate_request *req) 568 498 { 569 - struct clk_rcg2 *rcg = to_clk_rcg2(hw); 570 499 unsigned long request, src_rate; 571 500 int delta = 100000; 572 - const struct freq_tbl *f = rcg->freq_tbl; 573 501 const struct frac_entry *frac = frac_table_pixel; 574 - int index = qcom_find_src_index(hw, rcg->parent_map, f->src); 575 - 576 - req->best_parent_hw = clk_hw_get_parent_by_index(hw, index); 577 502 578 503 for (; frac->num; frac++) { 579 504 request = (req->rate * frac->den) / frac->num; ··· 590 525 unsigned long parent_rate) 591 526 { 592 527 struct clk_rcg2 *rcg = to_clk_rcg2(hw); 593 - struct freq_tbl f = *rcg->freq_tbl; 528 + struct freq_tbl f = { 0 }; 594 529 const struct frac_entry *frac = frac_table_pixel; 595 530 unsigned long request; 596 531 int delta = 100000; 597 532 u32 mask = BIT(rcg->hid_width) - 1; 598 - u32 hid_div; 533 + u32 hid_div, cfg; 534 + int i, num_parents = clk_hw_get_num_parents(hw); 535 + 536 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); 537 + cfg &= CFG_SRC_SEL_MASK; 538 + cfg >>= CFG_SRC_SEL_SHIFT; 539 + 540 + for (i = 0; i < num_parents; i++) 541 + if (cfg == rcg->parent_map[i].cfg) { 542 + f.src = rcg->parent_map[i].src; 543 + break; 544 + } 599 545 600 546 for (; frac->num; frac++) { 601 547 request = (rate * frac->den) / frac->num; ··· 631 555 static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, 632 556 unsigned long parent_rate, u8 index) 633 557 { 634 - /* Parent index is set statically in frequency table */ 635 558 return clk_pixel_set_rate(hw, rate, parent_rate); 636 559 } 637 560
+1 -13
drivers/clk/qcom/gcc-msm8916.c
··· 906 906 }, 907 907 }; 908 908 909 - static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = { 910 - { .src = P_DSI0_PHYPLL_BYTE }, 911 - { } 912 - }; 913 - 914 909 static struct clk_rcg2 byte0_clk_src = { 915 910 .cmd_rcgr = 0x4d044, 916 911 .hid_width = 5, 917 912 .parent_map = gcc_xo_gpll0a_dsibyte_map, 918 - .freq_tbl = ftbl_gcc_mdss_byte0_clk, 919 913 .clkr.hw.init = &(struct clk_init_data){ 920 914 .name = "byte0_clk_src", 921 915 .parent_names = gcc_xo_gpll0a_dsibyte, 922 916 .num_parents = 3, 923 - .ops = &clk_byte_ops, 917 + .ops = &clk_byte2_ops, 924 918 .flags = CLK_SET_RATE_PARENT, 925 919 }, 926 920 }; ··· 962 968 }, 963 969 }; 964 970 965 - static struct freq_tbl ftbl_gcc_mdss_pclk[] = { 966 - { .src = P_DSI0_PHYPLL_DSI }, 967 - { } 968 - }; 969 - 970 971 static struct clk_rcg2 pclk0_clk_src = { 971 972 .cmd_rcgr = 0x4d000, 972 973 .mnd_width = 8, 973 974 .hid_width = 5, 974 975 .parent_map = gcc_xo_gpll0a_dsiphy_map, 975 - .freq_tbl = ftbl_gcc_mdss_pclk, 976 976 .clkr.hw.init = &(struct clk_init_data){ 977 977 .name = "pclk0_clk_src", 978 978 .parent_names = gcc_xo_gpll0a_dsiphy,
+2 -16
drivers/clk/qcom/mmcc-apq8084.c
··· 571 571 }, 572 572 }; 573 573 574 - static struct freq_tbl pixel_freq_tbl[] = { 575 - { .src = P_DSI0PLL }, 576 - { } 577 - }; 578 - 579 574 static struct clk_rcg2 pclk0_clk_src = { 580 575 .cmd_rcgr = 0x2000, 581 576 .mnd_width = 8, 582 577 .hid_width = 5, 583 578 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 584 - .freq_tbl = pixel_freq_tbl, 585 579 .clkr.hw.init = &(struct clk_init_data){ 586 580 .name = "pclk0_clk_src", 587 581 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, ··· 590 596 .mnd_width = 8, 591 597 .hid_width = 5, 592 598 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 593 - .freq_tbl = pixel_freq_tbl, 594 599 .clkr.hw.init = &(struct clk_init_data){ 595 600 .name = "pclk1_clk_src", 596 601 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, ··· 837 844 }, 838 845 }; 839 846 840 - static struct freq_tbl byte_freq_tbl[] = { 841 - { .src = P_DSI0PLL_BYTE }, 842 - { } 843 - }; 844 - 845 847 static struct clk_rcg2 byte0_clk_src = { 846 848 .cmd_rcgr = 0x2120, 847 849 .hid_width = 5, 848 850 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, 849 - .freq_tbl = byte_freq_tbl, 850 851 .clkr.hw.init = &(struct clk_init_data){ 851 852 .name = "byte0_clk_src", 852 853 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, 853 854 .num_parents = 6, 854 - .ops = &clk_byte_ops, 855 + .ops = &clk_byte2_ops, 855 856 .flags = CLK_SET_RATE_PARENT, 856 857 }, 857 858 }; ··· 854 867 .cmd_rcgr = 0x2140, 855 868 .hid_width = 5, 856 869 .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, 857 - .freq_tbl = byte_freq_tbl, 858 870 .clkr.hw.init = &(struct clk_init_data){ 859 871 .name = "byte1_clk_src", 860 872 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, 861 873 .num_parents = 6, 862 - .ops = &clk_byte_ops, 874 + .ops = &clk_byte2_ops, 863 875 .flags = CLK_SET_RATE_PARENT, 864 876 }, 865 877 };
+2 -9
drivers/clk/qcom/mmcc-msm8974.c
··· 522 522 }, 523 523 }; 524 524 525 - static struct freq_tbl pixel_freq_tbl[] = { 526 - { .src = P_DSI0PLL }, 527 - { } 528 - }; 529 - 530 525 static struct clk_rcg2 pclk0_clk_src = { 531 526 .cmd_rcgr = 0x2000, 532 527 .mnd_width = 8, 533 528 .hid_width = 5, 534 529 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 535 - .freq_tbl = pixel_freq_tbl, 536 530 .clkr.hw.init = &(struct clk_init_data){ 537 531 .name = "pclk0_clk_src", 538 532 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, ··· 541 547 .mnd_width = 8, 542 548 .hid_width = 5, 543 549 .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, 544 - .freq_tbl = pixel_freq_tbl, 545 550 .clkr.hw.init = &(struct clk_init_data){ 546 551 .name = "pclk1_clk_src", 547 552 .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, ··· 778 785 .name = "byte0_clk_src", 779 786 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, 780 787 .num_parents = 6, 781 - .ops = &clk_byte_ops, 788 + .ops = &clk_byte2_ops, 782 789 .flags = CLK_SET_RATE_PARENT, 783 790 }, 784 791 }; ··· 792 799 .name = "byte1_clk_src", 793 800 .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, 794 801 .num_parents = 6, 795 - .ops = &clk_byte_ops, 802 + .ops = &clk_byte2_ops, 796 803 .flags = CLK_SET_RATE_PARENT, 797 804 }, 798 805 };