diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 4e38de7ddd3e..084b942d102d 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -56,6 +56,7 @@ config ARCH_QCOM select SOC_BUS select MSM_IRQ select THERMAL_WRITABLE_TRIPS + select RATIONAL help This enables support for the ARMv8 based Qualcomm chipsets. diff --git a/drivers/clk/msm/clock-local2.c b/drivers/clk/msm/clock-local2.c index 55fa76046def..6cf53c78d4d6 100644 --- a/drivers/clk/msm/clock-local2.c +++ b/drivers/clk/msm/clock-local2.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1735,6 +1736,46 @@ static struct clk *edp_clk_get_parent(struct clk *c) return freq->src_clk; } +static int rcg_clk_set_rate_dp(struct clk *clk, unsigned long rate) +{ + struct rcg_clk *rcg = to_rcg_clk(clk); + struct clk_freq_tbl *freq_tbl = rcg->current_freq; + unsigned long src_rate; + unsigned long num, den, flags; + + src_rate = clk_get_rate(clk->parent); + if (src_rate <= 0) { + pr_err("Invalid RCG parent rate\n"); + return -EINVAL; + } + + rational_best_approximation(src_rate, rate, + (unsigned long)(1 << 16) - 1, + (unsigned long)(1 << 16) - 1, &den, &num); + + if (!num || !den) { + pr_err("Invalid MN values derived for requested rate %lu\n", + rate); + return -EINVAL; + } + + freq_tbl->div_src_val &= ~BM(4, 0); + if (num == den) { + freq_tbl->m_val = 0; + freq_tbl->n_val = 0; + } else { + freq_tbl->m_val = num; + freq_tbl->n_val = ~(den - num); + freq_tbl->d_val = ~den; + } + + spin_lock_irqsave(&local_clock_reg_lock, flags); + if (!is_same_rcg_config(rcg, freq_tbl, true)) + __set_rate_mnd(rcg, freq_tbl); + spin_unlock_irqrestore(&local_clock_reg_lock, flags); + return 0; +} + static int gate_clk_enable(struct clk *c) { unsigned long flags; @@ -2291,6 +2332,15 @@ struct clk_ops clk_ops_rcg_edp = { .list_registers = rcg_hid_clk_list_registers, }; +struct clk_ops clk_ops_rcg_dp = { + .enable = rcg_clk_enable, + .disable = rcg_clk_disable, + .set_rate = rcg_clk_set_rate_dp, + .list_rate = rcg_clk_list_rate, + .handoff = pixel_rcg_handoff, + .list_registers = rcg_mnd_clk_list_registers, +}; + struct clk_ops clk_ops_branch = { .enable = branch_clk_enable, .prepare = branch_clk_prepare, diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c index 66807366d19d..53c657ef3a25 100644 --- a/drivers/clk/msm/clock-mmss-cobalt.c +++ b/drivers/clk/msm/clock-mmss-cobalt.c @@ -1107,6 +1107,29 @@ static struct rcg_clk dp_aux_clk_src = { }, }; +static struct clk_freq_tbl ftbl_dp_pixel_clk_src[] = { + { + .div_src_val = BVAL(10, 8, ext_dp_phy_pll_vco_mm_source_val), + .src_clk = &ext_dp_phy_pll_vco.c, + }, + F_END +}; + +static struct rcg_clk dp_pixel_clk_src = { + .cmd_rcgr_reg = MMSS_DP_PIXEL_CMD_RCGR, + .set_rate = set_rate_mnd, + .current_freq = ftbl_dp_pixel_clk_src, + .base = &virt_base, + .c = { + .dbg_name = "dp_pixel_clk_src", + .parent = &ext_dp_phy_pll_vco.c, + .ops = &clk_ops_rcg_dp, + VDD_DIG_FMAX_MAP3(LOWER, 148380000, LOW, 296740000, + NOMINAL, 593470000), + CLK_INIT(dp_pixel_clk_src.c), + }, +}; + static struct clk_freq_tbl ftbl_dp_link_clk_src[] = { F_SLEW( 162000000, 324000000, ext_dp_phy_pll_link, 2, 0, 0), F_SLEW( 270000000, 540000000, ext_dp_phy_pll_link, 2, 0, 0), @@ -2003,6 +2026,18 @@ static struct branch_clk mmss_mdss_dp_aux_clk = { }, }; +static struct branch_clk mmss_mdss_dp_pixel_clk = { + .cbcr_reg = MMSS_MDSS_DP_PIXEL_CBCR, + .has_sibling = 0, + .base = &virt_base, + .c = { + .dbg_name = "mmss_mdss_dp_pixel_clk", + .parent = &dp_pixel_clk_src.c, + .ops = &clk_ops_branch, + CLK_INIT(mmss_mdss_dp_pixel_clk.c), + }, +}; + static struct branch_clk mmss_mdss_dp_link_clk = { .cbcr_reg = MMSS_MDSS_DP_LINK_CBCR, .has_sibling = 0, @@ -2425,6 +2460,7 @@ static struct mux_clk mmss_debug_mux = { { &mmss_mdss_dp_link_clk.c, 0x0098 }, { &mmss_mdss_dp_link_intf_clk.c, 0x0099 }, { &mmss_mdss_dp_crypto_clk.c, 0x009a }, + { &mmss_mdss_dp_pixel_clk.c, 0x009b }, { &mmss_mdss_dp_aux_clk.c, 0x009c }, { &mmss_mdss_dp_gtc_clk.c, 0x009d }, { &mmss_mdss_byte0_intf_clk.c, 0x00ad }, @@ -2494,6 +2530,7 @@ static struct clk_lookup msm_clocks_mmss_cobalt[] = { CLK_LIST(extpclk_clk_src), CLK_LIST(ext_dp_phy_pll_vco), CLK_LIST(ext_dp_phy_pll_link), + CLK_LIST(dp_pixel_clk_src), CLK_LIST(dp_link_clk_src), CLK_LIST(dp_crypto_clk_src), CLK_LIST(csi0phytimer_clk_src), @@ -2576,6 +2613,7 @@ static struct clk_lookup msm_clocks_mmss_cobalt[] = { CLK_LIST(mmss_mdss_byte1_intf_clk), CLK_LIST(mmss_mdss_dp_aux_clk), CLK_LIST(mmss_mdss_dp_crypto_clk), + CLK_LIST(mmss_mdss_dp_pixel_clk), CLK_LIST(mmss_mdss_dp_link_clk), CLK_LIST(mmss_mdss_dp_link_intf_clk), CLK_LIST(mmss_mdss_dp_gtc_clk), diff --git a/include/soc/qcom/clock-local2.h b/include/soc/qcom/clock-local2.h index 7f785cf4d3a2..4f2fa36e920f 100644 --- a/include/soc/qcom/clock-local2.h +++ b/include/soc/qcom/clock-local2.h @@ -255,6 +255,7 @@ extern struct clk_ops clk_ops_branch_hw_ctl; extern struct clk_ops clk_ops_vote; extern struct clk_ops clk_ops_rcg_hdmi; extern struct clk_ops clk_ops_rcg_edp; +extern struct clk_ops clk_ops_rcg_dp; extern struct clk_ops clk_ops_byte; extern struct clk_ops clk_ops_pixel; extern struct clk_ops clk_ops_byte_multiparent;