1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or
3*4882a593Smuzhiyun * modify it under the terms of the GNU General Public License as
4*4882a593Smuzhiyun * published by the Free Software Foundation version 2.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is distributed "as is" WITHOUT ANY WARRANTY of any
7*4882a593Smuzhiyun * kind, whether express or implied; without even the implied warranty
8*4882a593Smuzhiyun * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9*4882a593Smuzhiyun * GNU General Public License for more details.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/clk.h>
13*4882a593Smuzhiyun #include <linux/clkdev.h>
14*4882a593Smuzhiyun #include <linux/clk-provider.h>
15*4882a593Smuzhiyun #include <linux/delay.h>
16*4882a593Smuzhiyun #include <linux/err.h>
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include <linux/math64.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/of_device.h>
21*4882a593Smuzhiyun #include <linux/string.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define ADPLL_PLLSS_MMR_LOCK_OFFSET 0x00 /* Managed by MPPULL */
24*4882a593Smuzhiyun #define ADPLL_PLLSS_MMR_LOCK_ENABLED 0x1f125B64
25*4882a593Smuzhiyun #define ADPLL_PLLSS_MMR_UNLOCK_MAGIC 0x1eda4c3d
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define ADPLL_PWRCTRL_OFFSET 0x00
28*4882a593Smuzhiyun #define ADPLL_PWRCTRL_PONIN 5
29*4882a593Smuzhiyun #define ADPLL_PWRCTRL_PGOODIN 4
30*4882a593Smuzhiyun #define ADPLL_PWRCTRL_RET 3
31*4882a593Smuzhiyun #define ADPLL_PWRCTRL_ISORET 2
32*4882a593Smuzhiyun #define ADPLL_PWRCTRL_ISOSCAN 1
33*4882a593Smuzhiyun #define ADPLL_PWRCTRL_OFFMODE 0
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define ADPLL_CLKCTRL_OFFSET 0x04
36*4882a593Smuzhiyun #define ADPLL_CLKCTRL_CLKDCOLDOEN 29
37*4882a593Smuzhiyun #define ADPLL_CLKCTRL_IDLE 23
38*4882a593Smuzhiyun #define ADPLL_CLKCTRL_CLKOUTEN 20
39*4882a593Smuzhiyun #define ADPLL_CLKINPHIFSEL_ADPLL_S 19 /* REVISIT: which bit? */
40*4882a593Smuzhiyun #define ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ 19
41*4882a593Smuzhiyun #define ADPLL_CLKCTRL_ULOWCLKEN 18
42*4882a593Smuzhiyun #define ADPLL_CLKCTRL_CLKDCOLDOPWDNZ 17
43*4882a593Smuzhiyun #define ADPLL_CLKCTRL_M2PWDNZ 16
44*4882a593Smuzhiyun #define ADPLL_CLKCTRL_M3PWDNZ_ADPLL_S 15
45*4882a593Smuzhiyun #define ADPLL_CLKCTRL_LOWCURRSTDBY_ADPLL_S 13
46*4882a593Smuzhiyun #define ADPLL_CLKCTRL_LPMODE_ADPLL_S 12
47*4882a593Smuzhiyun #define ADPLL_CLKCTRL_REGM4XEN_ADPLL_S 10
48*4882a593Smuzhiyun #define ADPLL_CLKCTRL_SELFREQDCO_ADPLL_LJ 10
49*4882a593Smuzhiyun #define ADPLL_CLKCTRL_TINITZ 0
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define ADPLL_TENABLE_OFFSET 0x08
52*4882a593Smuzhiyun #define ADPLL_TENABLEDIV_OFFSET 0x8c
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define ADPLL_M2NDIV_OFFSET 0x10
55*4882a593Smuzhiyun #define ADPLL_M2NDIV_M2 16
56*4882a593Smuzhiyun #define ADPLL_M2NDIV_M2_ADPLL_S_WIDTH 5
57*4882a593Smuzhiyun #define ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH 7
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define ADPLL_MN2DIV_OFFSET 0x14
60*4882a593Smuzhiyun #define ADPLL_MN2DIV_N2 16
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define ADPLL_FRACDIV_OFFSET 0x18
63*4882a593Smuzhiyun #define ADPLL_FRACDIV_REGSD 24
64*4882a593Smuzhiyun #define ADPLL_FRACDIV_FRACTIONALM 0
65*4882a593Smuzhiyun #define ADPLL_FRACDIV_FRACTIONALM_MASK 0x3ffff
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define ADPLL_BWCTRL_OFFSET 0x1c
68*4882a593Smuzhiyun #define ADPLL_BWCTRL_BWCONTROL 1
69*4882a593Smuzhiyun #define ADPLL_BWCTRL_BW_INCR_DECRZ 0
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define ADPLL_RESERVED_OFFSET 0x20
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define ADPLL_STATUS_OFFSET 0x24
74*4882a593Smuzhiyun #define ADPLL_STATUS_PONOUT 31
75*4882a593Smuzhiyun #define ADPLL_STATUS_PGOODOUT 30
76*4882a593Smuzhiyun #define ADPLL_STATUS_LDOPWDN 29
77*4882a593Smuzhiyun #define ADPLL_STATUS_RECAL_BSTATUS3 28
78*4882a593Smuzhiyun #define ADPLL_STATUS_RECAL_OPPIN 27
79*4882a593Smuzhiyun #define ADPLL_STATUS_PHASELOCK 10
80*4882a593Smuzhiyun #define ADPLL_STATUS_FREQLOCK 9
81*4882a593Smuzhiyun #define ADPLL_STATUS_BYPASSACK 8
82*4882a593Smuzhiyun #define ADPLL_STATUS_LOSSREF 6
83*4882a593Smuzhiyun #define ADPLL_STATUS_CLKOUTENACK 5
84*4882a593Smuzhiyun #define ADPLL_STATUS_LOCK2 4
85*4882a593Smuzhiyun #define ADPLL_STATUS_M2CHANGEACK 3
86*4882a593Smuzhiyun #define ADPLL_STATUS_HIGHJITTER 1
87*4882a593Smuzhiyun #define ADPLL_STATUS_BYPASS 0
88*4882a593Smuzhiyun #define ADPLL_STATUS_PREPARED_MASK (BIT(ADPLL_STATUS_PHASELOCK) | \
89*4882a593Smuzhiyun BIT(ADPLL_STATUS_FREQLOCK))
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #define ADPLL_M3DIV_OFFSET 0x28 /* Only on MPUPLL */
92*4882a593Smuzhiyun #define ADPLL_M3DIV_M3 0
93*4882a593Smuzhiyun #define ADPLL_M3DIV_M3_WIDTH 5
94*4882a593Smuzhiyun #define ADPLL_M3DIV_M3_MASK 0x1f
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun #define ADPLL_RAMPCTRL_OFFSET 0x2c /* Only on MPUPLL */
97*4882a593Smuzhiyun #define ADPLL_RAMPCTRL_CLKRAMPLEVEL 19
98*4882a593Smuzhiyun #define ADPLL_RAMPCTRL_CLKRAMPRATE 16
99*4882a593Smuzhiyun #define ADPLL_RAMPCTRL_RELOCK_RAMP_EN 0
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun #define MAX_ADPLL_INPUTS 3
102*4882a593Smuzhiyun #define MAX_ADPLL_OUTPUTS 4
103*4882a593Smuzhiyun #define ADPLL_MAX_RETRIES 5
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun #define to_dco(_hw) container_of(_hw, struct ti_adpll_dco_data, hw)
106*4882a593Smuzhiyun #define to_adpll(_hw) container_of(_hw, struct ti_adpll_data, dco)
107*4882a593Smuzhiyun #define to_clkout(_hw) container_of(_hw, struct ti_adpll_clkout_data, hw)
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun enum ti_adpll_clocks {
110*4882a593Smuzhiyun TI_ADPLL_DCO,
111*4882a593Smuzhiyun TI_ADPLL_DCO_GATE,
112*4882a593Smuzhiyun TI_ADPLL_N2,
113*4882a593Smuzhiyun TI_ADPLL_M2,
114*4882a593Smuzhiyun TI_ADPLL_M2_GATE,
115*4882a593Smuzhiyun TI_ADPLL_BYPASS,
116*4882a593Smuzhiyun TI_ADPLL_HIF,
117*4882a593Smuzhiyun TI_ADPLL_DIV2,
118*4882a593Smuzhiyun TI_ADPLL_CLKOUT,
119*4882a593Smuzhiyun TI_ADPLL_CLKOUT2,
120*4882a593Smuzhiyun TI_ADPLL_M3,
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun #define TI_ADPLL_NR_CLOCKS (TI_ADPLL_M3 + 1)
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun enum ti_adpll_inputs {
126*4882a593Smuzhiyun TI_ADPLL_CLKINP,
127*4882a593Smuzhiyun TI_ADPLL_CLKINPULOW,
128*4882a593Smuzhiyun TI_ADPLL_CLKINPHIF,
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun enum ti_adpll_s_outputs {
132*4882a593Smuzhiyun TI_ADPLL_S_DCOCLKLDO,
133*4882a593Smuzhiyun TI_ADPLL_S_CLKOUT,
134*4882a593Smuzhiyun TI_ADPLL_S_CLKOUTX2,
135*4882a593Smuzhiyun TI_ADPLL_S_CLKOUTHIF,
136*4882a593Smuzhiyun };
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun enum ti_adpll_lj_outputs {
139*4882a593Smuzhiyun TI_ADPLL_LJ_CLKDCOLDO,
140*4882a593Smuzhiyun TI_ADPLL_LJ_CLKOUT,
141*4882a593Smuzhiyun TI_ADPLL_LJ_CLKOUTLDO,
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun struct ti_adpll_platform_data {
145*4882a593Smuzhiyun const bool is_type_s;
146*4882a593Smuzhiyun const int nr_max_inputs;
147*4882a593Smuzhiyun const int nr_max_outputs;
148*4882a593Smuzhiyun const int output_index;
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun struct ti_adpll_clock {
152*4882a593Smuzhiyun struct clk *clk;
153*4882a593Smuzhiyun struct clk_lookup *cl;
154*4882a593Smuzhiyun void (*unregister)(struct clk *clk);
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun struct ti_adpll_dco_data {
158*4882a593Smuzhiyun struct clk_hw hw;
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun struct ti_adpll_clkout_data {
162*4882a593Smuzhiyun struct ti_adpll_data *adpll;
163*4882a593Smuzhiyun struct clk_gate gate;
164*4882a593Smuzhiyun struct clk_hw hw;
165*4882a593Smuzhiyun };
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun struct ti_adpll_data {
168*4882a593Smuzhiyun struct device *dev;
169*4882a593Smuzhiyun const struct ti_adpll_platform_data *c;
170*4882a593Smuzhiyun struct device_node *np;
171*4882a593Smuzhiyun unsigned long pa;
172*4882a593Smuzhiyun void __iomem *iobase;
173*4882a593Smuzhiyun void __iomem *regs;
174*4882a593Smuzhiyun spinlock_t lock; /* For ADPLL shared register access */
175*4882a593Smuzhiyun const char *parent_names[MAX_ADPLL_INPUTS];
176*4882a593Smuzhiyun struct clk *parent_clocks[MAX_ADPLL_INPUTS];
177*4882a593Smuzhiyun struct ti_adpll_clock *clocks;
178*4882a593Smuzhiyun struct clk_onecell_data outputs;
179*4882a593Smuzhiyun struct ti_adpll_dco_data dco;
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun
ti_adpll_clk_get_name(struct ti_adpll_data * d,int output_index,const char * postfix)182*4882a593Smuzhiyun static const char *ti_adpll_clk_get_name(struct ti_adpll_data *d,
183*4882a593Smuzhiyun int output_index,
184*4882a593Smuzhiyun const char *postfix)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun const char *name;
187*4882a593Smuzhiyun int err;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (output_index >= 0) {
190*4882a593Smuzhiyun err = of_property_read_string_index(d->np,
191*4882a593Smuzhiyun "clock-output-names",
192*4882a593Smuzhiyun output_index,
193*4882a593Smuzhiyun &name);
194*4882a593Smuzhiyun if (err)
195*4882a593Smuzhiyun return NULL;
196*4882a593Smuzhiyun } else {
197*4882a593Smuzhiyun name = devm_kasprintf(d->dev, GFP_KERNEL, "%08lx.adpll.%s",
198*4882a593Smuzhiyun d->pa, postfix);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun return name;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun #define ADPLL_MAX_CON_ID 16 /* See MAX_CON_ID */
205*4882a593Smuzhiyun
ti_adpll_setup_clock(struct ti_adpll_data * d,struct clk * clock,int index,int output_index,const char * name,void (* unregister)(struct clk * clk))206*4882a593Smuzhiyun static int ti_adpll_setup_clock(struct ti_adpll_data *d, struct clk *clock,
207*4882a593Smuzhiyun int index, int output_index, const char *name,
208*4882a593Smuzhiyun void (*unregister)(struct clk *clk))
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun struct clk_lookup *cl;
211*4882a593Smuzhiyun const char *postfix = NULL;
212*4882a593Smuzhiyun char con_id[ADPLL_MAX_CON_ID];
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun d->clocks[index].clk = clock;
215*4882a593Smuzhiyun d->clocks[index].unregister = unregister;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */
218*4882a593Smuzhiyun postfix = strrchr(name, '.');
219*4882a593Smuzhiyun if (postfix && strlen(postfix) > 1) {
220*4882a593Smuzhiyun if (strlen(postfix) > ADPLL_MAX_CON_ID)
221*4882a593Smuzhiyun dev_warn(d->dev, "clock %s con_id lookup may fail\n",
222*4882a593Smuzhiyun name);
223*4882a593Smuzhiyun snprintf(con_id, 16, "pll%03lx%s", d->pa & 0xfff, postfix + 1);
224*4882a593Smuzhiyun cl = clkdev_create(clock, con_id, NULL);
225*4882a593Smuzhiyun if (!cl)
226*4882a593Smuzhiyun return -ENOMEM;
227*4882a593Smuzhiyun d->clocks[index].cl = cl;
228*4882a593Smuzhiyun } else {
229*4882a593Smuzhiyun dev_warn(d->dev, "no con_id for clock %s\n", name);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (output_index < 0)
233*4882a593Smuzhiyun return 0;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun d->outputs.clks[output_index] = clock;
236*4882a593Smuzhiyun d->outputs.clk_num++;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
ti_adpll_init_divider(struct ti_adpll_data * d,enum ti_adpll_clocks index,int output_index,char * name,struct clk * parent_clock,void __iomem * reg,u8 shift,u8 width,u8 clk_divider_flags)241*4882a593Smuzhiyun static int ti_adpll_init_divider(struct ti_adpll_data *d,
242*4882a593Smuzhiyun enum ti_adpll_clocks index,
243*4882a593Smuzhiyun int output_index, char *name,
244*4882a593Smuzhiyun struct clk *parent_clock,
245*4882a593Smuzhiyun void __iomem *reg,
246*4882a593Smuzhiyun u8 shift, u8 width,
247*4882a593Smuzhiyun u8 clk_divider_flags)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun const char *child_name;
250*4882a593Smuzhiyun const char *parent_name;
251*4882a593Smuzhiyun struct clk *clock;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun child_name = ti_adpll_clk_get_name(d, output_index, name);
254*4882a593Smuzhiyun if (!child_name)
255*4882a593Smuzhiyun return -EINVAL;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun parent_name = __clk_get_name(parent_clock);
258*4882a593Smuzhiyun clock = clk_register_divider(d->dev, child_name, parent_name, 0,
259*4882a593Smuzhiyun reg, shift, width, clk_divider_flags,
260*4882a593Smuzhiyun &d->lock);
261*4882a593Smuzhiyun if (IS_ERR(clock)) {
262*4882a593Smuzhiyun dev_err(d->dev, "failed to register divider %s: %li\n",
263*4882a593Smuzhiyun name, PTR_ERR(clock));
264*4882a593Smuzhiyun return PTR_ERR(clock);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, index, output_index, child_name,
268*4882a593Smuzhiyun clk_unregister_divider);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
ti_adpll_init_mux(struct ti_adpll_data * d,enum ti_adpll_clocks index,char * name,struct clk * clk0,struct clk * clk1,void __iomem * reg,u8 shift)271*4882a593Smuzhiyun static int ti_adpll_init_mux(struct ti_adpll_data *d,
272*4882a593Smuzhiyun enum ti_adpll_clocks index,
273*4882a593Smuzhiyun char *name, struct clk *clk0,
274*4882a593Smuzhiyun struct clk *clk1,
275*4882a593Smuzhiyun void __iomem *reg,
276*4882a593Smuzhiyun u8 shift)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun const char *child_name;
279*4882a593Smuzhiyun const char *parents[2];
280*4882a593Smuzhiyun struct clk *clock;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun child_name = ti_adpll_clk_get_name(d, -ENODEV, name);
283*4882a593Smuzhiyun if (!child_name)
284*4882a593Smuzhiyun return -ENOMEM;
285*4882a593Smuzhiyun parents[0] = __clk_get_name(clk0);
286*4882a593Smuzhiyun parents[1] = __clk_get_name(clk1);
287*4882a593Smuzhiyun clock = clk_register_mux(d->dev, child_name, parents, 2, 0,
288*4882a593Smuzhiyun reg, shift, 1, 0, &d->lock);
289*4882a593Smuzhiyun if (IS_ERR(clock)) {
290*4882a593Smuzhiyun dev_err(d->dev, "failed to register mux %s: %li\n",
291*4882a593Smuzhiyun name, PTR_ERR(clock));
292*4882a593Smuzhiyun return PTR_ERR(clock);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name,
296*4882a593Smuzhiyun clk_unregister_mux);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
ti_adpll_init_gate(struct ti_adpll_data * d,enum ti_adpll_clocks index,int output_index,char * name,struct clk * parent_clock,void __iomem * reg,u8 bit_idx,u8 clk_gate_flags)299*4882a593Smuzhiyun static int ti_adpll_init_gate(struct ti_adpll_data *d,
300*4882a593Smuzhiyun enum ti_adpll_clocks index,
301*4882a593Smuzhiyun int output_index, char *name,
302*4882a593Smuzhiyun struct clk *parent_clock,
303*4882a593Smuzhiyun void __iomem *reg,
304*4882a593Smuzhiyun u8 bit_idx,
305*4882a593Smuzhiyun u8 clk_gate_flags)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun const char *child_name;
308*4882a593Smuzhiyun const char *parent_name;
309*4882a593Smuzhiyun struct clk *clock;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun child_name = ti_adpll_clk_get_name(d, output_index, name);
312*4882a593Smuzhiyun if (!child_name)
313*4882a593Smuzhiyun return -EINVAL;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun parent_name = __clk_get_name(parent_clock);
316*4882a593Smuzhiyun clock = clk_register_gate(d->dev, child_name, parent_name, 0,
317*4882a593Smuzhiyun reg, bit_idx, clk_gate_flags,
318*4882a593Smuzhiyun &d->lock);
319*4882a593Smuzhiyun if (IS_ERR(clock)) {
320*4882a593Smuzhiyun dev_err(d->dev, "failed to register gate %s: %li\n",
321*4882a593Smuzhiyun name, PTR_ERR(clock));
322*4882a593Smuzhiyun return PTR_ERR(clock);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, index, output_index, child_name,
326*4882a593Smuzhiyun clk_unregister_gate);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
ti_adpll_init_fixed_factor(struct ti_adpll_data * d,enum ti_adpll_clocks index,char * name,struct clk * parent_clock,unsigned int mult,unsigned int div)329*4882a593Smuzhiyun static int ti_adpll_init_fixed_factor(struct ti_adpll_data *d,
330*4882a593Smuzhiyun enum ti_adpll_clocks index,
331*4882a593Smuzhiyun char *name,
332*4882a593Smuzhiyun struct clk *parent_clock,
333*4882a593Smuzhiyun unsigned int mult,
334*4882a593Smuzhiyun unsigned int div)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun const char *child_name;
337*4882a593Smuzhiyun const char *parent_name;
338*4882a593Smuzhiyun struct clk *clock;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun child_name = ti_adpll_clk_get_name(d, -ENODEV, name);
341*4882a593Smuzhiyun if (!child_name)
342*4882a593Smuzhiyun return -ENOMEM;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun parent_name = __clk_get_name(parent_clock);
345*4882a593Smuzhiyun clock = clk_register_fixed_factor(d->dev, child_name, parent_name,
346*4882a593Smuzhiyun 0, mult, div);
347*4882a593Smuzhiyun if (IS_ERR(clock))
348*4882a593Smuzhiyun return PTR_ERR(clock);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, index, -ENODEV, child_name,
351*4882a593Smuzhiyun clk_unregister);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
ti_adpll_set_idle_bypass(struct ti_adpll_data * d)354*4882a593Smuzhiyun static void ti_adpll_set_idle_bypass(struct ti_adpll_data *d)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun unsigned long flags;
357*4882a593Smuzhiyun u32 v;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun spin_lock_irqsave(&d->lock, flags);
360*4882a593Smuzhiyun v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);
361*4882a593Smuzhiyun v |= BIT(ADPLL_CLKCTRL_IDLE);
362*4882a593Smuzhiyun writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET);
363*4882a593Smuzhiyun spin_unlock_irqrestore(&d->lock, flags);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
ti_adpll_clear_idle_bypass(struct ti_adpll_data * d)366*4882a593Smuzhiyun static void ti_adpll_clear_idle_bypass(struct ti_adpll_data *d)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun unsigned long flags;
369*4882a593Smuzhiyun u32 v;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun spin_lock_irqsave(&d->lock, flags);
372*4882a593Smuzhiyun v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);
373*4882a593Smuzhiyun v &= ~BIT(ADPLL_CLKCTRL_IDLE);
374*4882a593Smuzhiyun writel_relaxed(v, d->regs + ADPLL_CLKCTRL_OFFSET);
375*4882a593Smuzhiyun spin_unlock_irqrestore(&d->lock, flags);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
ti_adpll_clock_is_bypass(struct ti_adpll_data * d)378*4882a593Smuzhiyun static bool ti_adpll_clock_is_bypass(struct ti_adpll_data *d)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun u32 v;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun return v & BIT(ADPLL_STATUS_BYPASS);
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /*
388*4882a593Smuzhiyun * Locked and bypass are not actually mutually exclusive: if you only care
389*4882a593Smuzhiyun * about the DCO clock and not CLKOUT you can clear M2PWDNZ before enabling
390*4882a593Smuzhiyun * the PLL, resulting in status (FREQLOCK | PHASELOCK | BYPASS) after lock.
391*4882a593Smuzhiyun */
ti_adpll_is_locked(struct ti_adpll_data * d)392*4882a593Smuzhiyun static bool ti_adpll_is_locked(struct ti_adpll_data *d)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun u32 v = readl_relaxed(d->regs + ADPLL_STATUS_OFFSET);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun return (v & ADPLL_STATUS_PREPARED_MASK) == ADPLL_STATUS_PREPARED_MASK;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
ti_adpll_wait_lock(struct ti_adpll_data * d)399*4882a593Smuzhiyun static int ti_adpll_wait_lock(struct ti_adpll_data *d)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun int retries = ADPLL_MAX_RETRIES;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun do {
404*4882a593Smuzhiyun if (ti_adpll_is_locked(d))
405*4882a593Smuzhiyun return 0;
406*4882a593Smuzhiyun usleep_range(200, 300);
407*4882a593Smuzhiyun } while (retries--);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun dev_err(d->dev, "pll failed to lock\n");
410*4882a593Smuzhiyun return -ETIMEDOUT;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
ti_adpll_prepare(struct clk_hw * hw)413*4882a593Smuzhiyun static int ti_adpll_prepare(struct clk_hw *hw)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun struct ti_adpll_dco_data *dco = to_dco(hw);
416*4882a593Smuzhiyun struct ti_adpll_data *d = to_adpll(dco);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun ti_adpll_clear_idle_bypass(d);
419*4882a593Smuzhiyun ti_adpll_wait_lock(d);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun return 0;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
ti_adpll_unprepare(struct clk_hw * hw)424*4882a593Smuzhiyun static void ti_adpll_unprepare(struct clk_hw *hw)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun struct ti_adpll_dco_data *dco = to_dco(hw);
427*4882a593Smuzhiyun struct ti_adpll_data *d = to_adpll(dco);
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun ti_adpll_set_idle_bypass(d);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
ti_adpll_is_prepared(struct clk_hw * hw)432*4882a593Smuzhiyun static int ti_adpll_is_prepared(struct clk_hw *hw)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun struct ti_adpll_dco_data *dco = to_dco(hw);
435*4882a593Smuzhiyun struct ti_adpll_data *d = to_adpll(dco);
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun return ti_adpll_is_locked(d);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /*
441*4882a593Smuzhiyun * Note that the DCO clock is never subject to bypass: if the PLL is off,
442*4882a593Smuzhiyun * dcoclk is low.
443*4882a593Smuzhiyun */
ti_adpll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)444*4882a593Smuzhiyun static unsigned long ti_adpll_recalc_rate(struct clk_hw *hw,
445*4882a593Smuzhiyun unsigned long parent_rate)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun struct ti_adpll_dco_data *dco = to_dco(hw);
448*4882a593Smuzhiyun struct ti_adpll_data *d = to_adpll(dco);
449*4882a593Smuzhiyun u32 frac_m, divider, v;
450*4882a593Smuzhiyun u64 rate;
451*4882a593Smuzhiyun unsigned long flags;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (ti_adpll_clock_is_bypass(d))
454*4882a593Smuzhiyun return 0;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun spin_lock_irqsave(&d->lock, flags);
457*4882a593Smuzhiyun frac_m = readl_relaxed(d->regs + ADPLL_FRACDIV_OFFSET);
458*4882a593Smuzhiyun frac_m &= ADPLL_FRACDIV_FRACTIONALM_MASK;
459*4882a593Smuzhiyun rate = (u64)readw_relaxed(d->regs + ADPLL_MN2DIV_OFFSET) << 18;
460*4882a593Smuzhiyun rate += frac_m;
461*4882a593Smuzhiyun rate *= parent_rate;
462*4882a593Smuzhiyun divider = (readw_relaxed(d->regs + ADPLL_M2NDIV_OFFSET) + 1) << 18;
463*4882a593Smuzhiyun spin_unlock_irqrestore(&d->lock, flags);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun do_div(rate, divider);
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun if (d->c->is_type_s) {
468*4882a593Smuzhiyun v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);
469*4882a593Smuzhiyun if (v & BIT(ADPLL_CLKCTRL_REGM4XEN_ADPLL_S))
470*4882a593Smuzhiyun rate *= 4;
471*4882a593Smuzhiyun rate *= 2;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun return rate;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /* PLL parent is always clkinp, bypass only affects the children */
ti_adpll_get_parent(struct clk_hw * hw)478*4882a593Smuzhiyun static u8 ti_adpll_get_parent(struct clk_hw *hw)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun return 0;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun static const struct clk_ops ti_adpll_ops = {
484*4882a593Smuzhiyun .prepare = ti_adpll_prepare,
485*4882a593Smuzhiyun .unprepare = ti_adpll_unprepare,
486*4882a593Smuzhiyun .is_prepared = ti_adpll_is_prepared,
487*4882a593Smuzhiyun .recalc_rate = ti_adpll_recalc_rate,
488*4882a593Smuzhiyun .get_parent = ti_adpll_get_parent,
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
ti_adpll_init_dco(struct ti_adpll_data * d)491*4882a593Smuzhiyun static int ti_adpll_init_dco(struct ti_adpll_data *d)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun struct clk_init_data init;
494*4882a593Smuzhiyun struct clk *clock;
495*4882a593Smuzhiyun const char *postfix;
496*4882a593Smuzhiyun int width, err;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun d->outputs.clks = devm_kcalloc(d->dev,
499*4882a593Smuzhiyun MAX_ADPLL_OUTPUTS,
500*4882a593Smuzhiyun sizeof(struct clk *),
501*4882a593Smuzhiyun GFP_KERNEL);
502*4882a593Smuzhiyun if (!d->outputs.clks)
503*4882a593Smuzhiyun return -ENOMEM;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (d->c->output_index < 0)
506*4882a593Smuzhiyun postfix = "dco";
507*4882a593Smuzhiyun else
508*4882a593Smuzhiyun postfix = NULL;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun init.name = ti_adpll_clk_get_name(d, d->c->output_index, postfix);
511*4882a593Smuzhiyun if (!init.name)
512*4882a593Smuzhiyun return -EINVAL;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun init.parent_names = d->parent_names;
515*4882a593Smuzhiyun init.num_parents = d->c->nr_max_inputs;
516*4882a593Smuzhiyun init.ops = &ti_adpll_ops;
517*4882a593Smuzhiyun init.flags = CLK_GET_RATE_NOCACHE;
518*4882a593Smuzhiyun d->dco.hw.init = &init;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun if (d->c->is_type_s)
521*4882a593Smuzhiyun width = 5;
522*4882a593Smuzhiyun else
523*4882a593Smuzhiyun width = 4;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /* Internal input clock divider N2 */
526*4882a593Smuzhiyun err = ti_adpll_init_divider(d, TI_ADPLL_N2, -ENODEV, "n2",
527*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINP],
528*4882a593Smuzhiyun d->regs + ADPLL_MN2DIV_OFFSET,
529*4882a593Smuzhiyun ADPLL_MN2DIV_N2, width, 0);
530*4882a593Smuzhiyun if (err)
531*4882a593Smuzhiyun return err;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun clock = devm_clk_register(d->dev, &d->dco.hw);
534*4882a593Smuzhiyun if (IS_ERR(clock))
535*4882a593Smuzhiyun return PTR_ERR(clock);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, TI_ADPLL_DCO, d->c->output_index,
538*4882a593Smuzhiyun init.name, NULL);
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
ti_adpll_clkout_enable(struct clk_hw * hw)541*4882a593Smuzhiyun static int ti_adpll_clkout_enable(struct clk_hw *hw)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun struct ti_adpll_clkout_data *co = to_clkout(hw);
544*4882a593Smuzhiyun struct clk_hw *gate_hw = &co->gate.hw;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun __clk_hw_set_clk(gate_hw, hw);
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun return clk_gate_ops.enable(gate_hw);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
ti_adpll_clkout_disable(struct clk_hw * hw)551*4882a593Smuzhiyun static void ti_adpll_clkout_disable(struct clk_hw *hw)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun struct ti_adpll_clkout_data *co = to_clkout(hw);
554*4882a593Smuzhiyun struct clk_hw *gate_hw = &co->gate.hw;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun __clk_hw_set_clk(gate_hw, hw);
557*4882a593Smuzhiyun clk_gate_ops.disable(gate_hw);
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
ti_adpll_clkout_is_enabled(struct clk_hw * hw)560*4882a593Smuzhiyun static int ti_adpll_clkout_is_enabled(struct clk_hw *hw)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun struct ti_adpll_clkout_data *co = to_clkout(hw);
563*4882a593Smuzhiyun struct clk_hw *gate_hw = &co->gate.hw;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun __clk_hw_set_clk(gate_hw, hw);
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun return clk_gate_ops.is_enabled(gate_hw);
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun /* Setting PLL bypass puts clkout and clkoutx2 into bypass */
ti_adpll_clkout_get_parent(struct clk_hw * hw)571*4882a593Smuzhiyun static u8 ti_adpll_clkout_get_parent(struct clk_hw *hw)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun struct ti_adpll_clkout_data *co = to_clkout(hw);
574*4882a593Smuzhiyun struct ti_adpll_data *d = co->adpll;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun return ti_adpll_clock_is_bypass(d);
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
ti_adpll_init_clkout(struct ti_adpll_data * d,enum ti_adpll_clocks index,int output_index,int gate_bit,char * name,struct clk * clk0,struct clk * clk1)579*4882a593Smuzhiyun static int ti_adpll_init_clkout(struct ti_adpll_data *d,
580*4882a593Smuzhiyun enum ti_adpll_clocks index,
581*4882a593Smuzhiyun int output_index, int gate_bit,
582*4882a593Smuzhiyun char *name, struct clk *clk0,
583*4882a593Smuzhiyun struct clk *clk1)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun struct ti_adpll_clkout_data *co;
586*4882a593Smuzhiyun struct clk_init_data init;
587*4882a593Smuzhiyun struct clk_ops *ops;
588*4882a593Smuzhiyun const char *parent_names[2];
589*4882a593Smuzhiyun const char *child_name;
590*4882a593Smuzhiyun struct clk *clock;
591*4882a593Smuzhiyun int err;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun co = devm_kzalloc(d->dev, sizeof(*co), GFP_KERNEL);
594*4882a593Smuzhiyun if (!co)
595*4882a593Smuzhiyun return -ENOMEM;
596*4882a593Smuzhiyun co->adpll = d;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun err = of_property_read_string_index(d->np,
599*4882a593Smuzhiyun "clock-output-names",
600*4882a593Smuzhiyun output_index,
601*4882a593Smuzhiyun &child_name);
602*4882a593Smuzhiyun if (err)
603*4882a593Smuzhiyun return err;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun ops = devm_kzalloc(d->dev, sizeof(*ops), GFP_KERNEL);
606*4882a593Smuzhiyun if (!ops)
607*4882a593Smuzhiyun return -ENOMEM;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun init.name = child_name;
610*4882a593Smuzhiyun init.ops = ops;
611*4882a593Smuzhiyun init.flags = 0;
612*4882a593Smuzhiyun co->hw.init = &init;
613*4882a593Smuzhiyun parent_names[0] = __clk_get_name(clk0);
614*4882a593Smuzhiyun parent_names[1] = __clk_get_name(clk1);
615*4882a593Smuzhiyun init.parent_names = parent_names;
616*4882a593Smuzhiyun init.num_parents = 2;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun ops->get_parent = ti_adpll_clkout_get_parent;
619*4882a593Smuzhiyun ops->determine_rate = __clk_mux_determine_rate;
620*4882a593Smuzhiyun if (gate_bit) {
621*4882a593Smuzhiyun co->gate.lock = &d->lock;
622*4882a593Smuzhiyun co->gate.reg = d->regs + ADPLL_CLKCTRL_OFFSET;
623*4882a593Smuzhiyun co->gate.bit_idx = gate_bit;
624*4882a593Smuzhiyun ops->enable = ti_adpll_clkout_enable;
625*4882a593Smuzhiyun ops->disable = ti_adpll_clkout_disable;
626*4882a593Smuzhiyun ops->is_enabled = ti_adpll_clkout_is_enabled;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun clock = devm_clk_register(d->dev, &co->hw);
630*4882a593Smuzhiyun if (IS_ERR(clock)) {
631*4882a593Smuzhiyun dev_err(d->dev, "failed to register output %s: %li\n",
632*4882a593Smuzhiyun name, PTR_ERR(clock));
633*4882a593Smuzhiyun return PTR_ERR(clock);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun return ti_adpll_setup_clock(d, clock, index, output_index, child_name,
637*4882a593Smuzhiyun NULL);
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun
ti_adpll_init_children_adpll_s(struct ti_adpll_data * d)640*4882a593Smuzhiyun static int ti_adpll_init_children_adpll_s(struct ti_adpll_data *d)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun int err;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (!d->c->is_type_s)
645*4882a593Smuzhiyun return 0;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun /* Internal mux, sources from divider N2 or clkinpulow */
648*4882a593Smuzhiyun err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass",
649*4882a593Smuzhiyun d->clocks[TI_ADPLL_N2].clk,
650*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINPULOW],
651*4882a593Smuzhiyun d->regs + ADPLL_CLKCTRL_OFFSET,
652*4882a593Smuzhiyun ADPLL_CLKCTRL_ULOWCLKEN);
653*4882a593Smuzhiyun if (err)
654*4882a593Smuzhiyun return err;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun /* Internal divider M2, sources DCO */
657*4882a593Smuzhiyun err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV, "m2",
658*4882a593Smuzhiyun d->clocks[TI_ADPLL_DCO].clk,
659*4882a593Smuzhiyun d->regs + ADPLL_M2NDIV_OFFSET,
660*4882a593Smuzhiyun ADPLL_M2NDIV_M2,
661*4882a593Smuzhiyun ADPLL_M2NDIV_M2_ADPLL_S_WIDTH,
662*4882a593Smuzhiyun CLK_DIVIDER_ONE_BASED);
663*4882a593Smuzhiyun if (err)
664*4882a593Smuzhiyun return err;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun /* Internal fixed divider, after M2 before clkout */
667*4882a593Smuzhiyun err = ti_adpll_init_fixed_factor(d, TI_ADPLL_DIV2, "div2",
668*4882a593Smuzhiyun d->clocks[TI_ADPLL_M2].clk,
669*4882a593Smuzhiyun 1, 2);
670*4882a593Smuzhiyun if (err)
671*4882a593Smuzhiyun return err;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun /* Output clkout with a mux and gate, sources from div2 or bypass */
674*4882a593Smuzhiyun err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT,
675*4882a593Smuzhiyun ADPLL_CLKCTRL_CLKOUTEN, "clkout",
676*4882a593Smuzhiyun d->clocks[TI_ADPLL_DIV2].clk,
677*4882a593Smuzhiyun d->clocks[TI_ADPLL_BYPASS].clk);
678*4882a593Smuzhiyun if (err)
679*4882a593Smuzhiyun return err;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun /* Output clkoutx2 with a mux and gate, sources from M2 or bypass */
682*4882a593Smuzhiyun err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT2, TI_ADPLL_S_CLKOUTX2, 0,
683*4882a593Smuzhiyun "clkout2", d->clocks[TI_ADPLL_M2].clk,
684*4882a593Smuzhiyun d->clocks[TI_ADPLL_BYPASS].clk);
685*4882a593Smuzhiyun if (err)
686*4882a593Smuzhiyun return err;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /* Internal mux, sources from DCO and clkinphif */
689*4882a593Smuzhiyun if (d->parent_clocks[TI_ADPLL_CLKINPHIF]) {
690*4882a593Smuzhiyun err = ti_adpll_init_mux(d, TI_ADPLL_HIF, "hif",
691*4882a593Smuzhiyun d->clocks[TI_ADPLL_DCO].clk,
692*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINPHIF],
693*4882a593Smuzhiyun d->regs + ADPLL_CLKCTRL_OFFSET,
694*4882a593Smuzhiyun ADPLL_CLKINPHIFSEL_ADPLL_S);
695*4882a593Smuzhiyun if (err)
696*4882a593Smuzhiyun return err;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun /* Output clkouthif with a divider M3, sources from hif */
700*4882a593Smuzhiyun err = ti_adpll_init_divider(d, TI_ADPLL_M3, TI_ADPLL_S_CLKOUTHIF, "m3",
701*4882a593Smuzhiyun d->clocks[TI_ADPLL_HIF].clk,
702*4882a593Smuzhiyun d->regs + ADPLL_M3DIV_OFFSET,
703*4882a593Smuzhiyun ADPLL_M3DIV_M3,
704*4882a593Smuzhiyun ADPLL_M3DIV_M3_WIDTH,
705*4882a593Smuzhiyun CLK_DIVIDER_ONE_BASED);
706*4882a593Smuzhiyun if (err)
707*4882a593Smuzhiyun return err;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun /* Output clock dcoclkldo is the DCO */
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun return 0;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
ti_adpll_init_children_adpll_lj(struct ti_adpll_data * d)714*4882a593Smuzhiyun static int ti_adpll_init_children_adpll_lj(struct ti_adpll_data *d)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun int err;
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun if (d->c->is_type_s)
719*4882a593Smuzhiyun return 0;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* Output clkdcoldo, gated output of DCO */
722*4882a593Smuzhiyun err = ti_adpll_init_gate(d, TI_ADPLL_DCO_GATE, TI_ADPLL_LJ_CLKDCOLDO,
723*4882a593Smuzhiyun "clkdcoldo", d->clocks[TI_ADPLL_DCO].clk,
724*4882a593Smuzhiyun d->regs + ADPLL_CLKCTRL_OFFSET,
725*4882a593Smuzhiyun ADPLL_CLKCTRL_CLKDCOLDOEN, 0);
726*4882a593Smuzhiyun if (err)
727*4882a593Smuzhiyun return err;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun /* Internal divider M2, sources from DCO */
730*4882a593Smuzhiyun err = ti_adpll_init_divider(d, TI_ADPLL_M2, -ENODEV,
731*4882a593Smuzhiyun "m2", d->clocks[TI_ADPLL_DCO].clk,
732*4882a593Smuzhiyun d->regs + ADPLL_M2NDIV_OFFSET,
733*4882a593Smuzhiyun ADPLL_M2NDIV_M2,
734*4882a593Smuzhiyun ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH,
735*4882a593Smuzhiyun CLK_DIVIDER_ONE_BASED);
736*4882a593Smuzhiyun if (err)
737*4882a593Smuzhiyun return err;
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun /* Output clkoutldo, gated output of M2 */
740*4882a593Smuzhiyun err = ti_adpll_init_gate(d, TI_ADPLL_M2_GATE, TI_ADPLL_LJ_CLKOUTLDO,
741*4882a593Smuzhiyun "clkoutldo", d->clocks[TI_ADPLL_M2].clk,
742*4882a593Smuzhiyun d->regs + ADPLL_CLKCTRL_OFFSET,
743*4882a593Smuzhiyun ADPLL_CLKCTRL_CLKOUTLDOEN_ADPLL_LJ,
744*4882a593Smuzhiyun 0);
745*4882a593Smuzhiyun if (err)
746*4882a593Smuzhiyun return err;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* Internal mux, sources from divider N2 or clkinpulow */
749*4882a593Smuzhiyun err = ti_adpll_init_mux(d, TI_ADPLL_BYPASS, "bypass",
750*4882a593Smuzhiyun d->clocks[TI_ADPLL_N2].clk,
751*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINPULOW],
752*4882a593Smuzhiyun d->regs + ADPLL_CLKCTRL_OFFSET,
753*4882a593Smuzhiyun ADPLL_CLKCTRL_ULOWCLKEN);
754*4882a593Smuzhiyun if (err)
755*4882a593Smuzhiyun return err;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun /* Output clkout, sources M2 or bypass */
758*4882a593Smuzhiyun err = ti_adpll_init_clkout(d, TI_ADPLL_CLKOUT, TI_ADPLL_S_CLKOUT,
759*4882a593Smuzhiyun ADPLL_CLKCTRL_CLKOUTEN, "clkout",
760*4882a593Smuzhiyun d->clocks[TI_ADPLL_M2].clk,
761*4882a593Smuzhiyun d->clocks[TI_ADPLL_BYPASS].clk);
762*4882a593Smuzhiyun if (err)
763*4882a593Smuzhiyun return err;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun return 0;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun
ti_adpll_free_resources(struct ti_adpll_data * d)768*4882a593Smuzhiyun static void ti_adpll_free_resources(struct ti_adpll_data *d)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun int i;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun for (i = TI_ADPLL_M3; i >= 0; i--) {
773*4882a593Smuzhiyun struct ti_adpll_clock *ac = &d->clocks[i];
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun if (!ac || IS_ERR_OR_NULL(ac->clk))
776*4882a593Smuzhiyun continue;
777*4882a593Smuzhiyun if (ac->cl)
778*4882a593Smuzhiyun clkdev_drop(ac->cl);
779*4882a593Smuzhiyun if (ac->unregister)
780*4882a593Smuzhiyun ac->unregister(ac->clk);
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun /* MPU PLL manages the lock register for all PLLs */
ti_adpll_unlock_all(void __iomem * reg)785*4882a593Smuzhiyun static void ti_adpll_unlock_all(void __iomem *reg)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun u32 v;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun v = readl_relaxed(reg);
790*4882a593Smuzhiyun if (v == ADPLL_PLLSS_MMR_LOCK_ENABLED)
791*4882a593Smuzhiyun writel_relaxed(ADPLL_PLLSS_MMR_UNLOCK_MAGIC, reg);
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
ti_adpll_init_registers(struct ti_adpll_data * d)794*4882a593Smuzhiyun static int ti_adpll_init_registers(struct ti_adpll_data *d)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun int register_offset = 0;
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun if (d->c->is_type_s) {
799*4882a593Smuzhiyun register_offset = 8;
800*4882a593Smuzhiyun ti_adpll_unlock_all(d->iobase + ADPLL_PLLSS_MMR_LOCK_OFFSET);
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun d->regs = d->iobase + register_offset + ADPLL_PWRCTRL_OFFSET;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun return 0;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
ti_adpll_init_inputs(struct ti_adpll_data * d)808*4882a593Smuzhiyun static int ti_adpll_init_inputs(struct ti_adpll_data *d)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun const char *error = "need at least %i inputs";
811*4882a593Smuzhiyun struct clk *clock;
812*4882a593Smuzhiyun int nr_inputs;
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun nr_inputs = of_clk_get_parent_count(d->np);
815*4882a593Smuzhiyun if (nr_inputs < d->c->nr_max_inputs) {
816*4882a593Smuzhiyun dev_err(d->dev, error, nr_inputs);
817*4882a593Smuzhiyun return -EINVAL;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun of_clk_parent_fill(d->np, d->parent_names, nr_inputs);
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun clock = devm_clk_get(d->dev, d->parent_names[0]);
822*4882a593Smuzhiyun if (IS_ERR(clock)) {
823*4882a593Smuzhiyun dev_err(d->dev, "could not get clkinp\n");
824*4882a593Smuzhiyun return PTR_ERR(clock);
825*4882a593Smuzhiyun }
826*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINP] = clock;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun clock = devm_clk_get(d->dev, d->parent_names[1]);
829*4882a593Smuzhiyun if (IS_ERR(clock)) {
830*4882a593Smuzhiyun dev_err(d->dev, "could not get clkinpulow clock\n");
831*4882a593Smuzhiyun return PTR_ERR(clock);
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINPULOW] = clock;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun if (d->c->is_type_s) {
836*4882a593Smuzhiyun clock = devm_clk_get(d->dev, d->parent_names[2]);
837*4882a593Smuzhiyun if (IS_ERR(clock)) {
838*4882a593Smuzhiyun dev_err(d->dev, "could not get clkinphif clock\n");
839*4882a593Smuzhiyun return PTR_ERR(clock);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun d->parent_clocks[TI_ADPLL_CLKINPHIF] = clock;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun return 0;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun static const struct ti_adpll_platform_data ti_adpll_type_s = {
848*4882a593Smuzhiyun .is_type_s = true,
849*4882a593Smuzhiyun .nr_max_inputs = MAX_ADPLL_INPUTS,
850*4882a593Smuzhiyun .nr_max_outputs = MAX_ADPLL_OUTPUTS,
851*4882a593Smuzhiyun .output_index = TI_ADPLL_S_DCOCLKLDO,
852*4882a593Smuzhiyun };
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun static const struct ti_adpll_platform_data ti_adpll_type_lj = {
855*4882a593Smuzhiyun .is_type_s = false,
856*4882a593Smuzhiyun .nr_max_inputs = MAX_ADPLL_INPUTS - 1,
857*4882a593Smuzhiyun .nr_max_outputs = MAX_ADPLL_OUTPUTS - 1,
858*4882a593Smuzhiyun .output_index = -EINVAL,
859*4882a593Smuzhiyun };
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun static const struct of_device_id ti_adpll_match[] = {
862*4882a593Smuzhiyun { .compatible = "ti,dm814-adpll-s-clock", &ti_adpll_type_s },
863*4882a593Smuzhiyun { .compatible = "ti,dm814-adpll-lj-clock", &ti_adpll_type_lj },
864*4882a593Smuzhiyun {},
865*4882a593Smuzhiyun };
866*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ti_adpll_match);
867*4882a593Smuzhiyun
ti_adpll_probe(struct platform_device * pdev)868*4882a593Smuzhiyun static int ti_adpll_probe(struct platform_device *pdev)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun struct device_node *node = pdev->dev.of_node;
871*4882a593Smuzhiyun struct device *dev = &pdev->dev;
872*4882a593Smuzhiyun const struct of_device_id *match;
873*4882a593Smuzhiyun const struct ti_adpll_platform_data *pdata;
874*4882a593Smuzhiyun struct ti_adpll_data *d;
875*4882a593Smuzhiyun struct resource *res;
876*4882a593Smuzhiyun int err;
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun match = of_match_device(ti_adpll_match, dev);
879*4882a593Smuzhiyun if (match)
880*4882a593Smuzhiyun pdata = match->data;
881*4882a593Smuzhiyun else
882*4882a593Smuzhiyun return -ENODEV;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
885*4882a593Smuzhiyun if (!d)
886*4882a593Smuzhiyun return -ENOMEM;
887*4882a593Smuzhiyun d->dev = dev;
888*4882a593Smuzhiyun d->np = node;
889*4882a593Smuzhiyun d->c = pdata;
890*4882a593Smuzhiyun dev_set_drvdata(d->dev, d);
891*4882a593Smuzhiyun spin_lock_init(&d->lock);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
894*4882a593Smuzhiyun if (!res)
895*4882a593Smuzhiyun return -ENODEV;
896*4882a593Smuzhiyun d->pa = res->start;
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun d->iobase = devm_ioremap_resource(dev, res);
899*4882a593Smuzhiyun if (IS_ERR(d->iobase)) {
900*4882a593Smuzhiyun dev_err(dev, "could not get IO base: %li\n",
901*4882a593Smuzhiyun PTR_ERR(d->iobase));
902*4882a593Smuzhiyun return PTR_ERR(d->iobase);
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun err = ti_adpll_init_registers(d);
906*4882a593Smuzhiyun if (err)
907*4882a593Smuzhiyun return err;
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun err = ti_adpll_init_inputs(d);
910*4882a593Smuzhiyun if (err)
911*4882a593Smuzhiyun return err;
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun d->clocks = devm_kcalloc(d->dev,
914*4882a593Smuzhiyun TI_ADPLL_NR_CLOCKS,
915*4882a593Smuzhiyun sizeof(struct ti_adpll_clock),
916*4882a593Smuzhiyun GFP_KERNEL);
917*4882a593Smuzhiyun if (!d->clocks)
918*4882a593Smuzhiyun return -ENOMEM;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun err = ti_adpll_init_dco(d);
921*4882a593Smuzhiyun if (err) {
922*4882a593Smuzhiyun dev_err(dev, "could not register dco: %i\n", err);
923*4882a593Smuzhiyun goto free;
924*4882a593Smuzhiyun }
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun err = ti_adpll_init_children_adpll_s(d);
927*4882a593Smuzhiyun if (err)
928*4882a593Smuzhiyun goto free;
929*4882a593Smuzhiyun err = ti_adpll_init_children_adpll_lj(d);
930*4882a593Smuzhiyun if (err)
931*4882a593Smuzhiyun goto free;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun err = of_clk_add_provider(d->np, of_clk_src_onecell_get, &d->outputs);
934*4882a593Smuzhiyun if (err)
935*4882a593Smuzhiyun goto free;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun return 0;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun free:
940*4882a593Smuzhiyun WARN_ON(1);
941*4882a593Smuzhiyun ti_adpll_free_resources(d);
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun return err;
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun
ti_adpll_remove(struct platform_device * pdev)946*4882a593Smuzhiyun static int ti_adpll_remove(struct platform_device *pdev)
947*4882a593Smuzhiyun {
948*4882a593Smuzhiyun struct ti_adpll_data *d = dev_get_drvdata(&pdev->dev);
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun ti_adpll_free_resources(d);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun return 0;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun static struct platform_driver ti_adpll_driver = {
956*4882a593Smuzhiyun .driver = {
957*4882a593Smuzhiyun .name = "ti-adpll",
958*4882a593Smuzhiyun .of_match_table = ti_adpll_match,
959*4882a593Smuzhiyun },
960*4882a593Smuzhiyun .probe = ti_adpll_probe,
961*4882a593Smuzhiyun .remove = ti_adpll_remove,
962*4882a593Smuzhiyun };
963*4882a593Smuzhiyun
ti_adpll_init(void)964*4882a593Smuzhiyun static int __init ti_adpll_init(void)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun return platform_driver_register(&ti_adpll_driver);
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun core_initcall(ti_adpll_init);
969*4882a593Smuzhiyun
ti_adpll_exit(void)970*4882a593Smuzhiyun static void __exit ti_adpll_exit(void)
971*4882a593Smuzhiyun {
972*4882a593Smuzhiyun platform_driver_unregister(&ti_adpll_driver);
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun module_exit(ti_adpll_exit);
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun MODULE_DESCRIPTION("Clock driver for dm814x ADPLL");
977*4882a593Smuzhiyun MODULE_ALIAS("platform:dm814-adpll-clock");
978*4882a593Smuzhiyun MODULE_AUTHOR("Tony LIndgren <tony@atomide.com>");
979*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
980