Re: [PATCH v2 3/4] clk: qcom: Add support for controlling Fabia PLL

2018-03-19 Thread Stephen Boyd
Quoting Amit Nischal (2018-03-07 23:18:14)
> Fabia PLL is a Digital Frequency Locked Loop (DFLL) clock
> generator which has a wide range of frequency output. It
> supports dynamic updating of the output frequency
> ("frequency slewing") without need to turn off the PLL
> before configuration. Add support for initial configuration
> and programming sequence to control fabia PLLs.
> 
> Signed-off-by: Amit Nischal 
> ---

Applied to clk-next with a little adjustment below:


diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e6b8d62e5175..9722b701fbdb 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -891,8 +891,9 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw)
int ret;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 val, opmode_val;
+   struct regmap *regmap = pll->clkr.regmap;
 
-   ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+   ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
 
@@ -904,8 +905,7 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw)
return wait_for_pll_enable_active(pll);
}
 
-   /* Read opmode value */
-   ret = regmap_read(pll->clkr.regmap, PLL_OPMODE(pll), &opmode_val);
+   ret = regmap_read(regmap, PLL_OPMODE(pll), &opmode_val);
if (ret)
return ret;
 
@@ -913,30 +913,20 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw)
if ((opmode_val & FABIA_OPMODE_RUN) && (val & PLL_OUTCTRL))
return 0;
 
-   /* Disable PLL output */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
-   PLL_OUTCTRL, 0);
+   ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
if (ret)
return ret;
 
-   /* Set Operation mode to STANBY */
-   ret = regmap_write(pll->clkr.regmap, PLL_OPMODE(pll),
-   FABIA_OPMODE_STANDBY);
+   ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY);
if (ret)
return ret;
 
-   /* PLL should be in STANDBY mode before continuing */
-   mb();
-
-   /* Bring PLL out of reset */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
-   PLL_RESET_N, PLL_RESET_N);
+   ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N,
+PLL_RESET_N);
if (ret)
return ret;
 
-   /* Set Operation mode to RUN */
-   ret = regmap_write(pll->clkr.regmap, PLL_OPMODE(pll),
-   FABIA_OPMODE_RUN);
+   ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_RUN);
if (ret)
return ret;
 
@@ -944,22 +934,13 @@ static int alpha_pll_fabia_enable(struct clk_hw *hw)
if (ret)
return ret;
 
-   /* Enable the main PLL output */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
-   FABIA_PLL_OUT_MASK, FABIA_PLL_OUT_MASK);
-   if (ret)
-   return ret;
-
-   /* Enable PLL outputs */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
-   PLL_OUTCTRL, PLL_OUTCTRL);
+   ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),
+FABIA_PLL_OUT_MASK, FABIA_PLL_OUT_MASK);
if (ret)
return ret;
 
-   /* Ensure that the write above goes through before returning. */
-   mb();
-
-   return ret;
+   return regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL,
+PLL_OUTCTRL);
 }
 
 static void alpha_pll_fabia_disable(struct clk_hw *hw)
@@ -967,8 +948,9 @@ static void alpha_pll_fabia_disable(struct clk_hw *hw)
int ret;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 val;
+   struct regmap *regmap = pll->clkr.regmap;
 
-   ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+   ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return;
 
@@ -978,23 +960,18 @@ static void alpha_pll_fabia_disable(struct clk_hw *hw)
return;
}
 
-   /* Disable PLL outputs */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
-   PLL_OUTCTRL, 0);
+   ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
if (ret)
return;
 
/* Disable main outputs */
-   ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
-   FABIA_PLL_OUT_MASK, 0);
+   ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), FABIA_PLL_OUT_MASK,
+0)

[PATCH v2 3/4] clk: qcom: Add support for controlling Fabia PLL

2018-03-07 Thread Amit Nischal
Fabia PLL is a Digital Frequency Locked Loop (DFLL) clock
generator which has a wide range of frequency output. It
supports dynamic updating of the output frequency
("frequency slewing") without need to turn off the PLL
before configuration. Add support for initial configuration
and programming sequence to control fabia PLLs.

Signed-off-by: Amit Nischal 
---
 drivers/clk/qcom/clk-alpha-pll.c | 324 ++-
 drivers/clk/qcom/clk-alpha-pll.h |  18 ++-
 2 files changed, 334 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 6d04cd9..e6b8d62 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -58,6 +58,8 @@
 #define PLL_TEST_CTL(p)((p)->offset + 
(p)->regs[PLL_OFF_TEST_CTL])
 #define PLL_TEST_CTL_U(p)  ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
 #define PLL_STATUS(p)  ((p)->offset + (p)->regs[PLL_OFF_STATUS])
+#define PLL_OPMODE(p)  ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
+#define PLL_FRAC(p)((p)->offset + (p)->regs[PLL_OFF_FRAC])

 const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[CLK_ALPHA_PLL_TYPE_DEFAULT] =  {
@@ -90,6 +92,18 @@
[PLL_OFF_TEST_CTL] = 0x1c,
[PLL_OFF_STATUS] = 0x24,
},
+   [CLK_ALPHA_PLL_TYPE_FABIA] =  {
+   [PLL_OFF_L_VAL] = 0x04,
+   [PLL_OFF_USER_CTL] = 0x0c,
+   [PLL_OFF_USER_CTL_U] = 0x10,
+   [PLL_OFF_CONFIG_CTL] = 0x14,
+   [PLL_OFF_CONFIG_CTL_U] = 0x18,
+   [PLL_OFF_TEST_CTL] = 0x1c,
+   [PLL_OFF_TEST_CTL_U] = 0x20,
+   [PLL_OFF_STATUS] = 0x24,
+   [PLL_OFF_OPMODE] = 0x2c,
+   [PLL_OFF_FRAC] = 0x38,
+   },
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);

@@ -108,6 +122,12 @@
 #define PLL_HUAYRA_N_MASK  0xff
 #define PLL_HUAYRA_ALPHA_WIDTH 16

+#define FABIA_OPMODE_STANDBY   0x0
+#define FABIA_OPMODE_RUN   0x1
+
+#define FABIA_PLL_OUT_MASK 0x7
+#define FABIA_PLL_RATE_MARGIN  500
+
 #define pll_alpha_width(p) \
((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
@@ -441,16 +461,12 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
return alpha_pll_calc_rate(prate, l, a, alpha_width);
 }

-static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll,
- int (*is_enabled)(struct clk_hw *))
+
+static int __clk_alpha_pll_update_latch(struct clk_alpha_pll *pll)
 {
int ret;
u32 mode;

-   if (!is_enabled(&pll->clkr.hw) ||
-   !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
-   return 0;
-
regmap_read(pll->clkr.regmap, PLL_MODE(pll), &mode);

/* Latch the input to the PLL */
@@ -489,6 +505,16 @@ static int clk_alpha_pll_update_latch(struct clk_alpha_pll 
*pll,
return 0;
 }

+static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll,
+ int (*is_enabled)(struct clk_hw *))
+{
+   if (!is_enabled(&pll->clkr.hw) ||
+   !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
+   return 0;
+
+   return __clk_alpha_pll_update_latch(pll);
+}
+
 static int __clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate,
int (*is_enabled)(struct clk_hw *))
@@ -832,3 +858,287 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw 
*hw, unsigned long rate,
.recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops);
+
+void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+const struct alpha_pll_config *config)
+{
+   u32 val, mask;
+
+   if (config->l)
+   regmap_write(regmap, PLL_L_VAL(pll), config->l);
+
+   if (config->alpha)
+   regmap_write(regmap, PLL_FRAC(pll), config->alpha);
+
+   if (config->config_ctl_val)
+   regmap_write(regmap, PLL_CONFIG_CTL(pll),
+   config->config_ctl_val);
+
+   if (config->post_div_mask) {
+   mask = config->post_div_mask;
+   val = config->post_div_val;
+   regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);
+   }
+
+   regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS,
+   PLL_UPDATE_BYPASS);