[PATCH v4 2/4] drivers: clk: st: PLL rate change implementation for DVFS

2015-10-07 Thread Gabriel Fernandez
Change A9 PLL rate, as per requirement from the cpufreq framework,
for DVFS. For rate change, the A9 clock needs to be temporarily sourced
from PLL external to A9 and then sourced back to A9-PLL

Signed-off-by: Pankaj Dev 
Signed-off-by: Gabriel Fernandez 
---
 drivers/clk/st/clkgen-mux.c |   3 +
 drivers/clk/st/clkgen-pll.c | 221 ++--
 drivers/clk/st/clkgen.h |   2 +
 3 files changed, 216 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 4f7f6c0..5dc5ce2 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include "clkgen.h"
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
 static DEFINE_SPINLOCK(clkgenf_lock);
@@ -576,6 +577,7 @@ static struct clkgen_mux_data stih415_a9_mux_data = {
.offset = 0,
.shift = 1,
.width = 2,
+   .lock = _a9_lock,
 };
 static struct clkgen_mux_data stih416_a9_mux_data = {
.offset = 0,
@@ -586,6 +588,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
.offset = 0x1a4,
.shift = 0,
.width = 2,
+   .lock = _a9_lock,
 };
 
 static const struct of_device_id mux_of_match[] = {
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index 092f82c..494848e 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -23,6 +23,7 @@
 #include "clkgen.h"
 
 static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
+DEFINE_SPINLOCK(clkgen_a9_lock);
 
 /*
  * Common PLL configuration register bits for PLL800 and PLL1600 C65
@@ -39,6 +40,7 @@ static DEFINE_SPINLOCK(clkgena_c32_odf_lock);
 #define C32_IDF_MASK (0x7)
 #define C32_ODF_MASK (0x3f)
 #define C32_LDF_MASK (0x7f)
+#define C32_CP_MASK (0x1f)
 
 #define C32_MAX_ODFS (4)
 
@@ -51,15 +53,20 @@ struct clkgen_pll_data {
struct clkgen_field pdiv;
struct clkgen_field idf;
struct clkgen_field ldf;
+   struct clkgen_field cp;
unsigned int num_odfs;
struct clkgen_field odf[C32_MAX_ODFS];
struct clkgen_field odf_gate[C32_MAX_ODFS];
+   bool switch2pll_en;
+   struct clkgen_field switch2pll;
+   spinlock_t *lock;
const struct clk_ops *ops;
 };
 
 static const struct clk_ops st_pll1600c65_ops;
 static const struct clk_ops st_pll800c65_ops;
 static const struct clk_ops stm_pll3200c32_ops;
+static const struct clk_ops stm_pll3200c32_a9_ops;
 static const struct clk_ops st_pll1200c32_ops;
 
 static const struct clkgen_pll_data st_pll1600c65_ax = {
@@ -242,7 +249,11 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = 
{
.num_odfs = 1,
.odf= { CLKGEN_FIELD(0x1b0, C32_ODF_MASK,   8) },
.odf_gate   = { CLKGEN_FIELD(0x1ac, 0x1,28) },
-   .ops= _pll3200c32_ops,
+   .switch2pll_en  = true,
+   .cp = CLKGEN_FIELD(0x1a8,   C32_CP_MASK,1),
+   .switch2pll = CLKGEN_FIELD(0x1a4,   0x1,1),
+   .lock = _a9_lock,
+   .ops= _pll3200c32_a9_ops,
 };
 
 /**
@@ -268,10 +279,26 @@ struct clkgen_pll {
struct clk_hw   hw;
struct clkgen_pll_data  *data;
void __iomem*regs_base;
+   spinlock_t  *lock;
+
+   u32 ndiv;
+   u32 idf;
+   u32 odf;
+   u32 cp;
 };
 
 #define to_clkgen_pll(_hw) container_of(_hw, struct clkgen_pll, hw)
 
+struct stm_pll {
+   unsigned long mdiv;
+   unsigned long ndiv;
+   unsigned long pdiv;
+   unsigned long odf;
+   unsigned long idf;
+   unsigned long ldf;
+   unsigned long cp;
+};
+
 static int clkgen_pll_is_locked(struct clk_hw *hw)
 {
struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -287,7 +314,7 @@ static int clkgen_pll_is_enabled(struct clk_hw *hw)
return !poweroff;
 }
 
-static int clkgen_pll_enable(struct clk_hw *hw)
+static int __clkgen_pll_enable(struct clk_hw *hw)
 {
struct clkgen_pll *pll = to_clkgen_pll(hw);
void __iomem *base =  pll->regs_base;
@@ -303,24 +330,62 @@ static int clkgen_pll_enable(struct clk_hw *hw)
ret = readl_relaxed_poll_timeout(base + field->offset, reg,
!!((reg >> field->shift) & field->mask),  0, 1);
 
-   if (!ret)
+   if (!ret) {
+   if (pll->data->switch2pll_en)
+   CLKGEN_WRITE(pll, switch2pll, 0);
+
pr_debug("%s:%s enabled\n", __clk_get_name(hw->clk), __func__);
+   }
 
return ret;
 }
 
-static void clkgen_pll_disable(struct clk_hw *hw)
+static int clkgen_pll_enable(struct clk_hw *hw)
+{
+   struct clkgen_pll *pll = to_clkgen_pll(hw);
+   unsigned long flags = 0;
+   int ret = 0;
+
+   if (pll->lock)
+   spin_lock_irqsave(pll->lock, flags);
+
+   ret = __clkgen_pll_enable(hw);
+
+   if 

Re: [PATCH v4 2/4] drivers: clk: st: PLL rate change implementation for DVFS

2015-10-07 Thread Stephen Boyd
On 10/07, Gabriel Fernandez wrote:
> Change A9 PLL rate, as per requirement from the cpufreq framework,
> for DVFS. For rate change, the A9 clock needs to be temporarily sourced
> from PLL external to A9 and then sourced back to A9-PLL
> 
> Signed-off-by: Pankaj Dev 
> Signed-off-by: Gabriel Fernandez 
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html