aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2014-08-30 09:32:58 +0000
committerJohn Crispin <blogic@openwrt.org>2014-08-30 09:32:58 +0000
commita297ec8e13d10274155e0850228bb06c7648e541 (patch)
treea75e0d80b1664b748d679ea2e7f4797f58837703 /target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch
parent9f7cb06591148e3698ac731f7b8734e4d3d21b33 (diff)
downloadupstream-a297ec8e13d10274155e0850228bb06c7648e541.tar.gz
upstream-a297ec8e13d10274155e0850228bb06c7648e541.tar.bz2
upstream-a297ec8e13d10274155e0850228bb06c7648e541.zip
ipq806x: Add support for IPQ806x chip family
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> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@42334 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch')
-rw-r--r--target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch155
1 files changed, 155 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch b/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch
new file mode 100644
index 0000000000..2983b8444b
--- /dev/null
+++ b/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch
@@ -0,0 +1,155 @@
+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
+