linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4]  Add clock drivers for SM8350
@ 2021-01-05 15:46 Vinod Koul
  2021-01-05 15:46 ` [PATCH 1/4] clk: qcom: clk-alpha-pll: replace regval with val Vinod Koul
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Vinod Koul @ 2021-01-05 15:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross,
	Michael Turquette, Rob Herring, Taniya Das, linux-clk,
	devicetree, linux-kernel

This adds gcc clock controller drivers for the controller found
in SM8350 SoC

Changes in v3:
 - Drop rpmh clk patches applied
 - Add a new patch to replace regval with val as suggested by Stephen
 - Fix comments for new Lucid 5LPE PLL: sort new defines by BIT numbers, fix
   comments, use alpha_pll_check_rate_margin(), rework
   clk_lucid_5lpe_pll_postdiv_set_rate() logic
 - Add power domains and optional clocks in bindings
 - Fix comments for gcc sm8350 driver: clean includes used, use only
   .fw_name for clocks defined in DT, use floor ops for sdcc clocks, remove
   critical clocks and enable them in probe, add comments for clks using
   BRANCH_HALT_SKIP and BRANCH_HALT_DELAY

Changes in v2:
 - Add r-b from Bjorn
 - Add the gcc_qupv3_wrap_1_{m|s}_ahb_clk and gcc_qupv3_wrap1_s5_clk

Vinod Koul (2):
  clk: qcom: clk-alpha-pll: replace regval with val
  dt-bindings: clock: Add SM8350 GCC clock bindings

Vivek Aknurwar (2):
  clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL
  clk: qcom: gcc: Add clock driver for SM8350

 .../bindings/clock/qcom,gcc-sm8350.yaml       |   96 +
 drivers/clk/qcom/Kconfig                      |    8 +
 drivers/clk/qcom/Makefile                     |    1 +
 drivers/clk/qcom/clk-alpha-pll.c              |  237 +-
 drivers/clk/qcom/clk-alpha-pll.h              |    4 +
 drivers/clk/qcom/gcc-sm8350.c                 | 3790 +++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-sm8350.h   |  261 ++
 7 files changed, 4387 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
 create mode 100644 drivers/clk/qcom/gcc-sm8350.c
 create mode 100644 include/dt-bindings/clock/qcom,gcc-sm8350.h

-- 
2.26.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] clk: qcom: clk-alpha-pll: replace regval with val
  2021-01-05 15:46 [PATCH 0/4] Add clock drivers for SM8350 Vinod Koul
@ 2021-01-05 15:46 ` Vinod Koul
  2021-01-05 15:46 ` [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL Vinod Koul
  2021-01-05 15:46 ` [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings Vinod Koul
  2 siblings, 0 replies; 8+ messages in thread
From: Vinod Koul @ 2021-01-05 15:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross,
	Michael Turquette, Rob Herring, Taniya Das, linux-clk,
	devicetree, linux-kernel

Driver uses regval variable for holding register values, replace with a
shorter one val

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 21c357c26ec4..f7721088494c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -777,15 +777,15 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
 static int trion_pll_is_enabled(struct clk_alpha_pll *pll,
 				struct regmap *regmap)
 {
-	u32 mode_regval, opmode_regval;
+	u32 mode_val, opmode_val;
 	int ret;
 
-	ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval);
-	ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval);
+	ret = regmap_read(regmap, PLL_MODE(pll), &mode_val);
+	ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_val);
 	if (ret)
 		return 0;
 
-	return ((opmode_regval & PLL_RUN) && (mode_regval & PLL_OUTCTRL));
+	return ((opmode_val & PLL_RUN) && (mode_val & PLL_OUTCTRL));
 }
 
 static int clk_trion_pll_is_enabled(struct clk_hw *hw)
@@ -1445,12 +1445,12 @@ EXPORT_SYMBOL_GPL(clk_trion_pll_configure);
 static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done)
 {
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
-	u32 regval;
+	u32 val;
 	int ret;
 
 	/* Return early if calibration is not needed. */
-	regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &regval);
-	if (regval & pcal_done)
+	regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &val);
+	if (val & pcal_done)
 		return 0;
 
 	/* On/off to calibrate */
@@ -1476,7 +1476,7 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 	unsigned long rrate;
-	u32 regval, l, alpha_width = pll_alpha_width(pll);
+	u32 val, l, alpha_width = pll_alpha_width(pll);
 	u64 a;
 	int ret;
 
@@ -1497,8 +1497,8 @@ static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	/* Wait for 2 reference cycles before checking the ACK bit. */
 	udelay(1);
-	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &regval);
-	if (!(regval & ALPHA_PLL_ACK_LATCH)) {
+	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+	if (!(val & ALPHA_PLL_ACK_LATCH)) {
 		pr_err("Lucid PLL latch failed. Output may be unstable!\n");
 		return -EINVAL;
 	}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL
  2021-01-05 15:46 [PATCH 0/4] Add clock drivers for SM8350 Vinod Koul
  2021-01-05 15:46 ` [PATCH 1/4] clk: qcom: clk-alpha-pll: replace regval with val Vinod Koul
@ 2021-01-05 15:46 ` Vinod Koul
  2021-01-13 22:39   ` AngeloGioacchino Del Regno
  2021-01-05 15:46 ` [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings Vinod Koul
  2 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2021-01-05 15:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Bjorn Andersson, Vivek Aknurwar, Andy Gross,
	Michael Turquette, Rob Herring, Taniya Das, linux-clk,
	devicetree, linux-kernel, Jeevan Shriram, Vinod Koul

From: Vivek Aknurwar <viveka@codeaurora.org>

Lucid 5LPE is a slightly different Lucid PLL with different offsets and
porgramming sequence so add support for these

Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
Signed-off-by: Jeevan Shriram <jshriram@codeaurora.org>
[vkoul: rebase and tidy up for upstream]
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 217 +++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h |   4 +
 2 files changed, 221 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index f7721088494c..843c43649a5a 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -156,6 +156,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
 /* LUCID PLL specific settings and offsets */
 #define LUCID_PCAL_DONE		BIT(27)
 
+/* LUCID 5LPE PLL specific settings and offsets */
+#define LUCID_5LPE_PCAL_DONE		BIT(11)
+#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH	BIT(13)
+#define LUCID_5LPE_PLL_LATCH_INPUT	BIT(14)
+#define LUCID_5LPE_ENABLE_VOTE_RUN	BIT(21)
+
 #define pll_alpha_width(p)					\
 		((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ?	\
 				 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
@@ -1600,3 +1606,214 @@ const struct clk_ops clk_alpha_pll_agera_ops = {
 	.set_rate = clk_alpha_pll_agera_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
+
+static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 val;
+	int ret;
+
+	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
+	if (ret)
+		return ret;
+
+	/* If in FSM mode, just vote for it */
+	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
+		ret = clk_enable_regmap(hw);
+		if (ret)
+			return ret;
+		return wait_for_pll_enable_lock(pll);
+	}
+
+	/* Check if PLL is already enabled, return if enabled */
+	ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
+	if (ret)
+		return ret;
+
+	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);
+
+	ret = wait_for_pll_enable_lock(pll);
+	if (ret)
+		return ret;
+
+	/* Enable the PLL outputs */
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
+	if (ret)
+		return ret;
+
+	/* Enable the global PLL outputs */
+	return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
+}
+
+static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 val;
+	int ret;
+
+	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
+	if (ret)
+		return;
+
+	/* If in FSM mode, just unvote it */
+	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
+		clk_disable_regmap(hw);
+		return;
+	}
+
+	/* Disable the global PLL output */
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
+	if (ret)
+		return;
+
+	/* Disable the PLL outputs */
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
+	if (ret)
+		return;
+
+	/* Place the PLL mode in STANDBY */
+	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);
+}
+
+/*
+ * The Lucid 5LPE PLL requires a power-on self-calibration which happens
+ * when the PLL comes out of reset. Calibrate in case it is not completed.
+ */
+static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	struct clk_hw *p;
+	u32 val;
+	int ret;
+
+	/* Return early if calibration is not needed. */
+	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+	if (val & LUCID_5LPE_PCAL_DONE)
+		return 0;
+
+	p = clk_hw_get_parent(hw);
+	if (!p)
+		return -EINVAL;
+
+	ret = alpha_pll_lucid_5lpe_enable(hw);
+	if (ret)
+		return ret;
+
+	alpha_pll_lucid_5lpe_disable(hw);
+
+	return 0;
+}
+
+static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
+					 unsigned long prate)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	unsigned long rrate;
+	u32 val, l;
+	u64 a;
+	int ret;
+
+	rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
+
+	/*
+	 * Due to a limited number of bits for fractional rate programming, the
+	 * rounded up rate could be marginally higher than the requested rate.
+	 */
+	ret = alpha_pll_check_rate_margin(hw, rrate, rate);
+	if (ret)
+		return ret;
+
+	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
+
+	/* Latch the PLL input */
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
+				 LUCID_5LPE_PLL_LATCH_INPUT, LUCID_5LPE_PLL_LATCH_INPUT);
+	if (ret)
+		return ret;
+
+	/* Wait for 2 reference cycles before checking the ACK bit. */
+	udelay(1);
+	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+	if (!(val & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
+		pr_err("Lucid 5LPE PLL latch failed. Output may be unstable!\n");
+		return -EINVAL;
+	}
+
+	/* Return the latch input to 0 */
+	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), LUCID_5LPE_PLL_LATCH_INPUT, 0);
+	if (ret)
+		return ret;
+
+	if (clk_hw_is_enabled(hw)) {
+		ret = wait_for_pll_enable_lock(pll);
+		if (ret)
+			return ret;
+	}
+
+	/* Wait for PLL output to stabilize */
+	udelay(100);
+	return 0;
+}
+
+static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					       unsigned long parent_rate)
+{
+	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+	int i, val = 0, div, ret;
+	u32 mask;
+
+	/*
+	 * If the PLL is in FSM mode, then treat set_rate callback as a
+	 * no-operation.
+	 */
+	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
+	if (ret)
+		return ret;
+
+	if (val & LUCID_5LPE_ENABLE_VOTE_RUN)
+		return 0;
+
+	div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+	for (i = 0; i < pll->num_post_div; i++) {
+		if (pll->post_div_table[i].div == div) {
+			val = pll->post_div_table[i].val;
+			break;
+		}
+	}
+
+	mask = GENMASK(pll->width + pll->post_div_shift - 1, pll->post_div_shift);
+	return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
+				  mask, val << pll->post_div_shift);
+}
+
+const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
+	.prepare = alpha_pll_lucid_5lpe_prepare,
+	.enable = alpha_pll_lucid_5lpe_enable,
+	.disable = alpha_pll_lucid_5lpe_disable,
+	.is_enabled = clk_trion_pll_is_enabled,
+	.recalc_rate = clk_trion_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+	.set_rate = alpha_pll_lucid_5lpe_set_rate,
+};
+EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops);
+
+const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = {
+	.enable = alpha_pll_lucid_5lpe_enable,
+	.disable = alpha_pll_lucid_5lpe_disable,
+	.is_enabled = clk_trion_pll_is_enabled,
+	.recalc_rate = clk_trion_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+};
+EXPORT_SYMBOL(clk_alpha_pll_fixed_lucid_5lpe_ops);
+
+const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = {
+	.recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
+	.round_rate = clk_alpha_pll_postdiv_fabia_round_rate,
+	.set_rate = clk_lucid_5lpe_pll_postdiv_set_rate,
+};
+EXPORT_SYMBOL(clk_alpha_pll_postdiv_lucid_5lpe_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 0ea30d2f3da1..6943e933be0f 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -144,6 +144,10 @@ extern const struct clk_ops clk_alpha_pll_lucid_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
 extern const struct clk_ops clk_alpha_pll_agera_ops;
 
+extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops;
+extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops;
+extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
+
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 			     const struct alpha_pll_config *config);
 void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings
  2021-01-05 15:46 [PATCH 0/4] Add clock drivers for SM8350 Vinod Koul
  2021-01-05 15:46 ` [PATCH 1/4] clk: qcom: clk-alpha-pll: replace regval with val Vinod Koul
  2021-01-05 15:46 ` [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL Vinod Koul
@ 2021-01-05 15:46 ` Vinod Koul
  2021-01-11 23:37   ` Rob Herring
  2 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2021-01-05 15:46 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, Andy Gross,
	Michael Turquette, Rob Herring, Taniya Das, linux-clk,
	devicetree, linux-kernel

Add device tree bindings for global clock controller on SM8350 SoCs.

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../bindings/clock/qcom,gcc-sm8350.yaml       |  96 +++++++
 include/dt-bindings/clock/qcom,gcc-sm8350.h   | 261 ++++++++++++++++++
 2 files changed, 357 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
 create mode 100644 include/dt-bindings/clock/qcom,gcc-sm8350.h

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
new file mode 100644
index 000000000000..78f35832aa41
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8350.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller Binding for SM8350
+
+maintainers:
+  - Vinod Koul <vkoul@kernel.org>
+
+description: |
+  Qualcomm global clock control module which supports the clocks, resets and
+  power domains on SM8350.
+
+  See also:
+  - dt-bindings/clock/qcom,gcc-sm8350.h
+
+properties:
+  compatible:
+    const: qcom,gcc-sm8350
+
+  clocks:
+    items:
+      - description: Board XO source
+      - description: Sleep clock source
+      - description: PLL test clock source (Optional clock)
+      - description: PCIE 0 Pipe clock source (Optional clock)
+      - description: PCIE 1 Pipe clock source (Optional clock)
+      - description: UFS card Rx symbol 0 clock source (Optional clock)
+      - description: UFS card Rx symbol 1 clock source (Optional clock)
+      - description: UFS card Tx symbol 0 clock source (Optional clock)
+      - description: UFS phy Rx symbol 0 clock source (Optional clock)
+      - description: UFS phy Rx symbol 1 clock source (Optional clock)
+      - description: UFS phy Tx symbol 0 clock source (Optional clock)
+      - description: USB3 phy wrapper pipe clock source (Optional clock)
+      - description: USB3 phy sec pipe clock source (Optional clock)
+    minItems: 2
+    maxItems: 13
+
+  clock-names:
+    items:
+      - const: bi_tcxo
+      - const: sleep_clk
+      - const: core_bi_pll_test_se # Optional clock
+      - const: pcie_0_pipe_clk # Optional clock
+      - const: pcie_1_pipe_clk # Optional clock
+      - const: ufs_card_rx_symbol_0_clk # Optional clock
+      - const: ufs_card_rx_symbol_1_clk # Optional clock
+      - const: ufs_card_tx_symbol_0_clk # Optional clock
+      - const: ufs_phy_rx_symbol_0_clk # Optional clock
+      - const: ufs_phy_rx_symbol_1_clk # Optional clock
+      - const: ufs_phy_tx_symbol_0_clk # Optional clock
+      - const: usb3_phy_wrapper_gcc_usb30_pipe_clk # Optional clock
+      - const: usb3_uni_phy_sec_gcc_usb30_pipe_clk # Optional clock
+    minItems: 2
+    maxItems: 13
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+  '#power-domain-cells':
+    const: 1
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - clocks
+  - clock-names
+  - reg
+  - '#clock-cells'
+  - '#reset-cells'
+  - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    clock-controller@100000 {
+      compatible = "qcom,gcc-sm8350";
+      reg = <0x00100000 0x1f0000>;
+      clocks = <&rpmhcc RPMH_CXO_CLK>,
+               <&sleep_clk>;
+      clock-names = "bi_tcxo", "sleep_clk";
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+      #power-domain-cells = <1>;
+    };
+
+...
diff --git a/include/dt-bindings/clock/qcom,gcc-sm8350.h b/include/dt-bindings/clock/qcom,gcc-sm8350.h
new file mode 100644
index 000000000000..2b289c5c109f
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sm8350.h
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, Linaro Limited
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM8350_H
+#define _DT_BINDINGS_CLK_QCOM_GCC_SM8350_H
+
+/* GCC HW clocks */
+#define CORE_BI_PLL_TEST_SE					0
+#define PCIE_0_PIPE_CLK						1
+#define PCIE_1_PIPE_CLK						2
+#define UFS_CARD_RX_SYMBOL_0_CLK				3
+#define UFS_CARD_RX_SYMBOL_1_CLK				4
+#define UFS_CARD_TX_SYMBOL_0_CLK				5
+#define UFS_PHY_RX_SYMBOL_0_CLK					6
+#define UFS_PHY_RX_SYMBOL_1_CLK					7
+#define UFS_PHY_TX_SYMBOL_0_CLK					8
+#define USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK			9
+#define USB3_UNI_PHY_SEC_GCC_USB30_PIPE_CLK			10
+
+/* GCC clocks */
+#define GCC_AGGRE_NOC_PCIE_0_AXI_CLK				11
+#define GCC_AGGRE_NOC_PCIE_1_AXI_CLK				12
+#define GCC_AGGRE_NOC_PCIE_TBU_CLK				13
+#define GCC_AGGRE_UFS_CARD_AXI_CLK				14
+#define GCC_AGGRE_UFS_CARD_AXI_HW_CTL_CLK			15
+#define GCC_AGGRE_UFS_PHY_AXI_CLK				16
+#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK			17
+#define GCC_AGGRE_USB3_PRIM_AXI_CLK				18
+#define GCC_AGGRE_USB3_SEC_AXI_CLK				19
+#define GCC_BOOT_ROM_AHB_CLK					20
+#define GCC_CAMERA_AHB_CLK					21
+#define GCC_CAMERA_HF_AXI_CLK					22
+#define GCC_CAMERA_SF_AXI_CLK					23
+#define GCC_CAMERA_XO_CLK					24
+#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK				25
+#define GCC_CFG_NOC_USB3_SEC_AXI_CLK				26
+#define GCC_DDRSS_GPU_AXI_CLK					27
+#define GCC_DDRSS_PCIE_SF_TBU_CLK				28
+#define GCC_DISP_AHB_CLK					29
+#define GCC_DISP_HF_AXI_CLK					30
+#define GCC_DISP_SF_AXI_CLK					31
+#define GCC_DISP_XO_CLK						32
+#define GCC_GP1_CLK						33
+#define GCC_GP1_CLK_SRC						34
+#define GCC_GP2_CLK						35
+#define GCC_GP2_CLK_SRC						36
+#define GCC_GP3_CLK						37
+#define GCC_GP3_CLK_SRC						38
+#define GCC_GPLL0						39
+#define GCC_GPLL0_OUT_EVEN					40
+#define GCC_GPLL4						41
+#define GCC_GPLL9						42
+#define GCC_GPU_CFG_AHB_CLK					43
+#define GCC_GPU_GPLL0_CLK_SRC					44
+#define GCC_GPU_GPLL0_DIV_CLK_SRC				45
+#define GCC_GPU_IREF_EN						46
+#define GCC_GPU_MEMNOC_GFX_CLK					47
+#define GCC_GPU_SNOC_DVM_GFX_CLK				48
+#define GCC_PCIE0_PHY_RCHNG_CLK					49
+#define GCC_PCIE1_PHY_RCHNG_CLK					50
+#define GCC_PCIE_0_AUX_CLK					51
+#define GCC_PCIE_0_AUX_CLK_SRC					52
+#define GCC_PCIE_0_CFG_AHB_CLK					53
+#define GCC_PCIE_0_CLKREF_EN					54
+#define GCC_PCIE_0_MSTR_AXI_CLK					55
+#define GCC_PCIE_0_PHY_RCHNG_CLK_SRC				56
+#define GCC_PCIE_0_PIPE_CLK					57
+#define GCC_PCIE_0_PIPE_CLK_SRC					58
+#define GCC_PCIE_0_SLV_AXI_CLK					59
+#define GCC_PCIE_0_SLV_Q2A_AXI_CLK				60
+#define GCC_PCIE_1_AUX_CLK					61
+#define GCC_PCIE_1_AUX_CLK_SRC					62
+#define GCC_PCIE_1_CFG_AHB_CLK					63
+#define GCC_PCIE_1_CLKREF_EN					64
+#define GCC_PCIE_1_MSTR_AXI_CLK					65
+#define GCC_PCIE_1_PHY_RCHNG_CLK_SRC				66
+#define GCC_PCIE_1_PIPE_CLK					67
+#define GCC_PCIE_1_PIPE_CLK_SRC					68
+#define GCC_PCIE_1_SLV_AXI_CLK					69
+#define GCC_PCIE_1_SLV_Q2A_AXI_CLK				70
+#define GCC_PDM2_CLK						71
+#define GCC_PDM2_CLK_SRC					72
+#define GCC_PDM_AHB_CLK						73
+#define GCC_PDM_XO4_CLK						74
+#define GCC_QMIP_CAMERA_NRT_AHB_CLK				75
+#define GCC_QMIP_CAMERA_RT_AHB_CLK				76
+#define GCC_QMIP_DISP_AHB_CLK					77
+#define GCC_QMIP_VIDEO_CVP_AHB_CLK				78
+#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK				79
+#define GCC_QUPV3_WRAP0_CORE_2X_CLK				80
+#define GCC_QUPV3_WRAP0_CORE_CLK				81
+#define GCC_QUPV3_WRAP0_S0_CLK					82
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC				83
+#define GCC_QUPV3_WRAP0_S1_CLK					84
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC				85
+#define GCC_QUPV3_WRAP0_S2_CLK					86
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC				87
+#define GCC_QUPV3_WRAP0_S3_CLK					88
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC				89
+#define GCC_QUPV3_WRAP0_S4_CLK					90
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC				91
+#define GCC_QUPV3_WRAP0_S5_CLK					92
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC				93
+#define GCC_QUPV3_WRAP0_S6_CLK					94
+#define GCC_QUPV3_WRAP0_S6_CLK_SRC				95
+#define GCC_QUPV3_WRAP0_S7_CLK					96
+#define GCC_QUPV3_WRAP0_S7_CLK_SRC				97
+#define GCC_QUPV3_WRAP1_CORE_2X_CLK				98
+#define GCC_QUPV3_WRAP1_CORE_CLK				99
+#define GCC_QUPV3_WRAP1_S0_CLK					100
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC				101
+#define GCC_QUPV3_WRAP1_S1_CLK					102
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC				103
+#define GCC_QUPV3_WRAP1_S2_CLK					104
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC				105
+#define GCC_QUPV3_WRAP1_S3_CLK					106
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC				107
+#define GCC_QUPV3_WRAP1_S4_CLK					108
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC				109
+#define GCC_QUPV3_WRAP1_S5_CLK					110
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC				111
+#define GCC_QUPV3_WRAP2_CORE_2X_CLK				112
+#define GCC_QUPV3_WRAP2_CORE_CLK				113
+#define GCC_QUPV3_WRAP2_S0_CLK					114
+#define GCC_QUPV3_WRAP2_S0_CLK_SRC				115
+#define GCC_QUPV3_WRAP2_S1_CLK					116
+#define GCC_QUPV3_WRAP2_S1_CLK_SRC				117
+#define GCC_QUPV3_WRAP2_S2_CLK					118
+#define GCC_QUPV3_WRAP2_S2_CLK_SRC				119
+#define GCC_QUPV3_WRAP2_S3_CLK					120
+#define GCC_QUPV3_WRAP2_S3_CLK_SRC				121
+#define GCC_QUPV3_WRAP2_S4_CLK					122
+#define GCC_QUPV3_WRAP2_S4_CLK_SRC				123
+#define GCC_QUPV3_WRAP2_S5_CLK					124
+#define GCC_QUPV3_WRAP2_S5_CLK_SRC				125
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK				126
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK				127
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK				128
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK				129
+#define GCC_QUPV3_WRAP_2_M_AHB_CLK				130
+#define GCC_QUPV3_WRAP_2_S_AHB_CLK				131
+#define GCC_SDCC2_AHB_CLK					132
+#define GCC_SDCC2_APPS_CLK					133
+#define GCC_SDCC2_APPS_CLK_SRC					134
+#define GCC_SDCC4_AHB_CLK					135
+#define GCC_SDCC4_APPS_CLK					136
+#define GCC_SDCC4_APPS_CLK_SRC					137
+#define GCC_THROTTLE_PCIE_AHB_CLK				138
+#define GCC_UFS_1_CLKREF_EN					139
+#define GCC_UFS_CARD_AHB_CLK					140
+#define GCC_UFS_CARD_AXI_CLK					141
+#define GCC_UFS_CARD_AXI_CLK_SRC				142
+#define GCC_UFS_CARD_AXI_HW_CTL_CLK				143
+#define GCC_UFS_CARD_ICE_CORE_CLK				144
+#define GCC_UFS_CARD_ICE_CORE_CLK_SRC				145
+#define GCC_UFS_CARD_ICE_CORE_HW_CTL_CLK			146
+#define GCC_UFS_CARD_PHY_AUX_CLK				147
+#define GCC_UFS_CARD_PHY_AUX_CLK_SRC				148
+#define GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK				149
+#define GCC_UFS_CARD_RX_SYMBOL_0_CLK				150
+#define GCC_UFS_CARD_RX_SYMBOL_0_CLK_SRC			151
+#define GCC_UFS_CARD_RX_SYMBOL_1_CLK				152
+#define GCC_UFS_CARD_RX_SYMBOL_1_CLK_SRC			153
+#define GCC_UFS_CARD_TX_SYMBOL_0_CLK				154
+#define GCC_UFS_CARD_TX_SYMBOL_0_CLK_SRC			155
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK				156
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC			157
+#define GCC_UFS_CARD_UNIPRO_CORE_HW_CTL_CLK			158
+#define GCC_UFS_PHY_AHB_CLK					159
+#define GCC_UFS_PHY_AXI_CLK					160
+#define GCC_UFS_PHY_AXI_CLK_SRC					161
+#define GCC_UFS_PHY_AXI_HW_CTL_CLK				162
+#define GCC_UFS_PHY_ICE_CORE_CLK				163
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC				164
+#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK				165
+#define GCC_UFS_PHY_PHY_AUX_CLK					166
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC				167
+#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK				168
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK				169
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC				170
+#define GCC_UFS_PHY_RX_SYMBOL_1_CLK				171
+#define GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC				172
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK				173
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC				174
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK				175
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC				176
+#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK			177
+#define GCC_USB30_PRIM_MASTER_CLK				178
+#define GCC_USB30_PRIM_MASTER_CLK__FORCE_MEM_CORE_ON		179
+#define GCC_USB30_PRIM_MASTER_CLK_SRC				180
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK				181
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC			182
+#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC		183
+#define GCC_USB30_PRIM_SLEEP_CLK				184
+#define GCC_USB30_SEC_MASTER_CLK				185
+#define GCC_USB30_SEC_MASTER_CLK__FORCE_MEM_CORE_ON		186
+#define GCC_USB30_SEC_MASTER_CLK_SRC				187
+#define GCC_USB30_SEC_MOCK_UTMI_CLK				188
+#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC				189
+#define GCC_USB30_SEC_MOCK_UTMI_POSTDIV_CLK_SRC			190
+#define GCC_USB30_SEC_SLEEP_CLK					191
+#define GCC_USB3_PRIM_PHY_AUX_CLK				192
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC				193
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK				194
+#define GCC_USB3_PRIM_PHY_PIPE_CLK				195
+#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC				196
+#define GCC_USB3_SEC_CLKREF_EN					197
+#define GCC_USB3_SEC_PHY_AUX_CLK				198
+#define GCC_USB3_SEC_PHY_AUX_CLK_SRC				199
+#define GCC_USB3_SEC_PHY_COM_AUX_CLK				200
+#define GCC_USB3_SEC_PHY_PIPE_CLK				201
+#define GCC_USB3_SEC_PHY_PIPE_CLK_SRC				202
+#define GCC_VIDEO_AHB_CLK					203
+#define GCC_VIDEO_AXI0_CLK					204
+#define GCC_VIDEO_AXI1_CLK					205
+#define GCC_VIDEO_XO_CLK					206
+
+/* GCC resets */
+#define GCC_CAMERA_BCR						0
+#define GCC_DISPLAY_BCR						1
+#define GCC_GPU_BCR						2
+#define GCC_MMSS_BCR						3
+#define GCC_PCIE_0_BCR						4
+#define GCC_PCIE_0_LINK_DOWN_BCR				5
+#define GCC_PCIE_0_NOCSR_COM_PHY_BCR				6
+#define GCC_PCIE_0_PHY_BCR					7
+#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR			8
+#define GCC_PCIE_1_BCR						9
+#define GCC_PCIE_1_LINK_DOWN_BCR				10
+#define GCC_PCIE_1_NOCSR_COM_PHY_BCR				11
+#define GCC_PCIE_1_PHY_BCR					12
+#define GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR			13
+#define GCC_PCIE_PHY_CFG_AHB_BCR				14
+#define GCC_PCIE_PHY_COM_BCR					15
+#define GCC_PDM_BCR						16
+#define GCC_QUPV3_WRAPPER_0_BCR					17
+#define GCC_QUPV3_WRAPPER_1_BCR					18
+#define GCC_QUPV3_WRAPPER_2_BCR					19
+#define GCC_QUSB2PHY_PRIM_BCR					20
+#define GCC_QUSB2PHY_SEC_BCR					21
+#define GCC_SDCC2_BCR						22
+#define GCC_SDCC4_BCR						23
+#define GCC_UFS_CARD_BCR					24
+#define GCC_UFS_PHY_BCR						25
+#define GCC_USB30_PRIM_BCR					26
+#define GCC_USB30_SEC_BCR					27
+#define GCC_USB3_DP_PHY_PRIM_BCR				28
+#define GCC_USB3_DP_PHY_SEC_BCR					29
+#define GCC_USB3_PHY_PRIM_BCR					30
+#define GCC_USB3_PHY_SEC_BCR					31
+#define GCC_USB3PHY_PHY_PRIM_BCR				32
+#define GCC_USB3PHY_PHY_SEC_BCR					33
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR				34
+#define GCC_VIDEO_AXI0_CLK_ARES					35
+#define GCC_VIDEO_AXI1_CLK_ARES					36
+#define GCC_VIDEO_BCR						37
+
+#endif
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings
  2021-01-05 15:46 ` [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings Vinod Koul
@ 2021-01-11 23:37   ` Rob Herring
  0 siblings, 0 replies; 8+ messages in thread
From: Rob Herring @ 2021-01-11 23:37 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Bjorn Andersson, Rob Herring, Andy Gross, linux-arm-msm,
	devicetree, linux-clk, Stephen Boyd, linux-kernel,
	Michael Turquette, Taniya Das

On Tue, 05 Jan 2021 21:16:44 +0530, Vinod Koul wrote:
> Add device tree bindings for global clock controller on SM8350 SoCs.
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  .../bindings/clock/qcom,gcc-sm8350.yaml       |  96 +++++++
>  include/dt-bindings/clock/qcom,gcc-sm8350.h   | 261 ++++++++++++++++++
>  2 files changed, 357 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
>  create mode 100644 include/dt-bindings/clock/qcom,gcc-sm8350.h
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL
  2021-01-05 15:46 ` [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL Vinod Koul
@ 2021-01-13 22:39   ` AngeloGioacchino Del Regno
  2021-01-15 13:02     ` Vinod Koul
  0 siblings, 1 reply; 8+ messages in thread
From: AngeloGioacchino Del Regno @ 2021-01-13 22:39 UTC (permalink / raw)
  To: Vinod Koul, Stephen Boyd
  Cc: linux-arm-msm, Bjorn Andersson, Vivek Aknurwar, Andy Gross,
	Michael Turquette, Rob Herring, Taniya Das, linux-clk,
	devicetree, linux-kernel, Jeevan Shriram, konrad.dybcio,
	marijn.suijten, martin.botka

Il 05/01/21 16:46, Vinod Koul ha scritto:
> From: Vivek Aknurwar <viveka@codeaurora.org>
> 
> Lucid 5LPE is a slightly different Lucid PLL with different offsets and
> porgramming sequence so add support for these
> 
> Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
> Signed-off-by: Jeevan Shriram <jshriram@codeaurora.org>
> [vkoul: rebase and tidy up for upstream]
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/clk/qcom/clk-alpha-pll.c | 217 +++++++++++++++++++++++++++++++
>   drivers/clk/qcom/clk-alpha-pll.h |   4 +
>   2 files changed, 221 insertions(+)
> 
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index f7721088494c..843c43649a5a 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -156,6 +156,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
>   /* LUCID PLL specific settings and offsets */
>   #define LUCID_PCAL_DONE		BIT(27)
>   
> +/* LUCID 5LPE PLL specific settings and offsets */
> +#define LUCID_5LPE_PCAL_DONE		BIT(11)
> +#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH	BIT(13)
> +#define LUCID_5LPE_PLL_LATCH_INPUT	BIT(14)
> +#define LUCID_5LPE_ENABLE_VOTE_RUN	BIT(21)
> +
>   #define pll_alpha_width(p)					\
>   		((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ?	\
>   				 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
> @@ -1600,3 +1606,214 @@ const struct clk_ops clk_alpha_pll_agera_ops = {
>   	.set_rate = clk_alpha_pll_agera_set_rate,
>   };
>   EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
> +
> +static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
> +{
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	u32 val;
> +	int ret;
> +
> +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
> +	if (ret)
> +		return ret;
> +
> +	/* If in FSM mode, just vote for it */
> +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
> +		ret = clk_enable_regmap(hw);
> +		if (ret)
> +			return ret;
> +		return wait_for_pll_enable_lock(pll);
> +	}
> +
> +	/* Check if PLL is already enabled, return if enabled */
> +	ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
> +	if (ret)
> +		return ret;
> +
> +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);
> +
> +	ret = wait_for_pll_enable_lock(pll);
> +	if (ret)
> +		return ret;
> +
> +	/* Enable the PLL outputs */
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
> +	if (ret)
> +		return ret;
> +
> +	/* Enable the global PLL outputs */
> +	return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
> +}
> +
> +static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)
> +{
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	u32 val;
> +	int ret;
> +
> +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
> +	if (ret)
> +		return;
> +
> +	/* If in FSM mode, just unvote it */
> +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
> +		clk_disable_regmap(hw);
> +		return;
> +	}
> +
> +	/* Disable the global PLL output */
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
> +	if (ret)
> +		return;
> +
> +	/* Disable the PLL outputs */
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
> +	if (ret)
> +		return;
> +
> +	/* Place the PLL mode in STANDBY */
> +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);
> +}
> +
> +/*
> + * The Lucid 5LPE PLL requires a power-on self-calibration which happens
> + * when the PLL comes out of reset. Calibrate in case it is not completed.
> + */
> +static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)
> +{
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	struct clk_hw *p;
> +	u32 val;
> +	int ret;
> +
> +	/* Return early if calibration is not needed. */
> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> +	if (val & LUCID_5LPE_PCAL_DONE)
> +		return 0;
> +
> +	p = clk_hw_get_parent(hw);
> +	if (!p)
> +		return -EINVAL;
> +
> +	ret = alpha_pll_lucid_5lpe_enable(hw);
> +	if (ret)
> +		return ret;
> +
> +	alpha_pll_lucid_5lpe_disable(hw);
> +
> +	return 0;
> +}
> +
> +static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
> +					 unsigned long prate)
> +{
> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> +	unsigned long rrate;
> +	u32 val, l;
> +	u64 a;
> +	int ret;
> +
> +	rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
> +
> +	/*
> +	 * Due to a limited number of bits for fractional rate programming, the
> +	 * rounded up rate could be marginally higher than the requested rate.
> +	 */
> +	ret = alpha_pll_check_rate_margin(hw, rrate, rate);
> +	if (ret)
> +		return ret;
> +
> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
> +
> +	/* Latch the PLL input */
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
> +				 LUCID_5LPE_PLL_LATCH_INPUT, LUCID_5LPE_PLL_LATCH_INPUT);
> +	if (ret)
> +		return ret;
> +
> +	/* Wait for 2 reference cycles before checking the ACK bit. */
> +	udelay(1);
> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> +	if (!(val & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
> +		pr_err("Lucid 5LPE PLL latch failed. Output may be unstable!\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Return the latch input to 0 */
> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), LUCID_5LPE_PLL_LATCH_INPUT, 0);
> +	if (ret)
> +		return ret;
> +
> +	if (clk_hw_is_enabled(hw)) {
> +		ret = wait_for_pll_enable_lock(pll);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	/* Wait for PLL output to stabilize */
> +	udelay(100);
> +	return 0;
> +}
> +

This one looks exactly like alpha_pll_trion_set_rate() but:
1. You are forcing ALPHA_REG_16BIT_WIDTH for the alpha_pll_round_rate
    call: this is bad, you should actually use pll_alpha_width(pll) here,
    unless you have a very good reason that I didn't understand...
2. The only change between these two functions (trion and
    lucid_5lpe_set_rate) is that PLL_UPDATE becomes
    LUCID_5LPE_PLL_LATCH_INPUT, and that you check for
    LUCID_5LPE_ALPHA_PLL_ACK_LATCH instead of ALPHA_PLL_ACK_LATCH: this
    looks like being 95% code duplication.

The best options here, in my opinion, would be to commonize the function
alpha_pll_trion_set_rate: that will avoid this huge duplication.

> +static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
> +					       unsigned long parent_rate)
> +{
> +	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
> +	int i, val = 0, div, ret;
> +	u32 mask;
> +
> +	/*
> +	 * If the PLL is in FSM mode, then treat set_rate callback as a
> +	 * no-operation.
> +	 */
> +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN)
> +		return 0;
> +
> +	div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
> +	for (i = 0; i < pll->num_post_div; i++) {
> +		if (pll->post_div_table[i].div == div) {
> +			val = pll->post_div_table[i].val;
> +			break;
> +		}
> +	}
> +
> +	mask = GENMASK(pll->width + pll->post_div_shift - 1, pll->post_div_shift);
> +	return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
> +				  mask, val << pll->post_div_shift);
> +}
> +
> +const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {
> +	.prepare = alpha_pll_lucid_5lpe_prepare,
> +	.enable = alpha_pll_lucid_5lpe_enable,
> +	.disable = alpha_pll_lucid_5lpe_disable,
> +	.is_enabled = clk_trion_pll_is_enabled,
> +	.recalc_rate = clk_trion_pll_recalc_rate,
> +	.round_rate = clk_alpha_pll_round_rate,
> +	.set_rate = alpha_pll_lucid_5lpe_set_rate,
> +};
> +EXPORT_SYMBOL(clk_alpha_pll_lucid_5lpe_ops);
> +
> +const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = {
> +	.enable = alpha_pll_lucid_5lpe_enable,
> +	.disable = alpha_pll_lucid_5lpe_disable,
> +	.is_enabled = clk_trion_pll_is_enabled,
> +	.recalc_rate = clk_trion_pll_recalc_rate,
> +	.round_rate = clk_alpha_pll_round_rate,
> +};
> +EXPORT_SYMBOL(clk_alpha_pll_fixed_lucid_5lpe_ops);
> +
> +const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = {
> +	.recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,
> +	.round_rate = clk_alpha_pll_postdiv_fabia_round_rate,
> +	.set_rate = clk_lucid_5lpe_pll_postdiv_set_rate,
> +};
> +EXPORT_SYMBOL(clk_alpha_pll_postdiv_lucid_5lpe_ops);
> diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
> index 0ea30d2f3da1..6943e933be0f 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.h
> +++ b/drivers/clk/qcom/clk-alpha-pll.h
> @@ -144,6 +144,10 @@ extern const struct clk_ops clk_alpha_pll_lucid_ops;
>   extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops;
>   extern const struct clk_ops clk_alpha_pll_agera_ops;
>   
> +extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops;
> +extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops;
> +extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
> +
>   void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
>   			     const struct alpha_pll_config *config);
>   void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL
  2021-01-13 22:39   ` AngeloGioacchino Del Regno
@ 2021-01-15 13:02     ` Vinod Koul
  2021-01-15 13:09       ` AngeloGioacchino Del Regno
  0 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2021-01-15 13:02 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: Stephen Boyd, linux-arm-msm, Bjorn Andersson, Vivek Aknurwar,
	Andy Gross, Michael Turquette, Rob Herring, Taniya Das,
	linux-clk, devicetree, linux-kernel, Jeevan Shriram,
	konrad.dybcio, marijn.suijten, martin.botka

On 13-01-21, 23:39, AngeloGioacchino Del Regno wrote:
> Il 05/01/21 16:46, Vinod Koul ha scritto:
> > From: Vivek Aknurwar <viveka@codeaurora.org>
> > 
> > Lucid 5LPE is a slightly different Lucid PLL with different offsets and
> > porgramming sequence so add support for these
> > 
> > Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
> > Signed-off-by: Jeevan Shriram <jshriram@codeaurora.org>
> > [vkoul: rebase and tidy up for upstream]
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >   drivers/clk/qcom/clk-alpha-pll.c | 217 +++++++++++++++++++++++++++++++
> >   drivers/clk/qcom/clk-alpha-pll.h |   4 +
> >   2 files changed, 221 insertions(+)
> > 
> > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> > index f7721088494c..843c43649a5a 100644
> > --- a/drivers/clk/qcom/clk-alpha-pll.c
> > +++ b/drivers/clk/qcom/clk-alpha-pll.c
> > @@ -156,6 +156,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
> >   /* LUCID PLL specific settings and offsets */
> >   #define LUCID_PCAL_DONE		BIT(27)
> > +/* LUCID 5LPE PLL specific settings and offsets */
> > +#define LUCID_5LPE_PCAL_DONE		BIT(11)
> > +#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH	BIT(13)
> > +#define LUCID_5LPE_PLL_LATCH_INPUT	BIT(14)
> > +#define LUCID_5LPE_ENABLE_VOTE_RUN	BIT(21)
> > +
> >   #define pll_alpha_width(p)					\
> >   		((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ?	\
> >   				 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
> > @@ -1600,3 +1606,214 @@ const struct clk_ops clk_alpha_pll_agera_ops = {
> >   	.set_rate = clk_alpha_pll_agera_set_rate,
> >   };
> >   EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
> > +
> > +static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
> > +{
> > +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* If in FSM mode, just vote for it */
> > +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
> > +		ret = clk_enable_regmap(hw);
> > +		if (ret)
> > +			return ret;
> > +		return wait_for_pll_enable_lock(pll);
> > +	}
> > +
> > +	/* Check if PLL is already enabled, return if enabled */
> > +	ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
> > +	if (ret)
> > +		return ret;
> > +
> > +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);
> > +
> > +	ret = wait_for_pll_enable_lock(pll);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Enable the PLL outputs */
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Enable the global PLL outputs */
> > +	return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
> > +}
> > +
> > +static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)
> > +{
> > +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
> > +	if (ret)
> > +		return;
> > +
> > +	/* If in FSM mode, just unvote it */
> > +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
> > +		clk_disable_regmap(hw);
> > +		return;
> > +	}
> > +
> > +	/* Disable the global PLL output */
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
> > +	if (ret)
> > +		return;
> > +
> > +	/* Disable the PLL outputs */
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
> > +	if (ret)
> > +		return;
> > +
> > +	/* Place the PLL mode in STANDBY */
> > +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);
> > +}
> > +
> > +/*
> > + * The Lucid 5LPE PLL requires a power-on self-calibration which happens
> > + * when the PLL comes out of reset. Calibrate in case it is not completed.
> > + */
> > +static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)
> > +{
> > +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> > +	struct clk_hw *p;
> > +	u32 val;
> > +	int ret;
> > +
> > +	/* Return early if calibration is not needed. */
> > +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> > +	if (val & LUCID_5LPE_PCAL_DONE)
> > +		return 0;
> > +
> > +	p = clk_hw_get_parent(hw);
> > +	if (!p)
> > +		return -EINVAL;
> > +
> > +	ret = alpha_pll_lucid_5lpe_enable(hw);
> > +	if (ret)
> > +		return ret;
> > +
> > +	alpha_pll_lucid_5lpe_disable(hw);
> > +
> > +	return 0;
> > +}
> > +
> > +static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
> > +					 unsigned long prate)
> > +{
> > +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> > +	unsigned long rrate;
> > +	u32 val, l;
> > +	u64 a;
> > +	int ret;
> > +
> > +	rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
> > +
> > +	/*
> > +	 * Due to a limited number of bits for fractional rate programming, the
> > +	 * rounded up rate could be marginally higher than the requested rate.
> > +	 */
> > +	ret = alpha_pll_check_rate_margin(hw, rrate, rate);
> > +	if (ret)
> > +		return ret;
> > +
> > +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
> > +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
> > +
> > +	/* Latch the PLL input */
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
> > +				 LUCID_5LPE_PLL_LATCH_INPUT, LUCID_5LPE_PLL_LATCH_INPUT);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Wait for 2 reference cycles before checking the ACK bit. */
> > +	udelay(1);
> > +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> > +	if (!(val & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
> > +		pr_err("Lucid 5LPE PLL latch failed. Output may be unstable!\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Return the latch input to 0 */
> > +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), LUCID_5LPE_PLL_LATCH_INPUT, 0);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (clk_hw_is_enabled(hw)) {
> > +		ret = wait_for_pll_enable_lock(pll);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	/* Wait for PLL output to stabilize */
> > +	udelay(100);
> > +	return 0;
> > +}
> > +
> 
> This one looks exactly like alpha_pll_trion_set_rate() but:
> 1. You are forcing ALPHA_REG_16BIT_WIDTH for the alpha_pll_round_rate
>    call: this is bad, you should actually use pll_alpha_width(pll) here,
>    unless you have a very good reason that I didn't understand...
> 2. The only change between these two functions (trion and
>    lucid_5lpe_set_rate) is that PLL_UPDATE becomes
>    LUCID_5LPE_PLL_LATCH_INPUT, and that you check for
>    LUCID_5LPE_ALPHA_PLL_ACK_LATCH instead of ALPHA_PLL_ACK_LATCH: this
>    looks like being 95% code duplication.
> 
> The best options here, in my opinion, would be to commonize the function
> alpha_pll_trion_set_rate: that will avoid this huge duplication.

Yeah I agree we could reuse, I can redo this. I was thinking of making
this bit as one of the values in register and use that but that does not
look good as this is not a register offset, so only option is to have a
new type of PLL for this and use that as here..

-- 
~Vinod

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL
  2021-01-15 13:02     ` Vinod Koul
@ 2021-01-15 13:09       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 8+ messages in thread
From: AngeloGioacchino Del Regno @ 2021-01-15 13:09 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Stephen Boyd, linux-arm-msm, Bjorn Andersson, Vivek Aknurwar,
	Andy Gross, Michael Turquette, Rob Herring, Taniya Das,
	linux-clk, devicetree, linux-kernel, Jeevan Shriram,
	konrad.dybcio, marijn.suijten, martin.botka

Il 15/01/21 14:02, Vinod Koul ha scritto:
> On 13-01-21, 23:39, AngeloGioacchino Del Regno wrote:
>> Il 05/01/21 16:46, Vinod Koul ha scritto:
>>> From: Vivek Aknurwar <viveka@codeaurora.org>
>>>
>>> Lucid 5LPE is a slightly different Lucid PLL with different offsets and
>>> porgramming sequence so add support for these
>>>
>>> Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
>>> Signed-off-by: Jeevan Shriram <jshriram@codeaurora.org>
>>> [vkoul: rebase and tidy up for upstream]
>>> Signed-off-by: Vinod Koul <vkoul@kernel.org>
>>> ---
>>>    drivers/clk/qcom/clk-alpha-pll.c | 217 +++++++++++++++++++++++++++++++
>>>    drivers/clk/qcom/clk-alpha-pll.h |   4 +
>>>    2 files changed, 221 insertions(+)
>>>
>>> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
>>> index f7721088494c..843c43649a5a 100644
>>> --- a/drivers/clk/qcom/clk-alpha-pll.c
>>> +++ b/drivers/clk/qcom/clk-alpha-pll.c
>>> @@ -156,6 +156,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
>>>    /* LUCID PLL specific settings and offsets */
>>>    #define LUCID_PCAL_DONE		BIT(27)
>>> +/* LUCID 5LPE PLL specific settings and offsets */
>>> +#define LUCID_5LPE_PCAL_DONE		BIT(11)
>>> +#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH	BIT(13)
>>> +#define LUCID_5LPE_PLL_LATCH_INPUT	BIT(14)
>>> +#define LUCID_5LPE_ENABLE_VOTE_RUN	BIT(21)
>>> +
>>>    #define pll_alpha_width(p)					\
>>>    		((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ?	\
>>>    				 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
>>> @@ -1600,3 +1606,214 @@ const struct clk_ops clk_alpha_pll_agera_ops = {
>>>    	.set_rate = clk_alpha_pll_agera_set_rate,
>>>    };
>>>    EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);
>>> +
>>> +static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)
>>> +{
>>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>>> +	u32 val;
>>> +	int ret;
>>> +
>>> +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	/* If in FSM mode, just vote for it */
>>> +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
>>> +		ret = clk_enable_regmap(hw);
>>> +		if (ret)
>>> +			return ret;
>>> +		return wait_for_pll_enable_lock(pll);
>>> +	}
>>> +
>>> +	/* Check if PLL is already enabled, return if enabled */
>>> +	ret = trion_pll_is_enabled(pll, pll->clkr.regmap);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);
>>> +
>>> +	ret = wait_for_pll_enable_lock(pll);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	/* Enable the PLL outputs */
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	/* Enable the global PLL outputs */
>>> +	return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
>>> +}
>>> +
>>> +static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)
>>> +{
>>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>>> +	u32 val;
>>> +	int ret;
>>> +
>>> +	ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
>>> +	if (ret)
>>> +		return;
>>> +
>>> +	/* If in FSM mode, just unvote it */
>>> +	if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {
>>> +		clk_disable_regmap(hw);
>>> +		return;
>>> +	}
>>> +
>>> +	/* Disable the global PLL output */
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
>>> +	if (ret)
>>> +		return;
>>> +
>>> +	/* Disable the PLL outputs */
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);
>>> +	if (ret)
>>> +		return;
>>> +
>>> +	/* Place the PLL mode in STANDBY */
>>> +	regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);
>>> +}
>>> +
>>> +/*
>>> + * The Lucid 5LPE PLL requires a power-on self-calibration which happens
>>> + * when the PLL comes out of reset. Calibrate in case it is not completed.
>>> + */
>>> +static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)
>>> +{
>>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>>> +	struct clk_hw *p;
>>> +	u32 val;
>>> +	int ret;
>>> +
>>> +	/* Return early if calibration is not needed. */
>>> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
>>> +	if (val & LUCID_5LPE_PCAL_DONE)
>>> +		return 0;
>>> +
>>> +	p = clk_hw_get_parent(hw);
>>> +	if (!p)
>>> +		return -EINVAL;
>>> +
>>> +	ret = alpha_pll_lucid_5lpe_enable(hw);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	alpha_pll_lucid_5lpe_disable(hw);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,
>>> +					 unsigned long prate)
>>> +{
>>> +	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
>>> +	unsigned long rrate;
>>> +	u32 val, l;
>>> +	u64 a;
>>> +	int ret;
>>> +
>>> +	rrate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_16BIT_WIDTH);
>>> +
>>> +	/*
>>> +	 * Due to a limited number of bits for fractional rate programming, the
>>> +	 * rounded up rate could be marginally higher than the requested rate.
>>> +	 */
>>> +	ret = alpha_pll_check_rate_margin(hw, rrate, rate);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
>>> +	regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
>>> +
>>> +	/* Latch the PLL input */
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
>>> +				 LUCID_5LPE_PLL_LATCH_INPUT, LUCID_5LPE_PLL_LATCH_INPUT);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	/* Wait for 2 reference cycles before checking the ACK bit. */
>>> +	udelay(1);
>>> +	regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
>>> +	if (!(val & LUCID_5LPE_ALPHA_PLL_ACK_LATCH)) {
>>> +		pr_err("Lucid 5LPE PLL latch failed. Output may be unstable!\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	/* Return the latch input to 0 */
>>> +	ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), LUCID_5LPE_PLL_LATCH_INPUT, 0);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	if (clk_hw_is_enabled(hw)) {
>>> +		ret = wait_for_pll_enable_lock(pll);
>>> +		if (ret)
>>> +			return ret;
>>> +	}
>>> +
>>> +	/* Wait for PLL output to stabilize */
>>> +	udelay(100);
>>> +	return 0;
>>> +}
>>> +
>>
>> This one looks exactly like alpha_pll_trion_set_rate() but:
>> 1. You are forcing ALPHA_REG_16BIT_WIDTH for the alpha_pll_round_rate
>>     call: this is bad, you should actually use pll_alpha_width(pll) here,
>>     unless you have a very good reason that I didn't understand...
>> 2. The only change between these two functions (trion and
>>     lucid_5lpe_set_rate) is that PLL_UPDATE becomes
>>     LUCID_5LPE_PLL_LATCH_INPUT, and that you check for
>>     LUCID_5LPE_ALPHA_PLL_ACK_LATCH instead of ALPHA_PLL_ACK_LATCH: this
>>     looks like being 95% code duplication.
>>
>> The best options here, in my opinion, would be to commonize the function
>> alpha_pll_trion_set_rate: that will avoid this huge duplication.
> 
> Yeah I agree we could reuse, I can redo this. I was thinking of making
> this bit as one of the values in register and use that but that does not
> look good as this is not a register offset, so only option is to have a
> new type of PLL for this and use that as here..
> 

Just an idea:

static int __alpha_pll_trion_set_rate(struct clk_hw *hw,
                                       u32 upd_regbit, u32 latch_regbit,
                                       unsigned long rate,
                                       unsigned long prate)

static int alpha_pll_trion_set_rate( args here )
{
	return __alpha_pll_trion_set_rate(hw, PLL_UPDATE,
					 ALPHA_PLL_ACK_LATCH,
					 rate, prate);
}

static int alpha_pll_lucid_5lpe_set_rate( args )
{
	return __alpha_pll_trion_set_rate(hw, LUCID_5LPE_PLL_UPDATE,
					  LUCID_5LPE_PLL_ACK_LATCH,
					  rate, prate);
}

Perhaps, that would be good.

--Angelo

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-01-15 13:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-05 15:46 [PATCH 0/4] Add clock drivers for SM8350 Vinod Koul
2021-01-05 15:46 ` [PATCH 1/4] clk: qcom: clk-alpha-pll: replace regval with val Vinod Koul
2021-01-05 15:46 ` [PATCH 2/4] clk: qcom: clk-alpha-pll: Add support for Lucid 5LPE PLL Vinod Koul
2021-01-13 22:39   ` AngeloGioacchino Del Regno
2021-01-15 13:02     ` Vinod Koul
2021-01-15 13:09       ` AngeloGioacchino Del Regno
2021-01-05 15:46 ` [PATCH 3/4] dt-bindings: clock: Add SM8350 GCC clock bindings Vinod Koul
2021-01-11 23:37   ` Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).