linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] clk: qcom: PLL updates
@ 2016-07-11 10:50 Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 1/6] clk: Fix inconsistencies in usage of data types Rajendra Nayak
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Hi,

This series adds some additional support to the clk-alpha-pll and the
clk-pll drivers in preperation to add the CPU clock driver support
on msm8996

regards,
Rajendra

Rajendra Nayak (6):
  clk: Fix inconsistencies in usage of data types
  clk: qcom: Add support for alpha pll hwfsm ops
  clk: qcom: Add support to initialize alpha plls
  clk: qcom: Add support for PLLs with alpha mode
  clk: qcom: Add support for PLLs with early output
  clk: qcom: Add support for PLLs supporting dynamic reprogramming

 drivers/clk/clk.c                |   4 +-
 drivers/clk/qcom/clk-alpha-pll.c | 132 +++++++++++++++++++++++++++++++++++----
 drivers/clk/qcom/clk-alpha-pll.h |  14 +++++
 drivers/clk/qcom/clk-pll.c       | 116 +++++++++++++++++++++++++++++++++-
 drivers/clk/qcom/clk-pll.h       |  12 +++-
 include/linux/clk-provider.h     |   5 +-
 6 files changed, 263 insertions(+), 20 deletions(-)

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

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

* [PATCH 1/6] clk: Fix inconsistencies in usage of data types
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 2/6] clk: qcom: Add support for alpha pll hwfsm ops Rajendra Nayak
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

index is of type u8 in all places except in clk_hw_get_parent_by_index()
and return value of all round_rate functions is long except for
clk_hw_round_rate(). Make them consistent with the rest of the places

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/clk.c            | 4 ++--
 include/linux/clk-provider.h | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d584004..1af6989 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -359,7 +359,7 @@ static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 }
 
 struct clk_hw *
-clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index)
+clk_hw_get_parent_by_index(const struct clk_hw *hw, u8 index)
 {
 	struct clk_core *parent;
 
@@ -845,7 +845,7 @@ int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 }
 EXPORT_SYMBOL_GPL(__clk_determine_rate);
 
-unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
+long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
 {
 	int ret;
 	struct clk_rate_request req;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index fb39d5a..5cf82cc 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -729,8 +729,7 @@ const char *clk_hw_get_name(const struct clk_hw *hw);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
-struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
-					  unsigned int index);
+struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, u8 index);
 unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
@@ -757,7 +756,7 @@ static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 /*
  * FIXME clock api without lock protection
  */
-unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
+long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
 
 struct of_device_id;
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH 2/6] clk: qcom: Add support for alpha pll hwfsm ops
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 1/6] clk: Fix inconsistencies in usage of data types Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 3/6] clk: qcom: Add support to initialize alpha plls Rajendra Nayak
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Add support to enable/disable the alpha pll using hwfsm

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 109 ++++++++++++++++++++++++++++++++++-----
 drivers/clk/qcom/clk-alpha-pll.h |   1 +
 2 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e6a03ea..bae31f9 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -62,9 +62,10 @@
 #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
 					   struct clk_alpha_pll_postdiv, clkr)
 
-static int wait_for_pll(struct clk_alpha_pll *pll)
+static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
+			const char *action)
 {
-	u32 val, mask, off;
+	u32 val, off;
 	int count;
 	int ret;
 	const char *name = clk_hw_get_name(&pll->clkr.hw);
@@ -74,26 +75,101 @@ static int wait_for_pll(struct clk_alpha_pll *pll)
 	if (ret)
 		return ret;
 
-	if (val & PLL_VOTE_FSM_ENA)
-		mask = PLL_ACTIVE_FLAG;
-	else
-		mask = PLL_LOCK_DET;
-
-	/* Wait for pll to enable. */
 	for (count = 100; count > 0; count--) {
 		ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
 		if (ret)
 			return ret;
-		if ((val & mask) == mask)
+		if (inverse && (val & mask))
+			return 0;
+		else if ((val & mask) == mask)
 			return 0;
 
 		udelay(1);
 	}
 
-	WARN(1, "%s didn't enable after voting for it!\n", name);
+	WARN(1, "%s failed to %s!\n", name, action);
 	return -ETIMEDOUT;
 }
 
+static int wait_for_pll_enable(struct clk_alpha_pll *pll, u32 mask)
+{
+	return wait_for_pll(pll, mask, 0, "enable");
+}
+
+static int wait_for_pll_disable(struct clk_alpha_pll *pll, u32 mask)
+{
+	return wait_for_pll(pll, mask, 1, "disable");
+}
+
+static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask)
+{
+	return wait_for_pll(pll, mask, 0, "offline");
+}
+
+/* alpha pll with hwfsm support */
+#define PLL_OFFLINE_REQ		BIT(7)
+#define PLL_FSM_ENA		BIT(20)
+#define PLL_OFFLINE_ACK		BIT(28)
+#define PLL_ACTIVE_FLAG		BIT(30)
+
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+{
+	int ret;
+	u32 val, off;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return ret;
+
+	/* Enable HW FSM mode, clear OFFLINE request */
+	val |= PLL_FSM_ENA;
+	val &= ~PLL_OFFLINE_REQ;
+	ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
+	if (ret)
+		return ret;
+
+	/* Make sure enable request goes through before waiting for update */
+	mb();
+
+	ret = wait_for_pll_enable(pll, PLL_ACTIVE_FLAG);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+{
+	int ret;
+	u32 val, off;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return;
+
+	/* Request PLL_OFFLINE and wait for ack */
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
+	if (ret)
+		return;
+
+	ret = wait_for_pll_offline(pll, PLL_OFFLINE_ACK);
+	if (ret)
+		return;
+
+	/* Disable hwfsm */
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_FSM_ENA, 0);
+	if (ret)
+		return;
+
+	wait_for_pll_disable(pll, PLL_ACTIVE_FLAG);
+}
+
 static int clk_alpha_pll_enable(struct clk_hw *hw)
 {
 	int ret;
@@ -112,7 +188,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 		ret = clk_enable_regmap(hw);
 		if (ret)
 			return ret;
-		return wait_for_pll(pll);
+		return wait_for_pll_enable(pll, PLL_ACTIVE_FLAG);
 	}
 
 	/* Skip if already enabled */
@@ -136,7 +212,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 	if (ret)
 		return ret;
 
-	ret = wait_for_pll(pll);
+	ret = wait_for_pll_enable(pll, PLL_LOCK_DET);
 	if (ret)
 		return ret;
 
@@ -300,6 +376,15 @@ const struct clk_ops clk_alpha_pll_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
 
+const struct clk_ops clk_alpha_pll_hwfsm_ops = {
+	.enable = clk_alpha_pll_hwfsm_enable,
+	.disable = clk_alpha_pll_hwfsm_disable,
+	.recalc_rate = clk_alpha_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+	.set_rate = clk_alpha_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_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 90ce201..f78bf4c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -52,6 +52,7 @@ struct clk_alpha_pll_postdiv {
 };
 
 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_postdiv_ops;
 
 #endif
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH 3/6] clk: qcom: Add support to initialize alpha plls
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 1/6] clk: Fix inconsistencies in usage of data types Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 2/6] clk: qcom: Add support for alpha pll hwfsm ops Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 4/6] clk: qcom: Add support for PLLs with alpha mode Rajendra Nayak
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Add a function to do initial configuration of the alpha plls

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 23 +++++++++++++++++++++++
 drivers/clk/qcom/clk-alpha-pll.h | 13 +++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index bae31f9..8b8710f 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -112,6 +112,29 @@ static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask)
 #define PLL_OFFLINE_ACK		BIT(28)
 #define PLL_ACTIVE_FLAG		BIT(30)
 
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+			     const struct alpha_pll_config *config)
+{
+	u32 val, mask;
+
+	regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
+		     config->config_ctl_val);
+
+	val = config->main_output_mask;
+	val |= config->aux_output_mask;
+	val |= config->aux2_output_mask;
+	val |= config->early_output_mask;
+	val |= config->post_div_val;
+
+	mask = config->main_output_mask;
+	mask |= config->aux_output_mask;
+	mask |= config->aux2_output_mask;
+	mask |= config->early_output_mask;
+	mask |= config->post_div_mask;
+
+	regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, mask, val);
+}
+
 static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
 {
 	int ret;
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f78bf4c..12a349e 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -51,8 +51,21 @@ struct clk_alpha_pll_postdiv {
 	struct clk_regmap clkr;
 };
 
+struct alpha_pll_config {
+	u32 config_ctl_val;
+	u32 main_output_mask;
+	u32 aux_output_mask;
+	u32 aux2_output_mask;
+	u32 early_output_mask;
+	u32 post_div_val;
+	u32 post_div_mask;
+};
+
 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_postdiv_ops;
 
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+			     const struct alpha_pll_config *config);
+
 #endif
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH 4/6] clk: qcom: Add support for PLLs with alpha mode
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
                   ` (2 preceding siblings ...)
  2016-07-11 10:50 ` [PATCH 3/6] clk: qcom: Add support to initialize alpha plls Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 5/6] clk: qcom: Add support for PLLs with early output Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 6/6] clk: qcom: Add support for PLLs supporting dynamic reprogramming Rajendra Nayak
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Some PLLs can support an alpha mode, and a single alpha
register (instead of registers to program the M/N values),
the contents of which depend on the alpha mode selected.
(They are either treated as two's complement or M/N value)
Add support for this in the clk PLL driver.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/qcom/clk-pll.c | 8 ++++++--
 drivers/clk/qcom/clk-pll.h | 2 ++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 5b940d6..08d2fa2 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -255,8 +255,12 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 	u32 mask;
 
 	regmap_write(regmap, pll->l_reg, config->l);
-	regmap_write(regmap, pll->m_reg, config->m);
-	regmap_write(regmap, pll->n_reg, config->n);
+	if (pll->alpha_reg) {
+		regmap_write(regmap, pll->alpha_reg, config->alpha);
+	} else {
+		regmap_write(regmap, pll->m_reg, config->m);
+		regmap_write(regmap, pll->n_reg, config->n);
+	}
 
 	val = config->vco_val;
 	val |= config->pre_div_val;
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index ffd0c63..083727e 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -48,6 +48,7 @@ struct clk_pll {
 	u32	l_reg;
 	u32	m_reg;
 	u32	n_reg;
+	u32	alpha_reg;
 	u32	config_reg;
 	u32	mode_reg;
 	u32	status_reg;
@@ -70,6 +71,7 @@ struct pll_config {
 	u16 l;
 	u32 m;
 	u32 n;
+	u32 alpha;
 	u32 vco_val;
 	u32 vco_mask;
 	u32 pre_div_val;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

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

* [PATCH 5/6] clk: qcom: Add support for PLLs with early output
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
                   ` (3 preceding siblings ...)
  2016-07-11 10:50 ` [PATCH 4/6] clk: qcom: Add support for PLLs with alpha mode Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  2016-07-11 10:50 ` [PATCH 6/6] clk: qcom: Add support for PLLs supporting dynamic reprogramming Rajendra Nayak
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Some PLLs can have an additional early output (apart from
the main and aux outputs). Add support for the PLL driver
so it can be used to initialize/configure the early output

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/qcom/clk-pll.c | 2 ++
 drivers/clk/qcom/clk-pll.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 08d2fa2..b463432 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -268,6 +268,7 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 	val |= config->mn_ena_mask;
 	val |= config->main_output_mask;
 	val |= config->aux_output_mask;
+	val |= config->early_output_mask;
 
 	mask = config->vco_mask;
 	mask |= config->pre_div_mask;
@@ -275,6 +276,7 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 	mask |= config->mn_ena_mask;
 	mask |= config->main_output_mask;
 	mask |= config->aux_output_mask;
+	mask |= config->early_output_mask;
 
 	regmap_update_bits(regmap, pll->config_reg, mask, val);
 }
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index 083727e..dbe22a9 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -81,6 +81,7 @@ struct pll_config {
 	u32 mn_ena_mask;
 	u32 main_output_mask;
 	u32 aux_output_mask;
+	u32 early_output_mask;
 };
 
 void clk_pll_configure_sr(struct clk_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

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

* [PATCH 6/6] clk: qcom: Add support for PLLs supporting dynamic reprogramming
  2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
                   ` (4 preceding siblings ...)
  2016-07-11 10:50 ` [PATCH 5/6] clk: qcom: Add support for PLLs with early output Rajendra Nayak
@ 2016-07-11 10:50 ` Rajendra Nayak
  5 siblings, 0 replies; 7+ messages in thread
From: Rajendra Nayak @ 2016-07-11 10:50 UTC (permalink / raw)
  To: sboyd, stephen.boyd, mturquette
  Cc: linux-clk, linux-arm-msm, linux-kernel, Rajendra Nayak

Some PLLs can support dynamic reprogramming, which means just a L value
change is whats needed to change the PLL frequency without having to
explicitly enable/disable or bypass/re-lock the PLL.
Add support for such PLLs' initial configuration and the ops needed to
support the dynamic reprogramming thereafter.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
---
 drivers/clk/qcom/clk-pll.c | 106 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-pll.h |   9 +++-
 2 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index b463432..13d3f64 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -32,6 +32,7 @@
 #define PLL_BIAS_COUNT_SHIFT	14
 #define PLL_BIAS_COUNT_MASK	0x3f
 #define PLL_VOTE_FSM_ENA	BIT(20)
+#define PLL_DYN_FSM_ENA		BIT(20)
 #define PLL_VOTE_FSM_RESET	BIT(21)
 
 static int clk_pll_enable(struct clk_hw *hw)
@@ -248,6 +249,19 @@ clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
 		PLL_VOTE_FSM_ENA);
 }
 
+static void
+clk_pll_set_dynamic_fsm_mode(struct clk_pll *pll, struct regmap *regmap)
+{
+	u32 val;
+	u32 mask;
+
+	mask = PLL_BIAS_COUNT_MASK | PLL_DYN_FSM_ENA;
+	val = 6 << PLL_BIAS_COUNT_SHIFT;
+	val |= PLL_DYN_FSM_ENA;
+
+	regmap_update_bits(regmap, pll->mode_reg, mask, val);
+}
+
 static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 	const struct pll_config *config)
 {
@@ -299,6 +313,21 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
 
+void clk_pll_configure_dynamic(struct clk_pll *pll, struct regmap *regmap,
+			       const struct pll_config *config)
+{
+	u32 config_ctl_reg = pll->config_ctl_reg;
+	u32 config_ctl_hi_reg = pll->config_ctl_reg + 4;
+
+	clk_pll_configure(pll, regmap, config);
+
+	regmap_write(regmap, config_ctl_reg, config->config_ctl_val);
+	regmap_write(regmap, config_ctl_hi_reg, config->config_ctl_hi_val);
+
+	clk_pll_set_dynamic_fsm_mode(pll, regmap);
+}
+EXPORT_SYMBOL_GPL(clk_pll_configure_dynamic);
+
 static int clk_pll_sr2_enable(struct clk_hw *hw)
 {
 	struct clk_pll *pll = to_clk_pll(hw);
@@ -373,3 +402,80 @@ const struct clk_ops clk_pll_sr2_ops = {
 	.determine_rate = clk_pll_determine_rate,
 };
 EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
+
+static int clk_pll_dynamic_enable(struct clk_hw *hw)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+
+	/* Wait for 50us explicitly to avoid transient locks */
+	udelay(50);
+
+	return wait_for_pll(pll);
+};
+
+static void clk_pll_dynamic_disable(struct clk_hw *hw)
+{
+	/* 8 reference clock cycle delay mandated by the HPG */
+	udelay(1);
+};
+
+static unsigned long
+clk_pll_dynamic_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	u32 l_val;
+	int ret;
+
+	struct clk_pll *pll = to_clk_pll(hw);
+
+	ret = regmap_read(pll->clkr.regmap, pll->l_reg, &l_val);
+	if (ret)
+		return ret;
+
+	return l_val * parent_rate;
+};
+
+static int
+clk_pll_dynamic_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	const struct pll_freq_tbl *f;
+
+	f = find_freq(pll->freq_tbl, req->rate);
+	if (!f)
+		req->rate = DIV_ROUND_UP(req->rate, req->best_parent_rate)
+					* req->best_parent_rate;
+	else
+		req->rate = f->freq;
+
+	if (req->rate < pll->min_rate)
+		req->rate = pll->min_rate;
+	else if (req->rate > pll->max_rate)
+		req->rate = pll->max_rate;
+
+	return 0;
+}
+
+static int
+clk_pll_dynamic_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long prate)
+{
+	u32 l_val;
+	struct clk_pll *pll = to_clk_pll(hw);
+
+	if ((rate < pll->min_rate) || (rate > pll->max_rate) || !prate)
+		return -EINVAL;
+
+	l_val = rate / prate;
+	regmap_write(pll->clkr.regmap, pll->l_reg, l_val);
+
+	return 0;
+}
+
+const struct clk_ops clk_pll_dynamic_ops = {
+	.enable = clk_pll_dynamic_enable,
+	.disable = clk_pll_dynamic_disable,
+	.set_rate = clk_pll_dynamic_set_rate,
+	.recalc_rate = clk_pll_dynamic_recalc_rate,
+	.determine_rate = clk_pll_dynamic_determine_rate,
+};
+EXPORT_SYMBOL_GPL(clk_pll_dynamic_ops);
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index dbe22a9..627588f 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -52,9 +52,12 @@ struct clk_pll {
 	u32	config_reg;
 	u32	mode_reg;
 	u32	status_reg;
+	u32	config_ctl_reg;
 	u8	status_bit;
 	u8	post_div_width;
 	u8	post_div_shift;
+	unsigned long min_rate;
+	unsigned long max_rate;
 
 	const struct pll_freq_tbl *freq_tbl;
 
@@ -64,6 +67,7 @@ struct clk_pll {
 extern const struct clk_ops clk_pll_ops;
 extern const struct clk_ops clk_pll_vote_ops;
 extern const struct clk_ops clk_pll_sr2_ops;
+extern const struct clk_ops clk_pll_dynamic_ops;
 
 #define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)
 
@@ -78,6 +82,8 @@ struct pll_config {
 	u32 pre_div_mask;
 	u32 post_div_val;
 	u32 post_div_mask;
+	u32 config_ctl_val;
+	u32 config_ctl_hi_val;
 	u32 mn_ena_mask;
 	u32 main_output_mask;
 	u32 aux_output_mask;
@@ -88,5 +94,6 @@ void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
 		const struct pll_config *config, bool fsm_mode);
 void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 		const struct pll_config *config, bool fsm_mode);
-
+void clk_pll_configure_dynamic(struct clk_pll *pll, struct regmap *regmap,
+		const struct pll_config *config);
 #endif
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation

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

end of thread, other threads:[~2016-07-11 10:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-11 10:50 [PATCH 0/6] clk: qcom: PLL updates Rajendra Nayak
2016-07-11 10:50 ` [PATCH 1/6] clk: Fix inconsistencies in usage of data types Rajendra Nayak
2016-07-11 10:50 ` [PATCH 2/6] clk: qcom: Add support for alpha pll hwfsm ops Rajendra Nayak
2016-07-11 10:50 ` [PATCH 3/6] clk: qcom: Add support to initialize alpha plls Rajendra Nayak
2016-07-11 10:50 ` [PATCH 4/6] clk: qcom: Add support for PLLs with alpha mode Rajendra Nayak
2016-07-11 10:50 ` [PATCH 5/6] clk: qcom: Add support for PLLs with early output Rajendra Nayak
2016-07-11 10:50 ` [PATCH 6/6] clk: qcom: Add support for PLLs supporting dynamic reprogramming Rajendra Nayak

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).