All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/12] Misc patches for QCOM clocks
@ 2017-07-27 11:10 Abhishek Sahu
  2017-07-27 11:10 ` [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node Abhishek Sahu
                   ` (12 more replies)
  0 siblings, 13 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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


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

* [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 18:44   ` Stephen Boyd
  2017-07-27 11:10 ` [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL Abhishek Sahu
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

The current driver hardcodes the RCG2 register offsets. Some of
the RCG2’s use different offsets from the default one.

This patch adds the support to provide the register offsets array in
RCG2 clock node. If RCG2 clock node contains the register offsets
then this will be used instead of default one.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-rcg.h  | 11 +++++++
 drivers/clk/qcom/clk-rcg2.c | 78 ++++++++++++++++++++++++++++-----------------
 2 files changed, 60 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index 1b3e8d2..54add3b 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -17,6 +17,14 @@
 #include <linux/clk-provider.h>
 #include "clk-regmap.h"
 
+enum {
+	CLK_RCG2_CMD,
+	CLK_RCG2_CFG,
+	CLK_RCG2_M,
+	CLK_RCG2_N,
+	CLK_RCG2_D,
+};
+
 struct freq_tbl {
 	unsigned long freq;
 	u8 src;
@@ -154,6 +162,8 @@ struct clk_dyn_rcg {
  * @cmd_rcgr: corresponds to *_CMD_RCGR
  * @mnd_width: number of bits in m/n/d values
  * @hid_width: number of bits in half integer divider
+ * @offsets: offsets of RCG2 register from cmd_rcgr.
+ *	     default will be used in case of null
  * @parent_map: map from software's parent index to hardware's src_sel field
  * @freq_tbl: frequency table
  * @current_freq: last cached frequency when using branches with shared RCGs
@@ -164,6 +174,7 @@ struct clk_rcg2 {
 	u32			cmd_rcgr;
 	u8			mnd_width;
 	u8			hid_width;
+	const u8		*offsets;
 	const struct parent_map	*parent_map;
 	const struct freq_tbl	*freq_tbl;
 	unsigned long		current_freq;
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 1a0985a..7e1c8aa 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -26,7 +26,6 @@
 #include "clk-rcg.h"
 #include "common.h"
 
-#define CMD_REG			0x0
 #define CMD_UPDATE		BIT(0)
 #define CMD_ROOT_EN		BIT(1)
 #define CMD_DIRTY_CFG		BIT(4)
@@ -35,7 +34,6 @@
 #define CMD_DIRTY_D		BIT(7)
 #define CMD_ROOT_OFF		BIT(31)
 
-#define CFG_REG			0x4
 #define CFG_SRC_DIV_SHIFT	0
 #define CFG_SRC_SEL_SHIFT	8
 #define CFG_SRC_SEL_MASK	(0x7 << CFG_SRC_SEL_SHIFT)
@@ -43,22 +41,34 @@
 #define CFG_MODE_MASK		(0x3 << CFG_MODE_SHIFT)
 #define CFG_MODE_DUAL_EDGE	(0x2 << CFG_MODE_SHIFT)
 
-#define M_REG			0x8
-#define N_REG			0xc
-#define D_REG			0x10
+#define rcg2_cmd(rcg, offsets)	(rcg->cmd_rcgr)
+#define rcg2_cfg(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_CFG])
+#define rcg2_m(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_M])
+#define rcg2_n(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_N])
+#define rcg2_d(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_D])
+
+#define to_rcg2_offsets(rcg)	(rcg->offsets ?		\
+				 rcg->offsets : rcg2_default_offsets)
 
 enum freq_policy {
 	FLOOR,
 	CEIL,
 };
 
+static const u8 rcg2_default_offsets[] = {
+	[CLK_RCG2_CFG] = 0x4,
+	[CLK_RCG2_M] = 0x8,
+	[CLK_RCG2_N] = 0xc,
+	[CLK_RCG2_D] = 0x10,
+};
+
 static int clk_rcg2_is_enabled(struct clk_hw *hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	u32 cmd;
 	int ret;
 
-	ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
+	ret = regmap_read(rcg->clkr.regmap, rcg2_cmd(rcg, offsets), &cmd);
 	if (ret)
 		return ret;
 
@@ -68,11 +78,12 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
 static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	int num_parents = clk_hw_get_num_parents(hw);
 	u32 cfg;
 	int i, ret;
 
-	ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+	ret = regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets), &cfg);
 	if (ret)
 		goto err;
 
@@ -96,14 +107,15 @@ static int update_config(struct clk_rcg2 *rcg)
 	struct clk_hw *hw = &rcg->clkr.hw;
 	const char *name = clk_hw_get_name(hw);
 
-	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+	ret = regmap_update_bits(rcg->clkr.regmap, rcg2_cmd(rcg, offsets),
 				 CMD_UPDATE, CMD_UPDATE);
 	if (ret)
 		return ret;
 
 	/* Wait for update to take effect */
 	for (count = 500; count > 0; count--) {
-		ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
+		ret = regmap_read(rcg->clkr.regmap, rcg2_cmd(rcg, offsets),
+				  &cmd);
 		if (ret)
 			return ret;
 		if (!(cmd & CMD_UPDATE))
@@ -118,10 +130,11 @@ static int update_config(struct clk_rcg2 *rcg)
 static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	int ret;
 	u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
 
-	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
+	ret = regmap_update_bits(rcg->clkr.regmap, rcg2_cfg(rcg, offsets),
 				 CFG_SRC_SEL_MASK, cfg);
 	if (ret)
 		return ret;
@@ -158,15 +171,16 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
 clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
 
-	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+	regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets), &cfg);
 
 	if (rcg->mnd_width) {
 		mask = BIT(rcg->mnd_width) - 1;
-		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m);
+		regmap_read(rcg->clkr.regmap, rcg2_m(rcg, offsets), &m);
 		m &= mask;
-		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n);
+		regmap_read(rcg->clkr.regmap, rcg2_n(rcg, offsets), &n);
 		n =  ~n;
 		n &= mask;
 		n += m;
@@ -252,6 +266,7 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 {
 	u32 cfg, mask;
 	struct clk_hw *hw = &rcg->clkr.hw;
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
 	if (index < 0)
@@ -260,17 +275,17 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 	if (rcg->mnd_width && f->n) {
 		mask = BIT(rcg->mnd_width) - 1;
 		ret = regmap_update_bits(rcg->clkr.regmap,
-				rcg->cmd_rcgr + M_REG, mask, f->m);
+				rcg2_m(rcg, offsets), mask, f->m);
 		if (ret)
 			return ret;
 
 		ret = regmap_update_bits(rcg->clkr.regmap,
-				rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m));
+				rcg2_n(rcg, offsets), mask, ~(f->n - f->m));
 		if (ret)
 			return ret;
 
 		ret = regmap_update_bits(rcg->clkr.regmap,
-				rcg->cmd_rcgr + D_REG, mask, ~f->n);
+				rcg2_d(rcg, offsets), mask, ~f->n);
 		if (ret)
 			return ret;
 	}
@@ -282,7 +297,7 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 	if (rcg->mnd_width && f->n && (f->m != f->n))
 		cfg |= CFG_MODE_DUAL_EDGE;
 	ret = regmap_update_bits(rcg->clkr.regmap,
-			rcg->cmd_rcgr + CFG_REG, mask, cfg);
+			rcg2_cfg(rcg, offsets), mask, cfg);
 	if (ret)
 		return ret;
 
@@ -365,7 +380,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
 	int ret, count;
 
 	/* force enable RCG */
-	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+	ret = regmap_update_bits(rcg->clkr.regmap, rcg2_cmd(rcg, offsets),
 				 CMD_ROOT_EN, CMD_ROOT_EN);
 	if (ret)
 		return ret;
@@ -386,7 +401,7 @@ static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
 		return ret;
 
 	/* clear force enable RCG */
-	return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
+	return regmap_update_bits(rcg->clkr.regmap, rcg2_cmd(rcg, offsets),
 				 CMD_ROOT_EN, 0);
 }
 
@@ -468,6 +483,7 @@ static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long parent_rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	struct freq_tbl f = *rcg->freq_tbl;
 	const struct frac_entry *frac;
 	int delta = 100000;
@@ -489,8 +505,8 @@ static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 		    (src_rate > (request + delta)))
 			continue;
 
-		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
-				&hid_div);
+		regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets),
+			    &hid_div);
 		f.pre_div = hid_div;
 		f.pre_div >>= CFG_SRC_DIV_SHIFT;
 		f.pre_div &= mask;
@@ -514,6 +530,7 @@ static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
 					struct clk_rate_request *req)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	const struct freq_tbl *f = rcg->freq_tbl;
 	const struct frac_entry *frac;
 	int delta = 100000;
@@ -539,8 +556,8 @@ static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
 		    (req->best_parent_rate > (request + delta)))
 			continue;
 
-		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
-				&hid_div);
+		regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets),
+			    &hid_div);
 		hid_div >>= CFG_SRC_DIV_SHIFT;
 		hid_div &= mask;
 
@@ -649,6 +666,7 @@ static int clk_byte2_set_rate(struct clk_hw *hw, unsigned long rate,
 			 unsigned long parent_rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	struct freq_tbl f = { 0 };
 	unsigned long div;
 	int i, num_parents = clk_hw_get_num_parents(hw);
@@ -660,7 +678,7 @@ static int clk_byte2_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	f.pre_div = div;
 
-	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+	regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets), &cfg);
 	cfg &= CFG_SRC_SEL_MASK;
 	cfg >>= CFG_SRC_SEL_SHIFT;
 
@@ -727,6 +745,7 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 		unsigned long parent_rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	struct freq_tbl f = { 0 };
 	const struct frac_entry *frac = frac_table_pixel;
 	unsigned long request;
@@ -735,7 +754,7 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 	u32 hid_div, cfg;
 	int i, num_parents = clk_hw_get_num_parents(hw);
 
-	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+	regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets), &cfg);
 	cfg &= CFG_SRC_SEL_MASK;
 	cfg >>= CFG_SRC_SEL_SHIFT;
 
@@ -752,8 +771,8 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
 			(parent_rate > (request + delta)))
 			continue;
 
-		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
-				&hid_div);
+		regmap_read(rcg->clkr.regmap, rcg2_cfg(rcg, offsets),
+			    &hid_div);
 		f.pre_div = hid_div;
 		f.pre_div >>= CFG_SRC_DIV_SHIFT;
 		f.pre_div &= mask;
@@ -835,12 +854,13 @@ static int clk_gfx3d_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 		unsigned long parent_rate, u8 index)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const u8 *offsets = to_rcg2_offsets(rcg);
 	u32 cfg;
 	int ret;
 
 	/* Just mux it, we don't use the division or m/n hardware */
 	cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
-	ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg);
+	ret = regmap_write(rcg->clkr.regmap, rcg2_cfg(rcg, offsets), cfg);
 	if (ret)
 		return ret;
 
-- 
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] 26+ messages in thread

* [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
  2017-07-27 11:10 ` [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-28 18:33   ` Stephen Boyd
  2017-07-27 11:10 ` [RFC 03/12] clk: qcom: support for alpha mode configuration Abhishek Sahu
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

Some of the Alpha PLL’s (like Spark, Brammo PLL) do not have
CONFIG_CTL_U register. This patch adds the flag for PLL’s
which have CONFIG_CTL_U register and checks the same while
doing PLL initial configuration.

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

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 47a1da3..e6cde2d 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -118,7 +118,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 	regmap_write(regmap, off + PLL_L_VAL, config->l);
 	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
 	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
-	regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val);
+
+	if (pll->flags & SUPPORTS_64BIT_CONFIG_CTL)
+		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
+			     config->config_ctl_hi_val);
 
 	val = config->main_output_mask;
 	val |= config->aux_output_mask;
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index d6e1ee2..bbd6aa9 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -34,9 +34,10 @@ struct clk_alpha_pll {
 
 	const struct pll_vco *vco_table;
 	size_t num_vco;
-#define SUPPORTS_OFFLINE_REQ	BIT(0)
-#define SUPPORTS_16BIT_ALPHA	BIT(1)
-#define SUPPORTS_FSM_MODE	BIT(2)
+#define SUPPORTS_OFFLINE_REQ		BIT(0)
+#define SUPPORTS_16BIT_ALPHA		BIT(1)
+#define SUPPORTS_FSM_MODE		BIT(2)
+#define SUPPORTS_64BIT_CONFIG_CTL	BIT(3)
 	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

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

* [RFC 03/12] clk: qcom: support for alpha mode configuration
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
  2017-07-27 11:10 ` [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node Abhishek Sahu
  2017-07-27 11:10 ` [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 04/12] clk: qcom: use offset from alpha pll node Abhishek Sahu
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

The current configuration does not fully configure PLL alpha mode
and values so this patch

1. Configures PLL_ALPHA_VAL_U for PLL which supports 40 bit alpha.
2. Adds alpha enable and alpha mode configuration support.

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

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e6cde2d..6291048 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -123,6 +123,9 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
 			     config->config_ctl_hi_val);
 
+	if (!(pll->flags & SUPPORTS_16BIT_ALPHA))
+		regmap_write(regmap, off + PLL_ALPHA_VAL_U, config->alpha_hi);
+
 	val = config->main_output_mask;
 	val |= config->aux_output_mask;
 	val |= config->aux2_output_mask;
@@ -130,6 +133,8 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 	val |= config->pre_div_val;
 	val |= config->post_div_val;
 	val |= config->vco_val;
+	val |= config->alpha_en_mask;
+	val |= config->alpha_mode_mask;
 
 	mask = config->main_output_mask;
 	mask |= config->aux_output_mask;
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index bbd6aa9..39686db 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -59,12 +59,15 @@ struct clk_alpha_pll_postdiv {
 struct alpha_pll_config {
 	u32 l;
 	u32 alpha;
+	u32 alpha_hi;
 	u32 config_ctl_val;
 	u32 config_ctl_hi_val;
 	u32 main_output_mask;
 	u32 aux_output_mask;
 	u32 aux2_output_mask;
 	u32 early_output_mask;
+	u32 alpha_en_mask;
+	u32 alpha_mode_mask;
 	u32 pre_div_val;
 	u32 pre_div_mask;
 	u32 post_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] 26+ messages in thread

* [RFC 04/12] clk: qcom: use offset from alpha pll node
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (2 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 03/12] clk: qcom: support for alpha mode configuration Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-30 13:26   ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation Abhishek Sahu
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

Alpha PLL is a generic name used for Qualcomm PLL’s which uses L
and Alpha values for configuring the integer and fractional part.
Qualcomm SoC’s use different types of Alpha PLL’s for which basic
software configuration part is common. These PLL’s will have same
basic registers like PLL_MODE, L_VAL, ALPHA_VAL but some of the
register offsets are different in each PLL type.
Also, the offsets are not same in different instances of same
type of PLL in some cases so it’s better to get the offsets
from PLL node itself instead of hardcoding it.

This patch adds the support for giving the PLL offsets array in
PLL node itself and uses the same for calculating the offsets.
Now, this offsets array will be mandatory for all alpha PLL nodes.
This patch provides the default array of offsets which driver can use
in case where the PLL offsets are same. Some of the existing
Qualcomm SoC’s uses the alpha PLL nodes so this patch added the
default offsets in its nodes.

Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
---
 drivers/clk/qcom/clk-alpha-pll.c | 129 ++++++++++++++++++++-------------------
 drivers/clk/qcom/clk-alpha-pll.h |  28 +++++++--
 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 ++++++++++-----
 6 files changed, 141 insertions(+), 94 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 6291048..ef24c80 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -20,7 +20,6 @@
 #include "clk-alpha-pll.h"
 #include "common.h"
 
-#define PLL_MODE		0x00
 # define PLL_OUTCTRL		BIT(0)
 # define PLL_BYPASSNL		BIT(1)
 # define PLL_RESET_N		BIT(2)
@@ -36,25 +35,12 @@
 # define PLL_ACTIVE_FLAG	BIT(30)
 # define PLL_LOCK_DET		BIT(31)
 
-#define PLL_L_VAL		0x04
-#define PLL_ALPHA_VAL		0x08
-#define PLL_ALPHA_VAL_U		0x0c
-
-#define PLL_USER_CTL		0x10
 # define PLL_POST_DIV_SHIFT	8
 # define PLL_POST_DIV_MASK	0xf
 # define PLL_ALPHA_EN		BIT(24)
 # define PLL_VCO_SHIFT		20
 # define PLL_VCO_MASK		0x3
 
-#define PLL_USER_CTL_U		0x14
-
-#define PLL_CONFIG_CTL		0x18
-#define PLL_CONFIG_CTL_U	0x20
-#define PLL_TEST_CTL		0x1c
-#define PLL_TEST_CTL_U		0x20
-#define PLL_STATUS		0x24
-
 /*
  * Even though 40 bits are present, use only 32 for ease of calculation.
  */
@@ -62,27 +48,51 @@
 #define ALPHA_BITWIDTH		32
 #define ALPHA_16BIT_MASK	0xffff
 
+#define pll_mode(pll)		(pll->base + pll->offsets[ALPHA_PLL_MODE])
+#define pll_l(pll)		(pll->base + pll->offsets[ALPHA_PLL_L_VAL])
+#define pll_alpha(pll)		(pll->base + pll->offsets[ALPHA_PLL_ALPHA_VAL])
+#define pll_alpha_u(pll)	(pll->base + pll->offsets[ALPHA_PLL_ALPHA_VAL_U])
+#define pll_user_ctl(pll)	(pll->base + pll->offsets[ALPHA_PLL_USER_CTL])
+#define pll_user_ctl_u(pll)	(pll->base + pll->offsets[ALPHA_PLL_USER_CTL_U])
+#define pll_cfg_ctl(pll)	(pll->base + pll->offsets[ALPHA_PLL_CONFIG_CTL])
+#define pll_test_ctl(pll)	(pll->base + pll->offsets[ALPHA_PLL_TEST_CTL])
+#define pll_test_ctl_u(pll)	(pll->base + pll->offsets[ALPHA_PLL_TEST_CTL_U])
+#define pll_status(pll)		(pll->base + pll->offsets[ALPHA_PLL_STATUS])
+#define pll_cfg_ctl_u(pll)	(pll->base + pll->offsets[ALPHA_PLL_CONFIG_CTL_U])
+
 #define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
 					   struct clk_alpha_pll, clkr)
 
 #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
 					   struct clk_alpha_pll_postdiv, clkr)
 
+const u8 alpha_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_USER_CTL_U] = 0x14,
+	[ALPHA_PLL_CONFIG_CTL] = 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)
 {
-	u32 val, off;
+	u32 val;
 	int count;
 	int ret;
 	const char *name = clk_hw_get_name(&pll->clkr.hw);
 
-	off = pll->offset;
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return ret;
 
 	for (count = 100; count > 0; count--) {
-		ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+		ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 		if (ret)
 			return ret;
 		if (inverse && !(val & mask))
@@ -113,18 +123,17 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 			     const struct alpha_pll_config *config)
 {
 	u32 val, mask;
-	u32 off = pll->offset;
 
-	regmap_write(regmap, off + PLL_L_VAL, config->l);
-	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
-	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
+	regmap_write(regmap, pll_l(pll), config->l);
+	regmap_write(regmap, pll_alpha(pll), config->alpha);
+	regmap_write(regmap, pll_cfg_ctl(pll), config->config_ctl_val);
 
 	if (pll->flags & SUPPORTS_64BIT_CONFIG_CTL)
-		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
+		regmap_write(regmap, pll_cfg_ctl_u(pll),
 			     config->config_ctl_hi_val);
 
 	if (!(pll->flags & SUPPORTS_16BIT_ALPHA))
-		regmap_write(regmap, off + PLL_ALPHA_VAL_U, config->alpha_hi);
+		regmap_write(regmap, pll_alpha_u(pll), config->alpha_hi);
 
 	val = config->main_output_mask;
 	val |= config->aux_output_mask;
@@ -144,20 +153,19 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 	mask |= config->post_div_mask;
 	mask |= config->vco_mask;
 
-	regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val);
+	regmap_update_bits(regmap, pll_user_ctl(pll), mask, val);
 
 	if (pll->flags & SUPPORTS_FSM_MODE)
-		qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0);
+		qcom_pll_set_fsm_mode(regmap, pll_mode(pll), 6, 0);
 }
 
 static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
 {
 	int ret;
-	u32 val, off;
+	u32 val;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 
-	off = pll->offset;
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return ret;
 
@@ -166,7 +174,7 @@ static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
 	if (pll->flags & SUPPORTS_OFFLINE_REQ)
 		val &= ~PLL_OFFLINE_REQ;
 
-	ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
+	ret = regmap_write(pll->clkr.regmap, pll_mode(pll), val);
 	if (ret)
 		return ret;
 
@@ -179,16 +187,15 @@ static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
 static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
 {
 	int ret;
-	u32 val, off;
+	u32 val;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 
-	off = pll->offset;
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return;
 
 	if (pll->flags & SUPPORTS_OFFLINE_REQ) {
-		ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+		ret = regmap_update_bits(pll->clkr.regmap, pll_mode(pll),
 					 PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
 		if (ret)
 			return;
@@ -199,7 +206,7 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
 	}
 
 	/* Disable hwfsm */
-	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+	ret = regmap_update_bits(pll->clkr.regmap, pll_mode(pll),
 				 PLL_FSM_ENA, 0);
 	if (ret)
 		return;
@@ -210,11 +217,10 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
 static int pll_is_enabled(struct clk_hw *hw, u32 mask)
 {
 	int ret;
-	u32 val, off;
+	u32 val;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
 
-	off = pll->offset;
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return ret;
 
@@ -235,12 +241,10 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 {
 	int ret;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
-	u32 val, mask, off;
-
-	off = pll->offset;
+	u32 val, mask;
 
 	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return ret;
 
@@ -256,7 +260,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 	if ((val & mask) == mask)
 		return 0;
 
-	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+	ret = regmap_update_bits(pll->clkr.regmap, pll_mode(pll),
 				 PLL_BYPASSNL, PLL_BYPASSNL);
 	if (ret)
 		return ret;
@@ -268,7 +272,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 	mb();
 	udelay(5);
 
-	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+	ret = regmap_update_bits(pll->clkr.regmap, pll_mode(pll),
 				 PLL_RESET_N, PLL_RESET_N);
 	if (ret)
 		return ret;
@@ -277,7 +281,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
 	if (ret)
 		return ret;
 
-	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+	ret = regmap_update_bits(pll->clkr.regmap, pll_mode(pll),
 				 PLL_OUTCTRL, PLL_OUTCTRL);
 
 	/* Ensure that the write above goes through before returning. */
@@ -289,11 +293,9 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
 {
 	int ret;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
-	u32 val, mask, off;
-
-	off = pll->offset;
+	u32 val, mask;
 
-	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	ret = regmap_read(pll->clkr.regmap, pll_mode(pll), &val);
 	if (ret)
 		return;
 
@@ -304,14 +306,14 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
 	}
 
 	mask = PLL_OUTCTRL;
-	regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
+	regmap_update_bits(pll->clkr.regmap, pll_mode(pll), mask, 0);
 
 	/* Delay of 2 output clock ticks required until output is disabled */
 	mb();
 	udelay(1);
 
 	mask = PLL_RESET_N | PLL_BYPASSNL;
-	regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
+	regmap_update_bits(pll->clkr.regmap, pll_mode(pll), mask, 0);
 }
 
 static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
@@ -364,17 +366,16 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
 	u32 l, low, high, ctl;
 	u64 a = 0, prate = parent_rate;
 	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
-	u32 off = pll->offset;
 
-	regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
+	regmap_read(pll->clkr.regmap, pll_l(pll), &l);
 
-	regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
+	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
 	if (ctl & PLL_ALPHA_EN) {
-		regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
+		regmap_read(pll->clkr.regmap, pll_alpha(pll), &low);
 		if (pll->flags & SUPPORTS_16BIT_ALPHA) {
 			a = low & ALPHA_16BIT_MASK;
 		} else {
-			regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U,
+			regmap_read(pll->clkr.regmap, pll_alpha_u(pll),
 				    &high);
 			a = (u64)high << 32 | low;
 			a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
@@ -389,7 +390,7 @@ 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, off = pll->offset;
+	u32 l;
 	u64 a;
 
 	rate = alpha_pll_round_rate(rate, prate, &l, &a);
@@ -399,21 +400,21 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 		return -EINVAL;
 	}
 
-	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
+	regmap_write(pll->clkr.regmap, pll_l(pll), l);
 
 	if (pll->flags & SUPPORTS_16BIT_ALPHA) {
-		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL,
+		regmap_write(pll->clkr.regmap, pll_alpha(pll),
 			     a & ALPHA_16BIT_MASK);
 	} else {
 		a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
-		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+		regmap_write(pll->clkr.regmap, pll_alpha_u(pll), a >> 32);
 	}
 
-	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+	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, off + PLL_USER_CTL, PLL_ALPHA_EN,
+	regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll), PLL_ALPHA_EN,
 			   PLL_ALPHA_EN);
 
 	return 0;
@@ -463,7 +464,7 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
 	u32 ctl;
 
-	regmap_read(pll->clkr.regmap, pll->offset + PLL_USER_CTL, &ctl);
+	regmap_read(pll->clkr.regmap, pll_user_ctl(pll), &ctl);
 
 	ctl >>= PLL_POST_DIV_SHIFT;
 	ctl &= PLL_POST_DIV_MASK;
@@ -499,7 +500,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
 	/* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
 	div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
 
-	return regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
+	return regmap_update_bits(pll->clkr.regmap, pll_user_ctl(pll),
 				  PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
 				  div << PLL_POST_DIV_SHIFT);
 }
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 39686db..51a61a0 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -17,6 +17,20 @@
 #include <linux/clk-provider.h>
 #include "clk-regmap.h"
 
+enum {
+	ALPHA_PLL_MODE,
+	ALPHA_PLL_L_VAL,
+	ALPHA_PLL_ALPHA_VAL,
+	ALPHA_PLL_ALPHA_VAL_U,
+	ALPHA_PLL_USER_CTL,
+	ALPHA_PLL_USER_CTL_U,
+	ALPHA_PLL_CONFIG_CTL,
+	ALPHA_PLL_CONFIG_CTL_U,
+	ALPHA_PLL_TEST_CTL,
+	ALPHA_PLL_TEST_CTL_U,
+	ALPHA_PLL_STATUS,
+};
+
 struct pll_vco {
 	unsigned long min_freq;
 	unsigned long max_freq;
@@ -25,12 +39,14 @@ struct pll_vco {
 
 /**
  * struct clk_alpha_pll - phase locked loop (PLL)
- * @offset: base address of registers
+ * @base: base address of registers
+ * @offsets: array containing offsets of all PLL registers from base address
  * @vco_table: array of VCO settings
  * @clkr: regmap clock handle
  */
 struct clk_alpha_pll {
-	u32 offset;
+	u32 base;
+	const u8 *offsets;
 
 	const struct pll_vco *vco_table;
 	size_t num_vco;
@@ -45,12 +61,14 @@ struct clk_alpha_pll {
 
 /**
  * struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
- * @offset: base address of registers
+ * @base: base address of registers
+ * @offsets: array containing offsets of all PLL registers from base address
  * @width: width of post-divider
  * @clkr: regmap clock handle
  */
 struct clk_alpha_pll_postdiv {
-	u32 offset;
+	u32 base;
+	const u8 *offsets;
 	u8 width;
 
 	struct clk_regmap clkr;
@@ -76,6 +94,8 @@ struct alpha_pll_config {
 	u32 vco_mask;
 };
 
+extern const u8 alpha_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_postdiv_ops;
diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
index 0f735d3..4c68c84 100644
--- a/drivers/clk/qcom/gcc-ipq8074.c
+++ b/drivers/clk/qcom/gcc-ipq8074.c
@@ -51,7 +51,8 @@ enum {
 };
 
 static struct clk_alpha_pll gpll0_main = {
-	.offset = 0x21000,
+	.base = 0x21000,
+	.offsets = alpha_pll_offsets,
 	.clkr = {
 		.enable_reg = 0x0b000,
 		.enable_mask = BIT(0),
@@ -81,7 +82,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv gpll0 = {
-	.offset = 0x21000,
+	.base = 0x21000,
+	.offsets = alpha_pll_offsets,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0",
 		.parent_names = (const char *[]){
diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c
index 7983288..b3460d6 100644
--- a/drivers/clk/qcom/gcc-msm8994.c
+++ b/drivers/clk/qcom/gcc-msm8994.c
@@ -72,7 +72,8 @@ enum {
 };
 
 static struct clk_alpha_pll gpll0_early = {
-	.offset = 0x00000,
+	.base = 0x00000,
+	.offsets = alpha_pll_offsets,
 	.clkr = {
 		.enable_reg = 0x1480,
 		.enable_mask = BIT(0),
@@ -87,7 +88,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv gpll0 = {
-	.offset = 0x00000,
+	.base = 0x00000,
+	.offsets = alpha_pll_offsets,
 	.clkr.hw.init = &(struct clk_init_data)
 	{
 		.name = "gpll0",
@@ -98,7 +100,8 @@ enum {
 };
 
 static struct clk_alpha_pll gpll4_early = {
-	.offset = 0x1dc0,
+	.base = 0x1dc0,
+	.offsets = alpha_pll_offsets,
 	.clkr = {
 		.enable_reg = 0x1480,
 		.enable_mask = BIT(4),
@@ -113,7 +116,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv gpll4 = {
-	.offset = 0x1dc0,
+	.base = 0x1dc0,
+	.offsets = alpha_pll_offsets,
 	.clkr.hw.init = &(struct clk_init_data)
 	{
 		.name = "gpll4",
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index 8abc200..5778c16 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -226,7 +226,8 @@ enum {
 };
 
 static struct clk_alpha_pll gpll0_early = {
-	.offset = 0x00000,
+	.base = 0x00000,
+	.offsets = alpha_pll_offsets,
 	.clkr = {
 		.enable_reg = 0x52000,
 		.enable_mask = BIT(0),
@@ -251,7 +252,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv gpll0 = {
-	.offset = 0x00000,
+	.base = 0x00000,
+	.offsets = alpha_pll_offsets,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0",
 		.parent_names = (const char *[]){ "gpll0_early" },
@@ -261,7 +263,8 @@ enum {
 };
 
 static struct clk_alpha_pll gpll4_early = {
-	.offset = 0x77000,
+	.base = 0x77000,
+	.offsets = alpha_pll_offsets,
 	.clkr = {
 		.enable_reg = 0x52000,
 		.enable_mask = BIT(4),
@@ -275,7 +278,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv gpll4 = {
-	.offset = 0x77000,
+	.base = 0x77000,
+	.offsets = alpha_pll_offsets,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll4",
 		.parent_names = (const char *[]){ "gpll4_early" },
diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c
index 352394d..b118538 100644
--- a/drivers/clk/qcom/mmcc-msm8996.c
+++ b/drivers/clk/qcom/mmcc-msm8996.c
@@ -266,7 +266,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll0_early = {
-	.offset = 0x0,
+	.base = 0x0,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_p_vco,
 	.num_vco = ARRAY_SIZE(mmpll_p_vco),
 	.clkr = {
@@ -282,7 +283,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll0 = {
-	.offset = 0x0,
+	.base = 0x0,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll0",
@@ -294,7 +296,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll1_early = {
-	.offset = 0x30,
+	.base = 0x30,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_p_vco,
 	.num_vco = ARRAY_SIZE(mmpll_p_vco),
 	.clkr = {
@@ -310,7 +313,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll1 = {
-	.offset = 0x30,
+	.base = 0x30,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll1",
@@ -322,7 +326,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll2_early = {
-	.offset = 0x4100,
+	.base = 0x4100,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_gfx_vco,
 	.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -334,7 +339,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll2 = {
-	.offset = 0x4100,
+	.base = 0x4100,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll2",
@@ -346,7 +352,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll3_early = {
-	.offset = 0x60,
+	.base = 0x60,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_p_vco,
 	.num_vco = ARRAY_SIZE(mmpll_p_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -358,7 +365,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll3 = {
-	.offset = 0x60,
+	.base = 0x60,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll3",
@@ -370,7 +378,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll4_early = {
-	.offset = 0x90,
+	.base = 0x90,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_t_vco,
 	.num_vco = ARRAY_SIZE(mmpll_t_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -382,7 +391,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll4 = {
-	.offset = 0x90,
+	.base = 0x90,
+	.offsets = alpha_pll_offsets,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll4",
@@ -394,7 +404,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll5_early = {
-	.offset = 0xc0,
+	.base = 0xc0,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_p_vco,
 	.num_vco = ARRAY_SIZE(mmpll_p_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -406,7 +417,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll5 = {
-	.offset = 0xc0,
+	.base = 0xc0,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll5",
@@ -418,7 +430,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll8_early = {
-	.offset = 0x4130,
+	.base = 0x4130,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_gfx_vco,
 	.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -430,7 +443,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll8 = {
-	.offset = 0x4130,
+	.base = 0x4130,
+	.offsets = alpha_pll_offsets,
 	.width = 4,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll8",
@@ -442,7 +456,8 @@ enum {
 };
 
 static struct clk_alpha_pll mmpll9_early = {
-	.offset = 0x4200,
+	.base = 0x4200,
+	.offsets = alpha_pll_offsets,
 	.vco_table = mmpll_t_vco,
 	.num_vco = ARRAY_SIZE(mmpll_t_vco),
 	.clkr.hw.init = &(struct clk_init_data){
@@ -454,7 +469,8 @@ enum {
 };
 
 static struct clk_alpha_pll_postdiv mmpll9 = {
-	.offset = 0x4200,
+	.base = 0x4200,
+	.offsets = alpha_pll_offsets,
 	.width = 2,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "mmpll9",
-- 
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] 26+ messages in thread

* [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (3 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 04/12] clk: qcom: use offset from alpha pll node Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (4 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-28 18:34   ` Stephen Boyd
  2017-07-27 11:10 ` [RFC 07/12] clk: qcom: add flag for VCO operation Abhishek Sahu
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 07/12] clk: qcom: add flag for VCO operation
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (5 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 08/12] clk: qcom: support for Huayra PLL Abhishek Sahu
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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


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

* [RFC 08/12] clk: qcom: support for Huayra PLL
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (6 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 07/12] clk: qcom: add flag for VCO operation Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 09/12] clk: qcom: support for Brammo PLL Abhishek Sahu
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 09/12] clk: qcom: support for Brammo PLL
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (7 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 08/12] clk: qcom: support for Huayra PLL Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 10/12] clk: qcom: add read-only divider operations Abhishek Sahu
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 10/12] clk: qcom: add read-only divider operations
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (8 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 09/12] clk: qcom: support for Brammo PLL Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 11/12] clk: qcom: add read-only alpha pll post " Abhishek Sahu
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 11/12] clk: qcom: add read-only alpha pll post divider operations
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (9 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 10/12] clk: qcom: add read-only divider operations Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 11:10 ` [RFC 12/12] clk: qcom: add parent map for regmap mux Abhishek Sahu
  2017-07-27 18:39 ` [RFC 00/12] Misc patches for QCOM clocks Stephen Boyd
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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

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

* [RFC 12/12] clk: qcom: add parent map for regmap mux
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (10 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 11/12] clk: qcom: add read-only alpha pll post " Abhishek Sahu
@ 2017-07-27 11:10 ` Abhishek Sahu
  2017-07-27 18:39 ` [RFC 00/12] Misc patches for QCOM clocks Stephen Boyd
  12 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-27 11:10 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel, Abhishek Sahu

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


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

* Re: [RFC 00/12] Misc patches for QCOM clocks
  2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
                   ` (11 preceding siblings ...)
  2017-07-27 11:10 ` [RFC 12/12] clk: qcom: add parent map for regmap mux Abhishek Sahu
@ 2017-07-27 18:39 ` Stephen Boyd
  12 siblings, 0 replies; 26+ messages in thread
From: Stephen Boyd @ 2017-07-27 18:39 UTC (permalink / raw)
  To: Abhishek Sahu, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel

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


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

* Re: [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node
  2017-07-27 11:10 ` [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node Abhishek Sahu
@ 2017-07-27 18:44   ` Stephen Boyd
  2017-07-28  9:42     ` Abhishek Sahu
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2017-07-27 18:44 UTC (permalink / raw)
  To: Abhishek Sahu, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel

On 07/27/2017 04:10 AM, Abhishek Sahu wrote:
> The current driver hardcodes the RCG2 register offsets. Some of
> the RCG2’s use different offsets from the default one.
>
> This patch adds the support to provide the register offsets array in
> RCG2 clock node. If RCG2 clock node contains the register offsets
> then this will be used instead of default one.
>
> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  drivers/clk/qcom/clk-rcg.h  | 11 +++++++
>  drivers/clk/qcom/clk-rcg2.c | 78 ++++++++++++++++++++++++++++-----------------
>  2 files changed, 60 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
> index 1b3e8d2..54add3b 100644
> --- a/drivers/clk/qcom/clk-rcg.h
> +++ b/drivers/clk/qcom/clk-rcg.h
> @@ -17,6 +17,14 @@
>  #include <linux/clk-provider.h>
>  #include "clk-regmap.h"
>  
> +enum {
> +	CLK_RCG2_CMD,
> +	CLK_RCG2_CFG,
> +	CLK_RCG2_M,
> +	CLK_RCG2_N,
> +	CLK_RCG2_D,
> +};
> +
>  struct freq_tbl {
>  	unsigned long freq;
>  	u8 src;
> @@ -154,6 +162,8 @@ struct clk_dyn_rcg {
>   * @cmd_rcgr: corresponds to *_CMD_RCGR
>   * @mnd_width: number of bits in m/n/d values
>   * @hid_width: number of bits in half integer divider
> + * @offsets: offsets of RCG2 register from cmd_rcgr.
> + *	     default will be used in case of null
>   * @parent_map: map from software's parent index to hardware's src_sel field
>   * @freq_tbl: frequency table
>   * @current_freq: last cached frequency when using branches with shared RCGs
> @@ -164,6 +174,7 @@ struct clk_rcg2 {
>  	u32			cmd_rcgr;
>  	u8			mnd_width;
>  	u8			hid_width;
> +	const u8		*offsets;
>  	const struct parent_map	*parent_map;
>  	const struct freq_tbl	*freq_tbl;
>  	unsigned long		current_freq;
> diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
> index 1a0985a..7e1c8aa 100644
> --- a/drivers/clk/qcom/clk-rcg2.c
> +++ b/drivers/clk/qcom/clk-rcg2.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2013, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
>   *
>   * This software is licensed under the terms of the GNU General Public
>   * License version 2, as published by the Free Software Foundation, and
> @@ -26,7 +26,6 @@
>  #include "clk-rcg.h"
>  #include "common.h"
>  
> -#define CMD_REG			0x0
>  #define CMD_UPDATE		BIT(0)
>  #define CMD_ROOT_EN		BIT(1)
>  #define CMD_DIRTY_CFG		BIT(4)
> @@ -35,7 +34,6 @@
>  #define CMD_DIRTY_D		BIT(7)
>  #define CMD_ROOT_OFF		BIT(31)
>  
> -#define CFG_REG			0x4
>  #define CFG_SRC_DIV_SHIFT	0
>  #define CFG_SRC_SEL_SHIFT	8
>  #define CFG_SRC_SEL_MASK	(0x7 << CFG_SRC_SEL_SHIFT)
> @@ -43,22 +41,34 @@
>  #define CFG_MODE_MASK		(0x3 << CFG_MODE_SHIFT)
>  #define CFG_MODE_DUAL_EDGE	(0x2 << CFG_MODE_SHIFT)
>  
> -#define M_REG			0x8
> -#define N_REG			0xc
> -#define D_REG			0x10
> +#define rcg2_cmd(rcg, offsets)	(rcg->cmd_rcgr)
> +#define rcg2_cfg(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_CFG])
> +#define rcg2_m(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_M])
> +#define rcg2_n(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_N])
> +#define rcg2_d(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_D])
> +
> +#define to_rcg2_offsets(rcg)	(rcg->offsets ?		\
> +				 rcg->offsets : rcg2_default_offsets)
>  
>  enum freq_policy {
>  	FLOOR,
>  	CEIL,
>  };
>  
> +static const u8 rcg2_default_offsets[] = {
> +	[CLK_RCG2_CFG] = 0x4,
> +	[CLK_RCG2_M] = 0x8,
> +	[CLK_RCG2_N] = 0xc,
> +	[CLK_RCG2_D] = 0x10,
> +};

It looks like the two UBI clks that messed this up don't have an MN
counter, so instead of doing this maddness, just add a flag like
m_is_cfg and then make a rcg2_crmd() function that checks this flag and
returns cmd_rcg + CFG_REG or cmd_rgcr + M_REG depending on the flag. We
can also optimize further, and ifdef this whole branch out unless the
specific IPQ GCC driver is enabled. Also only update the generic RCG
code, and not the display/gpu specific ones. Then the diff is much
smaller, and we can go yell at hardware team to never do this again.

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

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

* Re: [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node
  2017-07-27 18:44   ` Stephen Boyd
@ 2017-07-28  9:42     ` Abhishek Sahu
  2017-07-28 17:55       ` Stephen Boyd
  0 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-28  9:42 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 2017-07-28 00:14, Stephen Boyd wrote:
> On 07/27/2017 04:10 AM, Abhishek Sahu wrote:
>> The current driver hardcodes the RCG2 register offsets. Some of
>> the RCG2’s use different offsets from the default one.
>> 
>> This patch adds the support to provide the register offsets array in
>> RCG2 clock node. If RCG2 clock node contains the register offsets
>> then this will be used instead of default one.
>> 

  <snip>

>> @@ -43,22 +41,34 @@
>>  #define CFG_MODE_MASK		(0x3 << CFG_MODE_SHIFT)
>>  #define CFG_MODE_DUAL_EDGE	(0x2 << CFG_MODE_SHIFT)
>> 
>> -#define M_REG			0x8
>> -#define N_REG			0xc
>> -#define D_REG			0x10
>> +#define rcg2_cmd(rcg, offsets)	(rcg->cmd_rcgr)
>> +#define rcg2_cfg(rcg, offsets)	(rcg->cmd_rcgr + 
>> offsets[CLK_RCG2_CFG])
>> +#define rcg2_m(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_M])
>> +#define rcg2_n(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_N])
>> +#define rcg2_d(rcg, offsets)	(rcg->cmd_rcgr + offsets[CLK_RCG2_D])
>> +
>> +#define to_rcg2_offsets(rcg)	(rcg->offsets ?		\
>> +				 rcg->offsets : rcg2_default_offsets)
>> 
>>  enum freq_policy {
>>  	FLOOR,
>>  	CEIL,
>>  };
>> 
>> +static const u8 rcg2_default_offsets[] = {
>> +	[CLK_RCG2_CFG] = 0x4,
>> +	[CLK_RCG2_M] = 0x8,
>> +	[CLK_RCG2_N] = 0xc,
>> +	[CLK_RCG2_D] = 0x10,
>> +};
> 
> It looks like the two UBI clks that messed this up don't have an MN
> counter, so instead of doing this maddness, just add a flag like

  I have given example for one of the RCG. IPQ8074 have more clocks for
  which the offsets are not continuous and some of the clocks have
  mn counter also (NSS Crypto and PCIE AUX)

  GCC_NSS_UBI0_CMD_RCGR 0x1868100
  GCC_NSS_UBI0_CFG_RCGR 0x1868108
  GCC_NSS_UBI1_CMD_RCGR 0x1868120
  GCC_NSS_UBI1_CFG_RCGR 0x1868128

  GCC_NSS_CRYPTO_CMD_RCGR 0x1868140
  GCC_NSS_CRYPTO_CFG_RCGR 0x1868148
  GCC_NSS_CRYPTO_M 0x186814C
  GCC_NSS_CRYPTO_N 0x1868150
  GCC_NSS_CRYPTO_D 0x1868154

  GCC_PCIE0_AUX_CMD_RCGR	0x1875020
  GCC_PCIE0_AUX_CFG_RCGR	0x1875028
  GCC_PCIE0_AUX_M 0x187502C
  GCC_PCIE0_AUX_N 0x1875030
  GCC_PCIE0_AUX_D 0x1875034

  GCC_PCIE0_AXI_CMD_RCGR 0x1875050
  GCC_PCIE0_AXI_CFG_RCGR 0x1875058

  Similarly for PCIE1 also.

> m_is_cfg and then make a rcg2_crmd() function that checks this flag and
> returns cmd_rcg + CFG_REG or cmd_rgcr + M_REG depending on the flag. We

  The original idea was to make this generic so in future for all the 
cases
  it will work. If we can make function and since some clocks have MN
  counter, so could we make function for CMD reg itself instead of CFG 
reg.
  For this, pass cmd_rcgr as + 4 from GCC driver and when this flag is 
set
  then do minus 4 for all CMD_REG

> can also optimize further, and ifdef this whole branch out unless the
> specific IPQ GCC driver is enabled. Also only update the generic RCG
> code, and not the display/gpu specific ones. Then the diff is much
> smaller, and we can go yell at hardware team to never do this again.

-- 
Abhishek Sahu

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

* Re: [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node
  2017-07-28  9:42     ` Abhishek Sahu
@ 2017-07-28 17:55       ` Stephen Boyd
  2017-07-30 12:57         ` Abhishek Sahu
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2017-07-28 17:55 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 07/28, Abhishek Sahu wrote:
> On 2017-07-28 00:14, Stephen Boyd wrote:
> >
> >It looks like the two UBI clks that messed this up don't have an MN
> >counter, so instead of doing this maddness, just add a flag like
> 
>  I have given example for one of the RCG. IPQ8074 have more clocks for
>  which the offsets are not continuous and some of the clocks have
>  mn counter also (NSS Crypto and PCIE AUX)
> 
>  GCC_NSS_UBI0_CMD_RCGR 0x1868100
>  GCC_NSS_UBI0_CFG_RCGR 0x1868108
>  GCC_NSS_UBI1_CMD_RCGR 0x1868120
>  GCC_NSS_UBI1_CFG_RCGR 0x1868128
> 
>  GCC_NSS_CRYPTO_CMD_RCGR 0x1868140
>  GCC_NSS_CRYPTO_CFG_RCGR 0x1868148
>  GCC_NSS_CRYPTO_M 0x186814C
>  GCC_NSS_CRYPTO_N 0x1868150
>  GCC_NSS_CRYPTO_D 0x1868154
> 
>  GCC_PCIE0_AUX_CMD_RCGR	0x1875020
>  GCC_PCIE0_AUX_CFG_RCGR	0x1875028
>  GCC_PCIE0_AUX_M 0x187502C
>  GCC_PCIE0_AUX_N 0x1875030
>  GCC_PCIE0_AUX_D 0x1875034
> 
>  GCC_PCIE0_AXI_CMD_RCGR 0x1875050
>  GCC_PCIE0_AXI_CFG_RCGR 0x1875058
> 
>  Similarly for PCIE1 also.

Wow. This is awful. Please make sure this never happens again. I
will go yell at someone as well.

> 
> >m_is_cfg and then make a rcg2_crmd() function that checks this flag and
> >returns cmd_rcg + CFG_REG or cmd_rgcr + M_REG depending on the flag. We
> 
>  The original idea was to make this generic so in future for all the
> cases
>  it will work. If we can make function and since some clocks have MN
>  counter, so could we make function for CMD reg itself instead of
> CFG reg.

I understand the idea. We don't want it to happen again in the
future though, so let's not make it easy to support in the future
with some register map thing. Hardware people should follow the
rules and stop messing with the register layout!

>  For this, pass cmd_rcgr as + 4 from GCC driver and when this flag
> is set
>  then do minus 4 for all CMD_REG
> 

Ok. That's a good solution.

Just to be clear, let's have a flag like 'cmd_reg_is_wrong' (feel
free to think of a better name) and then have the places where we
access CMD_REG subtract that by 4, again with some special
macro/function, and then have the IPQ gcc driver specify the
cmd_rcgr as the real register + 4. Then the other hardcoded
offsets can all be the same and the few places that we access
CMD_REG we can subtract 4 to get the true location. And put all
that under an ifdef in some macro, so that we don't care about
this problem at all if we're not compiling this broken hardware
driver.

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

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

* Re: [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL
  2017-07-27 11:10 ` [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL Abhishek Sahu
@ 2017-07-28 18:33   ` Stephen Boyd
  2017-07-30 13:04     ` Abhishek Sahu
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2017-07-28 18:33 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 07/27, Abhishek Sahu wrote:
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index 47a1da3..e6cde2d 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -118,7 +118,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
>  	regmap_write(regmap, off + PLL_L_VAL, config->l);
>  	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
>  	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
> -	regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val);
> +
> +	if (pll->flags & SUPPORTS_64BIT_CONFIG_CTL)
> +		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
> +			     config->config_ctl_hi_val);

Is there a hole there? I mean a RAZ/WI register so we can just
keep writing it and not care?

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

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

* Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
  2017-07-27 11:10 ` [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu
@ 2017-07-28 18:34   ` Stephen Boyd
  2017-07-30 13:57     ` Abhishek Sahu
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2017-07-28 18:34 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

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

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

* Re: [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node
  2017-07-28 17:55       ` Stephen Boyd
@ 2017-07-30 12:57         ` Abhishek Sahu
  0 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-30 12:57 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 2017-07-28 23:25, Stephen Boyd wrote:
> On 07/28, Abhishek Sahu wrote:
>> On 2017-07-28 00:14, Stephen Boyd wrote:
>> >
>> >It looks like the two UBI clks that messed this up don't have an MN
>> >counter, so instead of doing this maddness, just add a flag like
>> 
>>  I have given example for one of the RCG. IPQ8074 have more clocks for
>>  which the offsets are not continuous and some of the clocks have
>>  mn counter also (NSS Crypto and PCIE AUX)
>> 
>>  GCC_NSS_UBI0_CMD_RCGR 0x1868100
>>  GCC_NSS_UBI0_CFG_RCGR 0x1868108
>>  GCC_NSS_UBI1_CMD_RCGR 0x1868120
>>  GCC_NSS_UBI1_CFG_RCGR 0x1868128
>> 
>>  GCC_NSS_CRYPTO_CMD_RCGR 0x1868140
>>  GCC_NSS_CRYPTO_CFG_RCGR 0x1868148
>>  GCC_NSS_CRYPTO_M 0x186814C
>>  GCC_NSS_CRYPTO_N 0x1868150
>>  GCC_NSS_CRYPTO_D 0x1868154
>> 
>>  GCC_PCIE0_AUX_CMD_RCGR	0x1875020
>>  GCC_PCIE0_AUX_CFG_RCGR	0x1875028
>>  GCC_PCIE0_AUX_M 0x187502C
>>  GCC_PCIE0_AUX_N 0x1875030
>>  GCC_PCIE0_AUX_D 0x1875034
>> 
>>  GCC_PCIE0_AXI_CMD_RCGR 0x1875050
>>  GCC_PCIE0_AXI_CFG_RCGR 0x1875058
>> 
>>  Similarly for PCIE1 also.
> 
> Wow. This is awful. Please make sure this never happens again. I
> will go yell at someone as well.
> 

  Yes. We also yelled badly at HW team for this and raised
  the HW bug before tapeout itself but they didn't fix by
  saying that this change will be risky and can have side
  effects.

>> 
>> >m_is_cfg and then make a rcg2_crmd() function that checks this flag and
>> >returns cmd_rcg + CFG_REG or cmd_rgcr + M_REG depending on the flag. We
>> 
>>  The original idea was to make this generic so in future for all the
>> cases
>>  it will work. If we can make function and since some clocks have MN
>>  counter, so could we make function for CMD reg itself instead of
>> CFG reg.
> 
> I understand the idea. We don't want it to happen again in the
> future though, so let's not make it easy to support in the future
> with some register map thing. Hardware people should follow the
> rules and stop messing with the register layout!
> 
>>  For this, pass cmd_rcgr as + 4 from GCC driver and when this flag
>> is set
>>  then do minus 4 for all CMD_REG
>> 
> 
> Ok. That's a good solution.
> 
> Just to be clear, let's have a flag like 'cmd_reg_is_wrong' (feel
> free to think of a better name) and then have the places where we
> access CMD_REG subtract that by 4, again with some special
> macro/function, and then have the IPQ gcc driver specify the
> cmd_rcgr as the real register + 4. Then the other hardcoded
> offsets can all be the same and the few places that we access
> CMD_REG we can subtract 4 to get the true location. And put all
> that under an ifdef in some macro, so that we don't care about
> this problem at all if we're not compiling this broken hardware
> driver.

  Sure. Same plan here and I will do the same.

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

* Re: [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL
  2017-07-28 18:33   ` Stephen Boyd
@ 2017-07-30 13:04     ` Abhishek Sahu
  2017-08-01 21:17       ` Stephen Boyd
  0 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-30 13:04 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 2017-07-29 00:03, Stephen Boyd wrote:
> On 07/27, Abhishek Sahu wrote:
>> diff --git a/drivers/clk/qcom/clk-alpha-pll.c 
>> b/drivers/clk/qcom/clk-alpha-pll.c
>> index 47a1da3..e6cde2d 100644
>> --- a/drivers/clk/qcom/clk-alpha-pll.c
>> +++ b/drivers/clk/qcom/clk-alpha-pll.c
>> @@ -118,7 +118,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll 
>> *pll, struct regmap *regmap,
>>  	regmap_write(regmap, off + PLL_L_VAL, config->l);
>>  	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
>>  	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
>> -	regmap_write(regmap, off + PLL_CONFIG_CTL_U, 
>> config->config_ctl_hi_val);
>> +
>> +	if (pll->flags & SUPPORTS_64BIT_CONFIG_CTL)
>> +		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
>> +			     config->config_ctl_hi_val);
> 
> Is there a hole there? I mean a RAZ/WI register so we can just
> keep writing it and not care?

  We don't have hole for most of the alpha PLL. The offset for
  CONFIG_CTL itself is not same for all types of Alpha PLL
  and the same is being handled in patch 4 of this patch
  series.

  Spark PLL
  CONFIG_CTL	0x18
  TEST_CTL	0x1C
  TEST_CTL_U	0x20

  Brammo PLL
  CONFIG_CTL	0x18
  TEST_CTL	0x1C
  PLL_STATUS     0x24

  Hyuara PLL
  CONFIG_CTL	0x14
  CONFIG_CTL_U	0x18
  TEST_CTL       0x1c

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

* Re: [RFC 04/12] clk: qcom: use offset from alpha pll node
  2017-07-27 11:10 ` [RFC 04/12] clk: qcom: use offset from alpha pll node Abhishek Sahu
@ 2017-07-30 13:26   ` Abhishek Sahu
  0 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-30 13:26 UTC (permalink / raw)
  To: sboyd, mturquette
  Cc: andy.gross, david.brown, rnayak, linux-arm-msm, linux-soc,
	linux-clk, linux-kernel

On 2017-07-27 16:40, Abhishek Sahu wrote:
> Alpha PLL is a generic name used for Qualcomm PLL’s which uses L
> and Alpha values for configuring the integer and fractional part.
> Qualcomm SoC’s use different types of Alpha PLL’s for which basic
> software configuration part is common. These PLL’s will have same
> basic registers like PLL_MODE, L_VAL, ALPHA_VAL but some of the
> register offsets are different in each PLL type.
> Also, the offsets are not same in different instances of same
> type of PLL in some cases so it’s better to get the offsets
> from PLL node itself instead of hardcoding it.
> 
> This patch adds the support for giving the PLL offsets array in
> PLL node itself and uses the same for calculating the offsets.
> Now, this offsets array will be mandatory for all alpha PLL nodes.
> This patch provides the default array of offsets which driver can use
> in case where the PLL offsets are same. Some of the existing
> Qualcomm SoC’s uses the alpha PLL nodes so this patch added the
> default offsets in its nodes.
> 

  Did more analysis for this patch. Following are the
  offsets comparison of different types of Alpha PLL
  being used in different QCOM chips.

  Offsets                   Pious  Spark   Brammo  Huayra   Fabia  APSS 
PLL

  ALPHA_MODE                0x00   0x00    0x00    0x00     0x00  0x00
  ALPHA_L_VAL               0x04   0x04    0x04    0x04     0x04  0x08
  ALPHA_ALPHA_VAL           0x08   0x08    0x08    0x08     0x38  0x10
  ALPHA_ALPHA_VAL_U         0x0c   0x0c    0x0c    NA       NA    NA
  ALPHA_PLL_USER_CTL        0x10   0x10    0x10    0x10     0x0c  0x18
  ALPHA_PLL_USER_CTL_U      0x14   0x14    NA      NA       0x10  NA
  ALPHA_CONFIG_CTL          0x18   0x18    0x18    0x14     0x14  0x20
  ALPHA_CONFIG_CTL_U        NA     NA      NA      0x18     0x18  0x24
  ALPHA_TEST_CTL            0x1c   0x1c    0x1c    0x1c     0x1c  0x30
  ALPHA_TEST_CTL_U          0x20   0x20    NA      0x20     0x20  0x34
  ALPHA_STATUS              0x24   0x24    0x24    0x24     0x24  0x28

  where
  APPS PLL is Huayra PLL and being used in IPQ8074 and MSM8953
  MSM8994 uses Pious PLL
  MSM8996 uses Spark and Huayra PLL
  IPQ8074 uses Spark, Brammo and Huayra PLL
  MSM8998 uses Fabia PLL

> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
> ---
>  drivers/clk/qcom/clk-alpha-pll.c | 129 
> ++++++++++++++++++++-------------------
>  drivers/clk/qcom/clk-alpha-pll.h |  28 +++++++--
>  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 ++++++++++-----
>  6 files changed, 141 insertions(+), 94 deletions(-)
> 
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c 
> b/drivers/clk/qcom/clk-alpha-pll.c
> index 6291048..ef24c80 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -20,7 +20,6 @@
>  #include "clk-alpha-pll.h"
>  #include "common.h"
> 
> -#define PLL_MODE		0x00
>  # define PLL_OUTCTRL		BIT(0)
>  # define PLL_BYPASSNL		BIT(1)
>  # define PLL_RESET_N		BIT(2)
> @@ -36,25 +35,12 @@
>  # define PLL_ACTIVE_FLAG	BIT(30)
>  # define PLL_LOCK_DET		BIT(31)
> 
> -#define PLL_L_VAL		0x04
> -#define PLL_ALPHA_VAL		0x08
> -#define PLL_ALPHA_VAL_U		0x0c
> -
> -#define PLL_USER_CTL		0x10
>  # define PLL_POST_DIV_SHIFT	8
>  # define PLL_POST_DIV_MASK	0xf
>  # define PLL_ALPHA_EN		BIT(24)
>  # define PLL_VCO_SHIFT		20
>  # define PLL_VCO_MASK		0x3
> 
> -#define PLL_USER_CTL_U		0x14
> -
> -#define PLL_CONFIG_CTL		0x18
> -#define PLL_CONFIG_CTL_U	0x20
> -#define PLL_TEST_CTL		0x1c
> -#define PLL_TEST_CTL_U		0x20
> -#define PLL_STATUS		0x24
> -
>  /*
>   * Even though 40 bits are present, use only 32 for ease of 
> calculation.
>   */
> @@ -62,27 +48,51 @@
>  #define ALPHA_BITWIDTH		32
>  #define ALPHA_16BIT_MASK	0xffff
> 
> +#define pll_mode(pll)		(pll->base + pll->offsets[ALPHA_PLL_MODE])
> +#define pll_l(pll)		(pll->base + pll->offsets[ALPHA_PLL_L_VAL])
> +#define pll_alpha(pll)		(pll->base + 
> pll->offsets[ALPHA_PLL_ALPHA_VAL])
> +#define pll_alpha_u(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_ALPHA_VAL_U])
> +#define pll_user_ctl(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_USER_CTL])
> +#define pll_user_ctl_u(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_USER_CTL_U])
> +#define pll_cfg_ctl(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_CONFIG_CTL])
> +#define pll_test_ctl(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_TEST_CTL])
> +#define pll_test_ctl_u(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_TEST_CTL_U])
> +#define pll_status(pll)		(pll->base + pll->offsets[ALPHA_PLL_STATUS])
> +#define pll_cfg_ctl_u(pll)	(pll->base + 
> pll->offsets[ALPHA_PLL_CONFIG_CTL_U])
> +
>  #define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
>  					   struct clk_alpha_pll, clkr)
> 
>  #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), 
> \
>  					   struct clk_alpha_pll_postdiv, clkr)
> 
> +const u8 alpha_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_USER_CTL_U] = 0x14,
> +	[ALPHA_PLL_CONFIG_CTL] = 0x18,
> +	[ALPHA_PLL_TEST_CTL] = 0x1c,
> +	[ALPHA_PLL_TEST_CTL_U] = 0x20,
> +	[ALPHA_PLL_STATUS] = 0x24,
> +};
> +

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

* Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
  2017-07-28 18:34   ` Stephen Boyd
@ 2017-07-30 13:57     ` Abhishek Sahu
  2017-08-01 21:12       ` Stephen Boyd
  0 siblings, 1 reply; 26+ messages in thread
From: Abhishek Sahu @ 2017-07-30 13:57 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

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

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

* Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
  2017-07-30 13:57     ` Abhishek Sahu
@ 2017-08-01 21:12       ` Stephen Boyd
  2017-08-02 13:50         ` Abhishek Sahu
  0 siblings, 1 reply; 26+ messages in thread
From: Stephen Boyd @ 2017-08-01 21:12 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 07/30, Abhishek Sahu wrote:
> 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.

Ok.

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

Hopefully the users of a PLL that doesn't support dynamic rate
update can accept the fact that the clk will turn off while the
rate is reprogrammed. At least that seems to be true for Taniya
in that patch set. If it isn't true for your hardware, then don't
specify the flag? Or is the problem that you may not have the
flag set for certain PLLs that you're supporting?

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

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

* Re: [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL
  2017-07-30 13:04     ` Abhishek Sahu
@ 2017-08-01 21:17       ` Stephen Boyd
  0 siblings, 0 replies; 26+ messages in thread
From: Stephen Boyd @ 2017-08-01 21:17 UTC (permalink / raw)
  To: Abhishek Sahu
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 07/30, Abhishek Sahu wrote:
> On 2017-07-29 00:03, Stephen Boyd wrote:
> >On 07/27, Abhishek Sahu wrote:
> >>diff --git a/drivers/clk/qcom/clk-alpha-pll.c
> >>b/drivers/clk/qcom/clk-alpha-pll.c
> >>index 47a1da3..e6cde2d 100644
> >>--- a/drivers/clk/qcom/clk-alpha-pll.c
> >>+++ b/drivers/clk/qcom/clk-alpha-pll.c
> >>@@ -118,7 +118,10 @@ void clk_alpha_pll_configure(struct
> >>clk_alpha_pll *pll, struct regmap *regmap,
> >> 	regmap_write(regmap, off + PLL_L_VAL, config->l);
> >> 	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
> >> 	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
> >>-	regmap_write(regmap, off + PLL_CONFIG_CTL_U,
> >>config->config_ctl_hi_val);
> >>+
> >>+	if (pll->flags & SUPPORTS_64BIT_CONFIG_CTL)
> >>+		regmap_write(regmap, off + PLL_CONFIG_CTL_U,
> >>+			     config->config_ctl_hi_val);
> >
> >Is there a hole there? I mean a RAZ/WI register so we can just
> >keep writing it and not care?
> 
>  We don't have hole for most of the alpha PLL. The offset for
>  CONFIG_CTL itself is not same for all types of Alpha PLL
>  and the same is being handled in patch 4 of this patch
>  series.
> 
>  Spark PLL
>  CONFIG_CTL	0x18
>  TEST_CTL	0x1C
>  TEST_CTL_U	0x20
> 
>  Brammo PLL
>  CONFIG_CTL	0x18
>  TEST_CTL	0x1C
>  PLL_STATUS     0x24
> 
>  Hyuara PLL
>  CONFIG_CTL	0x14
>  CONFIG_CTL_U	0x18
>  TEST_CTL       0x1c

Ok. Thanks for checking.

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

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

* Re: [RFC 06/12] Clk: qcom: support for dynamic updating the PLL
  2017-08-01 21:12       ` Stephen Boyd
@ 2017-08-02 13:50         ` Abhishek Sahu
  0 siblings, 0 replies; 26+ messages in thread
From: Abhishek Sahu @ 2017-08-02 13:50 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: mturquette, andy.gross, david.brown, rnayak, linux-arm-msm,
	linux-soc, linux-clk, linux-kernel

On 2017-08-02 02:42, Stephen Boyd wrote:
> On 07/30, Abhishek Sahu wrote:
>> On 2017-07-29 00:04, Stephen Boyd wrote:
>> >On 07/27, Abhishek Sahu wrote:

>>  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.
>> 
> 
> Hopefully the users of a PLL that doesn't support dynamic rate
> update can accept the fact that the clk will turn off while the
> rate is reprogrammed. At least that seems to be true for Taniya
> in that patch set. If it isn't true for your hardware, then don't
> specify the flag? Or is the problem that you may not have the
> flag set for certain PLLs that you're supporting?

  The turning off PLL will happen in case of flag is not set.
  The turning off PLL in set rate is unsafe. If this PLL
  is driving multiple RCG's and one of the RCG is changing the
  PLL frequency by its clk_set_rate with CLK_SET_RATE_PARENT,
  then all the RCG's clock will go off for some
  time and it may trigger crash/silent reboot.

  If the user is aware, then it can turn off the clock first,
  then do the set rate and then it can enable again. In
  PLL set_rate we can check if PLL is enabled and can
  return EBUSY error.

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

end of thread, other threads:[~2017-08-02 13:50 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-27 11:10 [RFC 00/12] Misc patches for QCOM clocks Abhishek Sahu
2017-07-27 11:10 ` [RFC 01/12] clk: qcom: support for register offsets from rcg2 clock node Abhishek Sahu
2017-07-27 18:44   ` Stephen Boyd
2017-07-28  9:42     ` Abhishek Sahu
2017-07-28 17:55       ` Stephen Boyd
2017-07-30 12:57         ` Abhishek Sahu
2017-07-27 11:10 ` [RFC 02/12] clk: qcom: flag for 64 bit CONFIG_CTL Abhishek Sahu
2017-07-28 18:33   ` Stephen Boyd
2017-07-30 13:04     ` Abhishek Sahu
2017-08-01 21:17       ` Stephen Boyd
2017-07-27 11:10 ` [RFC 03/12] clk: qcom: support for alpha mode configuration Abhishek Sahu
2017-07-27 11:10 ` [RFC 04/12] clk: qcom: use offset from alpha pll node Abhishek Sahu
2017-07-30 13:26   ` Abhishek Sahu
2017-07-27 11:10 ` [RFC 05/12] clk: qcom: fix 16 bit alpha support calculation Abhishek Sahu
2017-07-27 11:10 ` [RFC 06/12] Clk: qcom: support for dynamic updating the PLL Abhishek Sahu
2017-07-28 18:34   ` Stephen Boyd
2017-07-30 13:57     ` Abhishek Sahu
2017-08-01 21:12       ` Stephen Boyd
2017-08-02 13:50         ` Abhishek Sahu
2017-07-27 11:10 ` [RFC 07/12] clk: qcom: add flag for VCO operation Abhishek Sahu
2017-07-27 11:10 ` [RFC 08/12] clk: qcom: support for Huayra PLL Abhishek Sahu
2017-07-27 11:10 ` [RFC 09/12] clk: qcom: support for Brammo PLL Abhishek Sahu
2017-07-27 11:10 ` [RFC 10/12] clk: qcom: add read-only divider operations Abhishek Sahu
2017-07-27 11:10 ` [RFC 11/12] clk: qcom: add read-only alpha pll post " Abhishek Sahu
2017-07-27 11:10 ` [RFC 12/12] clk: qcom: add parent map for regmap mux Abhishek Sahu
2017-07-27 18:39 ` [RFC 00/12] Misc patches for QCOM clocks Stephen Boyd

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.