xref: /OK3568_Linux_fs/kernel/drivers/clk/ti/adpll.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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