diff options
| author | Mike Turquette <mturquette@linaro.org> | 2014-09-26 19:10:57 -0400 |
|---|---|---|
| committer | Mike Turquette <mturquette@linaro.org> | 2014-09-26 19:10:57 -0400 |
| commit | db0bcc33a8aabab462c996baeac619f21616d938 (patch) | |
| tree | 935394b4fe27ab92ea260e7a095330524a5fe9f8 | |
| parent | b6b2fe5b6e956c8217a7584472a3ac5c068b61d4 (diff) | |
| parent | 229fd4a505553c3a475b90e9aa8e452f5d78eb3b (diff) | |
Merge tag 'qcom-clocks-for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom into clk-next
qcom clock changes for 3.18
Some fixes for the IPQ driver and some code consolidation
and refactoring.
| -rw-r--r-- | drivers/clk/qcom/clk-pll.c | 68 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-pll.h | 20 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-rcg.c | 115 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-rcg.h | 6 | ||||
| -rw-r--r-- | drivers/clk/qcom/clk-rcg2.c | 19 | ||||
| -rw-r--r-- | drivers/clk/qcom/common.c | 16 | ||||
| -rw-r--r-- | drivers/clk/qcom/common.h | 4 | ||||
| -rw-r--r-- | drivers/clk/qcom/gcc-ipq806x.c | 31 | ||||
| -rw-r--r-- | drivers/clk/qcom/mmcc-msm8960.c | 28 |
9 files changed, 219 insertions, 88 deletions
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index 9db03d3b1657..b823bc3b6250 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c | |||
| @@ -97,7 +97,7 @@ static unsigned long | |||
| 97 | clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | 97 | clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
| 98 | { | 98 | { |
| 99 | struct clk_pll *pll = to_clk_pll(hw); | 99 | struct clk_pll *pll = to_clk_pll(hw); |
| 100 | u32 l, m, n; | 100 | u32 l, m, n, config; |
| 101 | unsigned long rate; | 101 | unsigned long rate; |
| 102 | u64 tmp; | 102 | u64 tmp; |
| 103 | 103 | ||
| @@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |||
| 116 | do_div(tmp, n); | 116 | do_div(tmp, n); |
| 117 | rate += tmp; | 117 | rate += tmp; |
| 118 | } | 118 | } |
| 119 | if (pll->post_div_width) { | ||
| 120 | regmap_read(pll->clkr.regmap, pll->config_reg, &config); | ||
| 121 | config >>= pll->post_div_shift; | ||
| 122 | config &= BIT(pll->post_div_width) - 1; | ||
| 123 | rate /= config + 1; | ||
| 124 | } | ||
| 125 | |||
| 119 | return rate; | 126 | return rate; |
| 120 | } | 127 | } |
| 121 | 128 | ||
| 129 | static const | ||
| 130 | struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate) | ||
| 131 | { | ||
| 132 | if (!f) | ||
| 133 | return NULL; | ||
| 134 | |||
| 135 | for (; f->freq; f++) | ||
| 136 | if (rate <= f->freq) | ||
| 137 | return f; | ||
| 138 | |||
| 139 | return NULL; | ||
| 140 | } | ||
| 141 | |||
| 142 | static long | ||
| 143 | clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
| 144 | unsigned long *p_rate, struct clk **p) | ||
| 145 | { | ||
| 146 | struct clk_pll *pll = to_clk_pll(hw); | ||
| 147 | const struct pll_freq_tbl *f; | ||
| 148 | |||
| 149 | f = find_freq(pll->freq_tbl, rate); | ||
| 150 | if (!f) | ||
| 151 | return clk_pll_recalc_rate(hw, *p_rate); | ||
| 152 | |||
| 153 | return f->freq; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int | ||
| 157 | clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate) | ||
| 158 | { | ||
| 159 | struct clk_pll *pll = to_clk_pll(hw); | ||
| 160 | const struct pll_freq_tbl *f; | ||
| 161 | bool enabled; | ||
| 162 | u32 mode; | ||
| 163 | u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N; | ||
| 164 | |||
| 165 | f = find_freq(pll->freq_tbl, rate); | ||
| 166 | if (!f) | ||
| 167 | return -EINVAL; | ||
| 168 | |||
| 169 | regmap_read(pll->clkr.regmap, pll->mode_reg, &mode); | ||
| 170 | enabled = (mode & enable_mask) == enable_mask; | ||
| 171 | |||
| 172 | if (enabled) | ||
| 173 | clk_pll_disable(hw); | ||
| 174 | |||
| 175 | regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l); | ||
| 176 | regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m); | ||
| 177 | regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n); | ||
| 178 | regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits); | ||
| 179 | |||
| 180 | if (enabled) | ||
| 181 | clk_pll_enable(hw); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 122 | const struct clk_ops clk_pll_ops = { | 186 | const struct clk_ops clk_pll_ops = { |
| 123 | .enable = clk_pll_enable, | 187 | .enable = clk_pll_enable, |
| 124 | .disable = clk_pll_disable, | 188 | .disable = clk_pll_disable, |
| 125 | .recalc_rate = clk_pll_recalc_rate, | 189 | .recalc_rate = clk_pll_recalc_rate, |
| 190 | .determine_rate = clk_pll_determine_rate, | ||
| 191 | .set_rate = clk_pll_set_rate, | ||
| 126 | }; | 192 | }; |
| 127 | EXPORT_SYMBOL_GPL(clk_pll_ops); | 193 | EXPORT_SYMBOL_GPL(clk_pll_ops); |
| 128 | 194 | ||
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h index 3003e9962472..c9c0cda306d0 100644 --- a/drivers/clk/qcom/clk-pll.h +++ b/drivers/clk/qcom/clk-pll.h | |||
| @@ -18,6 +18,21 @@ | |||
| 18 | #include "clk-regmap.h" | 18 | #include "clk-regmap.h" |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * struct pll_freq_tbl - PLL frequency table | ||
| 22 | * @l: L value | ||
| 23 | * @m: M value | ||
| 24 | * @n: N value | ||
| 25 | * @ibits: internal values | ||
| 26 | */ | ||
| 27 | struct pll_freq_tbl { | ||
| 28 | unsigned long freq; | ||
| 29 | u16 l; | ||
| 30 | u16 m; | ||
| 31 | u16 n; | ||
| 32 | u32 ibits; | ||
| 33 | }; | ||
| 34 | |||
| 35 | /** | ||
| 21 | * struct clk_pll - phase locked loop (PLL) | 36 | * struct clk_pll - phase locked loop (PLL) |
| 22 | * @l_reg: L register | 37 | * @l_reg: L register |
| 23 | * @m_reg: M register | 38 | * @m_reg: M register |
| @@ -26,6 +41,7 @@ | |||
| 26 | * @mode_reg: mode register | 41 | * @mode_reg: mode register |
| 27 | * @status_reg: status register | 42 | * @status_reg: status register |
| 28 | * @status_bit: ANDed with @status_reg to determine if PLL is enabled | 43 | * @status_bit: ANDed with @status_reg to determine if PLL is enabled |
| 44 | * @freq_tbl: PLL frequency table | ||
| 29 | * @hw: handle between common and hardware-specific interfaces | 45 | * @hw: handle between common and hardware-specific interfaces |
| 30 | */ | 46 | */ |
| 31 | struct clk_pll { | 47 | struct clk_pll { |
| @@ -36,6 +52,10 @@ struct clk_pll { | |||
| 36 | u32 mode_reg; | 52 | u32 mode_reg; |
| 37 | u32 status_reg; | 53 | u32 status_reg; |
| 38 | u8 status_bit; | 54 | u8 status_bit; |
| 55 | u8 post_div_width; | ||
| 56 | u8 post_div_shift; | ||
| 57 | |||
| 58 | const struct pll_freq_tbl *freq_tbl; | ||
| 39 | 59 | ||
| 40 | struct clk_regmap clkr; | 60 | struct clk_regmap clkr; |
| 41 | }; | 61 | }; |
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index b638c5846dbf..b6e6959e89aa 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <asm/div64.h> | 21 | #include <asm/div64.h> |
| 22 | 22 | ||
| 23 | #include "clk-rcg.h" | 23 | #include "clk-rcg.h" |
| 24 | #include "common.h" | ||
| 24 | 25 | ||
| 25 | static u32 ns_to_src(struct src_sel *s, u32 ns) | 26 | static u32 ns_to_src(struct src_sel *s, u32 ns) |
| 26 | { | 27 | { |
| @@ -67,16 +68,16 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw) | |||
| 67 | { | 68 | { |
| 68 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); | 69 | struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); |
| 69 | int num_parents = __clk_get_num_parents(hw->clk); | 70 | int num_parents = __clk_get_num_parents(hw->clk); |
| 70 | u32 ns, ctl; | 71 | u32 ns, reg; |
| 71 | int bank; | 72 | int bank; |
| 72 | int i; | 73 | int i; |
| 73 | struct src_sel *s; | 74 | struct src_sel *s; |
| 74 | 75 | ||
| 75 | regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); | 76 | regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); |
| 76 | bank = reg_to_bank(rcg, ctl); | 77 | bank = reg_to_bank(rcg, reg); |
| 77 | s = &rcg->s[bank]; | 78 | s = &rcg->s[bank]; |
| 78 | 79 | ||
| 79 | regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); | 80 | regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); |
| 80 | ns = ns_to_src(s, ns); | 81 | ns = ns_to_src(s, ns); |
| 81 | 82 | ||
| 82 | for (i = 0; i < num_parents; i++) | 83 | for (i = 0; i < num_parents; i++) |
| @@ -192,90 +193,93 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val) | |||
