Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1697901 > unrolled thread

[RFC 00/12] Misc patches for QCOM clocks

Started byAbhishek Sahu <absahu@codeaurora.org>
First post2017-07-27 13:20 +0200
Last post2017-07-27 20:40 +0200
Articles 12 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 12/12] clk: qcom: add parent map for regmap mux Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
      Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Stephen Boyd <sboyd@codeaurora.org> - 2017-07-28 20:40 +0200
        Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu <absahu@codeaurora.org> - 2017-07-30 16:00 +0200
    [RFC 11/12] clk: qcom: add read-only alpha pll post divider operations Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 10/12] clk: qcom: add read-only divider operations Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 07/12] clk: qcom: add flag for VCO operation Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 08/12] clk: qcom: support for Huayra PLL Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    [RFC 09/12] clk: qcom: support for Brammo PLL Abhishek Sahu <absahu@codeaurora.org> - 2017-07-27 13:20 +0200
    Re: [RFC 00/12] Misc patches for QCOM clocks Stephen Boyd <sboyd@codeaurora.org> - 2017-07-27 20:40 +0200

#1697901 — [RFC 00/12] Misc patches for QCOM clocks

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 00/12] Misc patches for QCOM clocks
Message-ID<u7OZH-5qs-3@gated-at.bofh.it>
This patch series does the miscellaneous changes in different
types of Qualcomm clock nodes which are required for IPQ8074 SoC.
Following are the major changes in IPQ8074 for which the existing
code does not have support.

1. Some of the IPQ8074 RCG2 has CFG_RCGR at offset 8 from
   CMD_RCGR instead of offset 4. Following are the register
   offsets of UBI RCG2 in Qualcomm IPQ8074.

	GCC_NSS_UBI0_CMD_RCGR: 0x1868100
	GCC_NSS_UBI0_CFG_RCGR: 0x1868108

2. It uses Brammo and Huayra PLL’s for which the support is
   not available in existing alpha PLL code.
3. Its APSS and UBI PLL offsets are different although both
   are Huayra PLLs.
4. Some of the its divider should not be changed during
   frequency change.

These code changes are generic and it can be used by other
Qualcomm SoCs.  The major change is taking the register offsets
from PLL and RCG2 clock node.  Since this patch series is
touching common code so this has been raised as RFC.

Abhishek Sahu (12):
  clk: qcom: support for register offsets from rcg2 clock node
  clk: qcom: flag for 64 bit CONFIG_CTL
  clk: qcom: support for alpha mode configuration
  clk: qcom: use offset from alpha pll node
  clk: qcom: fix 16 bit alpha support calculation
  Clk: qcom: support for dynamic updating the PLL
  clk: qcom: add flag for VCO operation
  clk: qcom: support for Huayra PLL
  clk: qcom: support for Brammo PLL
  clk: qcom: add read-only divider operations
  clk: qcom: add read-only alpha pll post divider operations
  clk: qcom: add parent map for regmap mux

 drivers/clk/qcom/clk-alpha-pll.c      | 464 +++++++++++++++++++++++++++-------
 drivers/clk/qcom/clk-alpha-pll.h      |  49 +++-
 drivers/clk/qcom/clk-rcg.h            |  21 +-
 drivers/clk/qcom/clk-rcg2.c           |  78 +++---
 drivers/clk/qcom/clk-regmap-divider.c |  29 +++
 drivers/clk/qcom/clk-regmap-divider.h |   1 +
 drivers/clk/qcom/clk-regmap-mux.c     |   6 +
 drivers/clk/qcom/clk-regmap-mux.h     |   2 +
 drivers/clk/qcom/common.h             |  11 +-
 drivers/clk/qcom/gcc-ipq8074.c        |   6 +-
 drivers/clk/qcom/gcc-msm8994.c        |  12 +-
 drivers/clk/qcom/gcc-msm8996.c        |  12 +-
 drivers/clk/qcom/mmcc-msm8996.c       |  48 ++--
 13 files changed, 574 insertions(+), 165 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [next] | [standalone]


#1697902 — [RFC 12/12] clk: qcom: add parent map for regmap mux

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 12/12] clk: qcom: add parent map for regmap mux
Message-ID<u7OZI-5qs-31@gated-at.bofh.it>
In reply to#1697901
Currently the driver assumes the register configuration value
is identical to its index in the parent map. This patch adds
the parent map field in regmap mux clock node which contains
the mapping of parent index with actual register configuration
value. If regmap node contains this parent map then the
configuration value will be taken from this
parent map instead of simply writing the index value.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-rcg.h        | 10 ----------
 drivers/clk/qcom/clk-regmap-mux.c |  6 ++++++
 drivers/clk/qcom/clk-regmap-mux.h |  2 ++
 drivers/clk/qcom/common.h         | 11 ++++++++++-
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 54add3b..4fcd982 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -34,16 +34,6 @@ struct freq_tbl {
 };
 
 /**
- * struct parent_map - map table for PLL source select configuration values
- * @src: source PLL
- * @cfg: configuration value
- */
-struct parent_map {
-	u8 src;
-	u8 cfg;
-};
-
-/**
  * struct mn - M/N:D counter
  * @mnctr_en_bit: bit to enable mn counter
  * @mnctr_reset_bit: bit to assert mn counter reset
diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c
index cae3071..0f3a1bd 100644
--- a/drivers/clk/qcom/clk-regmap-mux.c
+++ b/drivers/clk/qcom/clk-regmap-mux.c
@@ -35,6 +35,9 @@ static u8 mux_get_parent(struct clk_hw *hw)
 	val >>= mux->shift;
 	val &= mask;
 
+	if (mux->parent_map)
+		return qcom_find_src_index(hw, mux->parent_map, val);
+
 	return val;
 }
 
@@ -45,6 +48,9 @@ static int mux_set_parent(struct clk_hw *hw, u8 index)
 	unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
 	unsigned int val;
 
+	if (mux->parent_map)
+		index = mux->parent_map[index].cfg;
+
 	val = index;
 	val <<= mux->shift;
 
diff --git a/drivers/clk/qcom/clk-regmap-mux.h b/drivers/clk/qcom/clk-regmap-mux.h
index 5cec761..7797cdd 100644
--- a/drivers/clk/qcom/clk-regmap-mux.h
+++ b/drivers/clk/qcom/clk-regmap-mux.h
@@ -16,11 +16,13 @@
 
 #include <linux/clk-provider.h>
 #include "clk-regmap.h"
+#include "common.h"
 
 struct clk_regmap_mux {
 	u32			reg;
 	u32			shift;
 	u32			width;
+	const struct parent_map	*parent_map;
 	struct clk_regmap	clkr;
 };
 
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 23c1927..00196ee 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -20,7 +20,6 @@
 struct regmap;
 struct freq_tbl;
 struct clk_hw;
-struct parent_map;
 
 #define PLL_LOCK_COUNT_SHIFT	8
 #define PLL_LOCK_COUNT_MASK	0x3f
@@ -39,6 +38,16 @@ struct qcom_cc_desc {
 	size_t num_gdscs;
 };
 
+/**
+ * struct parent_map - map table for source select configuration values
+ * @src: source
+ * @cfg: configuration value
+ */
+struct parent_map {
+	u8 src;
+	u8 cfg;
+};
+
 extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
 					     unsigned long rate);
 extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697903 — [RFC 06/12] Clk: qcom: support for dynamic updating the PLL

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 06/12] Clk: qcom: support for dynamic updating the PLL
Message-ID<u7OZI-5qs-37@gated-at.bofh.it>
In reply to#1697901
Some of the Alpha PLL’s support dynamic update in which the
frequency can be changed dynamically without turning off the PLL.

This dynamic update requires the following sequence

1. Write the desired values to pll_l_val and pll_alpha_val.
2. Toggle pll_latch_input from low to high.
3. Wait for pll_ack_latch to transition from low to high.
   The new L and alpha values have been latched. It make
   take some time for the PLL to fully settle with these
   new values.
4. Pull pll_latch_input low.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 62 +++++++++++++++++++++++++++++++++-------
 drivers/clk/qcom/clk-alpha-pll.h |  1 +
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 3a7ec42..e38f4d2 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -31,7 +31,10 @@
 # define PLL_VOTE_FSM_ENA	BIT(20)
 # define PLL_FSM_ENA		BIT(20)
 # define PLL_VOTE_FSM_RESET	BIT(21)
+# define PLL_UPDATE		BIT(22)
+# define PLL_UPDATE_BYPASS	BIT(23)
 # define PLL_OFFLINE_ACK	BIT(28)
+# define ALPHA_PLL_ACK_LATCH	BIT(29)
 # define PLL_ACTIVE_FLAG	BIT(30)
 # define PLL_LOCK_DET		BIT(31)
 
@@ -122,6 +125,15 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
 #define wait_for_pll_offline(pll) \
 	wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline")
 
+#define wait_for_pll_update(pll) \
+	wait_for_pll(pll, PLL_UPDATE, 1, "update")
+
+#define wait_for_pll_update_ack_set(pll) \
+	wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 0, "update_ack_set")
+
+#define wait_for_pll_update_ack_clear(pll) \
+	wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear")
+
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 			     const struct alpha_pll_config *config)
 {
@@ -398,7 +410,8 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 	const struct pll_vco *vco;
-	u32 l, alpha_width = pll_alpha_width(pll);
+	u32 l, mode, alpha_width = pll_alpha_width(pll);
+	int ret;
 	u64 a;
 
 	rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
@@ -410,22 +423,49 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	regmap_write(pll->clkr.regmap, pll_l(pll), l);
 
-	if (alpha_width > ALPHA_BITWIDTH) {
-		a <<= (alpha_width - ALPHA_BITWIDTH);
-		regmap_update_bits(pll->clkr.regmap, pll_alpha_u(pll),
-				   GENMASK(0, alpha_width - ALPHA_BITWIDTH - 1),
-				   a >> ALPHA_BITWIDTH);
-	}
+	a <<= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+
+	regmap_write(pll->clkr.regmap, pll_alpha(pll), a);
+	regmap_write(pll->clkr.regmap, pll_alpha_u(pll), a >> 32);
 
 	regmap_update_bits(pll->clkr.regmap, pll_alpha(pll),
 			   GENMASK(0, alpha_width - 1), a);
 
 	regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
-			   PLL_VCO_MASK << PLL_VCO_SHIFT,
-			   vco->val << PLL_VCO_SHIFT);
+			   PLL_ALPHA_EN, PLL_ALPHA_EN);
+
+	if (!clk_hw_is_enabled(hw) || !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
+		return 0;
+
+	regmap_read(pll->clkr.regmap, pll_mode(pll), &mode);
+	regmap_update_bits(pll->clkr.regmap, pll_mode(pll), PLL_UPDATE,
+			   PLL_UPDATE);
+
+	/* Make sure PLL_UPDATE request goes through*/
+	mb();
 
-	regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll), PLL_ALPHA_EN,
-			   PLL_ALPHA_EN);
+	/*
+	 * PLL will latch the new L, Alpha and freq control word.
+	 * PLL will respond by raising PLL_ACK_LATCH output when new programming
+	 * has been latched in and PLL is being updated. When
+	 * UPDATE_LOGIC_BYPASS bit is not set, PLL_UPDATE will be cleared
+	 * automatically by hardware when PLL_ACK_LATCH is asserted by PLL.
+	 */
+	if (!(mode & PLL_UPDATE_BYPASS))
+		return wait_for_pll_update(pll);
+
+	ret = wait_for_pll_update_ack_set(pll);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(pll->clkr.regmap, pll_mode(pll), PLL_UPDATE, 0);
+
+	/* Make sure PLL_UPDATE request goes through*/
+	mb();
+
+	ret = wait_for_pll_update_ack_clear(pll);
+	if (ret)
+		return ret;
 
 	return 0;
 }
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 51a61a0..6e40e09 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -54,6 +54,7 @@ struct clk_alpha_pll {
 #define SUPPORTS_16BIT_ALPHA		BIT(1)
 #define SUPPORTS_FSM_MODE		BIT(2)
 #define SUPPORTS_64BIT_CONFIG_CTL	BIT(3)
+#define SUPPORTS_DYNAMIC_UPDATE		BIT(4)
 	u8 flags;
 
 	struct clk_regmap clkr;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1699007 — Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL

FromStephen Boyd <sboyd@codeaurora.org>
Date2017-07-28 20:40 +0200
SubjectRe: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
Message-ID<u8il4-7oj-15@gated-at.bofh.it>
In reply to#1697903
On 07/27, Abhishek Sahu wrote:
> Some of the Alpha PLL’s support dynamic update in which the
> frequency can be changed dynamically without turning off the PLL.
> 
> This dynamic update requires the following sequence
> 
> 1. Write the desired values to pll_l_val and pll_alpha_val.
> 2. Toggle pll_latch_input from low to high.
> 3. Wait for pll_ack_latch to transition from low to high.
>    The new L and alpha values have been latched. It make
>    take some time for the PLL to fully settle with these
>    new values.
> 4. Pull pll_latch_input low.
> 
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>

I think Rajendra has a similar patch that was sent. Is this the
same? Can you please look on the list and find it and compare?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

[toc] | [prev] | [next] | [standalone]


#1699534 — Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-30 16:00 +0200
SubjectRe: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
Message-ID<u8WVb-11e-1@gated-at.bofh.it>
In reply to#1699007
On 2017-07-29 00:04, Stephen Boyd wrote:
> On 07/27, Abhishek Sahu wrote:
>> Some of the Alpha PLL’s support dynamic update in which the
>> frequency can be changed dynamically without turning off the PLL.
>> 
>> This dynamic update requires the following sequence
>> 
>> 1. Write the desired values to pll_l_val and pll_alpha_val.
>> 2. Toggle pll_latch_input from low to high.
>> 3. Wait for pll_ack_latch to transition from low to high.
>>    The new L and alpha values have been latched. It make
>>    take some time for the PLL to fully settle with these
>>    new values.
>> 4. Pull pll_latch_input low.
>> 
>> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> 
> I think Rajendra has a similar patch that was sent. Is this the
> same? Can you please look on the list and find it and compare?

  Checked the list. Rajendra has two patches

  1. https://www.spinics.net/lists/linux-arm-msm/msg23349.html

  Yes my patch does the same thing with minor diffs.
  My patch checks PLL_UPDATE_BYPASS and handles both
  the cases. We can merge both the patches. I will check
  with Rajendra and will work on this merge.

  2. Following patch fixes different issue although flag name
     is common.

  https://patchwork.kernel.org/patch/9662917/

  Shall I include this patch in my patch series but not
  sure we can directly turn off the PLL inside the PLL
  set rate operation since it will turn the PLL off for
  all its users.

-- 
Abhishek Sahu

[toc] | [prev] | [next] | [standalone]


#1697905 — [RFC 11/12] clk: qcom: add read-only alpha pll post divider operations

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 11/12] clk: qcom: add read-only alpha pll post divider operations
Message-ID<u7OZI-5qs-33@gated-at.bofh.it>
In reply to#1697901
Some of the divider settings are preconfigured and should not
be changed by the clock framework during frequency change. This
patch adds the read-only divider operation for QCOM alpha pll
post divider which is equivalent to generic divider operations in
'commit 79c6ab509558 ("clk: divider: add CLK_DIVIDER_READ_ONLY flag")'.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 25 +++++++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h |  1 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e37a3ab..c3f5435 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -737,6 +737,25 @@ static long clk_alpha_pll_huayra_round_rate(struct clk_hw *hw,
 				  pll->width, CLK_DIVIDER_POWER_OF_TWO);
 }
 
+static long
+clk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+	u32 ctl, div;
+
+	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
+
+	ctl >>= PLL_POST_DIV_SHIFT;
+	ctl &= BIT(pll->width) - 1;
+	div = 1 << fls(ctl);
+
+	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
+		*prate = clk_hw_round_rate(clk_hw_get_parent(hw), div * rate);
+
+	return DIV_ROUND_UP_ULL((u64)*prate, div);
+}
+
 static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
 					  unsigned long parent_rate)
 {
@@ -757,3 +776,9 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
 	.set_rate = clk_alpha_pll_postdiv_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);
+
+const struct clk_ops clk_alpha_pll_postdiv_ro_ops = {
+	.round_rate = clk_alpha_pll_postdiv_round_ro_rate,
+	.recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 891d14b..7138d03 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -109,6 +109,7 @@ struct alpha_pll_config {
 extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
 extern const struct clk_ops clk_alpha_pll_huayra_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_ops;
+extern const struct clk_ops clk_alpha_pll_postdiv_ro_ops;
 
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 			     const struct alpha_pll_config *config);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697906 — [RFC 10/12] clk: qcom: add read-only divider operations

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 10/12] clk: qcom: add read-only divider operations
Message-ID<u7OZJ-5qs-43@gated-at.bofh.it>
In reply to#1697901
Some of the divider settings are preconfigured and should not
be changed by the clock framework during frequency change. This
patch adds the read-only divider operation for QCOM dividers
which is equivalent to generic divider operations in
'commit 79c6ab509558 ("clk: divider: add CLK_DIVIDER_READ_ONLY flag")'.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-regmap-divider.c | 29 +++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-regmap-divider.h |  1 +
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c
index 5348491..6cf9005 100644
--- a/drivers/clk/qcom/clk-regmap-divider.c
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -23,6 +23,29 @@ static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw)
 	return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr);
 }
 
+static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *prate)
+{
+	struct clk_regmap_div *divider = to_clk_regmap_div(hw);
+	struct clk_regmap *clkr = &divider->clkr;
+	u32 div;
+	struct clk_hw *hw_parent = clk_hw_get_parent(hw);
+
+	regmap_read(clkr->regmap, divider->reg, &div);
+	div >>= divider->shift;
+	div &= BIT(divider->width) - 1;
+	div += 1;
+
+	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+		if (!hw_parent)
+			return -EINVAL;
+
+		*prate = clk_hw_round_rate(hw_parent, rate * div);
+	}
+
+	return DIV_ROUND_UP_ULL((u64)*prate, div);
+}
+
 static long div_round_rate(struct clk_hw *hw, unsigned long rate,
 			   unsigned long *prate)
 {
@@ -68,3 +91,9 @@ static unsigned long div_recalc_rate(struct clk_hw *hw,
 	.recalc_rate = div_recalc_rate,
 };
 EXPORT_SYMBOL_GPL(clk_regmap_div_ops);
+
+const struct clk_ops clk_regmap_div_ro_ops = {
+	.round_rate = div_round_ro_rate,
+	.recalc_rate = div_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_regmap_div_ro_ops);
diff --git a/drivers/clk/qcom/clk-regmap-divider.h b/drivers/clk/qcom/clk-regmap-divider.h
index fc4492e..8c39c27 100644
--- a/drivers/clk/qcom/clk-regmap-divider.h
+++ b/drivers/clk/qcom/clk-regmap-divider.h
@@ -25,5 +25,6 @@ struct clk_regmap_div {
 };
 
 extern const struct clk_ops clk_regmap_div_ops;
+extern const struct clk_ops clk_regmap_div_ro_ops;
 
 #endif
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697907 — [RFC 07/12] clk: qcom: add flag for VCO operation

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 07/12] clk: qcom: add flag for VCO operation
Message-ID<u7OZI-5qs-35@gated-at.bofh.it>
In reply to#1697901
Some of the Alpha PLL’s does not have VCO configuration so this
patch adds the flag and does not perform VCO operation if this
flag is set.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 19 ++++++++++++-------
 drivers/clk/qcom/clk-alpha-pll.h |  1 +
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e38f4d2..0ac9f96 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -415,10 +415,13 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 	u64 a;
 
 	rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
-	vco = alpha_pll_find_vco(pll, rate);
-	if (!vco) {
-		pr_err("alpha pll not in a valid vco range\n");
-		return -EINVAL;
+
+	if (!(pll->flags & HAVE_NO_VCO_CONF)) {
+		vco = alpha_pll_find_vco(pll, rate);
+		if (!vco) {
+			pr_err("alpha pll not in a valid vco range\n");
+			return -EINVAL;
+		}
 	}
 
 	regmap_write(pll->clkr.regmap, pll_l(pll), l);
@@ -428,8 +431,10 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 	regmap_write(pll->clkr.regmap, pll_alpha(pll), a);
 	regmap_write(pll->clkr.regmap, pll_alpha_u(pll), a >> 32);
 
-	regmap_update_bits(pll->clkr.regmap, pll_alpha(pll),
-			   GENMASK(0, alpha_width - 1), a);
+	if (!(pll->flags & HAVE_NO_VCO_CONF))
+		regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
+				   PLL_VCO_MASK << PLL_VCO_SHIFT,
+				   vco->val << PLL_VCO_SHIFT);
 
 	regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
 			   PLL_ALPHA_EN, PLL_ALPHA_EN);
@@ -479,7 +484,7 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	unsigned long min_freq, max_freq;
 
 	rate = alpha_pll_round_rate(rate, *prate, &l, &a, alpha_width);
-	if (alpha_pll_find_vco(pll, rate))
+	if ((pll->flags & HAVE_NO_VCO_CONF) || alpha_pll_find_vco(pll, rate))
 		return rate;
 
 	min_freq = pll->vco_table[0].min_freq;
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 6e40e09..01869a8 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -55,6 +55,7 @@ struct clk_alpha_pll {
 #define SUPPORTS_FSM_MODE		BIT(2)
 #define SUPPORTS_64BIT_CONFIG_CTL	BIT(3)
 #define SUPPORTS_DYNAMIC_UPDATE		BIT(4)
+#define HAVE_NO_VCO_CONF		BIT(5)
 	u8 flags;
 
 	struct clk_regmap clkr;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697908 — [RFC 08/12] clk: qcom: support for Huayra PLL

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 08/12] clk: qcom: support for Huayra PLL
Message-ID<u7OZI-5qs-19@gated-at.bofh.it>
In reply to#1697901
Following are the major differences in Huayra PLL

1. PLL Alpha Value is 16 bits
2. Depending on alpha_mode, the pll_alpha_val can be treated as
   M/N value or as a two’s compliment number.
3. Huayra PLL supports PLL dynamic programming. User can change
   L_VAL, without having to go through the power on sequence.

Since the decoding of alpha val and dynamic programming are
completely different for other Alpha PLL’s so this patch
made adds separate functions for Huayra PLL.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 179 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h |   6 ++
 2 files changed, 185 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 0ac9f96..d17d83a 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -41,9 +41,17 @@
 # define PLL_POST_DIV_SHIFT	8
 # define PLL_POST_DIV_MASK	0xf
 # define PLL_ALPHA_EN		BIT(24)
+# define PLL_ALPHA_MODE		BIT(25)
 # define PLL_VCO_SHIFT		20
 # define PLL_VCO_MASK		0x3
 
+#define PLL_HUAYRA_M_WIDTH		8
+#define PLL_HUAYRA_M_SHIFT		8
+#define PLL_HUAYRA_M_MASK		0xff
+#define PLL_HUAYRA_N_SHIFT		0
+#define PLL_HUAYRA_N_MASK		0xff
+#define PLL_HUAYRA_ALPHA_WIDTH		16
+
 /*
  * Even though 40 bits are present, use only 32 for ease of calculation.
  */
@@ -85,6 +93,18 @@
 	[ALPHA_PLL_STATUS] = 0x24,
 };
 
+const u8 huayra_pll_offsets[] = {
+	[ALPHA_PLL_MODE] = 0x00,
+	[ALPHA_PLL_L_VAL] = 0x04,
+	[ALPHA_PLL_ALPHA_VAL] = 0x08,
+	[ALPHA_PLL_USER_CTL] = 0x10,
+	[ALPHA_PLL_CONFIG_CTL] = 0x14,
+	[ALPHA_PLL_CONFIG_CTL_U] = 0x18,
+	[ALPHA_PLL_TEST_CTL] = 0x1c,
+	[ALPHA_PLL_TEST_CTL_U] = 0x20,
+	[ALPHA_PLL_STATUS] = 0x24,
+};
+
 static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
 			const char *action)
 {
@@ -493,6 +513,155 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	return clamp(rate, min_freq, max_freq);
 }
 
+static unsigned long
+alpha_pll_huayra_calc_rate(u64 prate, u32 l, u32 a)
+{
+	/*
+	 * a contains 16 bit alpha_val in two’s compliment number in the range
+	 * of [-0.5, 0.5).
+	 */
+	if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1))
+		l -= 1;
+
+	return (prate * l) + (prate * a >> PLL_HUAYRA_ALPHA_WIDTH);
+}
+
+static unsigned long
+alpha_pll_huayra_round_rate(unsigned long rate, unsigned long prate,
+			    u32 *l, u32 *a)
+{
+	u64 remainder;
+	u64 quotient;
+
+	quotient = rate;
+	remainder = do_div(quotient, prate);
+	*l = quotient;
+
+	if (!remainder) {
+		*a = 0;
+		return rate;
+	}
+
+	quotient = remainder << PLL_HUAYRA_ALPHA_WIDTH;
+	remainder = do_div(quotient, prate);
+
+	if (remainder)
+		quotient++;
+
+	/*
+	 * alpha_val should be in two’s compliment number in the range
+	 * of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value
+	 * since alpha value will be subtracted in this case.
+	 */
+	if (quotient >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1))
+		*l += 1;
+
+	*a = quotient;
+	return alpha_pll_huayra_calc_rate(prate, *l, *a);
+}
+
+static unsigned long
+clk_alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	u32 l, alpha = 0, ctl, alpha_m, alpha_n;
+	u64 rate = parent_rate, tmp;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	regmap_read(pll->clkr.regmap, pll_l(pll), &l);
+	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
+
+	if (ctl & PLL_ALPHA_EN) {
+		regmap_read(pll->clkr.regmap, pll_alpha(pll), &alpha);
+		/*
+		 * Depending upon alpha_mode, it can be treated as M/N value or
+		 * as a two’s compliment number. When
+		 * alpha_mode=1 pll_alpha_val<15:8>=M & pll_apla_val<7:0>=N
+		 *		Fout=FIN*(L+(M/N))
+		 * M is a signed number (-128 to 127) and N is unsigned
+		 * (0 to 255). M/N has to be within +/-0.5.
+		 *
+		 * alpha_mode=0, it is a two’s compliment number in the range
+		 * of [-0.5, 0.5).
+		 *		Fout=FIN*(L+(alpha_val)/2^16),where alpha_val is
+		 * two’s compliment number.
+		 */
+		if (!(ctl & PLL_ALPHA_MODE))
+			return alpha_pll_huayra_calc_rate(rate, l, alpha);
+
+		alpha_m = alpha >> PLL_HUAYRA_M_SHIFT & PLL_HUAYRA_M_MASK;
+		alpha_n = alpha >> PLL_HUAYRA_N_SHIFT & PLL_HUAYRA_N_MASK;
+
+		rate *= l;
+		tmp = parent_rate;
+		if (alpha_m >= BIT(PLL_HUAYRA_M_WIDTH - 1)) {
+			alpha_m = BIT(PLL_HUAYRA_M_WIDTH) - alpha_m;
+			tmp *= alpha_m;
+			do_div(tmp, alpha_n);
+			rate -= tmp;
+		} else {
+			tmp *= alpha_m;
+			do_div(tmp, alpha_n);
+			rate += tmp;
+		}
+
+		return rate;
+	}
+
+	return alpha_pll_huayra_calc_rate(rate, l, alpha);
+}
+
+static int clk_alpha_pll_huayra_set_rate(struct clk_hw *hw, unsigned long rate,
+					 unsigned long prate)
+{
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 l, a, ctl, cur_alpha = 0;
+
+	rate = alpha_pll_huayra_round_rate(rate, prate, &l, &a);
+
+	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
+
+	if (ctl & PLL_ALPHA_EN)
+		regmap_read(pll->clkr.regmap, pll_alpha(pll), &cur_alpha);
+
+	/*
+	 * Huayra PLL supports PLL dynamic programming. User can change L_VAL,
+	 * without having to go through the power on sequence.
+	 */
+	if (clk_hw_is_enabled(hw)) {
+		if (cur_alpha != a) {
+			pr_err("clock needs to be gated %s\n",
+			       clk_hw_get_name(hw));
+			return -EBUSY;
+		}
+
+		regmap_write(pll->clkr.regmap, pll_l(pll), l);
+		/* Ensure that the write above goes to detect L val change. */
+		mb();
+		return wait_for_pll_enable_lock(pll);
+	}
+
+	regmap_write(pll->clkr.regmap, pll_l(pll), l);
+	regmap_write(pll->clkr.regmap, pll_alpha(pll), a);
+
+	if (a == 0)
+		regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
+				   PLL_ALPHA_EN, 0x0);
+	else
+		regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
+				   PLL_ALPHA_EN | PLL_ALPHA_MODE, PLL_ALPHA_EN);
+
+	return 0;
+}
+
+static long clk_alpha_pll_huayra_round_rate(struct clk_hw *hw,
+					    unsigned long rate,
+					    unsigned long *prate)
+{
+	u32 l, a;
+
+	return alpha_pll_huayra_round_rate(rate, *prate, &l, &a);
+}
+
 const struct clk_ops clk_alpha_pll_ops = {
 	.enable = clk_alpha_pll_enable,
 	.disable = clk_alpha_pll_disable,
@@ -513,6 +682,16 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
 
+const struct clk_ops clk_alpha_pll_huayra_ops = {
+	.enable = clk_alpha_pll_enable,
+	.disable = clk_alpha_pll_disable,
+	.is_enabled = clk_alpha_pll_is_enabled,
+	.recalc_rate = clk_alpha_pll_huayra_recalc_rate,
+	.round_rate = clk_alpha_pll_huayra_round_rate,
+	.set_rate = clk_alpha_pll_huayra_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_huayra_ops);
+
 static unsigned long
 clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 01869a8..c98e7469 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -61,6 +61,10 @@ struct clk_alpha_pll {
 	struct clk_regmap clkr;
 };
 
+#define CLK_HUAYRA_PLL_FLAGS	(HAVE_NO_VCO_CONF | SUPPORTS_DYNAMIC_UPDATE | \
+				 SUPPORTS_64BIT_CONFIG_CTL |		      \
+				 SUPPORTS_16BIT_ALPHA)
+
 /**
  * struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
  * @base: base address of registers
@@ -97,9 +101,11 @@ struct alpha_pll_config {
 };
 
 extern const u8 alpha_pll_offsets[];
+extern const u8 huayra_pll_offsets[];
 
 extern const struct clk_ops clk_alpha_pll_ops;
 extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
+extern const struct clk_ops clk_alpha_pll_huayra_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_ops;
 
 void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697909 — [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 05/12] clk: qcom: fix 16 bit alpha support calculation
Message-ID<u7OZI-5qs-21@gated-at.bofh.it>
In reply to#1697901
The alpha value calculation function has been written for
40 bit alpha which is not coming properly for 16 bit alpha.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 58 +++++++++++++++++++++++-----------------
 1 file changed, 34 insertions(+), 24 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index ef24c80..3a7ec42 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -45,8 +45,11 @@
  * Even though 40 bits are present, use only 32 for ease of calculation.
  */
 #define ALPHA_REG_BITWIDTH	40
+#define ALPHA_REG_16BIT_WIDTH	16
 #define ALPHA_BITWIDTH		32
-#define ALPHA_16BIT_MASK	0xffff
+
+#define pll_alpha_width(pll)  (pll->flags & SUPPORTS_16BIT_ALPHA ?	\
+			       ALPHA_REG_16BIT_WIDTH : ALPHA_REG_BITWIDTH)
 
 #define pll_mode(pll)		(pll->base + pll->offsets[ALPHA_PLL_MODE])
 #define pll_l(pll)		(pll->base + pll->offsets[ALPHA_PLL_L_VAL])
@@ -316,13 +319,16 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
 	regmap_update_bits(pll->clkr.regmap, pll_mode(pll), mask, 0);
 }
 
-static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
+static unsigned long
+alpha_pll_calc_rate(u64 prate, u32 l, u32 a, u32 alpha_width)
 {
-	return (prate * l) + ((prate * a) >> ALPHA_BITWIDTH);
+	return (prate * l) + ((prate * a) >>
+		(alpha_width > ALPHA_BITWIDTH ? ALPHA_BITWIDTH : alpha_width));
 }
 
 static unsigned long
-alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a)
+alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a,
+		     u32 alpha_width)
 {
 	u64 remainder;
 	u64 quotient;
@@ -337,14 +343,16 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
 	}
 
 	/* Upper ALPHA_BITWIDTH bits of Alpha */
-	quotient = remainder << ALPHA_BITWIDTH;
+	quotient = remainder << (alpha_width > ALPHA_BITWIDTH ?
+				 ALPHA_BITWIDTH : alpha_width);
+
 	remainder = do_div(quotient, prate);
 
 	if (remainder)
 		quotient++;
 
 	*a = quotient;
-	return alpha_pll_calc_rate(prate, *l, *a);
+	return alpha_pll_calc_rate(prate, *l, *a, alpha_width);
 }
 
 static const struct pll_vco *
@@ -363,26 +371,26 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
 static unsigned long
 clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
-	u32 l, low, high, ctl;
-	u64 a = 0, prate = parent_rate;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+	u32 l, low, high, ctl, alpha_width = pll_alpha_width(pll);
+	u64 a = 0, prate = parent_rate;
 
 	regmap_read(pll->clkr.regmap, pll_l(pll), &l);
 
 	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
 	if (ctl & PLL_ALPHA_EN) {
 		regmap_read(pll->clkr.regmap, pll_alpha(pll), &low);
-		if (pll->flags & SUPPORTS_16BIT_ALPHA) {
-			a = low & ALPHA_16BIT_MASK;
-		} else {
+		if (alpha_width > ALPHA_BITWIDTH) {
 			regmap_read(pll->clkr.regmap, pll_alpha_u(pll),
 				    &high);
-			a = (u64)high << 32 | low;
-			a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+			a = (u64)high << ALPHA_BITWIDTH | low;
+			a >>= alpha_width - ALPHA_BITWIDTH;
+		} else {
+			a = low;
 		}
 	}
 
-	return alpha_pll_calc_rate(prate, l, a);
+	return alpha_pll_calc_rate(prate, l, a, alpha_width);
 }
 
 static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -390,10 +398,10 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 	const struct pll_vco *vco;
-	u32 l;
+	u32 l, alpha_width = pll_alpha_width(pll);
 	u64 a;
 
-	rate = alpha_pll_round_rate(rate, prate, &l, &a);
+	rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
 	vco = alpha_pll_find_vco(pll, rate);
 	if (!vco) {
 		pr_err("alpha pll not in a valid vco range\n");
@@ -402,14 +410,16 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	regmap_write(pll->clkr.regmap, pll_l(pll), l);
 
-	if (pll->flags & SUPPORTS_16BIT_ALPHA) {
-		regmap_write(pll->clkr.regmap, pll_alpha(pll),
-			     a & ALPHA_16BIT_MASK);
-	} else {
-		a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
-		regmap_write(pll->clkr.regmap, pll_alpha_u(pll), a >> 32);
+	if (alpha_width > ALPHA_BITWIDTH) {
+		a <<= (alpha_width - ALPHA_BITWIDTH);
+		regmap_update_bits(pll->clkr.regmap, pll_alpha_u(pll),
+				   GENMASK(0, alpha_width - ALPHA_BITWIDTH - 1),
+				   a >> ALPHA_BITWIDTH);
 	}
 
+	regmap_update_bits(pll->clkr.regmap, pll_alpha(pll),
+			   GENMASK(0, alpha_width - 1), a);
+
 	regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
 			   PLL_VCO_MASK << PLL_VCO_SHIFT,
 			   vco->val << PLL_VCO_SHIFT);
@@ -424,11 +434,11 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 				     unsigned long *prate)
 {
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
-	u32 l;
+	u32 l, alpha_width = pll_alpha_width(pll);
 	u64 a;
 	unsigned long min_freq, max_freq;
 
-	rate = alpha_pll_round_rate(rate, *prate, &l, &a);
+	rate = alpha_pll_round_rate(rate, *prate, &l, &a, alpha_width);
 	if (alpha_pll_find_vco(pll, rate))
 		return rate;
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1697910 — [RFC 09/12] clk: qcom: support for Brammo PLL

FromAbhishek Sahu <absahu@codeaurora.org>
Date2017-07-27 13:20 +0200
Subject[RFC 09/12] clk: qcom: support for Brammo PLL
Message-ID<u7OZI-5qs-25@gated-at.bofh.it>
In reply to#1697901
Brammo PLL does not allow configuration of VCO and it
supports the dynamic update in which the frequency can
be changed dynamically without turning off the PLL.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 12 ++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index d17d83a..e37a3ab 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -52,6 +52,7 @@
 #define PLL_HUAYRA_N_MASK		0xff
 #define PLL_HUAYRA_ALPHA_WIDTH		16
 
+#define PLL_BRAMMO_ALPHA_BITWIDTH	40
 /*
  * Even though 40 bits are present, use only 32 for ease of calculation.
  */
@@ -105,6 +106,17 @@
 	[ALPHA_PLL_STATUS] = 0x24,
 };
 
+const u8 brammo_pll_offsets[] = {
+	[ALPHA_PLL_MODE] = 0x00,
+	[ALPHA_PLL_L_VAL] = 0x04,
+	[ALPHA_PLL_ALPHA_VAL] = 0x08,
+	[ALPHA_PLL_ALPHA_VAL_U] = 0x0c,
+	[ALPHA_PLL_USER_CTL] = 0x10,
+	[ALPHA_PLL_CONFIG_CTL] = 0x18,
+	[ALPHA_PLL_TEST_CTL] = 0x1c,
+	[ALPHA_PLL_STATUS] = 0x24,
+};
+
 static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
 			const char *action)
 {
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index c98e7469..891d14b 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -64,6 +64,7 @@ struct clk_alpha_pll {
 #define CLK_HUAYRA_PLL_FLAGS	(HAVE_NO_VCO_CONF | SUPPORTS_DYNAMIC_UPDATE | \
 				 SUPPORTS_64BIT_CONFIG_CTL |		      \
 				 SUPPORTS_16BIT_ALPHA)
+#define CLK_BRAMMO_PLL_FLAGS	(HAVE_NO_VCO_CONF | SUPPORTS_DYNAMIC_UPDATE)
 
 /**
  * struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
@@ -102,6 +103,7 @@ struct alpha_pll_config {
 
 extern const u8 alpha_pll_offsets[];
 extern const u8 huayra_pll_offsets[];
+extern const u8 brammo_pll_offsets[];
 
 extern const struct clk_ops clk_alpha_pll_ops;
 extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

[toc] | [prev] | [next] | [standalone]


#1698237

FromStephen Boyd <sboyd@codeaurora.org>
Date2017-07-27 20:40 +0200
Message-ID<u7VRv-195-1@gated-at.bofh.it>
In reply to#1697901
On 07/27/2017 04:10 AM, Abhishek Sahu wrote:
> This patch series does the miscellaneous changes in different
> types of Qualcomm clock nodes which are required for IPQ8074 SoC.
> Following are the major changes in IPQ8074 for which the existing
> code does not have support.
>
> 1. Some of the IPQ8074 RCG2 has CFG_RCGR at offset 8 from
>    CMD_RCGR instead of offset 4. Following are the register
>    offsets of UBI RCG2 in Qualcomm IPQ8074.
>
> 	GCC_NSS_UBI0_CMD_RCGR: 0x1868100
> 	GCC_NSS_UBI0_CFG_RCGR: 0x1868108

That's insane. There's a hardware design mandate to not mess with the
register layout specifically for this reason. Amazing, but not
surprising that someone screwed it up.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web