xref: /linux/drivers/clk/sophgo/clk-sg2044-pll.c (revision 9f32a03e3e0d372c520d829dd4da6022fe88832a)
1*ff524079SInochi Amaoto // SPDX-License-Identifier: GPL-2.0
2*ff524079SInochi Amaoto /*
3*ff524079SInochi Amaoto  * Sophgo SG2044 PLL clock controller driver
4*ff524079SInochi Amaoto  *
5*ff524079SInochi Amaoto  * Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com>
6*ff524079SInochi Amaoto  */
7*ff524079SInochi Amaoto 
8*ff524079SInochi Amaoto #include <linux/array_size.h>
9*ff524079SInochi Amaoto #include <linux/bitfield.h>
10*ff524079SInochi Amaoto #include <linux/bits.h>
11*ff524079SInochi Amaoto #include <linux/cleanup.h>
12*ff524079SInochi Amaoto #include <linux/clk.h>
13*ff524079SInochi Amaoto #include <linux/clk-provider.h>
14*ff524079SInochi Amaoto #include <linux/io.h>
15*ff524079SInochi Amaoto #include <linux/iopoll.h>
16*ff524079SInochi Amaoto #include <linux/math64.h>
17*ff524079SInochi Amaoto #include <linux/mfd/syscon.h>
18*ff524079SInochi Amaoto #include <linux/platform_device.h>
19*ff524079SInochi Amaoto #include <linux/regmap.h>
20*ff524079SInochi Amaoto #include <linux/spinlock.h>
21*ff524079SInochi Amaoto 
22*ff524079SInochi Amaoto #include <dt-bindings/clock/sophgo,sg2044-pll.h>
23*ff524079SInochi Amaoto 
24*ff524079SInochi Amaoto /* Low Control part */
25*ff524079SInochi Amaoto #define PLL_VCOSEL_MASK		GENMASK(17, 16)
26*ff524079SInochi Amaoto 
27*ff524079SInochi Amaoto /* High Control part */
28*ff524079SInochi Amaoto #define PLL_FBDIV_MASK		GENMASK(11, 0)
29*ff524079SInochi Amaoto #define PLL_REFDIV_MASK		GENMASK(17, 12)
30*ff524079SInochi Amaoto #define PLL_POSTDIV1_MASK	GENMASK(20, 18)
31*ff524079SInochi Amaoto #define PLL_POSTDIV2_MASK	GENMASK(23, 21)
32*ff524079SInochi Amaoto 
33*ff524079SInochi Amaoto #define PLL_CALIBRATE_EN	BIT(24)
34*ff524079SInochi Amaoto #define PLL_CALIBRATE_MASK	GENMASK(29, 27)
35*ff524079SInochi Amaoto #define PLL_CALIBRATE_DEFAULT	FIELD_PREP(PLL_CALIBRATE_MASK, 2)
36*ff524079SInochi Amaoto #define PLL_UPDATE_EN		BIT(30)
37*ff524079SInochi Amaoto 
38*ff524079SInochi Amaoto #define PLL_HIGH_CTRL_MASK	\
39*ff524079SInochi Amaoto 	(PLL_FBDIV_MASK | PLL_REFDIV_MASK | \
40*ff524079SInochi Amaoto 	 PLL_POSTDIV1_MASK | PLL_POSTDIV2_MASK | \
41*ff524079SInochi Amaoto 	 PLL_CALIBRATE_EN | PLL_CALIBRATE_MASK | \
42*ff524079SInochi Amaoto 	 PLL_UPDATE_EN)
43*ff524079SInochi Amaoto 
44*ff524079SInochi Amaoto #define PLL_HIGH_CTRL_OFFSET	4
45*ff524079SInochi Amaoto 
46*ff524079SInochi Amaoto #define PLL_VCOSEL_1G6		0x2
47*ff524079SInochi Amaoto #define PLL_VCOSEL_2G4		0x3
48*ff524079SInochi Amaoto 
49*ff524079SInochi Amaoto #define PLL_LIMIT_FOUTVCO	0
50*ff524079SInochi Amaoto #define PLL_LIMIT_FOUT		1
51*ff524079SInochi Amaoto #define PLL_LIMIT_REFDIV	2
52*ff524079SInochi Amaoto #define PLL_LIMIT_FBDIV		3
53*ff524079SInochi Amaoto #define PLL_LIMIT_POSTDIV1	4
54*ff524079SInochi Amaoto #define PLL_LIMIT_POSTDIV2	5
55*ff524079SInochi Amaoto 
56*ff524079SInochi Amaoto #define for_each_pll_limit_range(_var, _limit) \
57*ff524079SInochi Amaoto 	for (_var = (_limit)->min; _var <= (_limit)->max; _var++)
58*ff524079SInochi Amaoto 
59*ff524079SInochi Amaoto struct sg2044_pll_limit {
60*ff524079SInochi Amaoto 	u64 min;
61*ff524079SInochi Amaoto 	u64 max;
62*ff524079SInochi Amaoto };
63*ff524079SInochi Amaoto 
64*ff524079SInochi Amaoto struct sg2044_pll_internal {
65*ff524079SInochi Amaoto 	u32 ctrl_offset;
66*ff524079SInochi Amaoto 	u32 status_offset;
67*ff524079SInochi Amaoto 	u32 enable_offset;
68*ff524079SInochi Amaoto 
69*ff524079SInochi Amaoto 	u8 status_lock_bit;
70*ff524079SInochi Amaoto 	u8 status_updating_bit;
71*ff524079SInochi Amaoto 	u8 enable_bit;
72*ff524079SInochi Amaoto 
73*ff524079SInochi Amaoto 	const struct sg2044_pll_limit *limits;
74*ff524079SInochi Amaoto };
75*ff524079SInochi Amaoto 
76*ff524079SInochi Amaoto struct sg2044_clk_common {
77*ff524079SInochi Amaoto 	struct clk_hw	hw;
78*ff524079SInochi Amaoto 	struct regmap	*regmap;
79*ff524079SInochi Amaoto 	spinlock_t	*lock;
80*ff524079SInochi Amaoto 	unsigned int	id;
81*ff524079SInochi Amaoto };
82*ff524079SInochi Amaoto 
83*ff524079SInochi Amaoto struct sg2044_pll {
84*ff524079SInochi Amaoto 	struct sg2044_clk_common	common;
85*ff524079SInochi Amaoto 	struct sg2044_pll_internal	pll;
86*ff524079SInochi Amaoto 	unsigned int			syscon_offset;
87*ff524079SInochi Amaoto };
88*ff524079SInochi Amaoto 
89*ff524079SInochi Amaoto struct sg2044_pll_desc_data {
90*ff524079SInochi Amaoto 	struct sg2044_clk_common	* const *pll;
91*ff524079SInochi Amaoto 	u16				num_pll;
92*ff524079SInochi Amaoto };
93*ff524079SInochi Amaoto 
94*ff524079SInochi Amaoto #define SG2044_SYSCON_PLL_OFFSET	0x98
95*ff524079SInochi Amaoto 
96*ff524079SInochi Amaoto struct sg2044_pll_ctrl {
97*ff524079SInochi Amaoto 	spinlock_t			lock;
98*ff524079SInochi Amaoto 	struct clk_hw_onecell_data	data;
99*ff524079SInochi Amaoto };
100*ff524079SInochi Amaoto 
101*ff524079SInochi Amaoto #define hw_to_sg2044_clk_common(_hw)					\
102*ff524079SInochi Amaoto 	container_of((_hw), struct sg2044_clk_common, hw)
103*ff524079SInochi Amaoto 
sg2044_clk_fit_limit(u64 value,const struct sg2044_pll_limit * limit)104*ff524079SInochi Amaoto static inline bool sg2044_clk_fit_limit(u64 value,
105*ff524079SInochi Amaoto 					const struct sg2044_pll_limit *limit)
106*ff524079SInochi Amaoto {
107*ff524079SInochi Amaoto 	return value >= limit->min && value <= limit->max;
108*ff524079SInochi Amaoto }
109*ff524079SInochi Amaoto 
hw_to_sg2044_pll(struct clk_hw * hw)110*ff524079SInochi Amaoto static inline struct sg2044_pll *hw_to_sg2044_pll(struct clk_hw *hw)
111*ff524079SInochi Amaoto {
112*ff524079SInochi Amaoto 	return container_of(hw_to_sg2044_clk_common(hw),
113*ff524079SInochi Amaoto 			    struct sg2044_pll, common);
114*ff524079SInochi Amaoto }
115*ff524079SInochi Amaoto 
sg2044_pll_calc_vco_rate(unsigned long parent_rate,unsigned long refdiv,unsigned long fbdiv)116*ff524079SInochi Amaoto static unsigned long sg2044_pll_calc_vco_rate(unsigned long parent_rate,
117*ff524079SInochi Amaoto 					      unsigned long refdiv,
118*ff524079SInochi Amaoto 					      unsigned long fbdiv)
119*ff524079SInochi Amaoto {
120*ff524079SInochi Amaoto 	u64 numerator = parent_rate * fbdiv;
121*ff524079SInochi Amaoto 
122*ff524079SInochi Amaoto 	return div64_ul(numerator, refdiv);
123*ff524079SInochi Amaoto }
124*ff524079SInochi Amaoto 
sg2044_pll_calc_rate(unsigned long parent_rate,unsigned long refdiv,unsigned long fbdiv,unsigned long postdiv1,unsigned long postdiv2)125*ff524079SInochi Amaoto static unsigned long sg2044_pll_calc_rate(unsigned long parent_rate,
126*ff524079SInochi Amaoto 					  unsigned long refdiv,
127*ff524079SInochi Amaoto 					  unsigned long fbdiv,
128*ff524079SInochi Amaoto 					  unsigned long postdiv1,
129*ff524079SInochi Amaoto 					  unsigned long postdiv2)
130*ff524079SInochi Amaoto {
131*ff524079SInochi Amaoto 	u64 numerator, denominator;
132*ff524079SInochi Amaoto 
133*ff524079SInochi Amaoto 	numerator = parent_rate * fbdiv;
134*ff524079SInochi Amaoto 	denominator = refdiv * (postdiv1 + 1) * (postdiv2 + 1);
135*ff524079SInochi Amaoto 
136*ff524079SInochi Amaoto 	return div64_u64(numerator, denominator);
137*ff524079SInochi Amaoto }
138*ff524079SInochi Amaoto 
sg2044_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)139*ff524079SInochi Amaoto static unsigned long sg2044_pll_recalc_rate(struct clk_hw *hw,
140*ff524079SInochi Amaoto 					    unsigned long parent_rate)
141*ff524079SInochi Amaoto {
142*ff524079SInochi Amaoto 	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
143*ff524079SInochi Amaoto 	u32 value;
144*ff524079SInochi Amaoto 	int ret;
145*ff524079SInochi Amaoto 
146*ff524079SInochi Amaoto 	ret = regmap_read(pll->common.regmap,
147*ff524079SInochi Amaoto 			  pll->syscon_offset + pll->pll.ctrl_offset + PLL_HIGH_CTRL_OFFSET,
148*ff524079SInochi Amaoto 			  &value);
149*ff524079SInochi Amaoto 	if (ret < 0)
150*ff524079SInochi Amaoto 		return 0;
151*ff524079SInochi Amaoto 
152*ff524079SInochi Amaoto 	return sg2044_pll_calc_rate(parent_rate,
153*ff524079SInochi Amaoto 				    FIELD_GET(PLL_REFDIV_MASK, value),
154*ff524079SInochi Amaoto 				    FIELD_GET(PLL_FBDIV_MASK, value),
155*ff524079SInochi Amaoto 				    FIELD_GET(PLL_POSTDIV1_MASK, value),
156*ff524079SInochi Amaoto 				    FIELD_GET(PLL_POSTDIV2_MASK, value));
157*ff524079SInochi Amaoto }
158*ff524079SInochi Amaoto 
pll_is_better_rate(unsigned long target,unsigned long now,unsigned long best)159*ff524079SInochi Amaoto static bool pll_is_better_rate(unsigned long target, unsigned long now,
160*ff524079SInochi Amaoto 			       unsigned long best)
161*ff524079SInochi Amaoto {
162*ff524079SInochi Amaoto 	return abs_diff(target, now) < abs_diff(target, best);
163*ff524079SInochi Amaoto }
164*ff524079SInochi Amaoto 
sg2042_pll_compute_postdiv(const struct sg2044_pll_limit * limits,unsigned long target,unsigned long parent_rate,unsigned int refdiv,unsigned int fbdiv,unsigned int * postdiv1,unsigned int * postdiv2)165*ff524079SInochi Amaoto static int sg2042_pll_compute_postdiv(const struct sg2044_pll_limit *limits,
166*ff524079SInochi Amaoto 				      unsigned long target,
167*ff524079SInochi Amaoto 				      unsigned long parent_rate,
168*ff524079SInochi Amaoto 				      unsigned int refdiv,
169*ff524079SInochi Amaoto 				      unsigned int fbdiv,
170*ff524079SInochi Amaoto 				      unsigned int *postdiv1,
171*ff524079SInochi Amaoto 				      unsigned int *postdiv2)
172*ff524079SInochi Amaoto {
173*ff524079SInochi Amaoto 	unsigned int div1, div2;
174*ff524079SInochi Amaoto 	unsigned long tmp, best_rate = 0;
175*ff524079SInochi Amaoto 	unsigned int best_div1 = 0, best_div2 = 0;
176*ff524079SInochi Amaoto 
177*ff524079SInochi Amaoto 	for_each_pll_limit_range(div2, &limits[PLL_LIMIT_POSTDIV2]) {
178*ff524079SInochi Amaoto 		for_each_pll_limit_range(div1, &limits[PLL_LIMIT_POSTDIV1]) {
179*ff524079SInochi Amaoto 			tmp = sg2044_pll_calc_rate(parent_rate,
180*ff524079SInochi Amaoto 						   refdiv, fbdiv,
181*ff524079SInochi Amaoto 						   div1, div2);
182*ff524079SInochi Amaoto 
183*ff524079SInochi Amaoto 			if (tmp > target)
184*ff524079SInochi Amaoto 				continue;
185*ff524079SInochi Amaoto 
186*ff524079SInochi Amaoto 			if (pll_is_better_rate(target, tmp, best_rate)) {
187*ff524079SInochi Amaoto 				best_div1 = div1;
188*ff524079SInochi Amaoto 				best_div2 = div2;
189*ff524079SInochi Amaoto 				best_rate = tmp;
190*ff524079SInochi Amaoto 
191*ff524079SInochi Amaoto 				if (tmp == target)
192*ff524079SInochi Amaoto 					goto find;
193*ff524079SInochi Amaoto 			}
194*ff524079SInochi Amaoto 		}
195*ff524079SInochi Amaoto 	}
196*ff524079SInochi Amaoto 
197*ff524079SInochi Amaoto find:
198*ff524079SInochi Amaoto 	if (best_rate) {
199*ff524079SInochi Amaoto 		*postdiv1 = best_div1;
200*ff524079SInochi Amaoto 		*postdiv2 = best_div2;
201*ff524079SInochi Amaoto 		return 0;
202*ff524079SInochi Amaoto 	}
203*ff524079SInochi Amaoto 
204*ff524079SInochi Amaoto 	return -EINVAL;
205*ff524079SInochi Amaoto }
206*ff524079SInochi Amaoto 
sg2044_compute_pll_setting(const struct sg2044_pll_limit * limits,unsigned long req_rate,unsigned long parent_rate,unsigned int * value)207*ff524079SInochi Amaoto static int sg2044_compute_pll_setting(const struct sg2044_pll_limit *limits,
208*ff524079SInochi Amaoto 				      unsigned long req_rate,
209*ff524079SInochi Amaoto 				      unsigned long parent_rate,
210*ff524079SInochi Amaoto 				      unsigned int *value)
211*ff524079SInochi Amaoto {
212*ff524079SInochi Amaoto 	unsigned int refdiv, fbdiv, postdiv1, postdiv2;
213*ff524079SInochi Amaoto 	unsigned int best_refdiv, best_fbdiv, best_postdiv1, best_postdiv2;
214*ff524079SInochi Amaoto 	unsigned long tmp, best_rate = 0;
215*ff524079SInochi Amaoto 	int ret;
216*ff524079SInochi Amaoto 
217*ff524079SInochi Amaoto 	for_each_pll_limit_range(fbdiv, &limits[PLL_LIMIT_FBDIV]) {
218*ff524079SInochi Amaoto 		for_each_pll_limit_range(refdiv, &limits[PLL_LIMIT_REFDIV]) {
219*ff524079SInochi Amaoto 			u64 vco = sg2044_pll_calc_vco_rate(parent_rate,
220*ff524079SInochi Amaoto 							   refdiv, fbdiv);
221*ff524079SInochi Amaoto 			if (!sg2044_clk_fit_limit(vco, &limits[PLL_LIMIT_FOUTVCO]))
222*ff524079SInochi Amaoto 				continue;
223*ff524079SInochi Amaoto 
224*ff524079SInochi Amaoto 			ret = sg2042_pll_compute_postdiv(limits,
225*ff524079SInochi Amaoto 							 req_rate, parent_rate,
226*ff524079SInochi Amaoto 							 refdiv, fbdiv,
227*ff524079SInochi Amaoto 							 &postdiv1, &postdiv2);
228*ff524079SInochi Amaoto 			if (ret)
229*ff524079SInochi Amaoto 				continue;
230*ff524079SInochi Amaoto 
231*ff524079SInochi Amaoto 			tmp = sg2044_pll_calc_rate(parent_rate,
232*ff524079SInochi Amaoto 						   refdiv, fbdiv,
233*ff524079SInochi Amaoto 						   postdiv1, postdiv2);
234*ff524079SInochi Amaoto 
235*ff524079SInochi Amaoto 			if (pll_is_better_rate(req_rate, tmp, best_rate)) {
236*ff524079SInochi Amaoto 				best_refdiv = refdiv;
237*ff524079SInochi Amaoto 				best_fbdiv = fbdiv;
238*ff524079SInochi Amaoto 				best_postdiv1 = postdiv1;
239*ff524079SInochi Amaoto 				best_postdiv2 = postdiv2;
240*ff524079SInochi Amaoto 				best_rate = tmp;
241*ff524079SInochi Amaoto 
242*ff524079SInochi Amaoto 				if (tmp == req_rate)
243*ff524079SInochi Amaoto 					goto find;
244*ff524079SInochi Amaoto 			}
245*ff524079SInochi Amaoto 		}
246*ff524079SInochi Amaoto 	}
247*ff524079SInochi Amaoto 
248*ff524079SInochi Amaoto find:
249*ff524079SInochi Amaoto 	if (best_rate) {
250*ff524079SInochi Amaoto 		*value = FIELD_PREP(PLL_REFDIV_MASK, best_refdiv) |
251*ff524079SInochi Amaoto 			 FIELD_PREP(PLL_FBDIV_MASK, best_fbdiv) |
252*ff524079SInochi Amaoto 			 FIELD_PREP(PLL_POSTDIV1_MASK, best_postdiv1) |
253*ff524079SInochi Amaoto 			 FIELD_PREP(PLL_POSTDIV2_MASK, best_postdiv2);
254*ff524079SInochi Amaoto 		return 0;
255*ff524079SInochi Amaoto 	}
256*ff524079SInochi Amaoto 
257*ff524079SInochi Amaoto 	return -EINVAL;
258*ff524079SInochi Amaoto }
259*ff524079SInochi Amaoto 
sg2044_pll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)260*ff524079SInochi Amaoto static int sg2044_pll_determine_rate(struct clk_hw *hw,
261*ff524079SInochi Amaoto 				     struct clk_rate_request *req)
262*ff524079SInochi Amaoto {
263*ff524079SInochi Amaoto 	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
264*ff524079SInochi Amaoto 	unsigned int value;
265*ff524079SInochi Amaoto 	u64 target;
266*ff524079SInochi Amaoto 	int ret;
267*ff524079SInochi Amaoto 
268*ff524079SInochi Amaoto 	target = clamp(req->rate, pll->pll.limits[PLL_LIMIT_FOUT].min,
269*ff524079SInochi Amaoto 		       pll->pll.limits[PLL_LIMIT_FOUT].max);
270*ff524079SInochi Amaoto 
271*ff524079SInochi Amaoto 	ret = sg2044_compute_pll_setting(pll->pll.limits, target,
272*ff524079SInochi Amaoto 					 req->best_parent_rate, &value);
273*ff524079SInochi Amaoto 	if (ret < 0)
274*ff524079SInochi Amaoto 		return ret;
275*ff524079SInochi Amaoto 
276*ff524079SInochi Amaoto 	req->rate = sg2044_pll_calc_rate(req->best_parent_rate,
277*ff524079SInochi Amaoto 					 FIELD_GET(PLL_REFDIV_MASK, value),
278*ff524079SInochi Amaoto 					 FIELD_GET(PLL_FBDIV_MASK, value),
279*ff524079SInochi Amaoto 					 FIELD_GET(PLL_POSTDIV1_MASK, value),
280*ff524079SInochi Amaoto 					 FIELD_GET(PLL_POSTDIV2_MASK, value));
281*ff524079SInochi Amaoto 
282*ff524079SInochi Amaoto 	return 0;
283*ff524079SInochi Amaoto }
284*ff524079SInochi Amaoto 
sg2044_pll_poll_update(struct sg2044_pll * pll)285*ff524079SInochi Amaoto static int sg2044_pll_poll_update(struct sg2044_pll *pll)
286*ff524079SInochi Amaoto {
287*ff524079SInochi Amaoto 	int ret;
288*ff524079SInochi Amaoto 	unsigned int value;
289*ff524079SInochi Amaoto 
290*ff524079SInochi Amaoto 	ret = regmap_read_poll_timeout_atomic(pll->common.regmap,
291*ff524079SInochi Amaoto 					      pll->syscon_offset + pll->pll.status_offset,
292*ff524079SInochi Amaoto 					      value,
293*ff524079SInochi Amaoto 					      (value & BIT(pll->pll.status_lock_bit)),
294*ff524079SInochi Amaoto 					      1, 100000);
295*ff524079SInochi Amaoto 	if (ret)
296*ff524079SInochi Amaoto 		return ret;
297*ff524079SInochi Amaoto 
298*ff524079SInochi Amaoto 	return regmap_read_poll_timeout_atomic(pll->common.regmap,
299*ff524079SInochi Amaoto 					       pll->syscon_offset + pll->pll.status_offset,
300*ff524079SInochi Amaoto 					       value,
301*ff524079SInochi Amaoto 					       (!(value & BIT(pll->pll.status_updating_bit))),
302*ff524079SInochi Amaoto 					       1, 100000);
303*ff524079SInochi Amaoto }
304*ff524079SInochi Amaoto 
sg2044_pll_enable(struct sg2044_pll * pll,bool en)305*ff524079SInochi Amaoto static int sg2044_pll_enable(struct sg2044_pll *pll, bool en)
306*ff524079SInochi Amaoto {
307*ff524079SInochi Amaoto 	if (en) {
308*ff524079SInochi Amaoto 		if (sg2044_pll_poll_update(pll) < 0)
309*ff524079SInochi Amaoto 			pr_warn("%s: fail to lock pll\n", clk_hw_get_name(&pll->common.hw));
310*ff524079SInochi Amaoto 
311*ff524079SInochi Amaoto 		return regmap_set_bits(pll->common.regmap,
312*ff524079SInochi Amaoto 				       pll->syscon_offset + pll->pll.enable_offset,
313*ff524079SInochi Amaoto 				       BIT(pll->pll.enable_bit));
314*ff524079SInochi Amaoto 	}
315*ff524079SInochi Amaoto 
316*ff524079SInochi Amaoto 	return regmap_clear_bits(pll->common.regmap,
317*ff524079SInochi Amaoto 				 pll->syscon_offset + pll->pll.enable_offset,
318*ff524079SInochi Amaoto 				 BIT(pll->pll.enable_bit));
319*ff524079SInochi Amaoto }
320*ff524079SInochi Amaoto 
sg2044_pll_update_vcosel(struct sg2044_pll * pll,u64 rate)321*ff524079SInochi Amaoto static int sg2044_pll_update_vcosel(struct sg2044_pll *pll, u64 rate)
322*ff524079SInochi Amaoto {
323*ff524079SInochi Amaoto 	unsigned int sel;
324*ff524079SInochi Amaoto 
325*ff524079SInochi Amaoto 	if (rate < U64_C(2400000000))
326*ff524079SInochi Amaoto 		sel = PLL_VCOSEL_1G6;
327*ff524079SInochi Amaoto 	else
328*ff524079SInochi Amaoto 		sel = PLL_VCOSEL_2G4;
329*ff524079SInochi Amaoto 
330*ff524079SInochi Amaoto 	return regmap_write_bits(pll->common.regmap,
331*ff524079SInochi Amaoto 				 pll->syscon_offset + pll->pll.ctrl_offset,
332*ff524079SInochi Amaoto 				 PLL_VCOSEL_MASK,
333*ff524079SInochi Amaoto 				 FIELD_PREP(PLL_VCOSEL_MASK, sel));
334*ff524079SInochi Amaoto }
335*ff524079SInochi Amaoto 
sg2044_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)336*ff524079SInochi Amaoto static int sg2044_pll_set_rate(struct clk_hw *hw,
337*ff524079SInochi Amaoto 			       unsigned long rate, unsigned long parent_rate)
338*ff524079SInochi Amaoto {
339*ff524079SInochi Amaoto 	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
340*ff524079SInochi Amaoto 	unsigned int value;
341*ff524079SInochi Amaoto 	u64 vco;
342*ff524079SInochi Amaoto 	int ret;
343*ff524079SInochi Amaoto 
344*ff524079SInochi Amaoto 	ret = sg2044_compute_pll_setting(pll->pll.limits, rate,
345*ff524079SInochi Amaoto 					 parent_rate, &value);
346*ff524079SInochi Amaoto 	if (ret < 0)
347*ff524079SInochi Amaoto 		return ret;
348*ff524079SInochi Amaoto 
349*ff524079SInochi Amaoto 	vco = sg2044_pll_calc_vco_rate(parent_rate,
350*ff524079SInochi Amaoto 				       FIELD_GET(PLL_REFDIV_MASK, value),
351*ff524079SInochi Amaoto 				       FIELD_GET(PLL_FBDIV_MASK, value));
352*ff524079SInochi Amaoto 
353*ff524079SInochi Amaoto 	value |= PLL_CALIBRATE_EN;
354*ff524079SInochi Amaoto 	value |= PLL_CALIBRATE_DEFAULT;
355*ff524079SInochi Amaoto 	value |= PLL_UPDATE_EN;
356*ff524079SInochi Amaoto 
357*ff524079SInochi Amaoto 	guard(spinlock_irqsave)(pll->common.lock);
358*ff524079SInochi Amaoto 
359*ff524079SInochi Amaoto 	ret = sg2044_pll_enable(pll, false);
360*ff524079SInochi Amaoto 	if (ret)
361*ff524079SInochi Amaoto 		return ret;
362*ff524079SInochi Amaoto 
363*ff524079SInochi Amaoto 	sg2044_pll_update_vcosel(pll, vco);
364*ff524079SInochi Amaoto 
365*ff524079SInochi Amaoto 	regmap_write_bits(pll->common.regmap,
366*ff524079SInochi Amaoto 			  pll->syscon_offset + pll->pll.ctrl_offset +
367*ff524079SInochi Amaoto 			  PLL_HIGH_CTRL_OFFSET,
368*ff524079SInochi Amaoto 			  PLL_HIGH_CTRL_MASK, value);
369*ff524079SInochi Amaoto 
370*ff524079SInochi Amaoto 	sg2044_pll_enable(pll, true);
371*ff524079SInochi Amaoto 
372*ff524079SInochi Amaoto 	return ret;
373*ff524079SInochi Amaoto }
374*ff524079SInochi Amaoto 
375*ff524079SInochi Amaoto static const struct clk_ops sg2044_pll_ops = {
376*ff524079SInochi Amaoto 	.recalc_rate = sg2044_pll_recalc_rate,
377*ff524079SInochi Amaoto 	.determine_rate = sg2044_pll_determine_rate,
378*ff524079SInochi Amaoto 	.set_rate = sg2044_pll_set_rate,
379*ff524079SInochi Amaoto };
380*ff524079SInochi Amaoto 
381*ff524079SInochi Amaoto static const struct clk_ops sg2044_pll_ro_ops = {
382*ff524079SInochi Amaoto 	.recalc_rate = sg2044_pll_recalc_rate,
383*ff524079SInochi Amaoto };
384*ff524079SInochi Amaoto 
385*ff524079SInochi Amaoto #define SG2044_CLK_COMMON_PDATA(_id, _name, _parents, _op, _flags)	\
386*ff524079SInochi Amaoto 	{								\
387*ff524079SInochi Amaoto 		.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents,	\
388*ff524079SInochi Amaoto 						    _op, (_flags)),	\
389*ff524079SInochi Amaoto 		.id = (_id),						\
390*ff524079SInochi Amaoto 	}
391*ff524079SInochi Amaoto 
392*ff524079SInochi Amaoto #define DEFINE_SG2044_PLL(_id, _name, _parent, _flags,			\
393*ff524079SInochi Amaoto 			  _ctrl_offset,					\
394*ff524079SInochi Amaoto 			  _status_offset, _status_lock_bit,		\
395*ff524079SInochi Amaoto 			  _status_updating_bit,				\
396*ff524079SInochi Amaoto 			  _enable_offset, _enable_bit,			\
397*ff524079SInochi Amaoto 			  _limits)					\
398*ff524079SInochi Amaoto 	struct sg2044_pll _name = {					\
399*ff524079SInochi Amaoto 		.common	= SG2044_CLK_COMMON_PDATA(_id, #_name, _parent,	\
400*ff524079SInochi Amaoto 						  &sg2044_pll_ops,	\
401*ff524079SInochi Amaoto 						  (_flags)),		\
402*ff524079SInochi Amaoto 		.pll = {						\
403*ff524079SInochi Amaoto 			.ctrl_offset = (_ctrl_offset),			\
404*ff524079SInochi Amaoto 			.status_offset = (_status_offset),		\
405*ff524079SInochi Amaoto 			.enable_offset = (_enable_offset),		\
406*ff524079SInochi Amaoto 			.status_lock_bit = (_status_lock_bit),		\
407*ff524079SInochi Amaoto 			.status_updating_bit = (_status_updating_bit),	\
408*ff524079SInochi Amaoto 			.enable_bit = (_enable_bit),			\
409*ff524079SInochi Amaoto 			.limits = (_limits),				\
410*ff524079SInochi Amaoto 		},							\
411*ff524079SInochi Amaoto 	}
412*ff524079SInochi Amaoto 
413*ff524079SInochi Amaoto #define DEFINE_SG2044_PLL_RO(_id, _name, _parent, _flags,		\
414*ff524079SInochi Amaoto 			     _ctrl_offset,				\
415*ff524079SInochi Amaoto 			     _status_offset, _status_lock_bit,		\
416*ff524079SInochi Amaoto 			     _status_updating_bit,			\
417*ff524079SInochi Amaoto 			     _enable_offset, _enable_bit,		\
418*ff524079SInochi Amaoto 			     _limits)					\
419*ff524079SInochi Amaoto 	struct sg2044_pll _name = {					\
420*ff524079SInochi Amaoto 		.common	= SG2044_CLK_COMMON_PDATA(_id, #_name, _parent,	\
421*ff524079SInochi Amaoto 						  &sg2044_pll_ro_ops,	\
422*ff524079SInochi Amaoto 						  (_flags)),		\
423*ff524079SInochi Amaoto 		.pll = {						\
424*ff524079SInochi Amaoto 			.ctrl_offset = (_ctrl_offset),			\
425*ff524079SInochi Amaoto 			.status_offset = (_status_offset),		\
426*ff524079SInochi Amaoto 			.enable_offset = (_enable_offset),		\
427*ff524079SInochi Amaoto 			.status_lock_bit = (_status_lock_bit),		\
428*ff524079SInochi Amaoto 			.status_updating_bit = (_status_updating_bit),	\
429*ff524079SInochi Amaoto 			.enable_bit = (_enable_bit),			\
430*ff524079SInochi Amaoto 			.limits = (_limits),				\
431*ff524079SInochi Amaoto 		},							\
432*ff524079SInochi Amaoto 	}
433*ff524079SInochi Amaoto 
434*ff524079SInochi Amaoto static const struct clk_parent_data osc_parents[] = {
435*ff524079SInochi Amaoto 	{ .index = 0 },
436*ff524079SInochi Amaoto };
437*ff524079SInochi Amaoto 
438*ff524079SInochi Amaoto static const struct sg2044_pll_limit pll_limits[] = {
439*ff524079SInochi Amaoto 	[PLL_LIMIT_FOUTVCO] = {
440*ff524079SInochi Amaoto 		.min = U64_C(1600000000),
441*ff524079SInochi Amaoto 		.max = U64_C(3200000000),
442*ff524079SInochi Amaoto 	},
443*ff524079SInochi Amaoto 	[PLL_LIMIT_FOUT] = {
444*ff524079SInochi Amaoto 		.min = U64_C(25000),
445*ff524079SInochi Amaoto 		.max = U64_C(3200000000),
446*ff524079SInochi Amaoto 	},
447*ff524079SInochi Amaoto 	[PLL_LIMIT_REFDIV] = {
448*ff524079SInochi Amaoto 		.min = U64_C(1),
449*ff524079SInochi Amaoto 		.max = U64_C(63),
450*ff524079SInochi Amaoto 	},
451*ff524079SInochi Amaoto 	[PLL_LIMIT_FBDIV] = {
452*ff524079SInochi Amaoto 		.min = U64_C(8),
453*ff524079SInochi Amaoto 		.max = U64_C(1066),
454*ff524079SInochi Amaoto 	},
455*ff524079SInochi Amaoto 	[PLL_LIMIT_POSTDIV1] = {
456*ff524079SInochi Amaoto 		.min = U64_C(0),
457*ff524079SInochi Amaoto 		.max = U64_C(7),
458*ff524079SInochi Amaoto 	},
459*ff524079SInochi Amaoto 	[PLL_LIMIT_POSTDIV2] = {
460*ff524079SInochi Amaoto 		.min = U64_C(0),
461*ff524079SInochi Amaoto 		.max = U64_C(7),
462*ff524079SInochi Amaoto 	},
463*ff524079SInochi Amaoto };
464*ff524079SInochi Amaoto 
465*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_FPLL0, clk_fpll0, osc_parents, CLK_IS_CRITICAL,
466*ff524079SInochi Amaoto 			    0x58, 0x00, 22, 6,
467*ff524079SInochi Amaoto 			    0x04, 6, pll_limits);
468*ff524079SInochi Amaoto 
469*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_FPLL1, clk_fpll1, osc_parents, CLK_IS_CRITICAL,
470*ff524079SInochi Amaoto 			    0x60, 0x00, 23, 7,
471*ff524079SInochi Amaoto 			    0x04, 7, pll_limits);
472*ff524079SInochi Amaoto 
473*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_FPLL2, clk_fpll2, osc_parents, CLK_IS_CRITICAL,
474*ff524079SInochi Amaoto 			    0x20, 0x08, 16, 0,
475*ff524079SInochi Amaoto 			    0x0c, 0, pll_limits);
476*ff524079SInochi Amaoto 
477*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL0, clk_dpll0, osc_parents, CLK_IS_CRITICAL,
478*ff524079SInochi Amaoto 			    0x68, 0x00, 24, 8,
479*ff524079SInochi Amaoto 			    0x04, 8, pll_limits);
480*ff524079SInochi Amaoto 
481*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL1, clk_dpll1, osc_parents, CLK_IS_CRITICAL,
482*ff524079SInochi Amaoto 			    0x70, 0x00, 25, 9,
483*ff524079SInochi Amaoto 			    0x04, 9, pll_limits);
484*ff524079SInochi Amaoto 
485*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL2, clk_dpll2, osc_parents, CLK_IS_CRITICAL,
486*ff524079SInochi Amaoto 			    0x78, 0x00, 26, 10,
487*ff524079SInochi Amaoto 			    0x04, 10, pll_limits);
488*ff524079SInochi Amaoto 
489*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL3, clk_dpll3, osc_parents, CLK_IS_CRITICAL,
490*ff524079SInochi Amaoto 			    0x80, 0x00, 27, 11,
491*ff524079SInochi Amaoto 			    0x04, 11, pll_limits);
492*ff524079SInochi Amaoto 
493*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL4, clk_dpll4, osc_parents, CLK_IS_CRITICAL,
494*ff524079SInochi Amaoto 			    0x88, 0x00, 28, 12,
495*ff524079SInochi Amaoto 			    0x04, 12, pll_limits);
496*ff524079SInochi Amaoto 
497*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL5, clk_dpll5, osc_parents, CLK_IS_CRITICAL,
498*ff524079SInochi Amaoto 			    0x90, 0x00, 29, 13,
499*ff524079SInochi Amaoto 			    0x04, 13, pll_limits);
500*ff524079SInochi Amaoto 
501*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL6, clk_dpll6, osc_parents, CLK_IS_CRITICAL,
502*ff524079SInochi Amaoto 			    0x98, 0x00, 30, 14,
503*ff524079SInochi Amaoto 			    0x04, 14, pll_limits);
504*ff524079SInochi Amaoto 
505*ff524079SInochi Amaoto static DEFINE_SG2044_PLL_RO(CLK_DPLL7, clk_dpll7, osc_parents, CLK_IS_CRITICAL,
506*ff524079SInochi Amaoto 			    0xa0, 0x00, 31, 15,
507*ff524079SInochi Amaoto 			    0x04, 15, pll_limits);
508*ff524079SInochi Amaoto 
509*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL0, clk_mpll0, osc_parents, CLK_IS_CRITICAL,
510*ff524079SInochi Amaoto 			 0x28, 0x00, 16, 0,
511*ff524079SInochi Amaoto 			 0x04, 0, pll_limits);
512*ff524079SInochi Amaoto 
513*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL1, clk_mpll1, osc_parents, CLK_IS_CRITICAL,
514*ff524079SInochi Amaoto 			 0x30, 0x00, 17, 1,
515*ff524079SInochi Amaoto 			 0x04, 1, pll_limits);
516*ff524079SInochi Amaoto 
517*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL2, clk_mpll2, osc_parents, CLK_IS_CRITICAL,
518*ff524079SInochi Amaoto 			 0x38, 0x00, 18, 2,
519*ff524079SInochi Amaoto 			 0x04, 2, pll_limits);
520*ff524079SInochi Amaoto 
521*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL3, clk_mpll3, osc_parents, CLK_IS_CRITICAL,
522*ff524079SInochi Amaoto 			 0x40, 0x00, 19, 3,
523*ff524079SInochi Amaoto 			 0x04, 3, pll_limits);
524*ff524079SInochi Amaoto 
525*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL4, clk_mpll4, osc_parents, CLK_IS_CRITICAL,
526*ff524079SInochi Amaoto 			 0x48, 0x00, 20, 4,
527*ff524079SInochi Amaoto 			 0x04, 4, pll_limits);
528*ff524079SInochi Amaoto 
529*ff524079SInochi Amaoto static DEFINE_SG2044_PLL(CLK_MPLL5, clk_mpll5, osc_parents, CLK_IS_CRITICAL,
530*ff524079SInochi Amaoto 			 0x50, 0x00, 21, 5,
531*ff524079SInochi Amaoto 			 0x04, 5, pll_limits);
532*ff524079SInochi Amaoto 
533*ff524079SInochi Amaoto static struct sg2044_clk_common * const sg2044_pll_commons[] = {
534*ff524079SInochi Amaoto 	&clk_fpll0.common,
535*ff524079SInochi Amaoto 	&clk_fpll1.common,
536*ff524079SInochi Amaoto 	&clk_fpll2.common,
537*ff524079SInochi Amaoto 	&clk_dpll0.common,
538*ff524079SInochi Amaoto 	&clk_dpll1.common,
539*ff524079SInochi Amaoto 	&clk_dpll2.common,
540*ff524079SInochi Amaoto 	&clk_dpll3.common,
541*ff524079SInochi Amaoto 	&clk_dpll4.common,
542*ff524079SInochi Amaoto 	&clk_dpll5.common,
543*ff524079SInochi Amaoto 	&clk_dpll6.common,
544*ff524079SInochi Amaoto 	&clk_dpll7.common,
545*ff524079SInochi Amaoto 	&clk_mpll0.common,
546*ff524079SInochi Amaoto 	&clk_mpll1.common,
547*ff524079SInochi Amaoto 	&clk_mpll2.common,
548*ff524079SInochi Amaoto 	&clk_mpll3.common,
549*ff524079SInochi Amaoto 	&clk_mpll4.common,
550*ff524079SInochi Amaoto 	&clk_mpll5.common,
551*ff524079SInochi Amaoto };
552*ff524079SInochi Amaoto 
sg2044_pll_init_ctrl(struct device * dev,struct regmap * regmap,struct sg2044_pll_ctrl * ctrl,const struct sg2044_pll_desc_data * desc)553*ff524079SInochi Amaoto static int sg2044_pll_init_ctrl(struct device *dev, struct regmap *regmap,
554*ff524079SInochi Amaoto 				struct sg2044_pll_ctrl *ctrl,
555*ff524079SInochi Amaoto 				const struct sg2044_pll_desc_data *desc)
556*ff524079SInochi Amaoto {
557*ff524079SInochi Amaoto 	int ret, i;
558*ff524079SInochi Amaoto 
559*ff524079SInochi Amaoto 	spin_lock_init(&ctrl->lock);
560*ff524079SInochi Amaoto 
561*ff524079SInochi Amaoto 	for (i = 0; i < desc->num_pll; i++) {
562*ff524079SInochi Amaoto 		struct sg2044_clk_common *common = desc->pll[i];
563*ff524079SInochi Amaoto 		struct sg2044_pll *pll = hw_to_sg2044_pll(&common->hw);
564*ff524079SInochi Amaoto 
565*ff524079SInochi Amaoto 		common->lock = &ctrl->lock;
566*ff524079SInochi Amaoto 		common->regmap = regmap;
567*ff524079SInochi Amaoto 		pll->syscon_offset = SG2044_SYSCON_PLL_OFFSET;
568*ff524079SInochi Amaoto 
569*ff524079SInochi Amaoto 		ret = devm_clk_hw_register(dev, &common->hw);
570*ff524079SInochi Amaoto 		if (ret)
571*ff524079SInochi Amaoto 			return ret;
572*ff524079SInochi Amaoto 
573*ff524079SInochi Amaoto 		ctrl->data.hws[common->id] = &common->hw;
574*ff524079SInochi Amaoto 	}
575*ff524079SInochi Amaoto 
576*ff524079SInochi Amaoto 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
577*ff524079SInochi Amaoto 					   &ctrl->data);
578*ff524079SInochi Amaoto }
579*ff524079SInochi Amaoto 
sg2044_pll_probe(struct platform_device * pdev)580*ff524079SInochi Amaoto static int sg2044_pll_probe(struct platform_device *pdev)
581*ff524079SInochi Amaoto {
582*ff524079SInochi Amaoto 	struct device *dev = &pdev->dev;
583*ff524079SInochi Amaoto 	struct sg2044_pll_ctrl *ctrl;
584*ff524079SInochi Amaoto 	const struct sg2044_pll_desc_data *desc;
585*ff524079SInochi Amaoto 	struct regmap *regmap;
586*ff524079SInochi Amaoto 
587*ff524079SInochi Amaoto 	regmap = device_node_to_regmap(pdev->dev.parent->of_node);
588*ff524079SInochi Amaoto 	if (IS_ERR(regmap))
589*ff524079SInochi Amaoto 		return dev_err_probe(dev, PTR_ERR(regmap),
590*ff524079SInochi Amaoto 				     "fail to get the regmap for PLL\n");
591*ff524079SInochi Amaoto 
592*ff524079SInochi Amaoto 	desc = (const struct sg2044_pll_desc_data *)platform_get_device_id(pdev)->driver_data;
593*ff524079SInochi Amaoto 	if (!desc)
594*ff524079SInochi Amaoto 		return dev_err_probe(dev, -EINVAL, "no match data for platform\n");
595*ff524079SInochi Amaoto 
596*ff524079SInochi Amaoto 	ctrl = devm_kzalloc(dev, struct_size(ctrl, data.hws, desc->num_pll), GFP_KERNEL);
597*ff524079SInochi Amaoto 	if (!ctrl)
598*ff524079SInochi Amaoto 		return -ENOMEM;
599*ff524079SInochi Amaoto 
600*ff524079SInochi Amaoto 	ctrl->data.num = desc->num_pll;
601*ff524079SInochi Amaoto 
602*ff524079SInochi Amaoto 	return sg2044_pll_init_ctrl(dev, regmap, ctrl, desc);
603*ff524079SInochi Amaoto }
604*ff524079SInochi Amaoto 
605*ff524079SInochi Amaoto static const struct sg2044_pll_desc_data sg2044_pll_desc_data = {
606*ff524079SInochi Amaoto 	.pll = sg2044_pll_commons,
607*ff524079SInochi Amaoto 	.num_pll = ARRAY_SIZE(sg2044_pll_commons),
608*ff524079SInochi Amaoto };
609*ff524079SInochi Amaoto 
610*ff524079SInochi Amaoto static const struct platform_device_id sg2044_pll_match[] = {
611*ff524079SInochi Amaoto 	{ .name = "sg2044-pll",
612*ff524079SInochi Amaoto 	  .driver_data = (unsigned long)&sg2044_pll_desc_data },
613*ff524079SInochi Amaoto 	{ /* sentinel */ }
614*ff524079SInochi Amaoto };
615*ff524079SInochi Amaoto MODULE_DEVICE_TABLE(platform, sg2044_pll_match);
616*ff524079SInochi Amaoto 
617*ff524079SInochi Amaoto static struct platform_driver sg2044_clk_driver = {
618*ff524079SInochi Amaoto 	.probe = sg2044_pll_probe,
619*ff524079SInochi Amaoto 	.driver = {
620*ff524079SInochi Amaoto 		.name = "sg2044-pll",
621*ff524079SInochi Amaoto 	},
622*ff524079SInochi Amaoto 	.id_table = sg2044_pll_match,
623*ff524079SInochi Amaoto };
624*ff524079SInochi Amaoto module_platform_driver(sg2044_clk_driver);
625*ff524079SInochi Amaoto 
626*ff524079SInochi Amaoto MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>");
627*ff524079SInochi Amaoto MODULE_DESCRIPTION("Sophgo SG2044 pll clock driver");
628*ff524079SInochi Amaoto MODULE_LICENSE("GPL");
629