3c1f6e358d
Patches are generated using the "format-patch" command from the following location: *https://www.codeaurora.org/cgit/quic/kernel/galak-msm/log/?h=apq_ipq_base *rev=0771849495b4128cac2faf7d49c85c729fc48b20 Patches numbered 76/77/102/103 have already been integrated in 3.14.12, so they're not in this list. All these patches are either integrated are pending integration into kernel.org, therefore these patches should go away once the kernel gets upgraded to 3.16. Support is currently limited to AP148 board but can be extended to other platforms in the future. These changes do not cover ethernet connectivity. Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> SVN-Revision: 42334
155 lines
3.8 KiB
Diff
155 lines
3.8 KiB
Diff
From fd06a2cc719296f65a280cb1533b125f63cfcb34 Mon Sep 17 00:00:00 2001
|
|
From: Stephen Boyd <sboyd@codeaurora.org>
|
|
Date: Mon, 28 Apr 2014 15:58:11 -0700
|
|
Subject: [PATCH 127/182] clk: qcom: Add support for setting rates on PLLs
|
|
|
|
Some PLLs may require changing their rate at runtime. Add support
|
|
for these PLLs.
|
|
|
|
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
|
|
---
|
|
drivers/clk/qcom/clk-pll.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
|
|
drivers/clk/qcom/clk-pll.h | 20 +++++++++++++
|
|
2 files changed, 87 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
|
|
index 0f927c5..80c7a76 100644
|
|
--- a/drivers/clk/qcom/clk-pll.c
|
|
+++ b/drivers/clk/qcom/clk-pll.c
|
|
@@ -97,7 +97,7 @@ static unsigned long
|
|
clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
|
{
|
|
struct clk_pll *pll = to_clk_pll(hw);
|
|
- u32 l, m, n;
|
|
+ u32 l, m, n, config;
|
|
unsigned long rate;
|
|
u64 tmp;
|
|
|
|
@@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
|
do_div(tmp, n);
|
|
rate += tmp;
|
|
}
|
|
+ if (pll->post_div_width) {
|
|
+ regmap_read(pll->clkr.regmap, pll->config_reg, &config);
|
|
+ config >>= pll->post_div_shift;
|
|
+ config &= BIT(pll->post_div_width) - 1;
|
|
+ rate /= config + 1;
|
|
+ }
|
|
+
|
|
return rate;
|
|
}
|
|
|
|
+static const
|
|
+struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
|
|
+{
|
|
+ if (!f)
|
|
+ return NULL;
|
|
+
|
|
+ for (; f->freq; f++)
|
|
+ if (rate <= f->freq)
|
|
+ return f;
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static long
|
|
+clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|
+ unsigned long *p_rate, struct clk **p)
|
|
+{
|
|
+ struct clk_pll *pll = to_clk_pll(hw);
|
|
+ const struct pll_freq_tbl *f;
|
|
+
|
|
+ f = find_freq(pll->freq_tbl, rate);
|
|
+ if (!f)
|
|
+ return clk_pll_recalc_rate(hw, *p_rate);
|
|
+
|
|
+ return f->freq;
|
|
+}
|
|
+
|
|
+static int
|
|
+clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
|
|
+{
|
|
+ struct clk_pll *pll = to_clk_pll(hw);
|
|
+ const struct pll_freq_tbl *f;
|
|
+ bool enabled;
|
|
+ u32 mode;
|
|
+ u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
|
|
+
|
|
+ f = find_freq(pll->freq_tbl, rate);
|
|
+ if (!f)
|
|
+ return -EINVAL;
|
|
+
|
|
+ regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
|
|
+ enabled = (mode & enable_mask) == enable_mask;
|
|
+
|
|
+ if (enabled)
|
|
+ clk_pll_disable(hw);
|
|
+
|
|
+ regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
|
|
+ regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
|
|
+ regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
|
|
+ regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
|
|
+
|
|
+ if (enabled)
|
|
+ clk_pll_enable(hw);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
const struct clk_ops clk_pll_ops = {
|
|
.enable = clk_pll_enable,
|
|
.disable = clk_pll_disable,
|
|
.recalc_rate = clk_pll_recalc_rate,
|
|
+ .determine_rate = clk_pll_determine_rate,
|
|
+ .set_rate = clk_pll_set_rate,
|
|
};
|
|
EXPORT_SYMBOL_GPL(clk_pll_ops);
|
|
|
|
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
|
|
index 0775a99..5f9928b 100644
|
|
--- a/drivers/clk/qcom/clk-pll.h
|
|
+++ b/drivers/clk/qcom/clk-pll.h
|
|
@@ -18,6 +18,21 @@
|
|
#include "clk-regmap.h"
|
|
|
|
/**
|
|
+ * struct pll_freq_tbl - PLL frequency table
|
|
+ * @l: L value
|
|
+ * @m: M value
|
|
+ * @n: N value
|
|
+ * @ibits: internal values
|
|
+ */
|
|
+struct pll_freq_tbl {
|
|
+ unsigned long freq;
|
|
+ u16 l;
|
|
+ u16 m;
|
|
+ u16 n;
|
|
+ u32 ibits;
|
|
+};
|
|
+
|
|
+/**
|
|
* struct clk_pll - phase locked loop (PLL)
|
|
* @l_reg: L register
|
|
* @m_reg: M register
|
|
@@ -26,6 +41,7 @@
|
|
* @mode_reg: mode register
|
|
* @status_reg: status register
|
|
* @status_bit: ANDed with @status_reg to determine if PLL is enabled
|
|
+ * @freq_tbl: PLL frequency table
|
|
* @hw: handle between common and hardware-specific interfaces
|
|
*/
|
|
struct clk_pll {
|
|
@@ -36,6 +52,10 @@ struct clk_pll {
|
|
u32 mode_reg;
|
|
u32 status_reg;
|
|
u8 status_bit;
|
|
+ u8 post_div_width;
|
|
+ u8 post_div_shift;
|
|
+
|
|
+ const struct pll_freq_tbl *freq_tbl;
|
|
|
|
struct clk_regmap clkr;
|
|
};
|
|
--
|
|
1.7.10.4
|
|
|