1 From fd06a2cc719296f65a280cb1533b125f63cfcb34 Mon Sep 17 00:00:00 2001
2 From: Stephen Boyd <sboyd@codeaurora.org>
3 Date: Mon, 28 Apr 2014 15:58:11 -0700
4 Subject: [PATCH 127/182] clk: qcom: Add support for setting rates on PLLs
6 Some PLLs may require changing their rate at runtime. Add support
9 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
11 drivers/clk/qcom/clk-pll.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
12 drivers/clk/qcom/clk-pll.h | 20 +++++++++++++
13 2 files changed, 87 insertions(+), 1 deletion(-)
15 --- a/drivers/clk/qcom/clk-pll.c
16 +++ b/drivers/clk/qcom/clk-pll.c
17 @@ -97,7 +97,7 @@ static unsigned long
18 clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
20 struct clk_pll *pll = to_clk_pll(hw);
22 + u32 l, m, n, config;
26 @@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, u
30 + if (pll->post_div_width) {
31 + regmap_read(pll->clkr.regmap, pll->config_reg, &config);
32 + config >>= pll->post_div_shift;
33 + config &= BIT(pll->post_div_width) - 1;
41 +struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
46 + for (; f->freq; f++)
47 + if (rate <= f->freq)
54 +clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
55 + unsigned long *p_rate, struct clk **p)
57 + struct clk_pll *pll = to_clk_pll(hw);
58 + const struct pll_freq_tbl *f;
60 + f = find_freq(pll->freq_tbl, rate);
62 + return clk_pll_recalc_rate(hw, *p_rate);
68 +clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
70 + struct clk_pll *pll = to_clk_pll(hw);
71 + const struct pll_freq_tbl *f;
74 + u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
76 + f = find_freq(pll->freq_tbl, rate);
80 + regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
81 + enabled = (mode & enable_mask) == enable_mask;
84 + clk_pll_disable(hw);
86 + regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
87 + regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
88 + regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
89 + regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
97 const struct clk_ops clk_pll_ops = {
98 .enable = clk_pll_enable,
99 .disable = clk_pll_disable,
100 .recalc_rate = clk_pll_recalc_rate,
101 + .determine_rate = clk_pll_determine_rate,
102 + .set_rate = clk_pll_set_rate,
104 EXPORT_SYMBOL_GPL(clk_pll_ops);
106 --- a/drivers/clk/qcom/clk-pll.h
107 +++ b/drivers/clk/qcom/clk-pll.h
109 #include "clk-regmap.h"
112 + * struct pll_freq_tbl - PLL frequency table
116 + * @ibits: internal values
118 +struct pll_freq_tbl {
119 + unsigned long freq;
127 * struct clk_pll - phase locked loop (PLL)
131 * @mode_reg: mode register
132 * @status_reg: status register
133 * @status_bit: ANDed with @status_reg to determine if PLL is enabled
134 + * @freq_tbl: PLL frequency table
135 * @hw: handle between common and hardware-specific interfaces
138 @@ -36,6 +52,10 @@ struct clk_pll {
145 + const struct pll_freq_tbl *freq_tbl;
147 struct clk_regmap clkr;