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, ¶ms, &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, ¶ms))
323*4882a593Smuzhiyun return rate;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun clk_fs660c32_vco_get_rate(*prate, ¶ms, &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, ¶ms);
347*4882a593Smuzhiyun if (ret)
348*4882a593Smuzhiyun return ret;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun clk_fs660c32_vco_get_rate(parent_rate, ¶ms, &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, ¶ms))
743*4882a593Smuzhiyun return 0;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun if (clk_fs_get_rate(parent_rate, ¶ms, &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, ¶ms);
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(¶ms, 0, sizeof(struct stm_fs));
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun hwrate = quadfs_find_best_rate(hw, rate, parent_rate, ¶ms);
800*4882a593Smuzhiyun if (!hwrate)
801*4882a593Smuzhiyun return -EINVAL;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun quadfs_program_and_enable(fs, ¶ms);
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