From: Taniya Das <quic_tdas@quicinc.com>
To: Bjorn Andersson <andersson@kernel.org>,
Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>,
Abhishek Sahu <absahu@codeaurora.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>
Cc: Ajit Pandey <quic_ajipan@quicinc.com>,
Imran Shaik <quic_imrashai@quicinc.com>,
Jagadeesh Kona <quic_jkona@quicinc.com>,
<linux-arm-msm@vger.kernel.org>, <linux-clk@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
Taniya Das <quic_tdas@quicinc.com>
Subject: [PATCH v3 02/11] clk: qcom: clk-alpha-pll: Add support for dynamic update for slewing PLLs
Date: Fri, 8 Nov 2024 09:39:19 +0530 [thread overview]
Message-ID: <20241108-qcs615-mm-clockcontroller-v3-2-7d3b2d235fdf@quicinc.com> (raw)
In-Reply-To: <20241108-qcs615-mm-clockcontroller-v3-0-7d3b2d235fdf@quicinc.com>
The alpha PLLs which slew to a new frequency at runtime would require
the PLL to calibrate at the mid point of the VCO. Add the new PLL ops
which can support the slewing of the PLL to a new frequency.
Reviewed-by: Imran Shaik <quic_imrashai@quicinc.com>
Signed-off-by: Taniya Das <quic_tdas@quicinc.com>
---
drivers/clk/qcom/clk-alpha-pll.c | 170 +++++++++++++++++++++++++++++++++++++++
drivers/clk/qcom/clk-alpha-pll.h | 1 +
2 files changed, 171 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 03cc7aa092480bfdd9eaa986d44f0545944b3b89..fe9e5d5344d7fa9a8a1f220f8982fbafc875c4c1 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -2758,3 +2758,173 @@ const struct clk_ops clk_alpha_pll_regera_ops = {
.set_rate = clk_zonda_pll_set_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops);
+
+static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll)
+{
+ int ret;
+ u32 val;
+
+ regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, PLL_UPDATE);
+ regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+
+ ret = wait_for_pll_update(pll);
+ if (ret)
+ return ret;
+ /*
+ * Hardware programming mandates a wait of at least 570ns before polling the LOCK
+ * detect bit. Have a delay of 1us just to be safe.
+ */
+ mb();
+ udelay(1);
+
+ return wait_for_pll_enable_lock(pll);
+}
+
+static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ unsigned long freq_hz;
+ const struct pll_vco *curr_vco, *vco;
+ u32 l, alpha_width = pll_alpha_width(pll);
+ u64 a;
+
+ freq_hz = alpha_pll_round_rate(rate, parent_rate, &l, &a, alpha_width);
+ if (freq_hz != rate) {
+ pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ curr_vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+ if (!curr_vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ vco = alpha_pll_find_vco(pll, freq_hz);
+ if (!vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Dynamic pll update will not support switching frequencies across
+ * vco ranges. In those cases fall back to normal alpha set rate.
+ */
+ if (curr_vco->val != vco->val)
+ return clk_alpha_pll_set_rate(hw, rate, parent_rate);
+
+ a = a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+ /* Ensure that the write above goes through before proceeding. */
+ mb();
+
+ if (clk_hw_is_enabled(hw))
+ return clk_alpha_pll_slew_update(pll);
+
+ return 0;
+}
+
+/*
+ * Slewing plls should be bought up at frequency which is in the middle of the
+ * desired VCO range. So after bringing up the pll at calibration freq, set it
+ * back to desired frequency(that was set by previous clk_set_rate).
+ */
+static int clk_alpha_pll_calibrate(struct clk_hw *hw)
+{
+ unsigned long calibration_freq, freq_hz;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ struct clk_hw *parent;
+ const struct pll_vco *vco;
+ u32 l, alpha_width = pll_alpha_width(pll);
+ int rc;
+ u64 a;
+
+ parent = clk_hw_get_parent(hw);
+ if (!parent) {
+ pr_err("alpha pll: no valid parent found\n");
+ return -EINVAL;
+ }
+
+ vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+ if (!vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ /*
+ * As during slewing plls vco_sel won't be allowed to change, vco table
+ * should have only one entry table, i.e. index = 0, find the
+ * calibration frequency.
+ */
+ calibration_freq = (pll->vco_table[0].min_freq + pll->vco_table[0].max_freq) / 2;
+
+ freq_hz = alpha_pll_round_rate(calibration_freq, clk_hw_get_rate(parent),
+ &l, &a, alpha_width);
+ if (freq_hz != calibration_freq) {
+ pr_err("alpha_pll: call clk_set_rate with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ /* Setup PLL for calibration frequency */
+ a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_VCO_MASK << PLL_VCO_SHIFT,
+ vco->val << PLL_VCO_SHIFT);
+
+ /* Bringup the pll at calibration frequency */
+ rc = clk_alpha_pll_enable(hw);
+ if (rc) {
+ pr_err("alpha pll calibration failed\n");
+ return rc;
+ }
+
+ /*
+ * PLL is already running at calibration frequency.
+ * So slew pll to the previously set frequency.
+ */
+ freq_hz = alpha_pll_round_rate(clk_hw_get_rate(hw),
+ clk_hw_get_rate(parent), &l, &a, alpha_width);
+
+ pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n",
+ clk_hw_get_name(hw), clk_hw_get_rate(hw), freq_hz);
+
+ /* Setup the PLL for the new frequency */
+ a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
+
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_ALPHA_EN, PLL_ALPHA_EN);
+
+ return clk_alpha_pll_slew_update(pll);
+}
+
+static int clk_alpha_pll_slew_enable(struct clk_hw *hw)
+{
+ int rc;
+
+ rc = clk_alpha_pll_calibrate(hw);
+ if (rc)
+ return rc;
+
+ return clk_alpha_pll_enable(hw);
+}
+
+const struct clk_ops clk_alpha_pll_slew_ops = {
+ .enable = clk_alpha_pll_slew_enable,
+ .disable = clk_alpha_pll_disable,
+ .recalc_rate = clk_alpha_pll_recalc_rate,
+ .round_rate = clk_alpha_pll_round_rate,
+ .set_rate = clk_alpha_pll_slew_set_rate,
+};
+EXPORT_SYMBOL(clk_alpha_pll_slew_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 55eca04b23a1fc3f3554f43a8fdd329a524dad0e..f149d10247bd4a85521940a1255cd019bde4729a 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -195,6 +195,7 @@ extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
#define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
extern const struct clk_ops clk_alpha_pll_regera_ops;
+extern const struct clk_ops clk_alpha_pll_slew_ops;
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
--
2.45.2
next prev parent reply other threads:[~2024-11-08 4:10 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-08 4:09 [PATCH v3 00/11] Add support for videocc, camcc, dispcc and gpucc on Qualcomm QCS615 platform Taniya Das
2024-11-08 4:09 ` [PATCH v3 01/11] clk: qcom: Update the support for alpha mode configuration Taniya Das
2024-11-08 4:09 ` Taniya Das [this message]
2024-11-08 4:09 ` [PATCH v3 03/11] dt-bindings: clock: Add Qualcomm QCS615 Camera clock controller Taniya Das
2024-11-08 12:28 ` Vladimir Zapolskiy
2024-12-02 7:31 ` Taniya Das
2024-11-08 17:22 ` Dmitry Baryshkov
2024-12-02 7:32 ` Taniya Das
2024-11-08 4:09 ` [PATCH v3 04/11] clk: qcom: camcc-qcs615: Add QCS615 camera clock controller driver Taniya Das
2024-11-08 17:36 ` Bryan O'Donoghue
2024-11-08 4:09 ` [PATCH v3 05/11] dt-bindings: clock: Add Qualcomm QCS615 Display clock controller Taniya Das
2024-11-08 5:46 ` Rob Herring (Arm)
2024-11-08 11:39 ` Krzysztof Kozlowski
2024-12-02 7:35 ` Taniya Das
2024-12-02 11:52 ` Dmitry Baryshkov
2024-11-08 4:09 ` [PATCH v3 06/11] clk: qcom: dispcc-qcs615: Add QCS615 display clock controller driver Taniya Das
2024-11-08 4:09 ` [PATCH v3 07/11] dt-bindings: clock: Add Qualcomm QCS615 Graphics clock controller Taniya Das
2024-11-08 5:46 ` Rob Herring (Arm)
2024-11-08 4:09 ` [PATCH v3 08/11] clk: qcom: gpucc-qcs615: Add QCS615 graphics clock controller driver Taniya Das
2024-11-08 4:09 ` [PATCH v3 09/11] dt-bindings: clock: Add Qualcomm QCS615 Video clock controller Taniya Das
2024-11-08 5:46 ` Rob Herring (Arm)
2024-11-08 4:09 ` [PATCH v3 10/11] clk: qcom: videocc-qcs615: Add QCS615 video clock controller driver Taniya Das
2024-11-09 0:16 ` Dmitry Baryshkov
2024-11-09 17:22 ` Bryan O'Donoghue
2024-12-02 7:36 ` Taniya Das
2024-11-08 4:09 ` [PATCH v3 11/11] arm64: defconfig: Enable QCS615 clock controllers Taniya Das
2024-12-02 4:25 ` [PATCH v3 00/11] Add support for videocc, camcc, dispcc and gpucc on Qualcomm QCS615 platform Bjorn Andersson
2024-12-02 7:39 ` Taniya Das
2024-12-02 12:11 ` Dmitry Baryshkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241108-qcs615-mm-clockcontroller-v3-2-7d3b2d235fdf@quicinc.com \
--to=quic_tdas@quicinc.com \
--cc=absahu@codeaurora.org \
--cc=andersson@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=quic_ajipan@quicinc.com \
--cc=quic_imrashai@quicinc.com \
--cc=quic_jkona@quicinc.com \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®