xref: /OK3568_Linux_fs/kernel/drivers/clk/st/clkgen-fsyn.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2014 STMicroelectronics R&D Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun /*
7*4882a593Smuzhiyun  * Authors:
8*4882a593Smuzhiyun  * Stephen Gallimore <stephen.gallimore@st.com>,
9*4882a593Smuzhiyun  * Pankaj Dev <pankaj.dev@st.com>.
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/of_address.h>
14*4882a593Smuzhiyun #include <linux/clk.h>
15*4882a593Smuzhiyun #include <linux/clk-provider.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "clkgen.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * Maximum input clock to the PLL before we divide it down by 2
21*4882a593Smuzhiyun  * although in reality in actual systems this has never been seen to
22*4882a593Smuzhiyun  * be used.
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun #define QUADFS_NDIV_THRESHOLD 30000000
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define PLL_BW_GOODREF   (0L)
27*4882a593Smuzhiyun #define PLL_BW_VBADREF   (1L)
28*4882a593Smuzhiyun #define PLL_BW_BADREF    (2L)
29*4882a593Smuzhiyun #define PLL_BW_VGOODREF  (3L)
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define QUADFS_MAX_CHAN 4
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct stm_fs {
34*4882a593Smuzhiyun 	unsigned long ndiv;
35*4882a593Smuzhiyun 	unsigned long mdiv;
36*4882a593Smuzhiyun 	unsigned long pe;
37*4882a593Smuzhiyun 	unsigned long sdiv;
38*4882a593Smuzhiyun 	unsigned long nsdiv;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun struct clkgen_quadfs_data {
42*4882a593Smuzhiyun 	bool reset_present;
43*4882a593Smuzhiyun 	bool bwfilter_present;
44*4882a593Smuzhiyun 	bool lockstatus_present;
45*4882a593Smuzhiyun 	bool powerup_polarity;
46*4882a593Smuzhiyun 	bool standby_polarity;
47*4882a593Smuzhiyun 	bool nsdiv_present;
48*4882a593Smuzhiyun 	bool nrst_present;
49*4882a593Smuzhiyun 	struct clkgen_field ndiv;
50*4882a593Smuzhiyun 	struct clkgen_field ref_bw;
51*4882a593Smuzhiyun 	struct clkgen_field nreset;
52*4882a593Smuzhiyun 	struct clkgen_field npda;
53*4882a593Smuzhiyun 	struct clkgen_field lock_status;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	struct clkgen_field nrst[QUADFS_MAX_CHAN];
56*4882a593Smuzhiyun 	struct clkgen_field nsb[QUADFS_MAX_CHAN];
57*4882a593Smuzhiyun 	struct clkgen_field en[QUADFS_MAX_CHAN];
58*4882a593Smuzhiyun 	struct clkgen_field mdiv[QUADFS_MAX_CHAN];
59*4882a593Smuzhiyun 	struct clkgen_field pe[QUADFS_MAX_CHAN];
60*4882a593Smuzhiyun 	struct clkgen_field sdiv[QUADFS_MAX_CHAN];
61*4882a593Smuzhiyun 	struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	const struct clk_ops *pll_ops;
64*4882a593Smuzhiyun 	int  (*get_params)(unsigned long, unsigned long, struct stm_fs *);
65*4882a593Smuzhiyun 	int  (*get_rate)(unsigned long , const struct stm_fs *,
66*4882a593Smuzhiyun 			unsigned long *);
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static const struct clk_ops st_quadfs_pll_c32_ops;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static int clk_fs660c32_dig_get_params(unsigned long input,
72*4882a593Smuzhiyun 		unsigned long output, struct stm_fs *fs);
73*4882a593Smuzhiyun static int clk_fs660c32_dig_get_rate(unsigned long, const struct stm_fs *,
74*4882a593Smuzhiyun 		unsigned long *);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun static const struct clkgen_quadfs_data st_fs660c32_C = {
77*4882a593Smuzhiyun 	.nrst_present = true,
78*4882a593Smuzhiyun 	.nrst	= { CLKGEN_FIELD(0x2f0, 0x1, 0),
79*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 1),
80*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 2),
81*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 3) },
82*4882a593Smuzhiyun 	.npda	= CLKGEN_FIELD(0x2f0, 0x1, 12),
83*4882a593Smuzhiyun 	.nsb	= { CLKGEN_FIELD(0x2f0, 0x1, 8),
84*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 9),
85*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 10),
86*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2f0, 0x1, 11) },
87*4882a593Smuzhiyun 	.nsdiv_present = true,
88*4882a593Smuzhiyun 	.nsdiv	= { CLKGEN_FIELD(0x304, 0x1, 24),
89*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x308, 0x1, 24),
90*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x30c, 0x1, 24),
91*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x310, 0x1, 24) },
92*4882a593Smuzhiyun 	.mdiv	= { CLKGEN_FIELD(0x304, 0x1f, 15),
93*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x308, 0x1f, 15),
94*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x30c, 0x1f, 15),
95*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x310, 0x1f, 15) },
96*4882a593Smuzhiyun 	.en	= { CLKGEN_FIELD(0x2fc, 0x1, 0),
97*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2fc, 0x1, 1),
98*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2fc, 0x1, 2),
99*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2fc, 0x1, 3) },
100*4882a593Smuzhiyun 	.ndiv	= CLKGEN_FIELD(0x2f4, 0x7, 16),
101*4882a593Smuzhiyun 	.pe	= { CLKGEN_FIELD(0x304, 0x7fff, 0),
102*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x308, 0x7fff, 0),
103*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x30c, 0x7fff, 0),
104*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x310, 0x7fff, 0) },
105*4882a593Smuzhiyun 	.sdiv	= { CLKGEN_FIELD(0x304, 0xf, 20),
106*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x308, 0xf, 20),
107*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x30c, 0xf, 20),
108*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x310, 0xf, 20) },
109*4882a593Smuzhiyun 	.lockstatus_present = true,
110*4882a593Smuzhiyun 	.lock_status = CLKGEN_FIELD(0x2f0, 0x1, 24),
111*4882a593Smuzhiyun 	.powerup_polarity = 1,
112*4882a593Smuzhiyun 	.standby_polarity = 1,
113*4882a593Smuzhiyun 	.pll_ops	= &st_quadfs_pll_c32_ops,
114*4882a593Smuzhiyun 	.get_params	= clk_fs660c32_dig_get_params,
115*4882a593Smuzhiyun 	.get_rate	= clk_fs660c32_dig_get_rate,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun static const struct clkgen_quadfs_data st_fs660c32_D = {
119*4882a593Smuzhiyun 	.nrst_present = true,
120*4882a593Smuzhiyun 	.nrst	= { CLKGEN_FIELD(0x2a0, 0x1, 0),
121*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 1),
122*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 2),
123*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 3) },
124*4882a593Smuzhiyun 	.ndiv	= CLKGEN_FIELD(0x2a4, 0x7, 16),
125*4882a593Smuzhiyun 	.pe	= { CLKGEN_FIELD(0x2b4, 0x7fff, 0),
126*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2b8, 0x7fff, 0),
127*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2bc, 0x7fff, 0),
128*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2c0, 0x7fff, 0) },
129*4882a593Smuzhiyun 	.sdiv	= { CLKGEN_FIELD(0x2b4, 0xf, 20),
130*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2b8, 0xf, 20),
131*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2bc, 0xf, 20),
132*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2c0, 0xf, 20) },
133*4882a593Smuzhiyun 	.npda	= CLKGEN_FIELD(0x2a0, 0x1, 12),
134*4882a593Smuzhiyun 	.nsb	= { CLKGEN_FIELD(0x2a0, 0x1, 8),
135*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 9),
136*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 10),
137*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2a0, 0x1, 11) },
138*4882a593Smuzhiyun 	.nsdiv_present = true,
139*4882a593Smuzhiyun 	.nsdiv	= { CLKGEN_FIELD(0x2b4, 0x1, 24),
140*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2b8, 0x1, 24),
141*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2bc, 0x1, 24),
142*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2c0, 0x1, 24) },
143*4882a593Smuzhiyun 	.mdiv	= { CLKGEN_FIELD(0x2b4, 0x1f, 15),
144*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2b8, 0x1f, 15),
145*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2bc, 0x1f, 15),
146*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2c0, 0x1f, 15) },
147*4882a593Smuzhiyun 	.en	= { CLKGEN_FIELD(0x2ac, 0x1, 0),
148*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2ac, 0x1, 1),
149*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2ac, 0x1, 2),
150*4882a593Smuzhiyun 		    CLKGEN_FIELD(0x2ac, 0x1, 3) },
151*4882a593Smuzhiyun 	.lockstatus_present = true,
152*4882a593Smuzhiyun 	.lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
153*4882a593Smuzhiyun 	.powerup_polarity = 1,
154*4882a593Smuzhiyun 	.standby_polarity = 1,
155*4882a593Smuzhiyun 	.pll_ops	= &st_quadfs_pll_c32_ops,
156*4882a593Smuzhiyun 	.get_params	= clk_fs660c32_dig_get_params,
157*4882a593Smuzhiyun 	.get_rate	= clk_fs660c32_dig_get_rate,};
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /**
160*4882a593Smuzhiyun  * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * Traits of this clock:
163*4882a593Smuzhiyun  * prepare - clk_(un)prepare only ensures parent is (un)prepared
164*4882a593Smuzhiyun  * enable - clk_enable and clk_disable are functional & control the Fsyn
165*4882a593Smuzhiyun  * rate - inherits rate from parent. set_rate/round_rate/recalc_rate
166*4882a593Smuzhiyun  * parent - fixed parent.  No clk_set_parent support
167*4882a593Smuzhiyun  */
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun /**
170*4882a593Smuzhiyun  * struct st_clk_quadfs_pll - A pll which outputs a fixed multiplier of
171*4882a593Smuzhiyun  *                                  its parent clock, found inside a type of
172*4882a593Smuzhiyun  *                                  ST quad channel frequency synthesizer block
173*4882a593Smuzhiyun  *
174*4882a593Smuzhiyun  * @hw: handle between common and hardware-specific interfaces.
175*4882a593Smuzhiyun  * @ndiv: regmap field for the ndiv control.
176*4882a593Smuzhiyun  * @regs_base: base address of the configuration registers.
177*4882a593Smuzhiyun  * @lock: spinlock.
178*4882a593Smuzhiyun  *
179*4882a593Smuzhiyun  */
180*4882a593Smuzhiyun struct st_clk_quadfs_pll {
181*4882a593Smuzhiyun 	struct clk_hw	hw;
182*4882a593Smuzhiyun 	void __iomem	*regs_base;
183*4882a593Smuzhiyun 	spinlock_t	*lock;
184*4882a593Smuzhiyun 	struct clkgen_quadfs_data *data;
185*4882a593Smuzhiyun 	u32 ndiv;
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun #define to_quadfs_pll(_hw) container_of(_hw, struct st_clk_quadfs_pll, hw)
189*4882a593Smuzhiyun 
quadfs_pll_enable(struct clk_hw * hw)190*4882a593Smuzhiyun static int quadfs_pll_enable(struct clk_hw *hw)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
193*4882a593Smuzhiyun 	unsigned long flags = 0, timeout = jiffies + msecs_to_jiffies(10);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	if (pll->lock)
196*4882a593Smuzhiyun 		spin_lock_irqsave(pll->lock, flags);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	/*
199*4882a593Smuzhiyun 	 * Bring block out of reset if we have reset control.
200*4882a593Smuzhiyun 	 */
201*4882a593Smuzhiyun 	if (pll->data->reset_present)
202*4882a593Smuzhiyun 		CLKGEN_WRITE(pll, nreset, 1);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	/*
205*4882a593Smuzhiyun 	 * Use a fixed input clock noise bandwidth filter for the moment
206*4882a593Smuzhiyun 	 */
207*4882a593Smuzhiyun 	if (pll->data->bwfilter_present)
208*4882a593Smuzhiyun 		CLKGEN_WRITE(pll, ref_bw, PLL_BW_GOODREF);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	/*
214*4882a593Smuzhiyun 	 * Power up the PLL
215*4882a593Smuzhiyun 	 */
216*4882a593Smuzhiyun 	CLKGEN_WRITE(pll, npda, !pll->data->powerup_polarity);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	if (pll->lock)
219*4882a593Smuzhiyun 		spin_unlock_irqrestore(pll->lock, flags);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (pll->data->lockstatus_present)
222*4882a593Smuzhiyun 		while (!CLKGEN_READ(pll, lock_status)) {
223*4882a593Smuzhiyun 			if (time_after(jiffies, timeout))
224*4882a593Smuzhiyun 				return -ETIMEDOUT;
225*4882a593Smuzhiyun 			cpu_relax();
226*4882a593Smuzhiyun 		}
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	return 0;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
quadfs_pll_disable(struct clk_hw * hw)231*4882a593Smuzhiyun static void quadfs_pll_disable(struct clk_hw *hw)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
234*4882a593Smuzhiyun 	unsigned long flags = 0;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	if (pll->lock)
237*4882a593Smuzhiyun 		spin_lock_irqsave(pll->lock, flags);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/*
240*4882a593Smuzhiyun 	 * Powerdown the PLL and then put block into soft reset if we have
241*4882a593Smuzhiyun 	 * reset control.
242*4882a593Smuzhiyun 	 */
243*4882a593Smuzhiyun 	CLKGEN_WRITE(pll, npda, pll->data->powerup_polarity);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	if (pll->data->reset_present)
246*4882a593Smuzhiyun 		CLKGEN_WRITE(pll, nreset, 0);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (pll->lock)
249*4882a593Smuzhiyun 		spin_unlock_irqrestore(pll->lock, flags);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
quadfs_pll_is_enabled(struct clk_hw * hw)252*4882a593Smuzhiyun static int quadfs_pll_is_enabled(struct clk_hw *hw)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
255*4882a593Smuzhiyun 	u32 npda = CLKGEN_READ(pll, npda);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	return pll->data->powerup_polarity ? !npda : !!npda;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
clk_fs660c32_vco_get_rate(unsigned long input,struct stm_fs * fs,unsigned long * rate)260*4882a593Smuzhiyun static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
261*4882a593Smuzhiyun 			   unsigned long *rate)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	unsigned long nd = fs->ndiv + 16; /* ndiv value */
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	*rate = input * nd;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return 0;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
quadfs_pll_fs660c32_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)270*4882a593Smuzhiyun static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
271*4882a593Smuzhiyun 					unsigned long parent_rate)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
274*4882a593Smuzhiyun 	unsigned long rate = 0;
275*4882a593Smuzhiyun 	struct stm_fs params;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	params.ndiv = CLKGEN_READ(pll, ndiv);
278*4882a593Smuzhiyun 	if (clk_fs660c32_vco_get_rate(parent_rate, &params, &rate))
279*4882a593Smuzhiyun 		pr_err("%s:%s error calculating rate\n",
280*4882a593Smuzhiyun 		       clk_hw_get_name(hw), __func__);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	pll->ndiv = params.ndiv;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	return rate;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
clk_fs660c32_vco_get_params(unsigned long input,unsigned long output,struct stm_fs * fs)287*4882a593Smuzhiyun static int clk_fs660c32_vco_get_params(unsigned long input,
288*4882a593Smuzhiyun 				unsigned long output, struct stm_fs *fs)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun /* Formula
291*4882a593Smuzhiyun    VCO frequency = (fin x ndiv) / pdiv
292*4882a593Smuzhiyun    ndiv = VCOfreq * pdiv / fin
293*4882a593Smuzhiyun    */
294*4882a593Smuzhiyun 	unsigned long pdiv = 1, n;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	/* Output clock range: 384Mhz to 660Mhz */
297*4882a593Smuzhiyun 	if (output < 384000000 || output > 660000000)
298*4882a593Smuzhiyun 		return -EINVAL;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	if (input > 40000000)
301*4882a593Smuzhiyun 		/* This means that PDIV would be 2 instead of 1.
302*4882a593Smuzhiyun 		   Not supported today. */
303*4882a593Smuzhiyun 		return -EINVAL;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	input /= 1000;
306*4882a593Smuzhiyun 	output /= 1000;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	n = output * pdiv / input;
309*4882a593Smuzhiyun 	if (n < 16)
310*4882a593Smuzhiyun 		n = 16;
311*4882a593Smuzhiyun 	fs->ndiv = n - 16; /* Converting formula value to reg value */
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
quadfs_pll_fs660c32_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)316*4882a593Smuzhiyun static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw,
317*4882a593Smuzhiyun 					   unsigned long rate,
318*4882a593Smuzhiyun 					   unsigned long *prate)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct stm_fs params;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (clk_fs660c32_vco_get_params(*prate, rate, &params))
323*4882a593Smuzhiyun 		return rate;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	clk_fs660c32_vco_get_rate(*prate, &params, &rate);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	pr_debug("%s: %s new rate %ld [ndiv=%u]\n",
328*4882a593Smuzhiyun 		 __func__, clk_hw_get_name(hw),
329*4882a593Smuzhiyun 		 rate, (unsigned int)params.ndiv);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return rate;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
quadfs_pll_fs660c32_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)334*4882a593Smuzhiyun static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
335*4882a593Smuzhiyun 				unsigned long parent_rate)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw);
338*4882a593Smuzhiyun 	struct stm_fs params;
339*4882a593Smuzhiyun 	long hwrate = 0;
340*4882a593Smuzhiyun 	unsigned long flags = 0;
341*4882a593Smuzhiyun 	int ret;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	if (!rate || !parent_rate)
344*4882a593Smuzhiyun 		return -EINVAL;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	ret = clk_fs660c32_vco_get_params(parent_rate, rate, &params);
347*4882a593Smuzhiyun 	if (ret)
348*4882a593Smuzhiyun 		return ret;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	clk_fs660c32_vco_get_rate(parent_rate, &params, &hwrate);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	pr_debug("%s: %s new rate %ld [ndiv=0x%x]\n",
353*4882a593Smuzhiyun 		 __func__, clk_hw_get_name(hw),
354*4882a593Smuzhiyun 		 hwrate, (unsigned int)params.ndiv);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	if (!hwrate)
357*4882a593Smuzhiyun 		return -EINVAL;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	pll->ndiv = params.ndiv;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (pll->lock)
362*4882a593Smuzhiyun 		spin_lock_irqsave(pll->lock, flags);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	CLKGEN_WRITE(pll, ndiv, pll->ndiv);
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	if (pll->lock)
367*4882a593Smuzhiyun 		spin_unlock_irqrestore(pll->lock, flags);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	return 0;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun static const struct clk_ops st_quadfs_pll_c32_ops = {
373*4882a593Smuzhiyun 	.enable		= quadfs_pll_enable,
374*4882a593Smuzhiyun 	.disable	= quadfs_pll_disable,
375*4882a593Smuzhiyun 	.is_enabled	= quadfs_pll_is_enabled,
376*4882a593Smuzhiyun 	.recalc_rate	= quadfs_pll_fs660c32_recalc_rate,
377*4882a593Smuzhiyun 	.round_rate	= quadfs_pll_fs660c32_round_rate,
378*4882a593Smuzhiyun 	.set_rate	= quadfs_pll_fs660c32_set_rate,
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun 
st_clk_register_quadfs_pll(const char * name,const char * parent_name,struct clkgen_quadfs_data * quadfs,void __iomem * reg,spinlock_t * lock)381*4882a593Smuzhiyun static struct clk * __init st_clk_register_quadfs_pll(
382*4882a593Smuzhiyun 		const char *name, const char *parent_name,
383*4882a593Smuzhiyun 		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
384*4882a593Smuzhiyun 		spinlock_t *lock)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	struct st_clk_quadfs_pll *pll;
387*4882a593Smuzhiyun 	struct clk *clk;
388*4882a593Smuzhiyun 	struct clk_init_data init;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	/*
391*4882a593Smuzhiyun 	 * Sanity check required pointers.
392*4882a593Smuzhiyun 	 */
393*4882a593Smuzhiyun 	if (WARN_ON(!name || !parent_name))
394*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
397*4882a593Smuzhiyun 	if (!pll)
398*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	init.name = name;
401*4882a593Smuzhiyun 	init.ops = quadfs->pll_ops;
402*4882a593Smuzhiyun 	init.flags = CLK_GET_RATE_NOCACHE;
403*4882a593Smuzhiyun 	init.parent_names = &parent_name;
404*4882a593Smuzhiyun 	init.num_parents = 1;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	pll->data = quadfs;
407*4882a593Smuzhiyun 	pll->regs_base = reg;
408*4882a593Smuzhiyun 	pll->lock = lock;
409*4882a593Smuzhiyun 	pll->hw.init = &init;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	clk = clk_register(NULL, &pll->hw);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	if (IS_ERR(clk))
414*4882a593Smuzhiyun 		kfree(pll);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	return clk;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun /**
420*4882a593Smuzhiyun  * DOC: A digital frequency synthesizer
421*4882a593Smuzhiyun  *
422*4882a593Smuzhiyun  * Traits of this clock:
423*4882a593Smuzhiyun  * prepare - clk_(un)prepare only ensures parent is (un)prepared
424*4882a593Smuzhiyun  * enable - clk_enable and clk_disable are functional
425*4882a593Smuzhiyun  * rate - set rate is functional
426*4882a593Smuzhiyun  * parent - fixed parent.  No clk_set_parent support
427*4882a593Smuzhiyun  */
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun /**
430*4882a593Smuzhiyun  * struct st_clk_quadfs_fsynth - One clock output from a four channel digital
431*4882a593Smuzhiyun  *                                  frequency synthesizer (fsynth) block.
432*4882a593Smuzhiyun  *
433*4882a593Smuzhiyun  * @hw: handle between common and hardware-specific interfaces
434*4882a593Smuzhiyun  *
435*4882a593Smuzhiyun  * @nsb: regmap field in the output control register for the digital
436*4882a593Smuzhiyun  *       standby of this fsynth channel. This control is active low so
437*4882a593Smuzhiyun  *       the channel is in standby when the control bit is cleared.
438*4882a593Smuzhiyun  *
439*4882a593Smuzhiyun  * @nsdiv: regmap field in the output control register for
440*4882a593Smuzhiyun  *          for the optional divide by 3 of this fsynth channel. This control
441*4882a593Smuzhiyun  *          is active low so the divide by 3 is active when the control bit is
442*4882a593Smuzhiyun  *          cleared and the divide is bypassed when the bit is set.
443*4882a593Smuzhiyun  */
444*4882a593Smuzhiyun struct st_clk_quadfs_fsynth {
445*4882a593Smuzhiyun 	struct clk_hw	hw;
446*4882a593Smuzhiyun 	void __iomem	*regs_base;
447*4882a593Smuzhiyun 	spinlock_t	*lock;
448*4882a593Smuzhiyun 	struct clkgen_quadfs_data *data;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	u32 chan;
451*4882a593Smuzhiyun 	/*
452*4882a593Smuzhiyun 	 * Cached hardware values from set_rate so we can program the
453*4882a593Smuzhiyun 	 * hardware in enable. There are two reasons for this:
454*4882a593Smuzhiyun 	 *
455*4882a593Smuzhiyun 	 *  1. The registers may not be writable until the parent has been
456*4882a593Smuzhiyun 	 *     enabled.
457*4882a593Smuzhiyun 	 *
458*4882a593Smuzhiyun 	 *  2. It restores the clock rate when a driver does an enable
459*4882a593Smuzhiyun 	 *     on PM restore, after a suspend to RAM has lost the hardware
460*4882a593Smuzhiyun 	 *     setup.
461*4882a593Smuzhiyun 	 */
462*4882a593Smuzhiyun 	u32 md;
463*4882a593Smuzhiyun 	u32 pe;
464*4882a593Smuzhiyun 	u32 sdiv;
465*4882a593Smuzhiyun 	u32 nsdiv;
466*4882a593Smuzhiyun };
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun #define to_quadfs_fsynth(_hw) \
469*4882a593Smuzhiyun 	container_of(_hw, struct st_clk_quadfs_fsynth, hw)
470*4882a593Smuzhiyun 
quadfs_fsynth_program_enable(struct st_clk_quadfs_fsynth * fs)471*4882a593Smuzhiyun static void quadfs_fsynth_program_enable(struct st_clk_quadfs_fsynth *fs)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	/*
474*4882a593Smuzhiyun 	 * Pulse the program enable register lsb to make the hardware take
475*4882a593Smuzhiyun 	 * notice of the new md/pe values with a glitchless transition.
476*4882a593Smuzhiyun 	 */
477*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, en[fs->chan], 1);
478*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, en[fs->chan], 0);
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
quadfs_fsynth_program_rate(struct st_clk_quadfs_fsynth * fs)481*4882a593Smuzhiyun static void quadfs_fsynth_program_rate(struct st_clk_quadfs_fsynth *fs)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	unsigned long flags = 0;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	/*
486*4882a593Smuzhiyun 	 * Ensure the md/pe parameters are ignored while we are
487*4882a593Smuzhiyun 	 * reprogramming them so we can get a glitchless change
488*4882a593Smuzhiyun 	 * when fine tuning the speed of a running clock.
489*4882a593Smuzhiyun 	 */
490*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, en[fs->chan], 0);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, mdiv[fs->chan], fs->md);
493*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, pe[fs->chan], fs->pe);
494*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, sdiv[fs->chan], fs->sdiv);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (fs->lock)
497*4882a593Smuzhiyun 		spin_lock_irqsave(fs->lock, flags);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	if (fs->data->nsdiv_present)
500*4882a593Smuzhiyun 		CLKGEN_WRITE(fs, nsdiv[fs->chan], fs->nsdiv);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	if (fs->lock)
503*4882a593Smuzhiyun 		spin_unlock_irqrestore(fs->lock, flags);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun 
quadfs_fsynth_enable(struct clk_hw * hw)506*4882a593Smuzhiyun static int quadfs_fsynth_enable(struct clk_hw *hw)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
509*4882a593Smuzhiyun 	unsigned long flags = 0;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	quadfs_fsynth_program_rate(fs);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	if (fs->lock)
516*4882a593Smuzhiyun 		spin_lock_irqsave(fs->lock, flags);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	if (fs->data->nrst_present)
521*4882a593Smuzhiyun 		CLKGEN_WRITE(fs, nrst[fs->chan], 0);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	if (fs->lock)
524*4882a593Smuzhiyun 		spin_unlock_irqrestore(fs->lock, flags);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	quadfs_fsynth_program_enable(fs);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	return 0;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
quadfs_fsynth_disable(struct clk_hw * hw)531*4882a593Smuzhiyun static void quadfs_fsynth_disable(struct clk_hw *hw)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
534*4882a593Smuzhiyun 	unsigned long flags = 0;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	pr_debug("%s: %s\n", __func__, clk_hw_get_name(hw));
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	if (fs->lock)
539*4882a593Smuzhiyun 		spin_lock_irqsave(fs->lock, flags);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity);
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	if (fs->lock)
544*4882a593Smuzhiyun 		spin_unlock_irqrestore(fs->lock, flags);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
quadfs_fsynth_is_enabled(struct clk_hw * hw)547*4882a593Smuzhiyun static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
550*4882a593Smuzhiyun 	u32 nsb = CLKGEN_READ(fs, nsb[fs->chan]);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	pr_debug("%s: %s enable bit = 0x%x\n",
553*4882a593Smuzhiyun 		 __func__, clk_hw_get_name(hw), nsb);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	return fs->data->standby_polarity ? !nsb : !!nsb;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun #define P20		(uint64_t)(1 << 20)
559*4882a593Smuzhiyun 
clk_fs660c32_dig_get_rate(unsigned long input,const struct stm_fs * fs,unsigned long * rate)560*4882a593Smuzhiyun static int clk_fs660c32_dig_get_rate(unsigned long input,
561*4882a593Smuzhiyun 				const struct stm_fs *fs, unsigned long *rate)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun 	unsigned long s = (1 << fs->sdiv);
564*4882a593Smuzhiyun 	unsigned long ns;
565*4882a593Smuzhiyun 	uint64_t res;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/*
568*4882a593Smuzhiyun 	 * 'nsdiv' is a register value ('BIN') which is translated
569*4882a593Smuzhiyun 	 * to a decimal value according to following rules.
570*4882a593Smuzhiyun 	 *
571*4882a593Smuzhiyun 	 *     nsdiv      ns.dec
572*4882a593Smuzhiyun 	 *       0        3
573*4882a593Smuzhiyun 	 *       1        1
574*4882a593Smuzhiyun 	 */
575*4882a593Smuzhiyun 	ns = (fs->nsdiv == 1) ? 1 : 3;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	res = (P20 * (32 + fs->mdiv) + 32 * fs->pe) * s * ns;
578*4882a593Smuzhiyun 	*rate = (unsigned long)div64_u64(input * P20 * 32, res);
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	return 0;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 
clk_fs660c32_get_pe(int m,int si,unsigned long * deviation,signed long input,unsigned long output,uint64_t * p,struct stm_fs * fs)584*4882a593Smuzhiyun static int clk_fs660c32_get_pe(int m, int si, unsigned long *deviation,
585*4882a593Smuzhiyun 		signed long input, unsigned long output, uint64_t *p,
586*4882a593Smuzhiyun 		struct stm_fs *fs)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun 	unsigned long new_freq, new_deviation;
589*4882a593Smuzhiyun 	struct stm_fs fs_tmp;
590*4882a593Smuzhiyun 	uint64_t val;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	val = (uint64_t)output << si;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	*p = (uint64_t)input * P20 - (32LL  + (uint64_t)m) * val * (P20 / 32LL);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	*p = div64_u64(*p, val);
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	if (*p > 32767LL)
599*4882a593Smuzhiyun 		return 1;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	fs_tmp.mdiv = (unsigned long) m;
602*4882a593Smuzhiyun 	fs_tmp.pe = (unsigned long)*p;
603*4882a593Smuzhiyun 	fs_tmp.sdiv = si;
604*4882a593Smuzhiyun 	fs_tmp.nsdiv = 1;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	new_deviation = abs(output - new_freq);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	if (new_deviation < *deviation) {
611*4882a593Smuzhiyun 		fs->mdiv = m;
612*4882a593Smuzhiyun 		fs->pe = (unsigned long)*p;
613*4882a593Smuzhiyun 		fs->sdiv = si;
614*4882a593Smuzhiyun 		fs->nsdiv = 1;
615*4882a593Smuzhiyun 		*deviation = new_deviation;
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 	return 0;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
clk_fs660c32_dig_get_params(unsigned long input,unsigned long output,struct stm_fs * fs)620*4882a593Smuzhiyun static int clk_fs660c32_dig_get_params(unsigned long input,
621*4882a593Smuzhiyun 		unsigned long output, struct stm_fs *fs)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	int si;	/* sdiv_reg (8 downto 0) */
624*4882a593Smuzhiyun 	int m; /* md value */
625*4882a593Smuzhiyun 	unsigned long new_freq, new_deviation;
626*4882a593Smuzhiyun 	/* initial condition to say: "infinite deviation" */
627*4882a593Smuzhiyun 	unsigned long deviation = ~0;
628*4882a593Smuzhiyun 	uint64_t p, p1, p2;	/* pe value */
629*4882a593Smuzhiyun 	int r1, r2;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	struct stm_fs fs_tmp;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	for (si = 0; (si <= 8) && deviation; si++) {
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 		/* Boundary test to avoid useless iteration */
636*4882a593Smuzhiyun 		r1 = clk_fs660c32_get_pe(0, si, &deviation,
637*4882a593Smuzhiyun 				input, output, &p1, fs);
638*4882a593Smuzhiyun 		r2 = clk_fs660c32_get_pe(31, si, &deviation,
639*4882a593Smuzhiyun 				input, output, &p2, fs);
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 		/* No solution */
642*4882a593Smuzhiyun 		if (r1 && r2 && (p1 > p2))
643*4882a593Smuzhiyun 			continue;
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 		/* Try to find best deviation */
646*4882a593Smuzhiyun 		for (m = 1; (m < 31) && deviation; m++)
647*4882a593Smuzhiyun 			clk_fs660c32_get_pe(m, si, &deviation,
648*4882a593Smuzhiyun 					input, output, &p, fs);
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	}
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (deviation == ~0) /* No solution found */
653*4882a593Smuzhiyun 		return -1;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	/* pe fine tuning if deviation not 0: +/- 2 around computed pe value */
656*4882a593Smuzhiyun 	if (deviation) {
657*4882a593Smuzhiyun 		fs_tmp.mdiv = fs->mdiv;
658*4882a593Smuzhiyun 		fs_tmp.sdiv = fs->sdiv;
659*4882a593Smuzhiyun 		fs_tmp.nsdiv = fs->nsdiv;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 		if (fs->pe > 2)
662*4882a593Smuzhiyun 			p2 = fs->pe - 2;
663*4882a593Smuzhiyun 		else
664*4882a593Smuzhiyun 			p2 = 0;
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 		for (; p2 < 32768ll && (p2 <= (fs->pe + 2)); p2++) {
667*4882a593Smuzhiyun 			fs_tmp.pe = (unsigned long)p2;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 			clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 			new_deviation = abs(output - new_freq);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 			/* Check if this is a better solution */
674*4882a593Smuzhiyun 			if (new_deviation < deviation) {
675*4882a593Smuzhiyun 				fs->pe = (unsigned long)p2;
676*4882a593Smuzhiyun 				deviation = new_deviation;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 			}
679*4882a593Smuzhiyun 		}
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 	return 0;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth * fs,struct stm_fs * params)684*4882a593Smuzhiyun static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs,
685*4882a593Smuzhiyun 		struct stm_fs *params)
686*4882a593Smuzhiyun {
687*4882a593Smuzhiyun 	/*
688*4882a593Smuzhiyun 	 * Get the initial hardware values for recalc_rate
689*4882a593Smuzhiyun 	 */
690*4882a593Smuzhiyun 	params->mdiv	= CLKGEN_READ(fs, mdiv[fs->chan]);
691*4882a593Smuzhiyun 	params->pe	= CLKGEN_READ(fs, pe[fs->chan]);
692*4882a593Smuzhiyun 	params->sdiv	= CLKGEN_READ(fs, sdiv[fs->chan]);
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	if (fs->data->nsdiv_present)
695*4882a593Smuzhiyun 		params->nsdiv = CLKGEN_READ(fs, nsdiv[fs->chan]);
696*4882a593Smuzhiyun 	else
697*4882a593Smuzhiyun 		params->nsdiv = 1;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	/*
700*4882a593Smuzhiyun 	 * If All are NULL then assume no clock rate is programmed.
701*4882a593Smuzhiyun 	 */
702*4882a593Smuzhiyun 	if (!params->mdiv && !params->pe && !params->sdiv)
703*4882a593Smuzhiyun 		return 1;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	fs->md = params->mdiv;
706*4882a593Smuzhiyun 	fs->pe = params->pe;
707*4882a593Smuzhiyun 	fs->sdiv = params->sdiv;
708*4882a593Smuzhiyun 	fs->nsdiv = params->nsdiv;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	return 0;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
quadfs_find_best_rate(struct clk_hw * hw,unsigned long drate,unsigned long prate,struct stm_fs * params)713*4882a593Smuzhiyun static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
714*4882a593Smuzhiyun 				unsigned long prate, struct stm_fs *params)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
717*4882a593Smuzhiyun 	int (*clk_fs_get_rate)(unsigned long ,
718*4882a593Smuzhiyun 				const struct stm_fs *, unsigned long *);
719*4882a593Smuzhiyun 	int (*clk_fs_get_params)(unsigned long, unsigned long, struct stm_fs *);
720*4882a593Smuzhiyun 	unsigned long rate = 0;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	clk_fs_get_rate = fs->data->get_rate;
723*4882a593Smuzhiyun 	clk_fs_get_params = fs->data->get_params;
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	if (!clk_fs_get_params(prate, drate, params))
726*4882a593Smuzhiyun 		clk_fs_get_rate(prate, params, &rate);
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	return rate;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
quadfs_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)731*4882a593Smuzhiyun static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
732*4882a593Smuzhiyun 		unsigned long parent_rate)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
735*4882a593Smuzhiyun 	unsigned long rate = 0;
736*4882a593Smuzhiyun 	struct stm_fs params;
737*4882a593Smuzhiyun 	int (*clk_fs_get_rate)(unsigned long ,
738*4882a593Smuzhiyun 				const struct stm_fs *, unsigned long *);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	clk_fs_get_rate = fs->data->get_rate;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	if (quadfs_fsynt_get_hw_value_for_recalc(fs, &params))
743*4882a593Smuzhiyun 		return 0;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	if (clk_fs_get_rate(parent_rate, &params, &rate)) {
746*4882a593Smuzhiyun 		pr_err("%s:%s error calculating rate\n",
747*4882a593Smuzhiyun 		       clk_hw_get_name(hw), __func__);
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	pr_debug("%s:%s rate %lu\n", clk_hw_get_name(hw), __func__, rate);
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	return rate;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun 
quadfs_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)755*4882a593Smuzhiyun static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
756*4882a593Smuzhiyun 				     unsigned long *prate)
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun 	struct stm_fs params;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	rate = quadfs_find_best_rate(hw, rate, *prate, &params);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
763*4882a593Smuzhiyun 		 __func__, clk_hw_get_name(hw),
764*4882a593Smuzhiyun 		 rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
765*4882a593Smuzhiyun 			 (unsigned int)params.pe, (unsigned int)params.nsdiv);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	return rate;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 
quadfs_program_and_enable(struct st_clk_quadfs_fsynth * fs,struct stm_fs * params)771*4882a593Smuzhiyun static void quadfs_program_and_enable(struct st_clk_quadfs_fsynth *fs,
772*4882a593Smuzhiyun 		struct stm_fs *params)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun 	fs->md = params->mdiv;
775*4882a593Smuzhiyun 	fs->pe = params->pe;
776*4882a593Smuzhiyun 	fs->sdiv = params->sdiv;
777*4882a593Smuzhiyun 	fs->nsdiv = params->nsdiv;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	/*
780*4882a593Smuzhiyun 	 * In some integrations you can only change the fsynth programming when
781*4882a593Smuzhiyun 	 * the parent entity containing it is enabled.
782*4882a593Smuzhiyun 	 */
783*4882a593Smuzhiyun 	quadfs_fsynth_program_rate(fs);
784*4882a593Smuzhiyun 	quadfs_fsynth_program_enable(fs);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun 
quadfs_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)787*4882a593Smuzhiyun static int quadfs_set_rate(struct clk_hw *hw, unsigned long rate,
788*4882a593Smuzhiyun 				  unsigned long parent_rate)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
791*4882a593Smuzhiyun 	struct stm_fs params;
792*4882a593Smuzhiyun 	long hwrate;
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 	if (!rate || !parent_rate)
795*4882a593Smuzhiyun 		return -EINVAL;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	memset(&params, 0, sizeof(struct stm_fs));
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	hwrate = quadfs_find_best_rate(hw, rate, parent_rate, &params);
800*4882a593Smuzhiyun 	if (!hwrate)
801*4882a593Smuzhiyun 		return -EINVAL;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	quadfs_program_and_enable(fs, &params);
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	return 0;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun static const struct clk_ops st_quadfs_ops = {
811*4882a593Smuzhiyun 	.enable		= quadfs_fsynth_enable,
812*4882a593Smuzhiyun 	.disable	= quadfs_fsynth_disable,
813*4882a593Smuzhiyun 	.is_enabled	= quadfs_fsynth_is_enabled,
814*4882a593Smuzhiyun 	.round_rate	= quadfs_round_rate,
815*4882a593Smuzhiyun 	.set_rate	= quadfs_set_rate,
816*4882a593Smuzhiyun 	.recalc_rate	= quadfs_recalc_rate,
817*4882a593Smuzhiyun };
818*4882a593Smuzhiyun 
st_clk_register_quadfs_fsynth(const char * name,const char * parent_name,struct clkgen_quadfs_data * quadfs,void __iomem * reg,u32 chan,unsigned long flags,spinlock_t * lock)819*4882a593Smuzhiyun static struct clk * __init st_clk_register_quadfs_fsynth(
820*4882a593Smuzhiyun 		const char *name, const char *parent_name,
821*4882a593Smuzhiyun 		struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan,
822*4882a593Smuzhiyun 		unsigned long flags, spinlock_t *lock)
823*4882a593Smuzhiyun {
824*4882a593Smuzhiyun 	struct st_clk_quadfs_fsynth *fs;
825*4882a593Smuzhiyun 	struct clk *clk;
826*4882a593Smuzhiyun 	struct clk_init_data init;
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	/*
829*4882a593Smuzhiyun 	 * Sanity check required pointers, note that nsdiv3 is optional.
830*4882a593Smuzhiyun 	 */
831*4882a593Smuzhiyun 	if (WARN_ON(!name || !parent_name))
832*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	fs = kzalloc(sizeof(*fs), GFP_KERNEL);
835*4882a593Smuzhiyun 	if (!fs)
836*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	init.name = name;
839*4882a593Smuzhiyun 	init.ops = &st_quadfs_ops;
840*4882a593Smuzhiyun 	init.flags = flags | CLK_GET_RATE_NOCACHE;
841*4882a593Smuzhiyun 	init.parent_names = &parent_name;
842*4882a593Smuzhiyun 	init.num_parents = 1;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	fs->data = quadfs;
845*4882a593Smuzhiyun 	fs->regs_base = reg;
846*4882a593Smuzhiyun 	fs->chan = chan;
847*4882a593Smuzhiyun 	fs->lock = lock;
848*4882a593Smuzhiyun 	fs->hw.init = &init;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	clk = clk_register(NULL, &fs->hw);
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	if (IS_ERR(clk))
853*4882a593Smuzhiyun 		kfree(fs);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	return clk;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun 
st_of_create_quadfs_fsynths(struct device_node * np,const char * pll_name,struct clkgen_quadfs_data * quadfs,void __iomem * reg,spinlock_t * lock)858*4882a593Smuzhiyun static void __init st_of_create_quadfs_fsynths(
859*4882a593Smuzhiyun 		struct device_node *np, const char *pll_name,
860*4882a593Smuzhiyun 		struct clkgen_quadfs_data *quadfs, void __iomem *reg,
861*4882a593Smuzhiyun 		spinlock_t *lock)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun 	struct clk_onecell_data *clk_data;
864*4882a593Smuzhiyun 	int fschan;
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
867*4882a593Smuzhiyun 	if (!clk_data)
868*4882a593Smuzhiyun 		return;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	clk_data->clk_num = QUADFS_MAX_CHAN;
871*4882a593Smuzhiyun 	clk_data->clks = kcalloc(QUADFS_MAX_CHAN, sizeof(struct clk *),
872*4882a593Smuzhiyun 				 GFP_KERNEL);
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	if (!clk_data->clks) {
875*4882a593Smuzhiyun 		kfree(clk_data);
876*4882a593Smuzhiyun 		return;
877*4882a593Smuzhiyun 	}
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) {
880*4882a593Smuzhiyun 		struct clk *clk;
881*4882a593Smuzhiyun 		const char *clk_name;
882*4882a593Smuzhiyun 		unsigned long flags = 0;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 		if (of_property_read_string_index(np, "clock-output-names",
885*4882a593Smuzhiyun 						  fschan, &clk_name)) {
886*4882a593Smuzhiyun 			break;
887*4882a593Smuzhiyun 		}
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 		/*
890*4882a593Smuzhiyun 		 * If we read an empty clock name then the channel is unused
891*4882a593Smuzhiyun 		 */
892*4882a593Smuzhiyun 		if (*clk_name == '\0')
893*4882a593Smuzhiyun 			continue;
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 		of_clk_detect_critical(np, fschan, &flags);
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 		clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
898*4882a593Smuzhiyun 						    quadfs, reg, fschan,
899*4882a593Smuzhiyun 						    flags, lock);
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun 		/*
902*4882a593Smuzhiyun 		 * If there was an error registering this clock output, clean
903*4882a593Smuzhiyun 		 * up and move on to the next one.
904*4882a593Smuzhiyun 		 */
905*4882a593Smuzhiyun 		if (!IS_ERR(clk)) {
906*4882a593Smuzhiyun 			clk_data->clks[fschan] = clk;
907*4882a593Smuzhiyun 			pr_debug("%s: parent %s rate %u\n",
908*4882a593Smuzhiyun 				__clk_get_name(clk),
909*4882a593Smuzhiyun 				__clk_get_name(clk_get_parent(clk)),
910*4882a593Smuzhiyun 				(unsigned int)clk_get_rate(clk));
911*4882a593Smuzhiyun 		}
912*4882a593Smuzhiyun 	}
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun 
st_of_quadfs_setup(struct device_node * np,struct clkgen_quadfs_data * data)917*4882a593Smuzhiyun static void __init st_of_quadfs_setup(struct device_node *np,
918*4882a593Smuzhiyun 		struct clkgen_quadfs_data *data)
919*4882a593Smuzhiyun {
920*4882a593Smuzhiyun 	struct clk *clk;
921*4882a593Smuzhiyun 	const char *pll_name, *clk_parent_name;
922*4882a593Smuzhiyun 	void __iomem *reg;
923*4882a593Smuzhiyun 	spinlock_t *lock;
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	reg = of_iomap(np, 0);
926*4882a593Smuzhiyun 	if (!reg)
927*4882a593Smuzhiyun 		return;
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 	clk_parent_name = of_clk_get_parent_name(np, 0);
930*4882a593Smuzhiyun 	if (!clk_parent_name)
931*4882a593Smuzhiyun 		return;
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	pll_name = kasprintf(GFP_KERNEL, "%pOFn.pll", np);
934*4882a593Smuzhiyun 	if (!pll_name)
935*4882a593Smuzhiyun 		return;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	lock = kzalloc(sizeof(*lock), GFP_KERNEL);
938*4882a593Smuzhiyun 	if (!lock)
939*4882a593Smuzhiyun 		goto err_exit;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	spin_lock_init(lock);
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data,
944*4882a593Smuzhiyun 			reg, lock);
945*4882a593Smuzhiyun 	if (IS_ERR(clk))
946*4882a593Smuzhiyun 		goto err_exit;
947*4882a593Smuzhiyun 	else
948*4882a593Smuzhiyun 		pr_debug("%s: parent %s rate %u\n",
949*4882a593Smuzhiyun 			__clk_get_name(clk),
950*4882a593Smuzhiyun 			__clk_get_name(clk_get_parent(clk)),
951*4882a593Smuzhiyun 			(unsigned int)clk_get_rate(clk));
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock);
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun err_exit:
956*4882a593Smuzhiyun 	kfree(pll_name); /* No longer need local copy of the PLL name */
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun 
st_of_quadfs660C_setup(struct device_node * np)959*4882a593Smuzhiyun static void __init st_of_quadfs660C_setup(struct device_node *np)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun 	st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C);
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup);
964*4882a593Smuzhiyun 
st_of_quadfs660D_setup(struct device_node * np)965*4882a593Smuzhiyun static void __init st_of_quadfs660D_setup(struct device_node *np)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun 	st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D);
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup);
970