xref: /openbmc/linux/drivers/clk/zynqmp/pll.c (revision 413d6ed3)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Zynq UltraScale+ MPSoC PLL driver
4  *
5  *  Copyright (C) 2016-2018 Xilinx
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/slab.h>
11 #include "clk-zynqmp.h"
12 
13 /**
14  * struct zynqmp_pll - PLL clock
15  * @hw:		Handle between common and hardware-specific interfaces
16  * @clk_id:	PLL clock ID
17  * @set_pll_mode:	Whether an IOCTL_SET_PLL_FRAC_MODE request be sent to ATF
18  */
19 struct zynqmp_pll {
20 	struct clk_hw hw;
21 	u32 clk_id;
22 	bool set_pll_mode;
23 };
24 
25 #define to_zynqmp_pll(_hw)	container_of(_hw, struct zynqmp_pll, hw)
26 
27 #define PLL_FBDIV_MIN	25
28 #define PLL_FBDIV_MAX	125
29 
30 #define PS_PLL_VCO_MIN 1500000000
31 #define PS_PLL_VCO_MAX 3000000000UL
32 
33 enum pll_mode {
34 	PLL_MODE_INT,
35 	PLL_MODE_FRAC,
36 };
37 
38 #define FRAC_OFFSET 0x8
39 #define PLLFCFG_FRAC_EN	BIT(31)
40 #define FRAC_DIV  BIT(16)  /* 2^16 */
41 
42 /**
43  * zynqmp_pll_get_mode() - Get mode of PLL
44  * @hw:		Handle between common and hardware-specific interfaces
45  *
46  * Return: Mode of PLL
47  */
48 static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw)
49 {
50 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
51 	u32 clk_id = clk->clk_id;
52 	const char *clk_name = clk_hw_get_name(hw);
53 	u32 ret_payload[PAYLOAD_ARG_CNT];
54 	int ret;
55 
56 	ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload);
57 	if (ret)
58 		pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n",
59 			     __func__, clk_name, ret);
60 
61 	return ret_payload[1];
62 }
63 
64 /**
65  * zynqmp_pll_set_mode() - Set the PLL mode
66  * @hw:		Handle between common and hardware-specific interfaces
67  * @on:		Flag to determine the mode
68  */
69 static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on)
70 {
71 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
72 	u32 clk_id = clk->clk_id;
73 	const char *clk_name = clk_hw_get_name(hw);
74 	int ret;
75 	u32 mode;
76 
77 	if (on)
78 		mode = PLL_MODE_FRAC;
79 	else
80 		mode = PLL_MODE_INT;
81 
82 	ret = zynqmp_pm_set_pll_frac_mode(clk_id, mode);
83 	if (ret)
84 		pr_warn_once("%s() PLL set frac mode failed for %s, ret = %d\n",
85 			     __func__, clk_name, ret);
86 	else
87 		clk->set_pll_mode = true;
88 }
89 
90 /**
91  * zynqmp_pll_round_rate() - Round a clock frequency
92  * @hw:		Handle between common and hardware-specific interfaces
93  * @rate:	Desired clock frequency
94  * @prate:	Clock frequency of parent clock
95  *
96  * Return: Frequency closest to @rate the hardware can generate
97  */
98 static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
99 				  unsigned long *prate)
100 {
101 	u32 fbdiv;
102 	long rate_div, f;
103 
104 	/* Enable the fractional mode if needed */
105 	rate_div = (rate * FRAC_DIV) / *prate;
106 	f = rate_div % FRAC_DIV;
107 	if (f) {
108 		if (rate > PS_PLL_VCO_MAX) {
109 			fbdiv = rate / PS_PLL_VCO_MAX;
110 			rate = rate / (fbdiv + 1);
111 		}
112 		if (rate < PS_PLL_VCO_MIN) {
113 			fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate);
114 			rate = rate * fbdiv;
115 		}
116 		return rate;
117 	}
118 
119 	fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
120 	fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
121 	return *prate * fbdiv;
122 }
123 
124 /**
125  * zynqmp_pll_recalc_rate() - Recalculate clock frequency
126  * @hw:			Handle between common and hardware-specific interfaces
127  * @parent_rate:	Clock frequency of parent clock
128  *
129  * Return: Current clock frequency
130  */
131 static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
132 					    unsigned long parent_rate)
133 {
134 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
135 	u32 clk_id = clk->clk_id;
136 	const char *clk_name = clk_hw_get_name(hw);
137 	u32 fbdiv, data;
138 	unsigned long rate, frac;
139 	u32 ret_payload[PAYLOAD_ARG_CNT];
140 	int ret;
141 
142 	ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv);
143 	if (ret)
144 		pr_warn_once("%s() get divider failed for %s, ret = %d\n",
145 			     __func__, clk_name, ret);
146 
147 	rate =  parent_rate * fbdiv;
148 	if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
149 		zynqmp_pm_get_pll_frac_data(clk_id, ret_payload);
150 		data = ret_payload[1];
151 		frac = (parent_rate * data) / FRAC_DIV;
152 		rate = rate + frac;
153 	}
154 
155 	return rate;
156 }
157 
158 /**
159  * zynqmp_pll_set_rate() - Set rate of PLL
160  * @hw:			Handle between common and hardware-specific interfaces
161  * @rate:		Frequency of clock to be set
162  * @parent_rate:	Clock frequency of parent clock
163  *
164  * Set PLL divider to set desired rate.
165  *
166  * Returns:            rate which is set on success else error code
167  */
168 static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
169 			       unsigned long parent_rate)
170 {
171 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
172 	u32 clk_id = clk->clk_id;
173 	const char *clk_name = clk_hw_get_name(hw);
174 	u32 fbdiv;
175 	long rate_div, frac, m, f;
176 	int ret;
177 
178 	rate_div = (rate * FRAC_DIV) / parent_rate;
179 	f = rate_div % FRAC_DIV;
180 	zynqmp_pll_set_mode(hw, !!f);
181 
182 	if (f) {
183 		m = rate_div / FRAC_DIV;
184 		m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX));
185 		rate = parent_rate * m;
186 		frac = (parent_rate * f) / FRAC_DIV;
187 
188 		ret = zynqmp_pm_clock_setdivider(clk_id, m);
189 		if (ret == -EUSERS)
190 			WARN(1, "More than allowed devices are using the %s, which is forbidden\n",
191 			     clk_name);
192 		else if (ret)
193 			pr_warn_once("%s() set divider failed for %s, ret = %d\n",
194 				     __func__, clk_name, ret);
195 		zynqmp_pm_set_pll_frac_data(clk_id, f);
196 
197 		return rate + frac;
198 	}
199 
200 	fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate);
201 	fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
202 	ret = zynqmp_pm_clock_setdivider(clk_id, fbdiv);
203 	if (ret)
204 		pr_warn_once("%s() set divider failed for %s, ret = %d\n",
205 			     __func__, clk_name, ret);
206 
207 	return parent_rate * fbdiv;
208 }
209 
210 /**
211  * zynqmp_pll_is_enabled() - Check if a clock is enabled
212  * @hw:		Handle between common and hardware-specific interfaces
213  *
214  * Return: 1 if the clock is enabled, 0 otherwise
215  */
216 static int zynqmp_pll_is_enabled(struct clk_hw *hw)
217 {
218 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
219 	const char *clk_name = clk_hw_get_name(hw);
220 	u32 clk_id = clk->clk_id;
221 	unsigned int state;
222 	int ret;
223 
224 	ret = zynqmp_pm_clock_getstate(clk_id, &state);
225 	if (ret) {
226 		pr_warn_once("%s() clock get state failed for %s, ret = %d\n",
227 			     __func__, clk_name, ret);
228 		return -EIO;
229 	}
230 
231 	return state ? 1 : 0;
232 }
233 
234 /**
235  * zynqmp_pll_enable() - Enable clock
236  * @hw:		Handle between common and hardware-specific interfaces
237  *
238  * Return: 0 on success else error code
239  */
240 static int zynqmp_pll_enable(struct clk_hw *hw)
241 {
242 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
243 	const char *clk_name = clk_hw_get_name(hw);
244 	u32 clk_id = clk->clk_id;
245 	int ret;
246 
247 	/*
248 	 * Don't skip enabling clock if there is an IOCTL_SET_PLL_FRAC_MODE request
249 	 * that has been sent to ATF.
250 	 */
251 	if (zynqmp_pll_is_enabled(hw) && (!clk->set_pll_mode))
252 		return 0;
253 
254 	clk->set_pll_mode = false;
255 
256 	ret = zynqmp_pm_clock_enable(clk_id);
257 	if (ret)
258 		pr_warn_once("%s() clock enable failed for %s, ret = %d\n",
259 			     __func__, clk_name, ret);
260 
261 	return ret;
262 }
263 
264 /**
265  * zynqmp_pll_disable() - Disable clock
266  * @hw:		Handle between common and hardware-specific interfaces
267  */
268 static void zynqmp_pll_disable(struct clk_hw *hw)
269 {
270 	struct zynqmp_pll *clk = to_zynqmp_pll(hw);
271 	const char *clk_name = clk_hw_get_name(hw);
272 	u32 clk_id = clk->clk_id;
273 	int ret;
274 
275 	if (!zynqmp_pll_is_enabled(hw))
276 		return;
277 
278 	ret = zynqmp_pm_clock_disable(clk_id);
279 	if (ret)
280 		pr_warn_once("%s() clock disable failed for %s, ret = %d\n",
281 			     __func__, clk_name, ret);
282 }
283 
284 static const struct clk_ops zynqmp_pll_ops = {
285 	.enable = zynqmp_pll_enable,
286 	.disable = zynqmp_pll_disable,
287 	.is_enabled = zynqmp_pll_is_enabled,
288 	.round_rate = zynqmp_pll_round_rate,
289 	.recalc_rate = zynqmp_pll_recalc_rate,
290 	.set_rate = zynqmp_pll_set_rate,
291 };
292 
293 /**
294  * zynqmp_clk_register_pll() - Register PLL with the clock framework
295  * @name:		PLL name
296  * @clk_id:		Clock ID
297  * @parents:		Name of this clock's parents
298  * @num_parents:	Number of parents
299  * @nodes:		Clock topology node
300  *
301  * Return: clock hardware to the registered clock
302  */
303 struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
304 				       const char * const *parents,
305 				       u8 num_parents,
306 				       const struct clock_topology *nodes)
307 {
308 	struct zynqmp_pll *pll;
309 	struct clk_hw *hw;
310 	struct clk_init_data init;
311 	int ret;
312 
313 	init.name = name;
314 	init.ops = &zynqmp_pll_ops;
315 	init.flags = nodes->flag;
316 	init.parent_names = parents;
317 	init.num_parents = 1;
318 
319 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
320 	if (!pll)
321 		return ERR_PTR(-ENOMEM);
322 
323 	pll->hw.init = &init;
324 	pll->clk_id = clk_id;
325 
326 	hw = &pll->hw;
327 	ret = clk_hw_register(NULL, hw);
328 	if (ret) {
329 		kfree(pll);
330 		return ERR_PTR(ret);
331 	}
332 
333 	clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX);
334 	if (ret < 0)
335 		pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret);
336 
337 	return hw;
338 }
339