xref: /openbmc/linux/drivers/clk/qcom/clk-pll.c (revision 9c92ab61)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/bitops.h>
8 #include <linux/err.h>
9 #include <linux/bug.h>
10 #include <linux/delay.h>
11 #include <linux/export.h>
12 #include <linux/clk-provider.h>
13 #include <linux/regmap.h>
14 
15 #include <asm/div64.h>
16 
17 #include "clk-pll.h"
18 #include "common.h"
19 
20 #define PLL_OUTCTRL		BIT(0)
21 #define PLL_BYPASSNL		BIT(1)
22 #define PLL_RESET_N		BIT(2)
23 
clk_pll_enable(struct clk_hw * hw)24 static int clk_pll_enable(struct clk_hw *hw)
25 {
26 	struct clk_pll *pll = to_clk_pll(hw);
27 	int ret;
28 	u32 mask, val;
29 
30 	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
31 	ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &val);
32 	if (ret)
33 		return ret;
34 
35 	/* Skip if already enabled or in FSM mode */
36 	if ((val & mask) == mask || val & PLL_VOTE_FSM_ENA)
37 		return 0;
38 
39 	/* Disable PLL bypass mode. */
40 	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
41 				 PLL_BYPASSNL);
42 	if (ret)
43 		return ret;
44 
45 	/*
46 	 * H/W requires a 5us delay between disabling the bypass and
47 	 * de-asserting the reset. Delay 10us just to be safe.
48 	 */
49 	udelay(10);
50 
51 	/* De-assert active-low PLL reset. */
52 	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
53 				 PLL_RESET_N);
54 	if (ret)
55 		return ret;
56 
57 	/* Wait until PLL is locked. */
58 	udelay(50);
59 
60 	/* Enable PLL output. */
61 	return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
62 				 PLL_OUTCTRL);
63 }
64 
clk_pll_disable(struct clk_hw * hw)65 static void clk_pll_disable(struct clk_hw *hw)
66 {
67 	struct clk_pll *pll = to_clk_pll(hw);
68 	u32 mask;
69 	u32 val;
70 
71 	regmap_read(pll->clkr.regmap, pll->mode_reg, &val);
72 	/* Skip if in FSM mode */
73 	if (val & PLL_VOTE_FSM_ENA)
74 		return;
75 	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
76 	regmap_update_bits(pll->clkr.regmap, pll->mode_reg, mask, 0);
77 }
78 
79 static unsigned long
clk_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)80 clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
81 {
82 	struct clk_pll *pll = to_clk_pll(hw);
83 	u32 l, m, n, config;
84 	unsigned long rate;
85 	u64 tmp;
86 
87 	regmap_read(pll->clkr.regmap, pll->l_reg, &l);
88 	regmap_read(pll->clkr.regmap, pll->m_reg, &m);
89 	regmap_read(pll->clkr.regmap, pll->n_reg, &n);
90 
91 	l &= 0x3ff;
92 	m &= 0x7ffff;
93 	n &= 0x7ffff;
94 
95 	rate = parent_rate * l;
96 	if (n) {
97 		tmp = parent_rate;
98 		tmp *= m;
99 		do_div(tmp, n);
100 		rate += tmp;
101 	}
102 	if (pll->post_div_width) {
103 		regmap_read(pll->clkr.regmap, pll->config_reg, &config);
104 		config >>= pll->post_div_shift;
105 		config &= BIT(pll->post_div_width) - 1;
106 		rate /= config + 1;
107 	}
108 
109 	return rate;
110 }
111 
112 static const
find_freq(const struct pll_freq_tbl * f,unsigned long rate)113 struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
114 {
115 	if (!f)
116 		return NULL;
117 
118 	for (; f->freq; f++)
119 		if (rate <= f->freq)
120 			return f;
121 
122 	return NULL;
123 }
124 
125 static int
clk_pll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)126 clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
127 {
128 	struct clk_pll *pll = to_clk_pll(hw);
129 	const struct pll_freq_tbl *f;
130 
131 	f = find_freq(pll->freq_tbl, req->rate);
132 	if (!f)
133 		req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
134 	else
135 		req->rate = f->freq;
136 
137 	return 0;
138 }
139 
140 static int
clk_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long p_rate)141 clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
142 {
143 	struct clk_pll *pll = to_clk_pll(hw);
144 	const struct pll_freq_tbl *f;
145 	bool enabled;
146 	u32 mode;
147 	u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
148 
149 	f = find_freq(pll->freq_tbl, rate);
150 	if (!f)
151 		return -EINVAL;
152 
153 	regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
154 	enabled = (mode & enable_mask) == enable_mask;
155 
156 	if (enabled)
157 		clk_pll_disable(hw);
158 
159 	regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
160 	regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
161 	regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
162 	regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
163 
164 	if (enabled)
165 		clk_pll_enable(hw);
166 
167 	return 0;
168 }
169 
170 const struct clk_ops clk_pll_ops = {
171 	.enable = clk_pll_enable,
172 	.disable = clk_pll_disable,
173 	.recalc_rate = clk_pll_recalc_rate,
174 	.determine_rate = clk_pll_determine_rate,
175 	.set_rate = clk_pll_set_rate,
176 };
177 EXPORT_SYMBOL_GPL(clk_pll_ops);
178 
wait_for_pll(struct clk_pll * pll)179 static int wait_for_pll(struct clk_pll *pll)
180 {
181 	u32 val;
182 	int count;
183 	int ret;
184 	const char *name = clk_hw_get_name(&pll->clkr.hw);
185 
186 	/* Wait for pll to enable. */
187 	for (count = 200; count > 0; count--) {
188 		ret = regmap_read(pll->clkr.regmap, pll->status_reg, &val);
189 		if (ret)
190 			return ret;
191 		if (val & BIT(pll->status_bit))
192 			return 0;
193 		udelay(1);
194 	}
195 
196 	WARN(1, "%s didn't enable after voting for it!\n", name);
197 	return -ETIMEDOUT;
198 }
199 
clk_pll_vote_enable(struct clk_hw * hw)200 static int clk_pll_vote_enable(struct clk_hw *hw)
201 {
202 	int ret;
203 	struct clk_pll *p = to_clk_pll(clk_hw_get_parent(hw));
204 
205 	ret = clk_enable_regmap(hw);
206 	if (ret)
207 		return ret;
208 
209 	return wait_for_pll(p);
210 }
211 
212 const struct clk_ops clk_pll_vote_ops = {
213 	.enable = clk_pll_vote_enable,
214 	.disable = clk_disable_regmap,
215 };
216 EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
217 
clk_pll_configure(struct clk_pll * pll,struct regmap * regmap,const struct pll_config * config)218 static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
219 	const struct pll_config *config)
220 {
221 	u32 val;
222 	u32 mask;
223 
224 	regmap_write(regmap, pll->l_reg, config->l);
225 	regmap_write(regmap, pll->m_reg, config->m);
226 	regmap_write(regmap, pll->n_reg, config->n);
227 
228 	val = config->vco_val;
229 	val |= config->pre_div_val;
230 	val |= config->post_div_val;
231 	val |= config->mn_ena_mask;
232 	val |= config->main_output_mask;
233 	val |= config->aux_output_mask;
234 
235 	mask = config->vco_mask;
236 	mask |= config->pre_div_mask;
237 	mask |= config->post_div_mask;
238 	mask |= config->mn_ena_mask;
239 	mask |= config->main_output_mask;
240 	mask |= config->aux_output_mask;
241 
242 	regmap_update_bits(regmap, pll->config_reg, mask, val);
243 }
244 
clk_pll_configure_sr(struct clk_pll * pll,struct regmap * regmap,const struct pll_config * config,bool fsm_mode)245 void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
246 		const struct pll_config *config, bool fsm_mode)
247 {
248 	clk_pll_configure(pll, regmap, config);
249 	if (fsm_mode)
250 		qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8);
251 }
252 EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
253 
clk_pll_configure_sr_hpm_lp(struct clk_pll * pll,struct regmap * regmap,const struct pll_config * config,bool fsm_mode)254 void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
255 		const struct pll_config *config, bool fsm_mode)
256 {
257 	clk_pll_configure(pll, regmap, config);
258 	if (fsm_mode)
259 		qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0);
260 }
261 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
262 
clk_pll_sr2_enable(struct clk_hw * hw)263 static int clk_pll_sr2_enable(struct clk_hw *hw)
264 {
265 	struct clk_pll *pll = to_clk_pll(hw);
266 	int ret;
267 	u32 mode;
268 
269 	ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
270 	if (ret)
271 		return ret;
272 
273 	/* Disable PLL bypass mode. */
274 	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
275 				 PLL_BYPASSNL);
276 	if (ret)
277 		return ret;
278 
279 	/*
280 	 * H/W requires a 5us delay between disabling the bypass and
281 	 * de-asserting the reset. Delay 10us just to be safe.
282 	 */
283 	udelay(10);
284 
285 	/* De-assert active-low PLL reset. */
286 	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
287 				 PLL_RESET_N);
288 	if (ret)
289 		return ret;
290 
291 	ret = wait_for_pll(pll);
292 	if (ret)
293 		return ret;
294 
295 	/* Enable PLL output. */
296 	return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
297 				 PLL_OUTCTRL);
298 }
299 
300 static int
clk_pll_sr2_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long prate)301 clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
302 {
303 	struct clk_pll *pll = to_clk_pll(hw);
304 	const struct pll_freq_tbl *f;
305 	bool enabled;
306 	u32 mode;
307 	u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
308 
309 	f = find_freq(pll->freq_tbl, rate);
310 	if (!f)
311 		return -EINVAL;
312 
313 	regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
314 	enabled = (mode & enable_mask) == enable_mask;
315 
316 	if (enabled)
317 		clk_pll_disable(hw);
318 
319 	regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
320 	regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
321 	regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
322 
323 	if (enabled)
324 		clk_pll_sr2_enable(hw);
325 
326 	return 0;
327 }
328 
329 const struct clk_ops clk_pll_sr2_ops = {
330 	.enable = clk_pll_sr2_enable,
331 	.disable = clk_pll_disable,
332 	.set_rate = clk_pll_sr2_set_rate,
333 	.recalc_rate = clk_pll_recalc_rate,
334 	.determine_rate = clk_pll_determine_rate,
335 };
336 EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
337