This patch series does the miscellaneous changes in QCOM Alpha PLL
operation and structure to support other types of Alpha PLL’s.
1. It adds the pll_type which will be used for determining all
the properties of Alpha PLL.
2. It adds the support for Brammo and Huayra PLL’s for which
the support is not available in existing alpha PLL code.
3. There won’t be any change in existing users of Alpha PLL’s
since all the newly added code will be under flag for the default
PLL operations.
The previous RFC series can be found for this in
https://www.spinics.net/lists/linux-clk/msg19305.html
Abhishek Sahu (13):
clk: qcom: remove redundant PLL_MODE macro offset
clk: qcom: minor code reorganization related with offset variable
clk: qcom: support for alpha pll properties
clk: qcom: fix 16 bit alpha support calculation
clk: qcom: add and use alpha register width from PLL properties
clk: qcom: flag for 64 bit CONFIG_CTL
clk: qcom: support for alpha mode configuration
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: support for 2 bit PLL post divider
clk: qcom: add read-only alpha pll post divider operations
drivers/clk/qcom/clk-alpha-pll.c | 701 +++++++++++++++++++++++++++++++++------
drivers/clk/qcom/clk-alpha-pll.h | 19 +-
2 files changed, 609 insertions(+), 111 deletions(-)
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Alpha PLL is a generic name used for QCOM PLL’s which uses L
and Alpha values for configuring the integer and fractional part.
QCOM SoC’s use different types of Alpha PLL’s for which basic
software configuration part is common with following differences.
1. All 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.
2. PLL dynamic programming sequence will be different in some
of the Alpha PLL’s
3. Some of the PLL won’t have 64 bit config control, 64 bit
user control, VCO configuration etc.
Now, this patch adds the Alpha PLL type in clock node and adds
alpha PLL properties structure inside clk-alpha-pll.c. This PLL
property will contain everything including register offsets, clock
operations and other properties since all these properties will be
fixed for Alpha PLL.
This allows to support other types of Alpha PLL without addition
of new flag and variable in structures of clk_alpha_pll.h. Also, we
don’t have to add operation for each Alpha PLL’s and export them.
In future, we can get rid of most of the flags like following
struct clk_alpha_pll {
#define SUPPORTS_OFFLINE_REQ BIT(0)
#define SUPPORTS_16BIT_ALPHA BIT(1)
#define SUPPORTS_FSM_MODE BIT(2)
u8 flags;
};
struct clk_alpha_pll_postdiv {
u8 width;
};
Since all the above properties will be always same for different
instances of same type of Alpha PLL’s.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 231 ++++++++++++++++++++++++++++++++-------
drivers/clk/qcom/clk-alpha-pll.h | 10 ++
2 files changed, 200 insertions(+), 41 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index ab2f23c..d5bfc52 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -35,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.
*/
@@ -61,12 +48,90 @@
#define ALPHA_BITWIDTH 32
#define ALPHA_16BIT_MASK 0xffff
+/* Returns the alpha_pll_clk_ops for pll type */
+#define pll_clk_ops(hw) (alpha_pll_props[to_clk_alpha_pll(hw)-> \
+ pll_type].ops)
+
+/* Returns the actual register offset for the reg crossponding to pll type */
+#define pll_reg(type, reg) alpha_pll_props[type].reg_offsets[reg]
+
+/* Helpers to return the actual register offset */
+#define pll_l(type) pll_reg(type, PLL_L_VAL)
+#define pll_alpha(type) pll_reg(type, PLL_ALPHA_VAL)
+#define pll_alpha_u(type) pll_reg(type, PLL_ALPHA_VAL_U)
+#define pll_user_ctl(type) pll_reg(type, PLL_USER_CTL)
+#define pll_user_ctl_u(type) pll_reg(type, PLL_USER_CTL_U)
+#define pll_cfg_ctl(type) pll_reg(type, PLL_CONFIG_CTL)
+#define pll_test_ctl(type) pll_reg(type, PLL_TEST_CTL)
+#define pll_test_ctl_u(type) pll_reg(type, PLL_TEST_CTL_U)
+#define pll_status(type) pll_reg(type, PLL_STATUS)
+#define pll_cfg_ctl_u(type) pll_reg(type, 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)
+/**
+ * Contains the index which will be used for mapping with actual
+ * register offset in Alpha PLL
+ */
+enum {
+ PLL_L_VAL,
+ PLL_ALPHA_VAL,
+ PLL_ALPHA_VAL_U,
+ PLL_USER_CTL,
+ PLL_USER_CTL_U,
+ PLL_CONFIG_CTL,
+ PLL_CONFIG_CTL_U,
+ PLL_TEST_CTL,
+ PLL_TEST_CTL_U,
+ PLL_STATUS,
+ PLL_MAX_REGS,
+};
+
+/**
+ * struct alpha_pll_clk_ops - operations for alpha PLL
+ * @enable: enable function when HW voting FSM is disabled
+ * @disable: disable function when HW voting FSM is disabled
+ * @is_enabled: check whether PLL is enabled when HW voting FSM is disabled
+ * @hwfsm_enable: check whether PLL is enabled when HW voting FSM is enabled
+ * @hwfsm_disable: check whether PLL is disabled when HW voting FSM is enabled
+ * @hwfsm_is_enabled: check whether PLL is enabled when HW voting FSM is enabled
+ * @recalc_rate: recalculate the rate of PLL by reading mode, L and Alpha Value
+ * @round_rate: returns the closest supported rate of PLL
+ * @set_rate: change the rate of this clock by actually programming the mode, L
+ * and Alpha Value registers
+ */
+struct alpha_pll_clk_ops {
+ int (*enable)(struct clk_hw *hw);
+ void (*disable)(struct clk_hw *hw);
+ int (*is_enabled)(struct clk_hw *hw);
+ int (*hwfsm_enable)(struct clk_hw *hw);
+ void (*hwfsm_disable)(struct clk_hw *hw);
+ int (*hwfsm_is_enabled)(struct clk_hw *hw);
+ unsigned long (*recalc_rate)(struct clk_hw *hw,
+ unsigned long parent_rate);
+ long (*round_rate)(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate);
+ int (*set_rate)(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+};
+
+/**
+ * struct alpha_pll_props - contains the various properties which
+ * will be fixed for PLL type.
+ * @reg_offsets: register offsets mapping array
+ * @ops: clock operations for alpha PLL
+ */
+struct alpha_pll_props {
+ u8 reg_offsets[PLL_MAX_REGS];
+ struct alpha_pll_clk_ops ops;
+};
+
+static const struct alpha_pll_props alpha_pll_props[];
+
static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
const char *action)
{
@@ -112,11 +177,13 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
{
u32 val, mask;
u32 off = pll->offset;
+ u8 type = pll->pll_type;
- 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);
+ regmap_write(regmap, off + pll_l(type), config->l);
+ regmap_write(regmap, off + pll_alpha(type), config->alpha);
+ regmap_write(regmap, off + pll_cfg_ctl(type), config->config_ctl_val);
+ regmap_write(regmap, off + pll_cfg_ctl_u(type),
+ config->config_ctl_hi_val);
val = config->main_output_mask;
val |= config->aux_output_mask;
@@ -134,13 +201,13 @@ 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, off + pll_user_ctl(type), mask, val);
if (pll->flags & SUPPORTS_FSM_MODE)
qcom_pll_set_fsm_mode(regmap, off, 6, 0);
}
-static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+static int alpha_pll_default_hwfsm_enable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
int ret;
@@ -165,7 +232,7 @@ static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
return wait_for_pll_enable_active(pll);
}
-static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+static void alpha_pll_default_hwfsm_disable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
int ret;
@@ -208,17 +275,17 @@ static int pll_is_enabled(struct clk_hw *hw, u32 mask)
return !!(val & mask);
}
-static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
+static int alpha_pll_default_hwfsm_is_enabled(struct clk_hw *hw)
{
return pll_is_enabled(hw, PLL_ACTIVE_FLAG);
}
-static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
+static int alpha_pll_default_is_enabled(struct clk_hw *hw)
{
return pll_is_enabled(hw, PLL_LOCK_DET);
}
-static int clk_alpha_pll_enable(struct clk_hw *hw)
+static int alpha_pll_default_enable(struct clk_hw *hw)
{
int ret;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
@@ -270,7 +337,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
return ret;
}
-static void clk_alpha_pll_disable(struct clk_hw *hw)
+static void alpha_pll_default_disable(struct clk_hw *hw)
{
int ret;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
@@ -342,22 +409,23 @@ 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)
+alpha_pll_default_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 off = pll->offset;
+ u8 type = pll->pll_type;
- regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
+ regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
- regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
+ regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
if (ctl & PLL_ALPHA_EN) {
- regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
+ regmap_read(pll->clkr.regmap, off + pll_alpha(type), &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, off + pll_alpha_u(type),
&high);
a = (u64)high << 32 | low;
a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
@@ -367,12 +435,13 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
return alpha_pll_calc_rate(prate, l, a);
}
-static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long prate)
+static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
const struct pll_vco *vco;
u32 l, off = pll->offset;
+ u8 type = pll->pll_type;
u64 a;
rate = alpha_pll_round_rate(rate, prate, &l, &a);
@@ -382,28 +451,29 @@ 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, off + pll_l(type), l);
if (pll->flags & SUPPORTS_16BIT_ALPHA) {
- regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL,
+ regmap_write(pll->clkr.regmap, off + pll_alpha(type),
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, off + pll_alpha_u(type),
+ a >> 32);
}
- regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+ regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
PLL_VCO_MASK << PLL_VCO_SHIFT,
vco->val << PLL_VCO_SHIFT);
- regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
- PLL_ALPHA_EN);
+ regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ PLL_ALPHA_EN, PLL_ALPHA_EN);
return 0;
}
-static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
u32 l;
@@ -420,6 +490,54 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
return clamp(rate, min_freq, max_freq);
}
+static int clk_alpha_pll_enable(struct clk_hw *hw)
+{
+ return pll_clk_ops(hw).enable(hw);
+}
+
+static void clk_alpha_pll_disable(struct clk_hw *hw)
+{
+ pll_clk_ops(hw).disable(hw);
+}
+
+static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
+{
+ return pll_clk_ops(hw).is_enabled(hw);
+}
+
+static unsigned long
+clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ return pll_clk_ops(hw).recalc_rate(hw, parent_rate);
+}
+
+static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ return pll_clk_ops(hw).round_rate(hw, rate, prate);
+}
+
+static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate)
+{
+ return pll_clk_ops(hw).set_rate(hw, rate, prate);
+}
+
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+{
+ return pll_clk_ops(hw).hwfsm_enable(hw);
+}
+
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+{
+ pll_clk_ops(hw).hwfsm_disable(hw);
+}
+
+static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
+{
+ return pll_clk_ops(hw).hwfsm_is_enabled(hw);
+}
+
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
@@ -446,7 +564,8 @@ 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->offset + pll_user_ctl(pll->pll_type),
+ &ctl);
ctl >>= PLL_POST_DIV_SHIFT;
ctl &= PLL_POST_DIV_MASK;
@@ -482,7 +601,8 @@ 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->offset +
+ pll_user_ctl(pll->pll_type),
PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
div << PLL_POST_DIV_SHIFT);
}
@@ -493,3 +613,32 @@ 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);
+
+/* Contains actual property values for different PLL types */
+static const struct
+alpha_pll_props alpha_pll_props[CLK_ALPHA_PLL_TYPE_MAX] = {
+ [CLK_ALPHA_PLL_TYPE_DEFAULT] = {
+ .reg_offsets = {
+ [PLL_L_VAL] = 0x04,
+ [PLL_ALPHA_VAL] = 0x08,
+ [PLL_ALPHA_VAL_U] = 0x0c,
+ [PLL_USER_CTL] = 0x10,
+ [PLL_USER_CTL_U] = 0x14,
+ [PLL_CONFIG_CTL] = 0x18,
+ [PLL_TEST_CTL] = 0x1c,
+ [PLL_TEST_CTL_U] = 0x20,
+ [PLL_STATUS] = 0x24,
+ },
+ .ops = {
+ .enable = alpha_pll_default_enable,
+ .disable = alpha_pll_default_disable,
+ .is_enabled = alpha_pll_default_is_enabled,
+ .hwfsm_enable = alpha_pll_default_hwfsm_enable,
+ .hwfsm_disable = alpha_pll_default_hwfsm_disable,
+ .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
+ .recalc_rate = alpha_pll_default_recalc_rate,
+ .round_rate = alpha_pll_default_round_rate,
+ .set_rate = alpha_pll_default_set_rate,
+ },
+ },
+};
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index d6e1ee2..4c91fbc 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -17,6 +17,12 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
+/* Alpha PLL types */
+enum {
+ CLK_ALPHA_PLL_TYPE_DEFAULT,
+ CLK_ALPHA_PLL_TYPE_MAX,
+};
+
struct pll_vco {
unsigned long min_freq;
unsigned long max_freq;
@@ -27,6 +33,7 @@ struct pll_vco {
* struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers
* @vco_table: array of VCO settings
+ * @pll_type: alpha pll type
* @clkr: regmap clock handle
*/
struct clk_alpha_pll {
@@ -38,6 +45,7 @@ struct clk_alpha_pll {
#define SUPPORTS_16BIT_ALPHA BIT(1)
#define SUPPORTS_FSM_MODE BIT(2)
u8 flags;
+ u8 pll_type;
struct clk_regmap clkr;
};
@@ -45,11 +53,13 @@ struct clk_alpha_pll {
/**
* struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
* @offset: base address of registers
+ * @pll_type: alpha pll type
* @width: width of post-divider
* @clkr: regmap clock handle
*/
struct clk_alpha_pll_postdiv {
u32 offset;
+ u8 pll_type;
u8 width;
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
Currently SUPPORTS_16BIT_ALPHA flag determines the PLL alpha
register width. If this flag is set then the alpha register width
is 16 bits otherwise it is 40 bits. The alpha width is always
fixed for PLL type so it can be added in PLL properties and clock
driver don’t have to specify explicitly.
The SUPPORTS_16BIT_ALPHA flag is unused in the current code so
it’s safe to remove this flags.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 16 ++++++++--------
drivers/clk/qcom/clk-alpha-pll.h | 3 +--
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index a12f7b4..78eb6bf 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -44,13 +44,10 @@
/*
* 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
-/* Returns the Alpha register width for pll */
-#define pll_alpha_width(pll) (pll->flags & SUPPORTS_16BIT_ALPHA ? \
- ALPHA_REG_16BIT_WIDTH : ALPHA_REG_BITWIDTH)
+/* Returns the Alpha register width for pll type */
+#define pll_alpha_width(type) (alpha_pll_props[type].alpha_width)
/* Returns the alpha_pll_clk_ops for pll type */
#define pll_clk_ops(hw) (alpha_pll_props[to_clk_alpha_pll(hw)-> \
@@ -127,10 +124,12 @@ struct alpha_pll_clk_ops {
* struct alpha_pll_props - contains the various properties which
* will be fixed for PLL type.
* @reg_offsets: register offsets mapping array
+ * @alpha_width: alpha value width
* @ops: clock operations for alpha PLL
*/
struct alpha_pll_props {
u8 reg_offsets[PLL_MAX_REGS];
+ u8 alpha_width;
struct alpha_pll_clk_ops ops;
};
@@ -423,8 +422,8 @@ static void alpha_pll_default_disable(struct clk_hw *hw)
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, alpha_width = pll_alpha_width(pll);
u8 type = pll->pll_type;
+ u32 off = pll->offset, alpha_width = pll_alpha_width(type);
regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
@@ -451,8 +450,8 @@ static int alpha_pll_default_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, alpha_width = pll_alpha_width(pll);
u8 type = pll->pll_type;
+ u32 l, off = pll->offset, alpha_width = pll_alpha_width(type);
u64 a;
rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
@@ -487,7 +486,7 @@ static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
- u32 l, alpha_width = pll_alpha_width(pll);
+ u32 l, alpha_width = pll_alpha_width(pll->pll_type);
u64 a;
unsigned long min_freq, max_freq;
@@ -640,6 +639,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
[PLL_TEST_CTL_U] = 0x20,
[PLL_STATUS] = 0x24,
},
+ .alpha_width = 40,
.ops = {
.enable = alpha_pll_default_enable,
.disable = alpha_pll_default_disable,
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 4c91fbc..b9caefc 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -42,8 +42,7 @@ 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_FSM_MODE BIT(1)
u8 flags;
u8 pll_type;
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
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: Rajendra Nayak <[email protected]>
Signed-off-by: Taniya Das <[email protected]>
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 69 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 07030d3..6f2d165 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)
@@ -134,7 +137,8 @@ struct alpha_pll_props {
u8 reg_offsets[PLL_MAX_REGS];
u8 alpha_width;
-#define HAVE_64BIT_CONFIG_CTL BIT(0)
+#define HAVE_64BIT_CONFIG_CTL BIT(0)
+#define SUPPORTS_DYNAMIC_UPDATE BIT(1)
u8 flags;
struct alpha_pll_clk_ops ops;
};
@@ -181,6 +185,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)
{
@@ -461,6 +474,54 @@ static void alpha_pll_default_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 ret;
+ u32 mode, off = pll->offset;
+
+ regmap_read(pll->clkr.regmap, off, &mode);
+
+ /* Latch the input to the PLL */
+ regmap_update_bits(pll->clkr.regmap, off, PLL_UPDATE, PLL_UPDATE);
+
+ /* Make sure PLL_UPDATE request goes through*/
+ mb();
+
+ /* Wait for 2 reference cycle before checking ACK bit */
+ udelay(1);
+
+ /*
+ * 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) {
+ ret = wait_for_pll_update_ack_set(pll);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(pll->clkr.regmap, off, PLL_UPDATE, 0);
+
+ /* Make sure PLL_UPDATE request goes through*/
+ mb();
+ } else {
+ ret = wait_for_pll_update(pll);
+ if (ret)
+ return ret;
+ }
+
+ ret = wait_for_pll_update_ack_clear(pll);
+ if (ret)
+ return ret;
+
+ /* Wait for PLL output to stabilize */
+ udelay(10);
+
+ return 0;
+}
+
static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
@@ -495,7 +556,11 @@ static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
PLL_ALPHA_EN, PLL_ALPHA_EN);
- return 0;
+ if (!clk_hw_is_enabled(hw) ||
+ !(pll_flags(type) & SUPPORTS_DYNAMIC_UPDATE))
+ return 0;
+
+ return clk_alpha_pll_update_latch(pll);
}
static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
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 from other Alpha PLL’s so this patch
made adds separate functions for Huayra PLL.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 184 +++++++++++++++++++++++++++++++++++++++
drivers/clk/qcom/clk-alpha-pll.h | 1 +
2 files changed, 185 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index bb35c60..4844e63 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.
*/
@@ -585,6 +593,157 @@ static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
return clamp(rate, min_freq, max_freq);
}
+static unsigned long
+alpha_huayra_pll_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_huayra_pll_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_huayra_pll_calc_rate(prate, *l, *a);
+}
+
+static unsigned long
+alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ u64 rate = parent_rate, tmp;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u8 type = pll->pll_type;
+ u32 l, alpha = 0, ctl, alpha_m, alpha_n, off = pll->offset;
+
+ regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
+ regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
+
+ if (ctl & PLL_ALPHA_EN) {
+ regmap_read(pll->clkr.regmap, off + pll_alpha(type), &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_huayra_pll_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_huayra_pll_calc_rate(rate, l, alpha);
+}
+
+static int 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);
+ u8 type = pll->pll_type;
+ u32 l, a, ctl, cur_alpha = 0, off = pll->offset;
+
+ rate = alpha_huayra_pll_round_rate(rate, prate, &l, &a);
+
+ regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
+
+ if (ctl & PLL_ALPHA_EN)
+ regmap_read(pll->clkr.regmap, off + pll_alpha(type),
+ &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, off + pll_l(type), 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, off + pll_l(type), l);
+ regmap_write(pll->clkr.regmap, off + pll_alpha(type), a);
+
+ if (a == 0)
+ regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ PLL_ALPHA_EN, 0x0);
+ else
+ regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ PLL_ALPHA_EN | PLL_ALPHA_MODE, PLL_ALPHA_EN);
+
+ return 0;
+}
+
+static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ u32 l, a;
+
+ return alpha_huayra_pll_round_rate(rate, *prate, &l, &a);
+}
+
static int clk_alpha_pll_enable(struct clk_hw *hw)
{
return pll_clk_ops(hw).enable(hw);
@@ -738,4 +897,29 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
.set_rate = alpha_pll_default_set_rate,
},
},
+ [CLK_ALPHA_PLL_TYPE_HUAYRA] = {
+ .reg_offsets = {
+ [PLL_L_VAL] = 0x04,
+ [PLL_ALPHA_VAL] = 0x08,
+ [PLL_USER_CTL] = 0x10,
+ [PLL_CONFIG_CTL] = 0x14,
+ [PLL_CONFIG_CTL_U] = 0x18,
+ [PLL_TEST_CTL] = 0x1c,
+ [PLL_TEST_CTL_U] = 0x20,
+ [PLL_STATUS] = 0x24,
+ },
+ .alpha_width = 16,
+ .flags = SUPPORTS_DYNAMIC_UPDATE | HAVE_64BIT_CONFIG_CTL,
+ .ops = {
+ .enable = alpha_pll_default_enable,
+ .disable = alpha_pll_default_disable,
+ .is_enabled = alpha_pll_default_is_enabled,
+ .hwfsm_enable = alpha_pll_default_hwfsm_enable,
+ .hwfsm_disable = alpha_pll_default_hwfsm_disable,
+ .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
+ .recalc_rate = alpha_pll_huayra_recalc_rate,
+ .round_rate = alpha_pll_huayra_round_rate,
+ .set_rate = alpha_pll_huayra_set_rate,
+ },
+ },
};
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 17aa27c..fed783e 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -20,6 +20,7 @@
/* Alpha PLL types */
enum {
CLK_ALPHA_PLL_TYPE_DEFAULT,
+ CLK_ALPHA_PLL_TYPE_HUAYRA,
CLK_ALPHA_PLL_TYPE_MAX,
};
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Current PLL driver only supports 4 bit PLL post divider so
modified the PLL divider operations to support 2 bit PLL
post divider.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index c682387..62b84fa 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -39,7 +39,6 @@
# define PLL_LOCK_DET BIT(31)
# 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
@@ -822,7 +821,7 @@ static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
&ctl);
ctl >>= PLL_POST_DIV_SHIFT;
- ctl &= PLL_POST_DIV_MASK;
+ ctl &= BIT(pll->width) - 1;
return parent_rate >> fls(ctl);
}
@@ -836,13 +835,26 @@ static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
{ }
};
+static const struct clk_div_table clk_alpha_2bit_div_table[] = {
+ { 0x0, 1 },
+ { 0x1, 2 },
+ { 0x3, 4 },
+ { }
+};
+
static long
clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
+ const struct clk_div_table *table;
- return divider_round_rate(hw, rate, prate, clk_alpha_div_table,
+ if (pll->width == 2)
+ table = clk_alpha_2bit_div_table;
+ else
+ table = clk_alpha_div_table;
+
+ return divider_round_rate(hw, rate, prate, table,
pll->width, CLK_DIVIDER_POWER_OF_TWO);
}
@@ -857,7 +869,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
return regmap_update_bits(pll->clkr.regmap, pll->offset +
pll_user_ctl(pll->pll_type),
- PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
+ (BIT(pll->width) - 1) << PLL_POST_DIV_SHIFT,
div << PLL_POST_DIV_SHIFT);
}
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
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 <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 6 ++++++
drivers/clk/qcom/clk-alpha-pll.h | 3 +++
2 files changed, 9 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index b33d120..07030d3 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -198,6 +198,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
regmap_write(regmap, off + pll_cfg_ctl_u(type),
config->config_ctl_hi_val);
+ if (pll_alpha_width(type) > 32)
+ regmap_write(regmap, off + pll_alpha_u(type),
+ config->alpha_hi);
+
val = config->main_output_mask;
val |= config->aux_output_mask;
val |= config->aux2_output_mask;
@@ -205,6 +209,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 b9caefc..17aa27c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -67,12 +67,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
1. Brammo PLL does not allow configuration of VCO
2. Supports the dynamic update in which the frequency can
be changed dynamically without turning off the PLL
3. The register offsets are different from normal Alpha PLL
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 24 ++++++++++++++++++++++++
drivers/clk/qcom/clk-alpha-pll.h | 1 +
2 files changed, 25 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 4844e63..c682387 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -922,4 +922,28 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
.set_rate = alpha_pll_huayra_set_rate,
},
},
+ [CLK_ALPHA_PLL_TYPE_BRAMMO] = {
+ .reg_offsets = {
+ [PLL_L_VAL] = 0x04,
+ [PLL_ALPHA_VAL] = 0x08,
+ [PLL_ALPHA_VAL_U] = 0x0c,
+ [PLL_USER_CTL] = 0x10,
+ [PLL_CONFIG_CTL] = 0x18,
+ [PLL_TEST_CTL] = 0x1c,
+ [PLL_STATUS] = 0x24,
+ },
+ .alpha_width = 40,
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .ops = {
+ .enable = alpha_pll_default_enable,
+ .disable = alpha_pll_default_disable,
+ .is_enabled = alpha_pll_default_is_enabled,
+ .hwfsm_enable = alpha_pll_default_hwfsm_enable,
+ .hwfsm_disable = alpha_pll_default_hwfsm_disable,
+ .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
+ .recalc_rate = alpha_pll_default_recalc_rate,
+ .round_rate = alpha_pll_default_round_rate,
+ .set_rate = alpha_pll_default_set_rate,
+ },
+ },
};
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index fed783e..dee71b4 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -21,6 +21,7 @@
enum {
CLK_ALPHA_PLL_TYPE_DEFAULT,
CLK_ALPHA_PLL_TYPE_HUAYRA,
+ CLK_ALPHA_PLL_TYPE_BRAMMO,
CLK_ALPHA_PLL_TYPE_MAX,
};
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Some of the Alpha PLL’s (like Spark, Brammo PLL) do not have
CONFIG_CTL_U register. This patch adds the flag in properties
for PLL’s which have CONFIG_CTL_U register and checks the same
while doing PLL initial configuration.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 78eb6bf..b33d120 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -49,6 +49,9 @@
/* Returns the Alpha register width for pll type */
#define pll_alpha_width(type) (alpha_pll_props[type].alpha_width)
+/* Returns the flags for pll type */
+#define pll_flags(type) (alpha_pll_props[type].flags)
+
/* Returns the alpha_pll_clk_ops for pll type */
#define pll_clk_ops(hw) (alpha_pll_props[to_clk_alpha_pll(hw)-> \
pll_type].ops)
@@ -130,6 +133,9 @@ struct alpha_pll_clk_ops {
struct alpha_pll_props {
u8 reg_offsets[PLL_MAX_REGS];
u8 alpha_width;
+
+#define HAVE_64BIT_CONFIG_CTL BIT(0)
+ u8 flags;
struct alpha_pll_clk_ops ops;
};
@@ -180,7 +186,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
{
u32 val, mask;
u32 off = pll->offset;
- u8 type = pll->pll_type;
+ u8 type = pll->pll_type, flags = pll_flags(type);
regmap_write(regmap, off + pll_l(type), config->l);
regmap_write(regmap, off + pll_alpha(type), config->alpha);
@@ -188,6 +194,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
regmap_write(regmap, off + pll_cfg_ctl_u(type),
config->config_ctl_hi_val);
+ if (flags & HAVE_64BIT_CONFIG_CTL)
+ regmap_write(regmap, off + pll_cfg_ctl_u(type),
+ config->config_ctl_hi_val);
+
val = config->main_output_mask;
val |= config->aux_output_mask;
val |= config->aux2_output_mask;
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
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 <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 26 ++++++++++++++++++++++++++
drivers/clk/qcom/clk-alpha-pll.h | 1 +
2 files changed, 27 insertions(+)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 62b84fa..443fd0b 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -858,6 +858,26 @@ static int clk_alpha_pll_hwfsm_is_enabled(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->offset + pll_user_ctl(pll->pll_type),
+ &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)
{
@@ -880,6 +900,12 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long 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);
+
/* Contains actual property values for different PLL types */
static const struct
alpha_pll_props alpha_pll_props[CLK_ALPHA_PLL_TYPE_MAX] = {
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index dee71b4..a9f8751 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -89,6 +89,7 @@ struct alpha_pll_config {
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;
+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
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 <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 6f2d165..bb35c60 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -139,6 +139,7 @@ struct alpha_pll_props {
#define HAVE_64BIT_CONFIG_CTL BIT(0)
#define SUPPORTS_DYNAMIC_UPDATE BIT(1)
+#define SUPPORTS_VCO BIT(2)
u8 flags;
struct alpha_pll_clk_ops ops;
};
@@ -527,15 +528,17 @@ static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
const struct pll_vco *vco;
- u8 type = pll->pll_type;
+ u8 type = pll->pll_type, flags = pll_flags(type);
u32 l, off = pll->offset, alpha_width = pll_alpha_width(type);
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 (flags & SUPPORTS_VCO) {
+ 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, off + pll_l(type), l);
@@ -549,15 +552,15 @@ static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
regmap_write(pll->clkr.regmap, off + pll_alpha(type), a);
- regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
- PLL_VCO_MASK << PLL_VCO_SHIFT,
- vco->val << PLL_VCO_SHIFT);
+ if (flags & SUPPORTS_VCO)
+ regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ PLL_VCO_MASK << PLL_VCO_SHIFT,
+ vco->val << PLL_VCO_SHIFT);
regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
PLL_ALPHA_EN, PLL_ALPHA_EN);
- if (!clk_hw_is_enabled(hw) ||
- !(pll_flags(type) & SUPPORTS_DYNAMIC_UPDATE))
+ if (!clk_hw_is_enabled(hw) || !(flags & SUPPORTS_DYNAMIC_UPDATE))
return 0;
return clk_alpha_pll_update_latch(pll);
@@ -567,12 +570,13 @@ static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
- u32 l, alpha_width = pll_alpha_width(pll->pll_type);
+ u8 type = pll->pll_type;
+ u32 l, alpha_width = pll_alpha_width(type);
u64 a;
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(type) & SUPPORTS_VCO) || alpha_pll_find_vco(pll, rate))
return rate;
min_freq = pll->vco_table[0].min_freq;
@@ -721,6 +725,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
[PLL_STATUS] = 0x24,
},
.alpha_width = 40,
+ .flags = SUPPORTS_VCO,
.ops = {
.enable = alpha_pll_default_enable,
.disable = alpha_pll_default_disable,
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
The alpha value calculation function has been written for 40 bit
alpha which is not coming properly for 16 bit
1. Alpha value is being calculated on the basis of
ALPHA_BITWIDTH to make the computation easy for 40 bit alpha.
After calculating the 32 bit alpha, It is being converted to 40
bit alpha by making making lower bits zero. But if actual alpha
register width is less than ALPHA_BITWIDTH, then the actual width
can be used for calculation
2. During 40 bit alpha pll set rate, the lower alpha register is
not being configured
Now the changes have been made to calculate the rate and register
values from alpha_width instead hardcoding it so that it can work
for all the cases.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 55 ++++++++++++++++++++++++----------------
1 file changed, 33 insertions(+), 22 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index d5bfc52..a12f7b4 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -45,8 +45,12 @@
* 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
+
+/* Returns the Alpha register width for pll */
+#define pll_alpha_width(pll) (pll->flags & SUPPORTS_16BIT_ALPHA ? \
+ ALPHA_REG_16BIT_WIDTH : ALPHA_REG_BITWIDTH)
/* Returns the alpha_pll_clk_ops for pll type */
#define pll_clk_ops(hw) (alpha_pll_props[to_clk_alpha_pll(hw)-> \
@@ -364,13 +368,16 @@ static void alpha_pll_default_disable(struct clk_hw *hw)
regmap_update_bits(pll->clkr.regmap, off, 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_width : ALPHA_BITWIDTH));
}
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;
@@ -385,14 +392,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_width : ALPHA_BITWIDTH);
+
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 *
@@ -414,7 +423,7 @@ 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;
+ u32 off = pll->offset, alpha_width = pll_alpha_width(pll);
u8 type = pll->pll_type;
regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
@@ -422,17 +431,19 @@ static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
if (ctl & PLL_ALPHA_EN) {
regmap_read(pll->clkr.regmap, off + pll_alpha(type), &low);
- if (pll->flags & SUPPORTS_16BIT_ALPHA) {
- a = low & ALPHA_16BIT_MASK;
- } else {
+ if (alpha_width > 32) {
regmap_read(pll->clkr.regmap, off + pll_alpha_u(type),
&high);
a = (u64)high << 32 | low;
- a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+ } else {
+ a = low & GENMASK(alpha_width - 1, 0);
}
+
+ if (alpha_width > ALPHA_BITWIDTH)
+ a >>= alpha_width - ALPHA_BITWIDTH;
}
- return alpha_pll_calc_rate(prate, l, a);
+ return alpha_pll_calc_rate(prate, l, a, alpha_width);
}
static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -440,11 +451,11 @@ static int alpha_pll_default_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, off = pll->offset, alpha_width = pll_alpha_width(pll);
u8 type = pll->pll_type;
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");
@@ -453,14 +464,14 @@ static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
regmap_write(pll->clkr.regmap, off + pll_l(type), l);
- if (pll->flags & SUPPORTS_16BIT_ALPHA) {
- regmap_write(pll->clkr.regmap, off + pll_alpha(type),
- a & ALPHA_16BIT_MASK);
- } else {
- a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+ if (alpha_width > ALPHA_BITWIDTH)
+ a <<= alpha_width - ALPHA_BITWIDTH;
+
+ if (alpha_width > 32)
regmap_write(pll->clkr.regmap, off + pll_alpha_u(type),
a >> 32);
- }
+
+ regmap_write(pll->clkr.regmap, off + pll_alpha(type), a);
regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
PLL_VCO_MASK << PLL_VCO_SHIFT,
@@ -476,11 +487,11 @@ static long alpha_pll_default_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
The PLL_MODE offset macro is redundant which is defined as zero.
The offset in PLL structure is the address of PLL_MODE register
itself so the PLL_MODE can be removed. It will help in subsequent
patches to support different PLL offset registers to reduce the
code diff.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 47a1da3..b9be822 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)
@@ -77,12 +76,12 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
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, off, &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, off, &val);
if (ret)
return ret;
if (inverse && !(val & mask))
@@ -139,7 +138,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
regmap_update_bits(regmap, off + PLL_USER_CTL, 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, off, 6, 0);
}
static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
@@ -149,7 +148,7 @@ static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
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, off, &val);
if (ret)
return ret;
@@ -158,7 +157,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, off, val);
if (ret)
return ret;
@@ -175,12 +174,12 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
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, off, &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, off,
PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
if (ret)
return;
@@ -191,7 +190,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, off,
PLL_FSM_ENA, 0);
if (ret)
return;
@@ -206,7 +205,7 @@ static int pll_is_enabled(struct clk_hw *hw, u32 mask)
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, off, &val);
if (ret)
return ret;
@@ -232,7 +231,7 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
off = pll->offset;
mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
- ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+ ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return ret;
@@ -248,7 +247,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, off,
PLL_BYPASSNL, PLL_BYPASSNL);
if (ret)
return ret;
@@ -260,7 +259,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, off,
PLL_RESET_N, PLL_RESET_N);
if (ret)
return ret;
@@ -269,7 +268,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, off,
PLL_OUTCTRL, PLL_OUTCTRL);
/* Ensure that the write above goes through before returning. */
@@ -285,7 +284,7 @@ static void clk_alpha_pll_disable(struct clk_hw *hw)
off = pll->offset;
- ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+ ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return;
@@ -296,14 +295,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, off, 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, off, mask, 0);
}
static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
This patch does minor code reorganization related with offset
variable assignment. The offset variable can be directly defined
which will help in subsequent patches to support different PLL
offset registers.
Signed-off-by: Abhishek Sahu <[email protected]>
---
drivers/clk/qcom/clk-alpha-pll.c | 26 +++++++++-----------------
1 file changed, 9 insertions(+), 17 deletions(-)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index b9be822..ab2f23c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -70,12 +70,11 @@
static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
const char *action)
{
- u32 val, off;
+ u32 val, off = pll->offset;
int count;
int ret;
const char *name = clk_hw_get_name(&pll->clkr.hw);
- off = pll->offset;
ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return ret;
@@ -143,11 +142,10 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
{
- int ret;
- u32 val, off;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ int ret;
+ u32 val, off = pll->offset;
- off = pll->offset;
ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return ret;
@@ -169,11 +167,10 @@ 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;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ int ret;
+ u32 val, off = pll->offset;
- off = pll->offset;
ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return;
@@ -200,11 +197,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;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ int ret;
+ u32 val, off = pll->offset;
- off = pll->offset;
ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
return ret;
@@ -226,9 +222,7 @@ 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, off = pll->offset;
mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
ret = regmap_read(pll->clkr.regmap, off, &val);
@@ -280,9 +274,7 @@ 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, off = pll->offset;
ret = regmap_read(pll->clkr.regmap, off, &val);
if (ret)
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
On 09/28, Abhishek Sahu wrote:
> This patch series does the miscellaneous changes in QCOM Alpha PLL
> operation and structure to support other types of Alpha PLL’s.
>
> 1. It adds the pll_type which will be used for determining all
> the properties of Alpha PLL.
> 2. It adds the support for Brammo and Huayra PLL’s for which
> the support is not available in existing alpha PLL code.
> 3. There won’t be any change in existing users of Alpha PLL’s
> since all the newly added code will be under flag for the default
> PLL operations.
>
Ok. I took a long look at this today. I rewrote a bunch of stuff.
Let me know if anything looks wrong. I'm not really interested in
having a type template design that causes us to jump through one
clk op to another set of them. I'd rather keep it flatter. I also
kept around the macros for the offsets and had it use a register
map in each struct instead. Yes, we have to go modify the PLL
types to point to the right register offset, but really that's
fine and I don't really care. We could have a default fallback
when the reg pointer is NULL, but I'm not sure that is useful.
The alternative is to make a bunch of new ops structures that
passes it down into the final functions but that seemed like more
work for the handful of PLLs we have to worry about. You seem to
agree here. All told, it got cut down by 100 lines so the patches
got smaller.
---8<----
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 443fd0b85e41..ad7478bf1655 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -20,6 +20,7 @@
#include "clk-alpha-pll.h"
#include "common.h"
+#define PLL_MODE(p) ((p)->offset + 0x0)
# define PLL_OUTCTRL BIT(0)
# define PLL_BYPASSNL BIT(1)
# define PLL_RESET_N BIT(2)
@@ -38,12 +39,67 @@
# define PLL_ACTIVE_FLAG BIT(30)
# define PLL_LOCK_DET BIT(31)
+#define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL])
+#define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL])
+#define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U])
+
+#define PLL_USER_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL])
# define PLL_POST_DIV_SHIFT 8
+# define PLL_POST_DIV_MASK(p) GENMASK((p)->width, 0)
# define PLL_ALPHA_EN BIT(24)
# define PLL_ALPHA_MODE BIT(25)
# define PLL_VCO_SHIFT 20
# define PLL_VCO_MASK 0x3
+#define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U])
+
+#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL])
+#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U])
+#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])
+
+const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
+ [CLK_ALPHA_PLL_TYPE_DEFAULT] = {
+ [PLL_OFF_L_VAL] = 0x04,
+ [PLL_OFF_ALPHA_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL_U] = 0x0c,
+ [PLL_OFF_USER_CTL] = 0x10,
+ [PLL_OFF_USER_CTL_U] = 0x14,
+ [PLL_OFF_CONFIG_CTL] = 0x18,
+ [PLL_OFF_TEST_CTL] = 0x1c,
+ [PLL_OFF_TEST_CTL_U] = 0x20,
+ [PLL_OFF_STATUS] = 0x24,
+ },
+ [CLK_ALPHA_PLL_TYPE_HUAYRA] = {
+ [PLL_OFF_L_VAL] = 0x04,
+ [PLL_OFF_ALPHA_VAL] = 0x08,
+ [PLL_OFF_USER_CTL] = 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,
+ },
+ [CLK_ALPHA_PLL_TYPE_BRAMMO] = {
+ [PLL_OFF_L_VAL] = 0x04,
+ [PLL_OFF_ALPHA_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL_U] = 0x0c,
+ [PLL_OFF_USER_CTL] = 0x10,
+ [PLL_OFF_CONFIG_CTL] = 0x18,
+ [PLL_OFF_TEST_CTL] = 0x1c,
+ [PLL_OFF_STATUS] = 0x24,
+ },
+};
+
+/*
+ * 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 32U
+#define ALPHA_SHIFT(w) min(w, ALPHA_BITWIDTH)
+
#define PLL_HUAYRA_M_WIDTH 8
#define PLL_HUAYRA_M_SHIFT 8
#define PLL_HUAYRA_M_MASK 0xff
@@ -51,35 +107,11 @@
#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.
- */
-#define ALPHA_BITWIDTH 32
-
-/* Returns the Alpha register width for pll type */
-#define pll_alpha_width(type) (alpha_pll_props[type].alpha_width)
-
-/* Returns the flags for pll type */
-#define pll_flags(type) (alpha_pll_props[type].flags)
-
-/* Returns the alpha_pll_clk_ops for pll type */
-#define pll_clk_ops(hw) (alpha_pll_props[to_clk_alpha_pll(hw)-> \
- pll_type].ops)
+#define pll_alpha_width(p) \
+ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
+ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
-/* Returns the actual register offset for the reg crossponding to pll type */
-#define pll_reg(type, reg) alpha_pll_props[type].reg_offsets[reg]
-
-/* Helpers to return the actual register offset */
-#define pll_l(type) pll_reg(type, PLL_L_VAL)
-#define pll_alpha(type) pll_reg(type, PLL_ALPHA_VAL)
-#define pll_alpha_u(type) pll_reg(type, PLL_ALPHA_VAL_U)
-#define pll_user_ctl(type) pll_reg(type, PLL_USER_CTL)
-#define pll_user_ctl_u(type) pll_reg(type, PLL_USER_CTL_U)
-#define pll_cfg_ctl(type) pll_reg(type, PLL_CONFIG_CTL)
-#define pll_test_ctl(type) pll_reg(type, PLL_TEST_CTL)
-#define pll_test_ctl_u(type) pll_reg(type, PLL_TEST_CTL_U)
-#define pll_status(type) pll_reg(type, PLL_STATUS)
-#define pll_cfg_ctl_u(type) pll_reg(type, PLL_CONFIG_CTL_U)
+#define pll_has_64bit_config(p) ((PLL_CONFIG_CTL_U(p) - PLL_CONFIG_CTL(p)) == 4)
#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
struct clk_alpha_pll, clkr)
@@ -87,86 +119,20 @@
#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
struct clk_alpha_pll_postdiv, clkr)
-/**
- * Contains the index which will be used for mapping with actual
- * register offset in Alpha PLL
- */
-enum {
- PLL_L_VAL,
- PLL_ALPHA_VAL,
- PLL_ALPHA_VAL_U,
- PLL_USER_CTL,
- PLL_USER_CTL_U,
- PLL_CONFIG_CTL,
- PLL_CONFIG_CTL_U,
- PLL_TEST_CTL,
- PLL_TEST_CTL_U,
- PLL_STATUS,
- PLL_MAX_REGS,
-};
-
-/**
- * struct alpha_pll_clk_ops - operations for alpha PLL
- * @enable: enable function when HW voting FSM is disabled
- * @disable: disable function when HW voting FSM is disabled
- * @is_enabled: check whether PLL is enabled when HW voting FSM is disabled
- * @hwfsm_enable: check whether PLL is enabled when HW voting FSM is enabled
- * @hwfsm_disable: check whether PLL is disabled when HW voting FSM is enabled
- * @hwfsm_is_enabled: check whether PLL is enabled when HW voting FSM is enabled
- * @recalc_rate: recalculate the rate of PLL by reading mode, L and Alpha Value
- * @round_rate: returns the closest supported rate of PLL
- * @set_rate: change the rate of this clock by actually programming the mode, L
- * and Alpha Value registers
- */
-struct alpha_pll_clk_ops {
- int (*enable)(struct clk_hw *hw);
- void (*disable)(struct clk_hw *hw);
- int (*is_enabled)(struct clk_hw *hw);
- int (*hwfsm_enable)(struct clk_hw *hw);
- void (*hwfsm_disable)(struct clk_hw *hw);
- int (*hwfsm_is_enabled)(struct clk_hw *hw);
- unsigned long (*recalc_rate)(struct clk_hw *hw,
- unsigned long parent_rate);
- long (*round_rate)(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate);
- int (*set_rate)(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate);
-};
-
-/**
- * struct alpha_pll_props - contains the various properties which
- * will be fixed for PLL type.
- * @reg_offsets: register offsets mapping array
- * @alpha_width: alpha value width
- * @ops: clock operations for alpha PLL
- */
-struct alpha_pll_props {
- u8 reg_offsets[PLL_MAX_REGS];
- u8 alpha_width;
-
-#define HAVE_64BIT_CONFIG_CTL BIT(0)
-#define SUPPORTS_DYNAMIC_UPDATE BIT(1)
-#define SUPPORTS_VCO BIT(2)
- u8 flags;
- struct alpha_pll_clk_ops ops;
-};
-
-static const struct alpha_pll_props alpha_pll_props[];
-
static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
const char *action)
{
- u32 val, off = pll->offset;
+ u32 val;
int count;
int ret;
const char *name = clk_hw_get_name(&pll->clkr.hw);
- ret = regmap_read(pll->clkr.regmap, off, &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, &val);
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
if (inverse && !(val & mask))
@@ -206,22 +172,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;
- u8 type = pll->pll_type, flags = pll_flags(type);
- regmap_write(regmap, off + pll_l(type), config->l);
- regmap_write(regmap, off + pll_alpha(type), config->alpha);
- regmap_write(regmap, off + pll_cfg_ctl(type), config->config_ctl_val);
- regmap_write(regmap, off + pll_cfg_ctl_u(type),
- config->config_ctl_hi_val);
+ regmap_write(regmap, PLL_L_VAL(pll), config->l);
+ regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+ regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);
- if (flags & HAVE_64BIT_CONFIG_CTL)
- regmap_write(regmap, off + pll_cfg_ctl_u(type),
+ if (pll_has_64bit_config(pll))
+ regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
config->config_ctl_hi_val);
- if (pll_alpha_width(type) > 32)
- regmap_write(regmap, off + pll_alpha_u(type),
- config->alpha_hi);
+ if (pll_alpha_width(pll) > 32)
+ regmap_write(regmap, PLL_ALPHA_VAL_U(pll), config->alpha_hi);
val = config->main_output_mask;
val |= config->aux_output_mask;
@@ -241,19 +202,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(type), 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, 6, 0);
+ qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0);
}
-static int alpha_pll_default_hwfsm_enable(struct clk_hw *hw)
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
{
- struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
int ret;
- u32 val, off = pll->offset;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 val;
- ret = regmap_read(pll->clkr.regmap, off, &val);
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
@@ -262,7 +223,7 @@ static int alpha_pll_default_hwfsm_enable(struct clk_hw *hw)
if (pll->flags & SUPPORTS_OFFLINE_REQ)
val &= ~PLL_OFFLINE_REQ;
- ret = regmap_write(pll->clkr.regmap, off, val);
+ ret = regmap_write(pll->clkr.regmap, PLL_MODE(pll), val);
if (ret)
return ret;
@@ -272,18 +233,18 @@ static int alpha_pll_default_hwfsm_enable(struct clk_hw *hw)
return wait_for_pll_enable_active(pll);
}
-static void alpha_pll_default_hwfsm_disable(struct clk_hw *hw)
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
{
- struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
int ret;
- u32 val, off = pll->offset;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 val;
- ret = regmap_read(pll->clkr.regmap, off, &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,
+ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
if (ret)
return;
@@ -294,7 +255,7 @@ static void alpha_pll_default_hwfsm_disable(struct clk_hw *hw)
}
/* Disable hwfsm */
- ret = regmap_update_bits(pll->clkr.regmap, off,
+ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_FSM_ENA, 0);
if (ret)
return;
@@ -304,35 +265,35 @@ static void alpha_pll_default_hwfsm_disable(struct clk_hw *hw)
static int pll_is_enabled(struct clk_hw *hw, u32 mask)
{
- struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
int ret;
- u32 val, off = pll->offset;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ u32 val;
- ret = regmap_read(pll->clkr.regmap, off, &val);
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
return !!(val & mask);
}
-static int alpha_pll_default_hwfsm_is_enabled(struct clk_hw *hw)
+static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
{
return pll_is_enabled(hw, PLL_ACTIVE_FLAG);
}
-static int alpha_pll_default_is_enabled(struct clk_hw *hw)
+static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
{
return pll_is_enabled(hw, PLL_LOCK_DET);
}
-static int alpha_pll_default_enable(struct clk_hw *hw)
+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 = pll->offset;
+ u32 val, mask;
mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
- ret = regmap_read(pll->clkr.regmap, off, &val);
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
@@ -348,7 +309,7 @@ static int alpha_pll_default_enable(struct clk_hw *hw)
if ((val & mask) == mask)
return 0;
- ret = regmap_update_bits(pll->clkr.regmap, off,
+ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_BYPASSNL, PLL_BYPASSNL);
if (ret)
return ret;
@@ -360,7 +321,7 @@ static int alpha_pll_default_enable(struct clk_hw *hw)
mb();
udelay(5);
- ret = regmap_update_bits(pll->clkr.regmap, off,
+ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_RESET_N, PLL_RESET_N);
if (ret)
return ret;
@@ -369,7 +330,7 @@ static int alpha_pll_default_enable(struct clk_hw *hw)
if (ret)
return ret;
- ret = regmap_update_bits(pll->clkr.regmap, off,
+ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),
PLL_OUTCTRL, PLL_OUTCTRL);
/* Ensure that the write above goes through before returning. */
@@ -377,13 +338,13 @@ static int alpha_pll_default_enable(struct clk_hw *hw)
return ret;
}
-static void alpha_pll_default_disable(struct clk_hw *hw)
+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 = pll->offset;
+ u32 val, mask;
- ret = regmap_read(pll->clkr.regmap, off, &val);
+ ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
if (ret)
return;
@@ -394,21 +355,20 @@ static void alpha_pll_default_disable(struct clk_hw *hw)
}
mask = PLL_OUTCTRL;
- regmap_update_bits(pll->clkr.regmap, off, 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, 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, u32 alpha_width)
{
- return (prate * l) + ((prate * a) >>
- (alpha_width < ALPHA_BITWIDTH ? alpha_width : ALPHA_BITWIDTH));
+ return (prate * l) + ((prate * a) >> ALPHA_SHIFT(alpha_width));
}
static unsigned long
@@ -428,8 +388,7 @@ alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a,
}
/* Upper ALPHA_BITWIDTH bits of Alpha */
- quotient = remainder << (alpha_width < ALPHA_BITWIDTH ?
- alpha_width : ALPHA_BITWIDTH);
+ quotient = remainder << ALPHA_SHIFT(alpha_width);
remainder = do_div(quotient, prate);
@@ -454,21 +413,20 @@ alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate)
}
static unsigned long
-alpha_pll_default_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+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);
- u8 type = pll->pll_type;
- u32 off = pll->offset, alpha_width = pll_alpha_width(type);
+ u32 alpha_width = pll_alpha_width(pll);
- regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
+ regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
- regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
+ regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
if (ctl & PLL_ALPHA_EN) {
- regmap_read(pll->clkr.regmap, off + pll_alpha(type), &low);
+ regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low);
if (alpha_width > 32) {
- regmap_read(pll->clkr.regmap, off + pll_alpha_u(type),
+ regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
&high);
a = (u64)high << 32 | low;
} else {
@@ -492,7 +450,7 @@ static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll)
/* Latch the input to the PLL */
regmap_update_bits(pll->clkr.regmap, off, PLL_UPDATE, PLL_UPDATE);
- /* Make sure PLL_UPDATE request goes through*/
+ /* Make sure PLL_UPDATE request goes through */
mb();
/* Wait for 2 reference cycle before checking ACK bit */
@@ -512,7 +470,7 @@ static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll)
regmap_update_bits(pll->clkr.regmap, off, PLL_UPDATE, 0);
- /* Make sure PLL_UPDATE request goes through*/
+ /* Make sure PLL_UPDATE request goes through */
mb();
} else {
ret = wait_for_pll_update(pll);
@@ -530,60 +488,56 @@ static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll)
return 0;
}
-static int alpha_pll_default_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long prate)
+static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
const struct pll_vco *vco;
- u8 type = pll->pll_type, flags = pll_flags(type);
- u32 l, off = pll->offset, alpha_width = pll_alpha_width(type);
+ u32 l, alpha_width = pll_alpha_width(pll);
u64 a;
rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
- if (flags & SUPPORTS_VCO) {
- vco = alpha_pll_find_vco(pll, rate);
- if (!vco) {
- pr_err("alpha pll not in a valid vco range\n");
- return -EINVAL;
- }
+ vco = alpha_pll_find_vco(pll, rate);
+ if (pll->vco_table && !vco) {
+ pr_err("alpha pll not in a valid vco range\n");
+ return -EINVAL;
}
- regmap_write(pll->clkr.regmap, off + pll_l(type), l);
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
if (alpha_width > ALPHA_BITWIDTH)
a <<= alpha_width - ALPHA_BITWIDTH;
if (alpha_width > 32)
- regmap_write(pll->clkr.regmap, off + pll_alpha_u(type),
- a >> 32);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);
- regmap_write(pll->clkr.regmap, off + pll_alpha(type), a);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
- if (flags & SUPPORTS_VCO)
- regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ if (vco) {
+ 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(type),
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
PLL_ALPHA_EN, PLL_ALPHA_EN);
- if (!clk_hw_is_enabled(hw) || !(flags & SUPPORTS_DYNAMIC_UPDATE))
+ if (!clk_hw_is_enabled(hw) || !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
return 0;
return clk_alpha_pll_update_latch(pll);
}
-static long alpha_pll_default_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+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);
- u8 type = pll->pll_type;
- u32 l, alpha_width = pll_alpha_width(type);
+ 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, alpha_width);
- if (!(pll_flags(type) & SUPPORTS_VCO) || alpha_pll_find_vco(pll, rate))
+ if (!pll->vco_table || alpha_pll_find_vco(pll, rate))
return rate;
min_freq = pll->vco_table[0].min_freq;
@@ -644,26 +598,29 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
u64 rate = parent_rate, tmp;
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
- u8 type = pll->pll_type;
- u32 l, alpha = 0, ctl, alpha_m, alpha_n, off = pll->offset;
+ u32 l, alpha = 0, ctl, alpha_m, alpha_n;
- regmap_read(pll->clkr.regmap, off + pll_l(type), &l);
- regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
+ regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);
+ regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
if (ctl & PLL_ALPHA_EN) {
- regmap_read(pll->clkr.regmap, off + pll_alpha(type), &alpha);
+ regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(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
+ * as a two’s compliment number. When alpha_mode=1,
+ * pll_alpha_val<15:8>=M and 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.
+ * When alpha_mode=0, it is a two’s compliment number in the
+ * range [-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_huayra_pll_calc_rate(rate, l, alpha);
@@ -694,16 +651,14 @@ static int 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);
- u8 type = pll->pll_type;
- u32 l, a, ctl, cur_alpha = 0, off = pll->offset;
+ u32 l, a, ctl, cur_alpha = 0;
rate = alpha_huayra_pll_round_rate(rate, prate, &l, &a);
- regmap_read(pll->clkr.regmap, off + pll_user_ctl(type), &ctl);
+ regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
if (ctl & PLL_ALPHA_EN)
- regmap_read(pll->clkr.regmap, off + pll_alpha(type),
- &cur_alpha);
+ regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &cur_alpha);
/*
* Huayra PLL supports PLL dynamic programming. User can change L_VAL,
@@ -716,20 +671,20 @@ static int alpha_pll_huayra_set_rate(struct clk_hw *hw, unsigned long rate,
return -EBUSY;
}
- regmap_write(pll->clkr.regmap, off + pll_l(type), l);
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(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, off + pll_l(type), l);
- regmap_write(pll->clkr.regmap, off + pll_alpha(type), a);
+ regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);
+ regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
if (a == 0)
- regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
PLL_ALPHA_EN, 0x0);
else
- regmap_update_bits(pll->clkr.regmap, off + pll_user_ctl(type),
+ regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
PLL_ALPHA_EN | PLL_ALPHA_MODE, PLL_ALPHA_EN);
return 0;
@@ -743,54 +698,6 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
return alpha_huayra_pll_round_rate(rate, *prate, &l, &a);
}
-static int clk_alpha_pll_enable(struct clk_hw *hw)
-{
- return pll_clk_ops(hw).enable(hw);
-}
-
-static void clk_alpha_pll_disable(struct clk_hw *hw)
-{
- pll_clk_ops(hw).disable(hw);
-}
-
-static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
-{
- return pll_clk_ops(hw).is_enabled(hw);
-}
-
-static unsigned long
-clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
-{
- return pll_clk_ops(hw).recalc_rate(hw, parent_rate);
-}
-
-static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
-{
- return pll_clk_ops(hw).round_rate(hw, rate, prate);
-}
-
-static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long prate)
-{
- return pll_clk_ops(hw).set_rate(hw, rate, prate);
-}
-
-static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
-{
- return pll_clk_ops(hw).hwfsm_enable(hw);
-}
-
-static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
-{
- pll_clk_ops(hw).hwfsm_disable(hw);
-}
-
-static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
-{
- return pll_clk_ops(hw).hwfsm_is_enabled(hw);
-}
-
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
@@ -801,6 +708,16 @@ const struct clk_ops clk_alpha_pll_ops = {
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_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 = alpha_pll_huayra_recalc_rate,
+ .round_rate = alpha_pll_huayra_round_rate,
+ .set_rate = alpha_pll_huayra_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_huayra_ops);
+
const struct clk_ops clk_alpha_pll_hwfsm_ops = {
.enable = clk_alpha_pll_hwfsm_enable,
.disable = clk_alpha_pll_hwfsm_disable,
@@ -817,11 +734,10 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_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(pll->pll_type),
- &ctl);
+ regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
ctl >>= PLL_POST_DIV_SHIFT;
- ctl &= BIT(pll->width) - 1;
+ ctl &= PLL_POST_DIV_MASK(pll);
return parent_rate >> fls(ctl);
}
@@ -865,8 +781,7 @@ clk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate,
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
u32 ctl, div;
- regmap_read(pll->clkr.regmap, pll->offset + pll_user_ctl(pll->pll_type),
- &ctl);
+ regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);
ctl >>= PLL_POST_DIV_SHIFT;
ctl &= BIT(pll->width) - 1;
@@ -887,9 +802,8 @@ 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(pll->pll_type),
- (BIT(pll->width) - 1) << PLL_POST_DIV_SHIFT,
+ return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
+ PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
div << PLL_POST_DIV_SHIFT);
}
@@ -905,83 +819,3 @@ const struct clk_ops clk_alpha_pll_postdiv_ro_ops = {
.recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops);
-
-/* Contains actual property values for different PLL types */
-static const struct
-alpha_pll_props alpha_pll_props[CLK_ALPHA_PLL_TYPE_MAX] = {
- [CLK_ALPHA_PLL_TYPE_DEFAULT] = {
- .reg_offsets = {
- [PLL_L_VAL] = 0x04,
- [PLL_ALPHA_VAL] = 0x08,
- [PLL_ALPHA_VAL_U] = 0x0c,
- [PLL_USER_CTL] = 0x10,
- [PLL_USER_CTL_U] = 0x14,
- [PLL_CONFIG_CTL] = 0x18,
- [PLL_TEST_CTL] = 0x1c,
- [PLL_TEST_CTL_U] = 0x20,
- [PLL_STATUS] = 0x24,
- },
- .alpha_width = 40,
- .flags = SUPPORTS_VCO,
- .ops = {
- .enable = alpha_pll_default_enable,
- .disable = alpha_pll_default_disable,
- .is_enabled = alpha_pll_default_is_enabled,
- .hwfsm_enable = alpha_pll_default_hwfsm_enable,
- .hwfsm_disable = alpha_pll_default_hwfsm_disable,
- .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
- .recalc_rate = alpha_pll_default_recalc_rate,
- .round_rate = alpha_pll_default_round_rate,
- .set_rate = alpha_pll_default_set_rate,
- },
- },
- [CLK_ALPHA_PLL_TYPE_HUAYRA] = {
- .reg_offsets = {
- [PLL_L_VAL] = 0x04,
- [PLL_ALPHA_VAL] = 0x08,
- [PLL_USER_CTL] = 0x10,
- [PLL_CONFIG_CTL] = 0x14,
- [PLL_CONFIG_CTL_U] = 0x18,
- [PLL_TEST_CTL] = 0x1c,
- [PLL_TEST_CTL_U] = 0x20,
- [PLL_STATUS] = 0x24,
- },
- .alpha_width = 16,
- .flags = SUPPORTS_DYNAMIC_UPDATE | HAVE_64BIT_CONFIG_CTL,
- .ops = {
- .enable = alpha_pll_default_enable,
- .disable = alpha_pll_default_disable,
- .is_enabled = alpha_pll_default_is_enabled,
- .hwfsm_enable = alpha_pll_default_hwfsm_enable,
- .hwfsm_disable = alpha_pll_default_hwfsm_disable,
- .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
- .recalc_rate = alpha_pll_huayra_recalc_rate,
- .round_rate = alpha_pll_huayra_round_rate,
- .set_rate = alpha_pll_huayra_set_rate,
- },
- },
- [CLK_ALPHA_PLL_TYPE_BRAMMO] = {
- .reg_offsets = {
- [PLL_L_VAL] = 0x04,
- [PLL_ALPHA_VAL] = 0x08,
- [PLL_ALPHA_VAL_U] = 0x0c,
- [PLL_USER_CTL] = 0x10,
- [PLL_CONFIG_CTL] = 0x18,
- [PLL_TEST_CTL] = 0x1c,
- [PLL_STATUS] = 0x24,
- },
- .alpha_width = 40,
- .flags = SUPPORTS_DYNAMIC_UPDATE,
- .ops = {
- .enable = alpha_pll_default_enable,
- .disable = alpha_pll_default_disable,
- .is_enabled = alpha_pll_default_is_enabled,
- .hwfsm_enable = alpha_pll_default_hwfsm_enable,
- .hwfsm_disable = alpha_pll_default_hwfsm_disable,
- .hwfsm_is_enabled = alpha_pll_default_hwfsm_is_enabled,
- .recalc_rate = alpha_pll_default_recalc_rate,
- .round_rate = alpha_pll_default_round_rate,
- .set_rate = alpha_pll_default_set_rate,
- },
- },
-};
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index a9f8751227f7..7593e8a56cf2 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -25,6 +25,22 @@ enum {
CLK_ALPHA_PLL_TYPE_MAX,
};
+enum {
+ PLL_OFF_L_VAL,
+ PLL_OFF_ALPHA_VAL,
+ PLL_OFF_ALPHA_VAL_U,
+ PLL_OFF_USER_CTL,
+ PLL_OFF_USER_CTL_U,
+ PLL_OFF_CONFIG_CTL,
+ PLL_OFF_CONFIG_CTL_U,
+ PLL_OFF_TEST_CTL,
+ PLL_OFF_TEST_CTL_U,
+ PLL_OFF_STATUS,
+ PLL_OFF_MAX_REGS
+};
+
+extern const u8 clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_MAX][PLL_OFF_MAX_REGS];
+
struct pll_vco {
unsigned long min_freq;
unsigned long max_freq;
@@ -35,18 +51,19 @@ struct pll_vco {
* struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers
* @vco_table: array of VCO settings
- * @pll_type: alpha pll type
+ * @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @clkr: regmap clock handle
*/
struct clk_alpha_pll {
u32 offset;
+ const u8 *regs;
const struct pll_vco *vco_table;
size_t num_vco;
#define SUPPORTS_OFFLINE_REQ BIT(0)
-#define SUPPORTS_FSM_MODE BIT(1)
+#define SUPPORTS_FSM_MODE BIT(2)
+#define SUPPORTS_DYNAMIC_UPDATE BIT(3)
u8 flags;
- u8 pll_type;
struct clk_regmap clkr;
};
@@ -54,14 +71,14 @@ struct clk_alpha_pll {
/**
* struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
* @offset: base address of registers
- * @pll_type: alpha pll type
+ * @regs: alpha pll register map (see @clk_alpha_pll_regs)
* @width: width of post-divider
* @clkr: regmap clock handle
*/
struct clk_alpha_pll_postdiv {
u32 offset;
- u8 pll_type;
u8 width;
+ const u8 *regs;
struct clk_regmap clkr;
};
@@ -89,6 +106,7 @@ struct alpha_pll_config {
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;
+extern const struct clk_ops clk_alpha_pll_huayra_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,
diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
index 0f735d37690f..ed2d00f55378 100644
--- a/drivers/clk/qcom/gcc-ipq8074.c
+++ b/drivers/clk/qcom/gcc-ipq8074.c
@@ -52,6 +52,7 @@ static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
static struct clk_alpha_pll gpll0_main = {
.offset = 0x21000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x0b000,
.enable_mask = BIT(0),
@@ -82,6 +83,7 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x21000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.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 7983288d9141..1e38efc37180 100644
--- a/drivers/clk/qcom/gcc-msm8994.c
+++ b/drivers/clk/qcom/gcc-msm8994.c
@@ -73,6 +73,7 @@ static struct clk_fixed_factor xo = {
static struct clk_alpha_pll gpll0_early = {
.offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x1480,
.enable_mask = BIT(0),
@@ -88,6 +89,7 @@ static struct clk_alpha_pll gpll0_early = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data)
{
.name = "gpll0",
@@ -99,6 +101,7 @@ static struct clk_alpha_pll_postdiv gpll0 = {
static struct clk_alpha_pll gpll4_early = {
.offset = 0x1dc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x1480,
.enable_mask = BIT(4),
@@ -114,6 +117,7 @@ static struct clk_alpha_pll gpll4_early = {
static struct clk_alpha_pll_postdiv gpll4 = {
.offset = 0x1dc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.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 7ddec886fcd3..5d7451209206 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -227,6 +227,7 @@ static struct clk_fixed_factor xo = {
static struct clk_alpha_pll gpll0_early = {
.offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x52000,
.enable_mask = BIT(0),
@@ -252,6 +253,7 @@ static struct clk_fixed_factor gpll0_early_div = {
static struct clk_alpha_pll_postdiv gpll0 = {
.offset = 0x00000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
.parent_names = (const char *[]){ "gpll0_early" },
@@ -262,6 +264,7 @@ static struct clk_alpha_pll_postdiv gpll0 = {
static struct clk_alpha_pll gpll4_early = {
.offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.clkr = {
.enable_reg = 0x52000,
.enable_mask = BIT(4),
@@ -276,6 +279,7 @@ static struct clk_alpha_pll gpll4_early = {
static struct clk_alpha_pll_postdiv gpll4 = {
.offset = 0x77000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.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 352394d8fd8c..66a2fa4ec93c 100644
--- a/drivers/clk/qcom/mmcc-msm8996.c
+++ b/drivers/clk/qcom/mmcc-msm8996.c
@@ -267,6 +267,7 @@ static struct pll_vco mmpll_t_vco[] = {
static struct clk_alpha_pll mmpll0_early = {
.offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr = {
@@ -283,6 +284,7 @@ static struct clk_alpha_pll mmpll0_early = {
static struct clk_alpha_pll_postdiv mmpll0 = {
.offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll0",
@@ -295,6 +297,7 @@ static struct clk_alpha_pll_postdiv mmpll0 = {
static struct clk_alpha_pll mmpll1_early = {
.offset = 0x30,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr = {
@@ -311,6 +314,7 @@ static struct clk_alpha_pll mmpll1_early = {
static struct clk_alpha_pll_postdiv mmpll1 = {
.offset = 0x30,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll1",
@@ -323,6 +327,7 @@ static struct clk_alpha_pll_postdiv mmpll1 = {
static struct clk_alpha_pll mmpll2_early = {
.offset = 0x4100,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_gfx_vco,
.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -335,6 +340,7 @@ static struct clk_alpha_pll mmpll2_early = {
static struct clk_alpha_pll_postdiv mmpll2 = {
.offset = 0x4100,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll2",
@@ -347,6 +353,7 @@ static struct clk_alpha_pll_postdiv mmpll2 = {
static struct clk_alpha_pll mmpll3_early = {
.offset = 0x60,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -359,6 +366,7 @@ static struct clk_alpha_pll mmpll3_early = {
static struct clk_alpha_pll_postdiv mmpll3 = {
.offset = 0x60,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll3",
@@ -371,6 +379,7 @@ static struct clk_alpha_pll_postdiv mmpll3 = {
static struct clk_alpha_pll mmpll4_early = {
.offset = 0x90,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_t_vco,
.num_vco = ARRAY_SIZE(mmpll_t_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -383,6 +392,7 @@ static struct clk_alpha_pll mmpll4_early = {
static struct clk_alpha_pll_postdiv mmpll4 = {
.offset = 0x90,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll4",
@@ -395,6 +405,7 @@ static struct clk_alpha_pll_postdiv mmpll4 = {
static struct clk_alpha_pll mmpll5_early = {
.offset = 0xc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_p_vco,
.num_vco = ARRAY_SIZE(mmpll_p_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -407,6 +418,7 @@ static struct clk_alpha_pll mmpll5_early = {
static struct clk_alpha_pll_postdiv mmpll5 = {
.offset = 0xc0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll5",
@@ -419,6 +431,7 @@ static struct clk_alpha_pll_postdiv mmpll5 = {
static struct clk_alpha_pll mmpll8_early = {
.offset = 0x4130,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_gfx_vco,
.num_vco = ARRAY_SIZE(mmpll_gfx_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -431,6 +444,7 @@ static struct clk_alpha_pll mmpll8_early = {
static struct clk_alpha_pll_postdiv mmpll8 = {
.offset = 0x4130,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll8",
@@ -443,6 +457,7 @@ static struct clk_alpha_pll_postdiv mmpll8 = {
static struct clk_alpha_pll mmpll9_early = {
.offset = 0x4200,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.vco_table = mmpll_t_vco,
.num_vco = ARRAY_SIZE(mmpll_t_vco),
.clkr.hw.init = &(struct clk_init_data){
@@ -455,6 +470,7 @@ static struct clk_alpha_pll mmpll9_early = {
static struct clk_alpha_pll_postdiv mmpll9 = {
.offset = 0x4200,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll9",
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 2017-12-07 11:53, Stephen Boyd wrote:
> On 09/28, Abhishek Sahu wrote:
>> This patch series does the miscellaneous changes in QCOM Alpha PLL
>> operation and structure to support other types of Alpha PLL’s.
>>
>> 1. It adds the pll_type which will be used for determining all
>> the properties of Alpha PLL.
>> 2. It adds the support for Brammo and Huayra PLL’s for which
>> the support is not available in existing alpha PLL code.
>> 3. There won’t be any change in existing users of Alpha PLL’s
>> since all the newly added code will be under flag for the default
>> PLL operations.
>>
>
> Ok. I took a long look at this today. I rewrote a bunch of stuff.
Thanks Stephen for reviewing the changes and making the code
cleaner. I checked all the code changes and everything looks
good. It will work for all of our requirement. I will check
with other PLL users also once and then update the patch
series with all your suggested code changes after complete
testing.
> Let me know if anything looks wrong. I'm not really interested in
> having a type template design that causes us to jump through one
> clk op to another set of them. I'd rather keep it flatter. I also
> kept around the macros for the offsets and had it use a register
> map in each struct instead. Yes, we have to go modify the PLL
> types to point to the right register offset, but really that's
> fine and I don't really care. We could have a default fallback
> when the reg pointer is NULL, but I'm not sure that is useful.
The main reason for going with type template design is due to
different register offsets. Now, if passing the register
offsets from pll structure is ok, then we can get rid of this
function indirection approach.
Adding NULL check seems to be overhead in all our register macros
since these PLL structure will be populated by QCOM clock drivers
only and now, we are making this parameter mandatory.
> The alternative is to make a bunch of new ops structures that
> passes it down into the final functions but that seemed like more
> work for the handful of PLLs we have to worry about. You seem to
> agree here. All told, it got cut down by 100 lines so the patches
> got smaller.
>
Passing the ops into final function will be lead to again type
template design for passing the register offsets. Since, now we
have very few PLL's in current upstream code so adding register
offsets will be more convenient and maintainable.
Also, now the register offset is coming from our own array
so always we can retrieve the PLL type from that. In future,
if someone want to have code which requires PLL type then,
it can be retrieved from diff of passed pll structure
address and array base address.
Thanks,
Abhishek
On 12/08, Abhishek Sahu wrote:
> On 2017-12-07 11:53, Stephen Boyd wrote:
> >On 09/28, Abhishek Sahu wrote:
> >>This patch series does the miscellaneous changes in QCOM Alpha PLL
> >>operation and structure to support other types of Alpha PLL’s.
> >>
> >>1. It adds the pll_type which will be used for determining all
> >> the properties of Alpha PLL.
> >>2. It adds the support for Brammo and Huayra PLL’s for which
> >> the support is not available in existing alpha PLL code.
> >>3. There won’t be any change in existing users of Alpha PLL’s
> >> since all the newly added code will be under flag for the default
> >> PLL operations.
> >>
> >
> >Ok. I took a long look at this today. I rewrote a bunch of stuff.
>
> Thanks Stephen for reviewing the changes and making the code
> cleaner. I checked all the code changes and everything looks
> good. It will work for all of our requirement. I will check
> with other PLL users also once and then update the patch
> series with all your suggested code changes after complete
> testing.
Ok. Please don't resend. I've pushed out the branch to clk-next,
and it can be adjusted if needed, or dropped and rewritten if
something is totally busted.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> 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 <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> Current PLL driver only supports 4 bit PLL post divider so
> modified the PLL divider operations to support 2 bit PLL
> post divider.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, 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: Rajendra Nayak <[email protected]>
> Signed-off-by: Taniya Das <[email protected]>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> 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 <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> The alpha value calculation function has been written for 40 bit
> alpha which is not coming properly for 16 bit
>
> 1. Alpha value is being calculated on the basis of
> ALPHA_BITWIDTH to make the computation easy for 40 bit alpha.
> After calculating the 32 bit alpha, It is being converted to 40
> bit alpha by making making lower bits zero. But if actual alpha
> register width is less than ALPHA_BITWIDTH, then the actual width
> can be used for calculation
>
> 2. During 40 bit alpha pll set rate, the lower alpha register is
> not being configured
>
> Now the changes have been made to calculate the rate and register
> values from alpha_width instead hardcoding it so that it can work
> for all the cases.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> Alpha PLL is a generic name used for QCOM PLL’s which uses L
> and Alpha values for configuring the integer and fractional part.
> QCOM SoC’s use different types of Alpha PLL’s for which basic
> software configuration part is common with following differences.
>
> 1. All 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.
> 2. PLL dynamic programming sequence will be different in some
> of the Alpha PLL’s
> 3. Some of the PLL won’t have 64 bit config control, 64 bit
> user control, VCO configuration etc.
>
> Now, this patch adds the Alpha PLL type in clock node and adds
> alpha PLL properties structure inside clk-alpha-pll.c. This PLL
> property will contain everything including register offsets, clock
> operations and other properties since all these properties will be
> fixed for Alpha PLL.
>
> This allows to support other types of Alpha PLL without addition
> of new flag and variable in structures of clk_alpha_pll.h. Also, we
> don’t have to add operation for each Alpha PLL’s and export them.
>
> In future, we can get rid of most of the flags like following
>
> struct clk_alpha_pll {
> #define SUPPORTS_OFFLINE_REQ BIT(0)
> #define SUPPORTS_16BIT_ALPHA BIT(1)
> #define SUPPORTS_FSM_MODE BIT(2)
> u8 flags;
> };
>
> struct clk_alpha_pll_postdiv {
> u8 width;
> };
>
> Since all the above properties will be always same for different
> instances of same type of Alpha PLL’s.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> Currently SUPPORTS_16BIT_ALPHA flag determines the PLL alpha
> register width. If this flag is set then the alpha register width
> is 16 bits otherwise it is 40 bits. The alpha width is always
> fixed for PLL type so it can be added in PLL properties and clock
> driver don’t have to specify explicitly.
>
> The SUPPORTS_16BIT_ALPHA flag is unused in the current code so
> it’s safe to remove this flags.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> Some of the Alpha PLL’s (like Spark, Brammo PLL) do not have
> CONFIG_CTL_U register. This patch adds the flag in properties
> for PLL’s which have CONFIG_CTL_U register and checks the same
> while doing PLL initial configuration.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> 1. Brammo PLL does not allow configuration of VCO
> 2. Supports the dynamic update in which the frequency can
> be changed dynamically without turning off the PLL
> 3. The register offsets are different from normal Alpha PLL
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> 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 <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 09/28, Abhishek Sahu wrote:
> 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 from other Alpha PLL’s so this patch
> made adds separate functions for Huayra PLL.
>
> Signed-off-by: Abhishek Sahu <[email protected]>
> ---
Applied to clk-next
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 2017-12-09 05:46, Stephen Boyd wrote:
> On 12/08, Abhishek Sahu wrote:
>> On 2017-12-07 11:53, Stephen Boyd wrote:
>> >On 09/28, Abhishek Sahu wrote:
>> >>This patch series does the miscellaneous changes in QCOM Alpha PLL
>> >>operation and structure to support other types of Alpha PLL’s.
>> >>
>> >>1. It adds the pll_type which will be used for determining all
>> >> the properties of Alpha PLL.
>> >>2. It adds the support for Brammo and Huayra PLL’s for which
>> >> the support is not available in existing alpha PLL code.
>> >>3. There won’t be any change in existing users of Alpha PLL’s
>> >> since all the newly added code will be under flag for the default
>> >> PLL operations.
>> >>
>> >
>> >Ok. I took a long look at this today. I rewrote a bunch of stuff.
>>
>> Thanks Stephen for reviewing the changes and making the code
>> cleaner. I checked all the code changes and everything looks
>> good. It will work for all of our requirement. I will check
>> with other PLL users also once and then update the patch
>> series with all your suggested code changes after complete
>> testing.
>
> Ok. Please don't resend. I've pushed out the branch to clk-next,
> and it can be adjusted if needed, or dropped and rewritten if
> something is totally busted.
Thanks Stephen for your great help and support.
It seems, we are getting the error in the following error with these
patches because of missing EXPORT_SYMBOL_GPL for
clk_alpha_pll_regs and clk_hw_is_enabled.
ERROR: "clk_alpha_pll_regs" [drivers/clk/qcom/mmcc-msm8996.ko]
undefined!
ERROR: "clk_hw_is_enabled" [drivers/clk/qcom/clk-qcom.ko] undefined!
Caused by commits
d1506b749e92 ("clk: qcom: support for alpha pll properties")
e66a4d6d0081 ("clk: qcom: support for dynamic updating the PLL")
301803e6013b ("clk: qcom: support Huayra type Alpha PLL")
On 12/11, Abhishek Sahu wrote:
> On 2017-12-09 05:46, Stephen Boyd wrote:
> >On 12/08, Abhishek Sahu wrote:
> >>On 2017-12-07 11:53, Stephen Boyd wrote:
> >>>On 09/28, Abhishek Sahu wrote:
> >>>>This patch series does the miscellaneous changes in QCOM Alpha PLL
> >>>>operation and structure to support other types of Alpha PLL’s.
> >>>>
> >>>>1. It adds the pll_type which will be used for determining all
> >>>> the properties of Alpha PLL.
> >>>>2. It adds the support for Brammo and Huayra PLL’s for which
> >>>> the support is not available in existing alpha PLL code.
> >>>>3. There won’t be any change in existing users of Alpha PLL’s
> >>>> since all the newly added code will be under flag for the default
> >>>> PLL operations.
> >>>>
> >>>
> >>>Ok. I took a long look at this today. I rewrote a bunch of stuff.
> >>
> >> Thanks Stephen for reviewing the changes and making the code
> >> cleaner. I checked all the code changes and everything looks
> >> good. It will work for all of our requirement. I will check
> >> with other PLL users also once and then update the patch
> >> series with all your suggested code changes after complete
> >> testing.
> >
> >Ok. Please don't resend. I've pushed out the branch to clk-next,
> >and it can be adjusted if needed, or dropped and rewritten if
> >something is totally busted.
>
> Thanks Stephen for your great help and support.
> It seems, we are getting the error in the following error with these
> patches because of missing EXPORT_SYMBOL_GPL for
> clk_alpha_pll_regs and clk_hw_is_enabled.
>
>
> ERROR: "clk_alpha_pll_regs" [drivers/clk/qcom/mmcc-msm8996.ko]
> undefined!
>
> ERROR: "clk_hw_is_enabled" [drivers/clk/qcom/clk-qcom.ko] undefined!
>
> Caused by commits
>
> d1506b749e92 ("clk: qcom: support for alpha pll properties")
> e66a4d6d0081 ("clk: qcom: support for dynamic updating the PLL")
> 301803e6013b ("clk: qcom: support Huayra type Alpha PLL")
Yep. I'll export the regs and remove the clk_hw_is_enabled()
usage. Should be possible to do that inside the ops directly
instead of going through the framework for it.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On 2017-12-14 03:53, Stephen Boyd wrote:
> On 12/11, Abhishek Sahu wrote:
>> On 2017-12-09 05:46, Stephen Boyd wrote:
>> >On 12/08, Abhishek Sahu wrote:
>> >>On 2017-12-07 11:53, Stephen Boyd wrote:
>> >>>On 09/28, Abhishek Sahu wrote:
>> >>>>This patch series does the miscellaneous changes in QCOM Alpha PLL
>> >>>>operation and structure to support other types of Alpha PLL’s.
>> >>>>
>> >>>>1. It adds the pll_type which will be used for determining all
>> >>>> the properties of Alpha PLL.
>> >>>>2. It adds the support for Brammo and Huayra PLL’s for which
>> >>>> the support is not available in existing alpha PLL code.
>> >>>>3. There won’t be any change in existing users of Alpha PLL’s
>> >>>> since all the newly added code will be under flag for the default
>> >>>> PLL operations.
>> >>>>
>> >>>
>> >>>Ok. I took a long look at this today. I rewrote a bunch of stuff.
>> >>
>> >> Thanks Stephen for reviewing the changes and making the code
>> >> cleaner. I checked all the code changes and everything looks
>> >> good. It will work for all of our requirement. I will check
>> >> with other PLL users also once and then update the patch
>> >> series with all your suggested code changes after complete
>> >> testing.
>> >
>> >Ok. Please don't resend. I've pushed out the branch to clk-next,
>> >and it can be adjusted if needed, or dropped and rewritten if
>> >something is totally busted.
>>
>> Thanks Stephen for your great help and support.
>> It seems, we are getting the error in the following error with these
>> patches because of missing EXPORT_SYMBOL_GPL for
>> clk_alpha_pll_regs and clk_hw_is_enabled.
>>
>>
>> ERROR: "clk_alpha_pll_regs" [drivers/clk/qcom/mmcc-msm8996.ko]
>> undefined!
>>
>> ERROR: "clk_hw_is_enabled" [drivers/clk/qcom/clk-qcom.ko] undefined!
>>
>> Caused by commits
>>
>> d1506b749e92 ("clk: qcom: support for alpha pll properties")
>> e66a4d6d0081 ("clk: qcom: support for dynamic updating the PLL")
>> 301803e6013b ("clk: qcom: support Huayra type Alpha PLL")
>
> Yep. I'll export the regs and remove the clk_hw_is_enabled()
> usage. Should be possible to do that inside the ops directly
> instead of going through the framework for it.
Thanks Stephen for updating the patches :-)
Correct. clk_alpha_pll_is_enabled can do that.