1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Xilinx 'Clocking Wizard' driver
4 *
5 *  Copyright (C) 2013 - 2021 Xilinx
6 *
7 *  S��ren Brinkmann <soren.brinkmann@xilinx.com>
8 *
9 */
10
11#include <linux/bitfield.h>
12#include <linux/platform_device.h>
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
15#include <linux/slab.h>
16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/math64.h>
19#include <linux/module.h>
20#include <linux/err.h>
21#include <linux/iopoll.h>
22
23#define WZRD_NUM_OUTPUTS	7
24#define WZRD_ACLK_MAX_FREQ	250000000UL
25
26#define WZRD_CLK_CFG_REG(v, n)	(0x200 + 0x130 * (v) + 4 * (n))
27
28#define WZRD_CLKOUT0_FRAC_EN	BIT(18)
29#define WZRD_CLKFBOUT_1		0
30#define WZRD_CLKFBOUT_2		1
31#define WZRD_CLKOUT0_1		2
32#define WZRD_CLKOUT0_2		3
33#define WZRD_DESKEW_2		20
34#define WZRD_DIVCLK		21
35#define WZRD_CLKFBOUT_4		51
36#define WZRD_CLKFBOUT_3		48
37#define WZRD_DUTY_CYCLE		2
38#define WZRD_O_DIV		4
39
40#define WZRD_CLKFBOUT_FRAC_EN	BIT(1)
41#define WZRD_CLKFBOUT_PREDIV2	(BIT(11) | BIT(12) | BIT(9))
42#define WZRD_MULT_PREDIV2	(BIT(10) | BIT(9) | BIT(12))
43#define WZRD_CLKFBOUT_EDGE	BIT(8)
44#define WZRD_P5EN		BIT(13)
45#define WZRD_P5EN_SHIFT		13
46#define WZRD_P5FEDGE		BIT(15)
47#define WZRD_DIVCLK_EDGE	BIT(10)
48#define WZRD_P5FEDGE_SHIFT	15
49#define WZRD_CLKOUT0_PREDIV2	BIT(11)
50#define WZRD_EDGE_SHIFT		8
51
52#define WZRD_CLKFBOUT_MULT_SHIFT	8
53#define WZRD_CLKFBOUT_MULT_MASK		(0xff << WZRD_CLKFBOUT_MULT_SHIFT)
54#define WZRD_CLKFBOUT_L_SHIFT	0
55#define WZRD_CLKFBOUT_H_SHIFT	8
56#define WZRD_CLKFBOUT_L_MASK	GENMASK(7, 0)
57#define WZRD_CLKFBOUT_H_MASK	GENMASK(15, 8)
58#define WZRD_CLKFBOUT_FRAC_SHIFT	16
59#define WZRD_CLKFBOUT_FRAC_MASK		(0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT)
60#define WZRD_VERSAL_FRAC_MASK		GENMASK(5, 0)
61#define WZRD_DIVCLK_DIVIDE_SHIFT	0
62#define WZRD_DIVCLK_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
63#define WZRD_CLKOUT_DIVIDE_SHIFT	0
64#define WZRD_CLKOUT_DIVIDE_WIDTH	8
65#define WZRD_CLKOUT_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
66#define WZRD_CLKOUT_FRAC_SHIFT		8
67#define WZRD_CLKOUT_FRAC_MASK		0x3ff
68#define WZRD_CLKOUT0_FRAC_MASK		GENMASK(17, 8)
69
70#define WZRD_DR_MAX_INT_DIV_VALUE	255
71#define WZRD_DR_STATUS_REG_OFFSET	0x04
72#define WZRD_DR_LOCK_BIT_MASK		0x00000001
73#define WZRD_DR_INIT_REG_OFFSET		0x25C
74#define WZRD_DR_INIT_VERSAL_OFFSET	0x14
75#define WZRD_DR_DIV_TO_PHASE_OFFSET	4
76#define WZRD_DR_BEGIN_DYNA_RECONF	0x03
77#define WZRD_DR_BEGIN_DYNA_RECONF_5_2	0x07
78#define WZRD_DR_BEGIN_DYNA_RECONF1_5_2	0x02
79
80#define WZRD_USEC_POLL		10
81#define WZRD_TIMEOUT_POLL		1000
82#define WZRD_FRAC_GRADIENT		64
83#define PREDIV2_MULT			2
84
85/* Divider limits, from UG572 Table 3-4 for Ultrascale+ */
86#define DIV_O				0x01
87#define DIV_ALL				0x03
88
89#define WZRD_M_MIN			2
90#define WZRD_M_MAX			128
91#define WZRD_D_MIN			1
92#define WZRD_D_MAX			106
93#define WZRD_VCO_MIN			800000000
94#define WZRD_VCO_MAX			1600000000
95#define WZRD_O_MIN			1
96#define WZRD_O_MAX			128
97#define VER_WZRD_M_MIN			4
98#define VER_WZRD_M_MAX			432
99#define VER_WZRD_D_MIN			1
100#define VER_WZRD_D_MAX			123
101#define VER_WZRD_VCO_MIN		2160000000ULL
102#define VER_WZRD_VCO_MAX		4320000000ULL
103#define VER_WZRD_O_MIN			2
104#define VER_WZRD_O_MAX			511
105#define WZRD_MIN_ERR			20000
106#define WZRD_FRAC_POINTS		1000
107
108/* Get the mask from width */
109#define div_mask(width)			((1 << (width)) - 1)
110
111/* Extract divider instance from clock hardware instance */
112#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw)
113
114enum clk_wzrd_int_clks {
115	wzrd_clk_mul,
116	wzrd_clk_mul_div,
117	wzrd_clk_mul_frac,
118	wzrd_clk_int_max
119};
120
121/**
122 * struct clk_wzrd - Clock wizard private data structure
123 *
124 * @clk_data:		Clock data
125 * @nb:			Notifier block
126 * @base:		Memory base
127 * @clk_in1:		Handle to input clock 'clk_in1'
128 * @axi_clk:		Handle to input clock 's_axi_aclk'
129 * @clks_internal:	Internal clocks
130 * @clkout:		Output clocks
131 * @speed_grade:	Speed grade of the device
132 * @suspended:		Flag indicating power state of the device
133 */
134struct clk_wzrd {
135	struct clk_onecell_data clk_data;
136	struct notifier_block nb;
137	void __iomem *base;
138	struct clk *clk_in1;
139	struct clk *axi_clk;
140	struct clk *clks_internal[wzrd_clk_int_max];
141	struct clk *clkout[WZRD_NUM_OUTPUTS];
142	unsigned int speed_grade;
143	bool suspended;
144};
145
146/**
147 * struct clk_wzrd_divider - clock divider specific to clk_wzrd
148 *
149 * @hw:		handle between common and hardware-specific interfaces
150 * @base:	base address of register containing the divider
151 * @offset:	offset address of register containing the divider
152 * @shift:	shift to the divider bit field
153 * @width:	width of the divider bit field
154 * @flags:	clk_wzrd divider flags
155 * @table:	array of value/divider pairs, last entry should have div = 0
156 * @m:	value of the multiplier
157 * @d:	value of the common divider
158 * @o:	value of the leaf divider
159 * @lock:	register lock
160 */
161struct clk_wzrd_divider {
162	struct clk_hw hw;
163	void __iomem *base;
164	u16 offset;
165	u8 shift;
166	u8 width;
167	u8 flags;
168	const struct clk_div_table *table;
169	u32 m;
170	u32 d;
171	u32 o;
172	spinlock_t *lock;  /* divider lock */
173};
174
175struct versal_clk_data {
176	bool is_versal;
177};
178
179#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
180
181/* maximum frequencies for input/output clocks per speed grade */
182static const unsigned long clk_wzrd_max_freq[] = {
183	800000000UL,
184	933000000UL,
185	1066000000UL
186};
187
188/* spin lock variable for clk_wzrd */
189static DEFINE_SPINLOCK(clkwzrd_lock);
190
191static unsigned long clk_wzrd_recalc_rate_ver(struct clk_hw *hw,
192					      unsigned long parent_rate)
193{
194	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
195	void __iomem *div_addr = divider->base + divider->offset;
196	u32 div, p5en, edge, prediv2, all;
197	unsigned int vall, valh;
198
199	edge = !!(readl(div_addr) & WZRD_CLKFBOUT_EDGE);
200	p5en = !!(readl(div_addr) & WZRD_P5EN);
201	prediv2 = !!(readl(div_addr) & WZRD_CLKOUT0_PREDIV2);
202	vall = readl(div_addr + 4) & WZRD_CLKFBOUT_L_MASK;
203	valh = readl(div_addr + 4) >> WZRD_CLKFBOUT_H_SHIFT;
204	all = valh + vall + edge;
205	if (!all)
206		all = 1;
207
208	if (prediv2)
209		div = 2 * all + prediv2 * p5en;
210	else
211		div = all;
212
213	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
214}
215
216static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw,
217					  unsigned long parent_rate)
218{
219	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
220	void __iomem *div_addr = divider->base + divider->offset;
221	unsigned int val;
222
223	val = readl(div_addr) >> divider->shift;
224	val &= div_mask(divider->width);
225
226	return divider_recalc_rate(hw, parent_rate, val, divider->table,
227			divider->flags, divider->width);
228}
229
230static int clk_wzrd_ver_dynamic_reconfig(struct clk_hw *hw, unsigned long rate,
231					 unsigned long parent_rate)
232{
233	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
234	void __iomem *div_addr = divider->base + divider->offset;
235	u32 value, regh, edged, p5en, p5fedge, regval, regval1;
236	unsigned long flags;
237	int err;
238
239	spin_lock_irqsave(divider->lock, flags);
240
241	value = DIV_ROUND_CLOSEST(parent_rate, rate);
242
243	regh = (value / 4);
244	regval1 = readl(div_addr);
245	regval1 |= WZRD_CLKFBOUT_PREDIV2;
246	regval1 = regval1 & ~(WZRD_CLKFBOUT_EDGE | WZRD_P5EN | WZRD_P5FEDGE);
247	if (value % 4 > 1) {
248		edged = 1;
249		regval1 |= (edged << WZRD_EDGE_SHIFT);
250	}
251	p5fedge = value % 2;
252	p5en = value % 2;
253	regval1 = regval1 | p5en << WZRD_P5EN_SHIFT | p5fedge << WZRD_P5FEDGE_SHIFT;
254	writel(regval1, div_addr);
255
256	regval = regh | regh << WZRD_CLKFBOUT_H_SHIFT;
257	writel(regval, div_addr + 4);
258	/* Check status register */
259	err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET,
260					value, value & WZRD_DR_LOCK_BIT_MASK,
261					WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
262	if (err)
263		goto err_reconfig;
264
265	/* Initiate reconfiguration */
266	writel(WZRD_DR_BEGIN_DYNA_RECONF,
267	       divider->base + WZRD_DR_INIT_VERSAL_OFFSET);
268
269	/* Check status register */
270	err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET,
271					value, value & WZRD_DR_LOCK_BIT_MASK,
272					WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
273err_reconfig:
274	spin_unlock_irqrestore(divider->lock, flags);
275	return err;
276}
277
278static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate,
279				     unsigned long parent_rate)
280{
281	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
282	void __iomem *div_addr = divider->base + divider->offset;
283	unsigned long flags;
284	u32 value;
285	int err;
286
287	spin_lock_irqsave(divider->lock, flags);
288
289	value = DIV_ROUND_CLOSEST(parent_rate, rate);
290
291	/* Cap the value to max */
292	min_t(u32, value, WZRD_DR_MAX_INT_DIV_VALUE);
293
294	/* Set divisor and clear phase offset */
295	writel(value, div_addr);
296	writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
297
298	/* Check status register */
299	err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET,
300					value, value & WZRD_DR_LOCK_BIT_MASK,
301					WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
302	if (err)
303		goto err_reconfig;
304
305	/* Initiate reconfiguration */
306	writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2,
307	       divider->base + WZRD_DR_INIT_REG_OFFSET);
308	writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2,
309	       divider->base + WZRD_DR_INIT_REG_OFFSET);
310
311	/* Check status register */
312	err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET,
313					value, value & WZRD_DR_LOCK_BIT_MASK,
314					WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
315err_reconfig:
316	spin_unlock_irqrestore(divider->lock, flags);
317	return err;
318}
319
320static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate,
321				unsigned long *prate)
322{
323	u8 div;
324
325	/*
326	 * since we don't change parent rate we just round rate to closest
327	 * achievable
328	 */
329	div = DIV_ROUND_CLOSEST(*prate, rate);
330
331	return *prate / div;
332}
333
334static int clk_wzrd_get_divisors_ver(struct clk_hw *hw, unsigned long rate,
335				     unsigned long parent_rate)
336{
337	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
338	u64 vco_freq, freq, diff, vcomin, vcomax;
339	u32 m, d, o;
340	u32 mmin, mmax, dmin, dmax, omin, omax;
341
342	mmin = VER_WZRD_M_MIN;
343	mmax = VER_WZRD_M_MAX;
344	dmin = VER_WZRD_D_MIN;
345	dmax = VER_WZRD_D_MAX;
346	omin = VER_WZRD_O_MIN;
347	omax = VER_WZRD_O_MAX;
348	vcomin = VER_WZRD_VCO_MIN;
349	vcomax = VER_WZRD_VCO_MAX;
350
351	for (m = mmin; m <= mmax; m++) {
352		for (d = dmin; d <= dmax; d++) {
353			vco_freq = DIV_ROUND_CLOSEST((parent_rate * m), d);
354			if (vco_freq >= vcomin && vco_freq <= vcomax) {
355				for (o = omin; o <= omax; o++) {
356					freq = DIV_ROUND_CLOSEST_ULL(vco_freq, o);
357					diff = abs(freq - rate);
358
359					if (diff < WZRD_MIN_ERR) {
360						divider->m = m;
361						divider->d = d;
362						divider->o = o;
363						return 0;
364					}
365				}
366			}
367		}
368	}
369	return -EBUSY;
370}
371
372static int clk_wzrd_get_divisors(struct clk_hw *hw, unsigned long rate,
373				 unsigned long parent_rate)
374{
375	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
376	u64 vco_freq, freq, diff, vcomin, vcomax;
377	u32 m, d, o;
378	u32 mmin, mmax, dmin, dmax, omin, omax;
379
380	mmin = WZRD_M_MIN;
381	mmax = WZRD_M_MAX;
382	dmin = WZRD_D_MIN;
383	dmax = WZRD_D_MAX;
384	omin = WZRD_O_MIN;
385	omax = WZRD_O_MAX;
386	vcomin = WZRD_VCO_MIN;
387	vcomax = WZRD_VCO_MAX;
388
389	for (m = mmin; m <= mmax; m++) {
390		for (d = dmin; d <= dmax; d++) {
391			vco_freq = DIV_ROUND_CLOSEST((parent_rate * m), d);
392			if (vco_freq >= vcomin && vco_freq <= vcomax) {
393				for (o = omin; o <= omax; o++) {
394					freq = DIV_ROUND_CLOSEST_ULL(vco_freq, o);
395					diff = abs(freq - rate);
396
397					if (diff < WZRD_MIN_ERR) {
398						divider->m = m;
399						divider->d = d;
400						divider->o = o;
401						return 0;
402					}
403				}
404			}
405		}
406	}
407	return -EBUSY;
408}
409
410static int clk_wzrd_reconfig(struct clk_wzrd_divider *divider, void __iomem *div_addr)
411{
412	u32 value;
413	int err;
414
415	/* Check status register */
416	err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
417					value & WZRD_DR_LOCK_BIT_MASK,
418					WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
419	if (err)
420		return -ETIMEDOUT;
421
422	/* Initiate reconfiguration */
423	writel(WZRD_DR_BEGIN_DYNA_RECONF, div_addr);
424	/* Check status register */
425	return readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
426				 value & WZRD_DR_LOCK_BIT_MASK,
427				 WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
428}
429
430static int clk_wzrd_dynamic_ver_all_nolock(struct clk_hw *hw, unsigned long rate,
431					   unsigned long parent_rate)
432{
433	u32 regh, edged, p5en, p5fedge, value2, m, regval, regval1, value;
434	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
435	void __iomem *div_addr;
436	int err;
437
438	err = clk_wzrd_get_divisors_ver(hw, rate, parent_rate);
439	if (err)
440		return err;
441
442	writel(0, divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_4));
443
444	m = divider->m;
445	edged = m % WZRD_DUTY_CYCLE;
446	regh = m / WZRD_DUTY_CYCLE;
447	regval1 = readl(divider->base + WZRD_CLK_CFG_REG(1,
448							 WZRD_CLKFBOUT_1));
449	regval1 |= WZRD_MULT_PREDIV2;
450	if (edged)
451		regval1 = regval1 | WZRD_CLKFBOUT_EDGE;
452	else
453		regval1 = regval1 & ~WZRD_CLKFBOUT_EDGE;
454
455	writel(regval1, divider->base + WZRD_CLK_CFG_REG(1,
456							 WZRD_CLKFBOUT_1));
457	regval1 = regh | regh << WZRD_CLKFBOUT_H_SHIFT;
458	writel(regval1, divider->base + WZRD_CLK_CFG_REG(1,
459							 WZRD_CLKFBOUT_2));
460
461	value2 = divider->d;
462	edged = value2 % WZRD_DUTY_CYCLE;
463	regh = (value2 / WZRD_DUTY_CYCLE);
464	regval1 = FIELD_PREP(WZRD_DIVCLK_EDGE, edged);
465	writel(regval1, divider->base + WZRD_CLK_CFG_REG(1,
466							 WZRD_DESKEW_2));
467	regval1 = regh | regh << WZRD_CLKFBOUT_H_SHIFT;
468	writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, WZRD_DIVCLK));
469
470	value = divider->o;
471	regh = value / WZRD_O_DIV;
472	regval1 = readl(divider->base + WZRD_CLK_CFG_REG(1,
473							 WZRD_CLKOUT0_1));
474	regval1 |= WZRD_CLKFBOUT_PREDIV2;
475	regval1 = regval1 & ~(WZRD_CLKFBOUT_EDGE | WZRD_P5EN | WZRD_P5FEDGE);
476
477	if (value % WZRD_O_DIV > 1) {
478		edged = 1;
479		regval1 |= edged << WZRD_CLKFBOUT_H_SHIFT;
480	}
481
482	p5fedge = value % WZRD_DUTY_CYCLE;
483	p5en = value % WZRD_DUTY_CYCLE;
484
485	regval1 = regval1 | FIELD_PREP(WZRD_P5EN, p5en) | FIELD_PREP(WZRD_P5FEDGE, p5fedge);
486	writel(regval1, divider->base + WZRD_CLK_CFG_REG(1,
487							 WZRD_CLKOUT0_1));
488	regval = regh | regh << WZRD_CLKFBOUT_H_SHIFT;
489	writel(regval, divider->base + WZRD_CLK_CFG_REG(1,
490							WZRD_CLKOUT0_2));
491	div_addr = divider->base + WZRD_DR_INIT_VERSAL_OFFSET;
492
493	return clk_wzrd_reconfig(divider, div_addr);
494}
495
496static int clk_wzrd_dynamic_all_nolock(struct clk_hw *hw, unsigned long rate,
497				       unsigned long parent_rate)
498{
499	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
500	unsigned long vco_freq, rate_div, clockout0_div;
501	void __iomem *div_addr;
502	u32 reg, pre, f;
503	int err;
504
505	err = clk_wzrd_get_divisors(hw, rate, parent_rate);
506	if (err)
507		return err;
508
509	vco_freq = DIV_ROUND_CLOSEST(parent_rate * divider->m, divider->d);
510	rate_div = DIV_ROUND_CLOSEST_ULL((vco_freq * WZRD_FRAC_POINTS), rate);
511
512	clockout0_div = div_u64(rate_div,  WZRD_FRAC_POINTS);
513
514	pre = DIV_ROUND_CLOSEST_ULL(vco_freq * WZRD_FRAC_POINTS, rate);
515	f = (pre - (clockout0_div * WZRD_FRAC_POINTS));
516	f &= WZRD_CLKOUT_FRAC_MASK;
517
518	reg = FIELD_PREP(WZRD_CLKOUT_DIVIDE_MASK, clockout0_div) |
519	      FIELD_PREP(WZRD_CLKOUT0_FRAC_MASK, f);
520
521	writel(reg, divider->base + WZRD_CLK_CFG_REG(0, 2));
522	/* Set divisor and clear phase offset */
523	reg = FIELD_PREP(WZRD_CLKFBOUT_MULT_MASK, divider->m) |
524	      FIELD_PREP(WZRD_DIVCLK_DIVIDE_MASK, divider->d);
525	writel(reg, divider->base + WZRD_CLK_CFG_REG(0, 0));
526	writel(divider->o, divider->base + WZRD_CLK_CFG_REG(0, 2));
527	writel(0, divider->base + WZRD_CLK_CFG_REG(0, 3));
528	div_addr = divider->base + WZRD_DR_INIT_REG_OFFSET;
529	return clk_wzrd_reconfig(divider, div_addr);
530}
531
532static int clk_wzrd_dynamic_all(struct clk_hw *hw, unsigned long rate,
533				unsigned long parent_rate)
534{
535	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
536	unsigned long flags;
537	int ret;
538
539	spin_lock_irqsave(divider->lock, flags);
540
541	ret = clk_wzrd_dynamic_all_nolock(hw, rate, parent_rate);
542
543	spin_unlock_irqrestore(divider->lock, flags);
544
545	return ret;
546}
547
548static int clk_wzrd_dynamic_all_ver(struct clk_hw *hw, unsigned long rate,
549				    unsigned long parent_rate)
550{
551	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
552	unsigned long flags;
553	int ret;
554
555	spin_lock_irqsave(divider->lock, flags);
556
557	ret = clk_wzrd_dynamic_ver_all_nolock(hw, rate, parent_rate);
558
559	spin_unlock_irqrestore(divider->lock, flags);
560
561	return ret;
562}
563
564static unsigned long clk_wzrd_recalc_rate_all(struct clk_hw *hw,
565					      unsigned long parent_rate)
566{
567	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
568	u32 m, d, o, div, reg, f;
569
570	reg = readl(divider->base + WZRD_CLK_CFG_REG(0, 0));
571	d = FIELD_GET(WZRD_DIVCLK_DIVIDE_MASK, reg);
572	m = FIELD_GET(WZRD_CLKFBOUT_MULT_MASK, reg);
573	reg = readl(divider->base + WZRD_CLK_CFG_REG(0, 2));
574	o = FIELD_GET(WZRD_DIVCLK_DIVIDE_MASK, reg);
575	f = FIELD_GET(WZRD_CLKOUT0_FRAC_MASK, reg);
576
577	div = DIV_ROUND_CLOSEST(d * (WZRD_FRAC_POINTS * o + f), WZRD_FRAC_POINTS);
578	return divider_recalc_rate(hw, parent_rate * m, div, divider->table,
579		divider->flags, divider->width);
580}
581
582static unsigned long clk_wzrd_recalc_rate_all_ver(struct clk_hw *hw,
583						  unsigned long parent_rate)
584{
585	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
586	u32 edged, div2, p5en, edge, prediv2, all, regl, regh, mult;
587	u32 div, reg;
588
589	edge = !!(readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_1)) &
590			WZRD_CLKFBOUT_EDGE);
591
592	reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_2));
593	regl = FIELD_GET(WZRD_CLKFBOUT_L_MASK, reg);
594	regh = FIELD_GET(WZRD_CLKFBOUT_H_MASK, reg);
595
596	mult = regl + regh + edge;
597	if (!mult)
598		mult = 1;
599
600	regl = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_4)) &
601		     WZRD_CLKFBOUT_FRAC_EN;
602	if (regl) {
603		regl = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_3))
604				& WZRD_VERSAL_FRAC_MASK;
605		mult = mult * WZRD_FRAC_GRADIENT + regl;
606		parent_rate = DIV_ROUND_CLOSEST((parent_rate * mult), WZRD_FRAC_GRADIENT);
607	} else {
608		parent_rate = parent_rate * mult;
609	}
610
611	/* O Calculation */
612	reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKOUT0_1));
613	edged = FIELD_GET(WZRD_CLKFBOUT_EDGE, reg);
614	p5en = FIELD_GET(WZRD_P5EN, reg);
615	prediv2 = FIELD_GET(WZRD_CLKOUT0_PREDIV2, reg);
616
617	reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKOUT0_2));
618	/* Low time */
619	regl = FIELD_GET(WZRD_CLKFBOUT_L_MASK, reg);
620	/* High time */
621	regh = FIELD_GET(WZRD_CLKFBOUT_H_MASK, reg);
622	all = regh + regl + edged;
623	if (!all)
624		all = 1;
625
626	if (prediv2)
627		div2 = PREDIV2_MULT * all + p5en;
628	else
629		div2 = all;
630
631	/* D calculation */
632	edged = !!(readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_DESKEW_2)) &
633		     WZRD_DIVCLK_EDGE);
634	reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_DIVCLK));
635	/* Low time */
636	regl = FIELD_GET(WZRD_CLKFBOUT_L_MASK, reg);
637	/* High time */
638	regh = FIELD_GET(WZRD_CLKFBOUT_H_MASK, reg);
639	div = regl + regh + edged;
640	if (!div)
641		div = 1;
642
643	div = div * div2;
644	return divider_recalc_rate(hw, parent_rate, div, divider->table,
645			divider->flags, divider->width);
646}
647
648static long clk_wzrd_round_rate_all(struct clk_hw *hw, unsigned long rate,
649				    unsigned long *prate)
650{
651	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
652	unsigned long int_freq;
653	u32 m, d, o, div, f;
654	int err;
655
656	err = clk_wzrd_get_divisors(hw, rate, *prate);
657	if (err)
658		return err;
659
660	m = divider->m;
661	d = divider->d;
662	o = divider->o;
663
664	div = d * o;
665	int_freq =  divider_recalc_rate(hw, *prate * m, div, divider->table,
666					divider->flags, divider->width);
667
668	if (rate > int_freq) {
669		f = DIV_ROUND_CLOSEST_ULL(rate * WZRD_FRAC_POINTS, int_freq);
670		rate = DIV_ROUND_CLOSEST(int_freq * f, WZRD_FRAC_POINTS);
671	}
672	return rate;
673}
674
675static const struct clk_ops clk_wzrd_ver_divider_ops = {
676	.round_rate = clk_wzrd_round_rate,
677	.set_rate = clk_wzrd_ver_dynamic_reconfig,
678	.recalc_rate = clk_wzrd_recalc_rate_ver,
679};
680
681static const struct clk_ops clk_wzrd_ver_div_all_ops = {
682	.round_rate = clk_wzrd_round_rate_all,
683	.set_rate = clk_wzrd_dynamic_all_ver,
684	.recalc_rate = clk_wzrd_recalc_rate_all_ver,
685};
686
687static const struct clk_ops clk_wzrd_clk_divider_ops = {
688	.round_rate = clk_wzrd_round_rate,
689	.set_rate = clk_wzrd_dynamic_reconfig,
690	.recalc_rate = clk_wzrd_recalc_rate,
691};
692
693static const struct clk_ops clk_wzrd_clk_div_all_ops = {
694	.round_rate = clk_wzrd_round_rate_all,
695	.set_rate = clk_wzrd_dynamic_all,
696	.recalc_rate = clk_wzrd_recalc_rate_all,
697};
698
699static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw,
700					   unsigned long parent_rate)
701{
702	unsigned int val;
703	u32 div, frac;
704	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
705	void __iomem *div_addr = divider->base + divider->offset;
706
707	val = readl(div_addr);
708	div = val & div_mask(divider->width);
709	frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK;
710
711	return mult_frac(parent_rate, 1000, (div * 1000) + frac);
712}
713
714static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate,
715				       unsigned long parent_rate)
716{
717	int err;
718	u32 value, pre;
719	unsigned long rate_div, f, clockout0_div;
720	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
721	void __iomem *div_addr = divider->base + divider->offset;
722
723	rate_div = DIV_ROUND_DOWN_ULL(parent_rate * 1000, rate);
724	clockout0_div = rate_div / 1000;
725
726	pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate);
727	f = (u32)(pre - (clockout0_div * 1000));
728	f = f & WZRD_CLKOUT_FRAC_MASK;
729	f = f << WZRD_CLKOUT_DIVIDE_WIDTH;
730
731	value = (f  | (clockout0_div & WZRD_CLKOUT_DIVIDE_MASK));
732
733	/* Set divisor and clear phase offset */
734	writel(value, div_addr);
735	writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
736
737	/* Check status register */
738	err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
739				 value & WZRD_DR_LOCK_BIT_MASK,
740				 WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
741	if (err)
742		return err;
743
744	/* Initiate reconfiguration */
745	writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2,
746	       divider->base + WZRD_DR_INIT_REG_OFFSET);
747	writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2,
748	       divider->base + WZRD_DR_INIT_REG_OFFSET);
749
750	/* Check status register */
751	return readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value,
752				value & WZRD_DR_LOCK_BIT_MASK,
753				WZRD_USEC_POLL, WZRD_TIMEOUT_POLL);
754}
755
756static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate,
757				  unsigned long *prate)
758{
759	return rate;
760}
761
762static const struct clk_ops clk_wzrd_clk_divider_ops_f = {
763	.round_rate = clk_wzrd_round_rate_f,
764	.set_rate = clk_wzrd_dynamic_reconfig_f,
765	.recalc_rate = clk_wzrd_recalc_ratef,
766};
767
768static struct clk *clk_wzrd_register_divf(struct device *dev,
769					  const char *name,
770					  const char *parent_name,
771					  unsigned long flags,
772					  void __iomem *base, u16 offset,
773					  u8 shift, u8 width,
774					  u8 clk_divider_flags,
775					  u32 div_type,
776					  spinlock_t *lock)
777{
778	struct clk_wzrd_divider *div;
779	struct clk_hw *hw;
780	struct clk_init_data init;
781	int ret;
782
783	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
784	if (!div)
785		return ERR_PTR(-ENOMEM);
786
787	init.name = name;
788
789	init.ops = &clk_wzrd_clk_divider_ops_f;
790
791	init.flags = flags;
792	init.parent_names = &parent_name;
793	init.num_parents = 1;
794
795	div->base = base;
796	div->offset = offset;
797	div->shift = shift;
798	div->width = width;
799	div->flags = clk_divider_flags;
800	div->lock = lock;
801	div->hw.init = &init;
802
803	hw = &div->hw;
804	ret =  devm_clk_hw_register(dev, hw);
805	if (ret)
806		return ERR_PTR(ret);
807
808	return hw->clk;
809}
810
811static struct clk *clk_wzrd_ver_register_divider(struct device *dev,
812						 const char *name,
813						 const char *parent_name,
814						 unsigned long flags,
815						 void __iomem *base,
816						 u16 offset,
817						 u8 shift, u8 width,
818						 u8 clk_divider_flags,
819						 u32 div_type,
820						 spinlock_t *lock)
821{
822	struct clk_wzrd_divider *div;
823	struct clk_hw *hw;
824	struct clk_init_data init;
825	int ret;
826
827	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
828	if (!div)
829		return ERR_PTR(-ENOMEM);
830
831	init.name = name;
832	if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
833		init.ops = &clk_divider_ro_ops;
834	else if (div_type == DIV_O)
835		init.ops = &clk_wzrd_ver_divider_ops;
836	else
837		init.ops = &clk_wzrd_ver_div_all_ops;
838	init.flags = flags;
839	init.parent_names =  &parent_name;
840	init.num_parents =  1;
841
842	div->base = base;
843	div->offset = offset;
844	div->shift = shift;
845	div->width = width;
846	div->flags = clk_divider_flags;
847	div->lock = lock;
848	div->hw.init = &init;
849
850	hw = &div->hw;
851	ret = devm_clk_hw_register(dev, hw);
852	if (ret)
853		return ERR_PTR(ret);
854
855	return hw->clk;
856}
857
858static struct clk *clk_wzrd_register_divider(struct device *dev,
859					     const char *name,
860					     const char *parent_name,
861					     unsigned long flags,
862					     void __iomem *base, u16 offset,
863					     u8 shift, u8 width,
864					     u8 clk_divider_flags,
865					     u32 div_type,
866					     spinlock_t *lock)
867{
868	struct clk_wzrd_divider *div;
869	struct clk_hw *hw;
870	struct clk_init_data init;
871	int ret;
872
873	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
874	if (!div)
875		return ERR_PTR(-ENOMEM);
876
877	init.name = name;
878	if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
879		init.ops = &clk_divider_ro_ops;
880	else if (div_type == DIV_O)
881		init.ops = &clk_wzrd_clk_divider_ops;
882	else
883		init.ops = &clk_wzrd_clk_div_all_ops;
884	init.flags = flags;
885	init.parent_names =  &parent_name;
886	init.num_parents =  1;
887
888	div->base = base;
889	div->offset = offset;
890	div->shift = shift;
891	div->width = width;
892	div->flags = clk_divider_flags;
893	div->lock = lock;
894	div->hw.init = &init;
895
896	hw = &div->hw;
897	ret = devm_clk_hw_register(dev, hw);
898	if (ret)
899		return ERR_PTR(ret);
900
901	return hw->clk;
902}
903
904static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event,
905				 void *data)
906{
907	unsigned long max;
908	struct clk_notifier_data *ndata = data;
909	struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb);
910
911	if (clk_wzrd->suspended)
912		return NOTIFY_OK;
913
914	if (ndata->clk == clk_wzrd->clk_in1)
915		max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1];
916	else if (ndata->clk == clk_wzrd->axi_clk)
917		max = WZRD_ACLK_MAX_FREQ;
918	else
919		return NOTIFY_DONE;	/* should never happen */
920
921	switch (event) {
922	case PRE_RATE_CHANGE:
923		if (ndata->new_rate > max)
924			return NOTIFY_BAD;
925		return NOTIFY_OK;
926	case POST_RATE_CHANGE:
927	case ABORT_RATE_CHANGE:
928	default:
929		return NOTIFY_DONE;
930	}
931}
932
933static int __maybe_unused clk_wzrd_suspend(struct device *dev)
934{
935	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
936
937	clk_disable_unprepare(clk_wzrd->axi_clk);
938	clk_wzrd->suspended = true;
939
940	return 0;
941}
942
943static int __maybe_unused clk_wzrd_resume(struct device *dev)
944{
945	int ret;
946	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
947
948	ret = clk_prepare_enable(clk_wzrd->axi_clk);
949	if (ret) {
950		dev_err(dev, "unable to enable s_axi_aclk\n");
951		return ret;
952	}
953
954	clk_wzrd->suspended = false;
955
956	return 0;
957}
958
959static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend,
960			 clk_wzrd_resume);
961
962static const struct versal_clk_data versal_data = {
963	.is_versal	= true,
964};
965
966static int clk_wzrd_probe(struct platform_device *pdev)
967{
968	const char *clkout_name, *clk_name, *clk_mul_name;
969	u32 regl, regh, edge, regld, reghd, edged, div;
970	struct device_node *np = pdev->dev.of_node;
971	const struct versal_clk_data *data;
972	struct clk_wzrd *clk_wzrd;
973	unsigned long flags = 0;
974	void __iomem *ctrl_reg;
975	u32 reg, reg_f, mult;
976	bool is_versal = false;
977	unsigned long rate;
978	int nr_outputs;
979	int i, ret;
980
981	clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
982	if (!clk_wzrd)
983		return -ENOMEM;
984	platform_set_drvdata(pdev, clk_wzrd);
985
986	clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0);
987	if (IS_ERR(clk_wzrd->base))
988		return PTR_ERR(clk_wzrd->base);
989
990	ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade);
991	if (!ret) {
992		if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) {
993			dev_warn(&pdev->dev, "invalid speed grade '%d'\n",
994				 clk_wzrd->speed_grade);
995			clk_wzrd->speed_grade = 0;
996		}
997	}
998
999	clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
1000	if (IS_ERR(clk_wzrd->clk_in1))
1001		return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1),
1002				     "clk_in1 not found\n");
1003
1004	clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
1005	if (IS_ERR(clk_wzrd->axi_clk))
1006		return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk),
1007				     "s_axi_aclk not found\n");
1008	ret = clk_prepare_enable(clk_wzrd->axi_clk);
1009	if (ret) {
1010		dev_err(&pdev->dev, "enabling s_axi_aclk failed\n");
1011		return ret;
1012	}
1013	rate = clk_get_rate(clk_wzrd->axi_clk);
1014	if (rate > WZRD_ACLK_MAX_FREQ) {
1015		dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n",
1016			rate);
1017		ret = -EINVAL;
1018		goto err_disable_clk;
1019	}
1020
1021	data = device_get_match_data(&pdev->dev);
1022	if (data)
1023		is_versal = data->is_versal;
1024
1025	ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs);
1026	if (ret || nr_outputs > WZRD_NUM_OUTPUTS) {
1027		ret = -EINVAL;
1028		goto err_disable_clk;
1029	}
1030
1031	clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_out0", dev_name(&pdev->dev));
1032	if (!clkout_name) {
1033		ret = -ENOMEM;
1034		goto err_disable_clk;
1035	}
1036
1037	if (is_versal) {
1038		if (nr_outputs == 1) {
1039			clk_wzrd->clkout[0] = clk_wzrd_ver_register_divider
1040				(&pdev->dev, clkout_name,
1041				__clk_get_name(clk_wzrd->clk_in1), 0,
1042				clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3),
1043				WZRD_CLKOUT_DIVIDE_SHIFT,
1044				WZRD_CLKOUT_DIVIDE_WIDTH,
1045				CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
1046				DIV_ALL, &clkwzrd_lock);
1047
1048			goto out;
1049		}
1050		/* register multiplier */
1051		edge = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0)) &
1052				BIT(8));
1053		regl = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 1)) &
1054			     WZRD_CLKFBOUT_L_MASK) >> WZRD_CLKFBOUT_L_SHIFT;
1055		regh = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 1)) &
1056			     WZRD_CLKFBOUT_H_MASK) >> WZRD_CLKFBOUT_H_SHIFT;
1057		mult = regl + regh + edge;
1058		if (!mult)
1059			mult = 1;
1060		mult = mult * WZRD_FRAC_GRADIENT;
1061
1062		regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 51)) &
1063			     WZRD_CLKFBOUT_FRAC_EN;
1064		if (regl) {
1065			regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 48)) &
1066				WZRD_VERSAL_FRAC_MASK;
1067			mult = mult + regl;
1068		}
1069		div = 64;
1070	} else {
1071		if (nr_outputs == 1) {
1072			clk_wzrd->clkout[0] = clk_wzrd_register_divider
1073				(&pdev->dev, clkout_name,
1074				__clk_get_name(clk_wzrd->clk_in1), 0,
1075				clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3),
1076				WZRD_CLKOUT_DIVIDE_SHIFT,
1077				WZRD_CLKOUT_DIVIDE_WIDTH,
1078				CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
1079				DIV_ALL, &clkwzrd_lock);
1080
1081			goto out;
1082		}
1083		reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0));
1084		reg_f = reg & WZRD_CLKFBOUT_FRAC_MASK;
1085		reg_f =  reg_f >> WZRD_CLKFBOUT_FRAC_SHIFT;
1086
1087		reg = reg & WZRD_CLKFBOUT_MULT_MASK;
1088		reg =  reg >> WZRD_CLKFBOUT_MULT_SHIFT;
1089		mult = (reg * 1000) + reg_f;
1090		div = 1000;
1091	}
1092	clk_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_mul", dev_name(&pdev->dev));
1093	if (!clk_name) {
1094		ret = -ENOMEM;
1095		goto err_disable_clk;
1096	}
1097	clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor
1098			(&pdev->dev, clk_name,
1099			 __clk_get_name(clk_wzrd->clk_in1),
1100			0, mult, div);
1101	if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) {
1102		dev_err(&pdev->dev, "unable to register fixed-factor clock\n");
1103		ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]);
1104		goto err_disable_clk;
1105	}
1106
1107	clk_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev));
1108	if (!clk_name) {
1109		ret = -ENOMEM;
1110		goto err_rm_int_clk;
1111	}
1112
1113	if (is_versal) {
1114		edged = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 20)) &
1115			     BIT(10));
1116		regld = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 21)) &
1117			     WZRD_CLKFBOUT_L_MASK) >> WZRD_CLKFBOUT_L_SHIFT;
1118		reghd = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 21)) &
1119		     WZRD_CLKFBOUT_H_MASK) >> WZRD_CLKFBOUT_H_SHIFT;
1120		div = (regld  + reghd + edged);
1121		if (!div)
1122			div = 1;
1123
1124		clk_mul_name = __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]);
1125		clk_wzrd->clks_internal[wzrd_clk_mul_div] =
1126			clk_register_fixed_factor(&pdev->dev, clk_name,
1127						  clk_mul_name, 0, 1, div);
1128	} else {
1129		ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0);
1130		clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider
1131			(&pdev->dev, clk_name,
1132			 __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]),
1133			flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED |
1134			CLK_DIVIDER_ALLOW_ZERO, &clkwzrd_lock);
1135	}
1136	if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) {
1137		dev_err(&pdev->dev, "unable to register divider clock\n");
1138		ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]);
1139		goto err_rm_int_clk;
1140	}
1141
1142	/* register div per output */
1143	for (i = nr_outputs - 1; i >= 0 ; i--) {
1144		clkout_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
1145					     "%s_out%d", dev_name(&pdev->dev), i);
1146		if (!clkout_name) {
1147			ret = -ENOMEM;
1148			goto err_rm_int_clk;
1149		}
1150
1151		if (is_versal) {
1152			clk_wzrd->clkout[i] = clk_wzrd_ver_register_divider
1153						(&pdev->dev,
1154						 clkout_name, clk_name, 0,
1155						 clk_wzrd->base,
1156						 (WZRD_CLK_CFG_REG(is_versal, 3) + i * 8),
1157						 WZRD_CLKOUT_DIVIDE_SHIFT,
1158						 WZRD_CLKOUT_DIVIDE_WIDTH,
1159						 CLK_DIVIDER_ONE_BASED |
1160						 CLK_DIVIDER_ALLOW_ZERO,
1161						 DIV_O, &clkwzrd_lock);
1162		} else {
1163			if (!i)
1164				clk_wzrd->clkout[i] = clk_wzrd_register_divf
1165					(&pdev->dev, clkout_name, clk_name, flags, clk_wzrd->base,
1166					(WZRD_CLK_CFG_REG(is_versal, 2) + i * 12),
1167					WZRD_CLKOUT_DIVIDE_SHIFT,
1168					WZRD_CLKOUT_DIVIDE_WIDTH,
1169					CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
1170					DIV_O, &clkwzrd_lock);
1171			else
1172				clk_wzrd->clkout[i] = clk_wzrd_register_divider
1173					(&pdev->dev, clkout_name, clk_name, 0, clk_wzrd->base,
1174					(WZRD_CLK_CFG_REG(is_versal, 2) + i * 12),
1175					WZRD_CLKOUT_DIVIDE_SHIFT,
1176					WZRD_CLKOUT_DIVIDE_WIDTH,
1177					CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
1178					DIV_O, &clkwzrd_lock);
1179		}
1180		if (IS_ERR(clk_wzrd->clkout[i])) {
1181			int j;
1182
1183			for (j = i + 1; j < nr_outputs; j++)
1184				clk_unregister(clk_wzrd->clkout[j]);
1185			dev_err(&pdev->dev,
1186				"unable to register divider clock\n");
1187			ret = PTR_ERR(clk_wzrd->clkout[i]);
1188			goto err_rm_int_clks;
1189		}
1190	}
1191
1192out:
1193	clk_wzrd->clk_data.clks = clk_wzrd->clkout;
1194	clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout);
1195	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data);
1196
1197	if (clk_wzrd->speed_grade) {
1198		clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier;
1199
1200		ret = clk_notifier_register(clk_wzrd->clk_in1,
1201					    &clk_wzrd->nb);
1202		if (ret)
1203			dev_warn(&pdev->dev,
1204				 "unable to register clock notifier\n");
1205
1206		ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb);
1207		if (ret)
1208			dev_warn(&pdev->dev,
1209				 "unable to register clock notifier\n");
1210	}
1211
1212	return 0;
1213
1214err_rm_int_clks:
1215	clk_unregister(clk_wzrd->clks_internal[1]);
1216err_rm_int_clk:
1217	clk_unregister(clk_wzrd->clks_internal[0]);
1218err_disable_clk:
1219	clk_disable_unprepare(clk_wzrd->axi_clk);
1220
1221	return ret;
1222}
1223
1224static void clk_wzrd_remove(struct platform_device *pdev)
1225{
1226	int i;
1227	struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);
1228
1229	of_clk_del_provider(pdev->dev.of_node);
1230
1231	for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
1232		clk_unregister(clk_wzrd->clkout[i]);
1233	for (i = 0; i < wzrd_clk_int_max; i++)
1234		clk_unregister(clk_wzrd->clks_internal[i]);
1235
1236	if (clk_wzrd->speed_grade) {
1237		clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb);
1238		clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb);
1239	}
1240
1241	clk_disable_unprepare(clk_wzrd->axi_clk);
1242}
1243
1244static const struct of_device_id clk_wzrd_ids[] = {
1245	{ .compatible = "xlnx,versal-clk-wizard", .data = &versal_data },
1246	{ .compatible = "xlnx,clocking-wizard"   },
1247	{ .compatible = "xlnx,clocking-wizard-v5.2"   },
1248	{ .compatible = "xlnx,clocking-wizard-v6.0"  },
1249	{ },
1250};
1251MODULE_DEVICE_TABLE(of, clk_wzrd_ids);
1252
1253static struct platform_driver clk_wzrd_driver = {
1254	.driver = {
1255		.name = "clk-wizard",
1256		.of_match_table = clk_wzrd_ids,
1257		.pm = &clk_wzrd_dev_pm_ops,
1258	},
1259	.probe = clk_wzrd_probe,
1260	.remove_new = clk_wzrd_remove,
1261};
1262module_platform_driver(clk_wzrd_driver);
1263
1264MODULE_LICENSE("GPL");
1265MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com");
1266MODULE_DESCRIPTION("Driver for the Xilinx Clocking Wizard IP core");
1267