Lines Matching +full:max +full:- +full:bit +full:- +full:rate

1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2013 - 2021 Xilinx
14 #include <linux/clk-provider.h>
29 #define WZRD_CLKOUT0_FRAC_EN BIT(18)
41 #define WZRD_CLKFBOUT_FRAC_EN BIT(1)
42 #define WZRD_CLKFBOUT_PREDIV2 (BIT(11) | BIT(12) | BIT(9))
43 #define WZRD_MULT_PREDIV2 (BIT(10) | BIT(9) | BIT(12))
44 #define WZRD_CLKFBOUT_EDGE BIT(8)
45 #define WZRD_P5EN BIT(13)
47 #define WZRD_P5FEDGE BIT(15)
48 #define WZRD_DIVCLK_EDGE BIT(10)
50 #define WZRD_CLKOUT0_PREDIV2 BIT(11)
88 /* Divider limits, from UG572 Table 3-4 for Ultrascale+ */
112 #define div_mask(width) ((1 << (width)) - 1)
125 * struct clk_wzrd - Clock wizard private data structure
148 * struct clk_wzrd_divider - clock divider specific to clk_wzrd
150 * @hw: handle between common and hardware-specific interfaces
153 * @shift: shift to the divider bit field
154 * @width: width of the divider bit field
200 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_recalc_rate_ver()
225 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_recalc_rate()
228 val = readl(div_addr) >> divider->shift; in clk_wzrd_recalc_rate()
229 val &= div_mask(divider->width); in clk_wzrd_recalc_rate()
231 return divider_recalc_rate(hw, parent_rate, val, divider->table, in clk_wzrd_recalc_rate()
232 divider->flags, divider->width); in clk_wzrd_recalc_rate()
235 static int clk_wzrd_ver_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, in clk_wzrd_ver_dynamic_reconfig() argument
239 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_ver_dynamic_reconfig()
244 spin_lock_irqsave(divider->lock, flags); in clk_wzrd_ver_dynamic_reconfig()
246 value = DIV_ROUND_CLOSEST(parent_rate, rate); in clk_wzrd_ver_dynamic_reconfig()
264 err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, in clk_wzrd_ver_dynamic_reconfig()
272 divider->base + WZRD_DR_INIT_VERSAL_OFFSET); in clk_wzrd_ver_dynamic_reconfig()
275 err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, in clk_wzrd_ver_dynamic_reconfig()
279 spin_unlock_irqrestore(divider->lock, flags); in clk_wzrd_ver_dynamic_reconfig()
283 static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_reconfig() argument
287 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_dynamic_reconfig()
292 spin_lock_irqsave(divider->lock, flags); in clk_wzrd_dynamic_reconfig()
294 value = DIV_ROUND_CLOSEST(parent_rate, rate); in clk_wzrd_dynamic_reconfig()
296 /* Cap the value to max */ in clk_wzrd_dynamic_reconfig()
304 err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, in clk_wzrd_dynamic_reconfig()
312 divider->base + WZRD_DR_INIT_REG_OFFSET); in clk_wzrd_dynamic_reconfig()
314 divider->base + WZRD_DR_INIT_REG_OFFSET); in clk_wzrd_dynamic_reconfig()
317 err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, in clk_wzrd_dynamic_reconfig()
321 spin_unlock_irqrestore(divider->lock, flags); in clk_wzrd_dynamic_reconfig()
331 * since we don't change parent rate we just round rate to closest in clk_wzrd_determine_rate()
334 div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate); in clk_wzrd_determine_rate()
336 req->rate = req->best_parent_rate / div; in clk_wzrd_determine_rate()
341 static int clk_wzrd_get_divisors_ver(struct clk_hw *hw, unsigned long rate, in clk_wzrd_get_divisors_ver() argument
345 u64 vco_freq, freq, diff, vcomin, vcomax, best_diff = -1ULL; in clk_wzrd_get_divisors_ver()
364 o = DIV_ROUND_CLOSEST_ULL(vco_freq, rate); in clk_wzrd_get_divisors_ver()
368 diff = abs(freq - rate); in clk_wzrd_get_divisors_ver()
372 divider->m = m; in clk_wzrd_get_divisors_ver()
373 divider->d = d; in clk_wzrd_get_divisors_ver()
374 divider->o = o; in clk_wzrd_get_divisors_ver()
383 static int clk_wzrd_get_divisors(struct clk_hw *hw, unsigned long rate, in clk_wzrd_get_divisors() argument
387 u64 vco_freq, freq, diff, vcomin, vcomax, best_diff = -1ULL; in clk_wzrd_get_divisors()
401 mdmin = max(dmin, div64_u64(parent_rate * m + vcomax / 2, vcomax)); in clk_wzrd_get_divisors()
405 o = DIV_ROUND_CLOSEST_ULL(vco_freq, rate); in clk_wzrd_get_divisors()
409 diff = freq - rate; in clk_wzrd_get_divisors()
412 divider->m = m >> 3; in clk_wzrd_get_divisors()
413 divider->m_frac = (m - (divider->m << 3)) * 125; in clk_wzrd_get_divisors()
414 divider->d = d; in clk_wzrd_get_divisors()
415 divider->o = o >> 3; in clk_wzrd_get_divisors()
416 divider->o_frac = (o - (divider->o << 3)) * 125; in clk_wzrd_get_divisors()
420 return best_diff < WZRD_MIN_ERR ? 0 : -EBUSY; in clk_wzrd_get_divisors()
429 err = readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, in clk_wzrd_reconfig()
433 return -ETIMEDOUT; in clk_wzrd_reconfig()
438 return readl_poll_timeout_atomic(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, in clk_wzrd_reconfig()
443 static int clk_wzrd_dynamic_ver_all_nolock(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_ver_all_nolock() argument
451 err = clk_wzrd_get_divisors_ver(hw, rate, parent_rate); in clk_wzrd_dynamic_ver_all_nolock()
455 writel(0, divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_4)); in clk_wzrd_dynamic_ver_all_nolock()
457 m = divider->m; in clk_wzrd_dynamic_ver_all_nolock()
460 regval1 = readl(divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
468 writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
471 writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
474 value2 = divider->d; in clk_wzrd_dynamic_ver_all_nolock()
478 writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
481 writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, WZRD_DIVCLK)); in clk_wzrd_dynamic_ver_all_nolock()
483 value = divider->o; in clk_wzrd_dynamic_ver_all_nolock()
485 regval1 = readl(divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
499 writel(regval1, divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
502 writel(regval, divider->base + WZRD_CLK_CFG_REG(1, in clk_wzrd_dynamic_ver_all_nolock()
504 div_addr = divider->base + WZRD_DR_INIT_VERSAL_OFFSET; in clk_wzrd_dynamic_ver_all_nolock()
509 static int clk_wzrd_dynamic_all_nolock(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_all_nolock() argument
517 err = clk_wzrd_get_divisors(hw, rate, parent_rate); in clk_wzrd_dynamic_all_nolock()
521 reg = FIELD_PREP(WZRD_CLKOUT_DIVIDE_MASK, divider->o) | in clk_wzrd_dynamic_all_nolock()
522 FIELD_PREP(WZRD_CLKOUT0_FRAC_MASK, divider->o_frac); in clk_wzrd_dynamic_all_nolock()
524 writel(reg, divider->base + WZRD_CLK_CFG_REG(0, 2)); in clk_wzrd_dynamic_all_nolock()
525 reg = FIELD_PREP(WZRD_CLKFBOUT_MULT_MASK, divider->m) | in clk_wzrd_dynamic_all_nolock()
526 FIELD_PREP(WZRD_CLKFBOUT_MULT_FRAC_MASK, divider->m_frac) | in clk_wzrd_dynamic_all_nolock()
527 FIELD_PREP(WZRD_DIVCLK_DIVIDE_MASK, divider->d); in clk_wzrd_dynamic_all_nolock()
528 writel(reg, divider->base + WZRD_CLK_CFG_REG(0, 0)); in clk_wzrd_dynamic_all_nolock()
529 writel(0, divider->base + WZRD_CLK_CFG_REG(0, 3)); in clk_wzrd_dynamic_all_nolock()
530 div_addr = divider->base + WZRD_DR_INIT_REG_OFFSET; in clk_wzrd_dynamic_all_nolock()
534 static int clk_wzrd_dynamic_all(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_all() argument
541 spin_lock_irqsave(divider->lock, flags); in clk_wzrd_dynamic_all()
543 ret = clk_wzrd_dynamic_all_nolock(hw, rate, parent_rate); in clk_wzrd_dynamic_all()
545 spin_unlock_irqrestore(divider->lock, flags); in clk_wzrd_dynamic_all()
550 static int clk_wzrd_dynamic_all_ver(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_all_ver() argument
557 spin_lock_irqsave(divider->lock, flags); in clk_wzrd_dynamic_all_ver()
559 ret = clk_wzrd_dynamic_ver_all_nolock(hw, rate, parent_rate); in clk_wzrd_dynamic_all_ver()
561 spin_unlock_irqrestore(divider->lock, flags); in clk_wzrd_dynamic_all_ver()
573 reg = readl(divider->base + WZRD_CLK_CFG_REG(0, 0)); in clk_wzrd_recalc_rate_all()
577 reg = readl(divider->base + WZRD_CLK_CFG_REG(0, 2)); in clk_wzrd_recalc_rate_all()
592 edge = !!(readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_1)) & in clk_wzrd_recalc_rate_all_ver()
595 reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_2)); in clk_wzrd_recalc_rate_all_ver()
603 regl = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_4)) & in clk_wzrd_recalc_rate_all_ver()
606 regl = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKFBOUT_3)) in clk_wzrd_recalc_rate_all_ver()
615 reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKOUT0_1)); in clk_wzrd_recalc_rate_all_ver()
620 reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_CLKOUT0_2)); in clk_wzrd_recalc_rate_all_ver()
635 edged = !!(readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_DESKEW_2)) & in clk_wzrd_recalc_rate_all_ver()
637 reg = readl(divider->base + WZRD_CLK_CFG_REG(1, WZRD_DIVCLK)); in clk_wzrd_recalc_rate_all_ver()
647 return divider_recalc_rate(hw, parent_rate, div, divider->table, in clk_wzrd_recalc_rate_all_ver()
648 divider->flags, divider->width); in clk_wzrd_recalc_rate_all_ver()
658 err = clk_wzrd_get_divisors(hw, req->rate, req->best_parent_rate); in clk_wzrd_determine_rate_all()
662 m = divider->m; in clk_wzrd_determine_rate_all()
663 d = divider->d; in clk_wzrd_determine_rate_all()
664 o = divider->o; in clk_wzrd_determine_rate_all()
666 req->rate = div_u64(req->best_parent_rate * (m * 1000 + divider->m_frac), in clk_wzrd_determine_rate_all()
667 d * (o * 1000 + divider->o_frac)); in clk_wzrd_determine_rate_all()
679 err = clk_wzrd_get_divisors_ver(hw, req->rate, req->best_parent_rate); in clk_wzrd_ver_determine_rate_all()
683 m = divider->m; in clk_wzrd_ver_determine_rate_all()
684 d = divider->d; in clk_wzrd_ver_determine_rate_all()
685 o = divider->o; in clk_wzrd_ver_determine_rate_all()
688 int_freq = divider_recalc_rate(hw, req->best_parent_rate * m, div, in clk_wzrd_ver_determine_rate_all()
689 divider->table, in clk_wzrd_ver_determine_rate_all()
690 divider->flags, divider->width); in clk_wzrd_ver_determine_rate_all()
692 if (req->rate > int_freq) { in clk_wzrd_ver_determine_rate_all()
693 f = DIV_ROUND_CLOSEST_ULL(req->rate * WZRD_FRAC_POINTS, in clk_wzrd_ver_determine_rate_all()
695 req->rate = DIV_ROUND_CLOSEST(int_freq * f, WZRD_FRAC_POINTS); in clk_wzrd_ver_determine_rate_all()
730 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_recalc_ratef()
733 div = val & div_mask(divider->width); in clk_wzrd_recalc_ratef()
739 static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, in clk_wzrd_dynamic_reconfig_f() argument
746 void __iomem *div_addr = divider->base + divider->offset; in clk_wzrd_dynamic_reconfig_f()
748 rate_div = DIV_ROUND_DOWN_ULL(parent_rate * 1000, rate); in clk_wzrd_dynamic_reconfig_f()
751 pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); in clk_wzrd_dynamic_reconfig_f()
752 f = (u32)(pre - (clockout0_div * 1000)); in clk_wzrd_dynamic_reconfig_f()
763 err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, in clk_wzrd_dynamic_reconfig_f()
771 divider->base + WZRD_DR_INIT_REG_OFFSET); in clk_wzrd_dynamic_reconfig_f()
773 divider->base + WZRD_DR_INIT_REG_OFFSET); in clk_wzrd_dynamic_reconfig_f()
776 return readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, in clk_wzrd_dynamic_reconfig_f()
810 return ERR_PTR(-ENOMEM); in clk_wzrd_register_divf()
820 div->base = base; in clk_wzrd_register_divf()
821 div->offset = offset; in clk_wzrd_register_divf()
822 div->shift = shift; in clk_wzrd_register_divf()
823 div->width = width; in clk_wzrd_register_divf()
824 div->flags = clk_divider_flags; in clk_wzrd_register_divf()
825 div->lock = lock; in clk_wzrd_register_divf()
826 div->hw.init = &init; in clk_wzrd_register_divf()
828 hw = &div->hw; in clk_wzrd_register_divf()
854 return ERR_PTR(-ENOMEM); in clk_wzrd_ver_register_divider()
867 div->base = base; in clk_wzrd_ver_register_divider()
868 div->offset = offset; in clk_wzrd_ver_register_divider()
869 div->shift = shift; in clk_wzrd_ver_register_divider()
870 div->width = width; in clk_wzrd_ver_register_divider()
871 div->flags = clk_divider_flags; in clk_wzrd_ver_register_divider()
872 div->lock = lock; in clk_wzrd_ver_register_divider()
873 div->hw.init = &init; in clk_wzrd_ver_register_divider()
875 hw = &div->hw; in clk_wzrd_ver_register_divider()
900 return ERR_PTR(-ENOMEM); in clk_wzrd_register_divider()
913 div->base = base; in clk_wzrd_register_divider()
914 div->offset = offset; in clk_wzrd_register_divider()
915 div->shift = shift; in clk_wzrd_register_divider()
916 div->width = width; in clk_wzrd_register_divider()
917 div->flags = clk_divider_flags; in clk_wzrd_register_divider()
918 div->lock = lock; in clk_wzrd_register_divider()
919 div->hw.init = &init; in clk_wzrd_register_divider()
921 hw = &div->hw; in clk_wzrd_register_divider()
932 unsigned long max; in clk_wzrd_clk_notifier() local
936 if (clk_wzrd->suspended) in clk_wzrd_clk_notifier()
939 if (ndata->clk == clk_wzrd->clk_in1) in clk_wzrd_clk_notifier()
940 max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; in clk_wzrd_clk_notifier()
941 else if (ndata->clk == clk_wzrd->axi_clk) in clk_wzrd_clk_notifier()
942 max = WZRD_ACLK_MAX_FREQ; in clk_wzrd_clk_notifier()
948 if (ndata->new_rate > max) in clk_wzrd_clk_notifier()
962 clk_disable_unprepare(clk_wzrd->axi_clk); in clk_wzrd_suspend()
963 clk_wzrd->suspended = true; in clk_wzrd_suspend()
973 ret = clk_prepare_enable(clk_wzrd->axi_clk); in clk_wzrd_resume()
979 clk_wzrd->suspended = false; in clk_wzrd_resume()
1005 is_versal = data->is_versal; in clk_wzrd_register_output_clocks()
1009 return -ENOMEM; in clk_wzrd_register_output_clocks()
1013 clk_wzrd->clk_data.hws[0] = clk_wzrd_ver_register_divider in clk_wzrd_register_output_clocks()
1015 __clk_get_name(clk_wzrd->clk_in1), 0, in clk_wzrd_register_output_clocks()
1016 clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3), in clk_wzrd_register_output_clocks()
1025 edge = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0)) & in clk_wzrd_register_output_clocks()
1026 BIT(8)); in clk_wzrd_register_output_clocks()
1027 regl = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 1)) & in clk_wzrd_register_output_clocks()
1029 regh = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 1)) & in clk_wzrd_register_output_clocks()
1036 regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 51)) & in clk_wzrd_register_output_clocks()
1039 regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 48)) & in clk_wzrd_register_output_clocks()
1046 clk_wzrd->clk_data.hws[0] = clk_wzrd_register_divider in clk_wzrd_register_output_clocks()
1048 __clk_get_name(clk_wzrd->clk_in1), 0, in clk_wzrd_register_output_clocks()
1049 clk_wzrd->base, WZRD_CLK_CFG_REG(is_versal, 3), in clk_wzrd_register_output_clocks()
1057 reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0)); in clk_wzrd_register_output_clocks()
1068 return -ENOMEM; in clk_wzrd_register_output_clocks()
1069 clk_wzrd->clks_internal[wzrd_clk_mul] = devm_clk_hw_register_fixed_factor in clk_wzrd_register_output_clocks()
1071 __clk_get_name(clk_wzrd->clk_in1), in clk_wzrd_register_output_clocks()
1073 if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) { in clk_wzrd_register_output_clocks()
1074 dev_err(dev, "unable to register fixed-factor clock\n"); in clk_wzrd_register_output_clocks()
1075 return PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]); in clk_wzrd_register_output_clocks()
1080 return -ENOMEM; in clk_wzrd_register_output_clocks()
1083 edged = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 20)) & in clk_wzrd_register_output_clocks()
1084 BIT(10)); in clk_wzrd_register_output_clocks()
1085 regld = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 21)) & in clk_wzrd_register_output_clocks()
1087 reghd = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 21)) & in clk_wzrd_register_output_clocks()
1093 clk_mul_name = clk_hw_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]); in clk_wzrd_register_output_clocks()
1094 clk_wzrd->clks_internal[wzrd_clk_mul_div] = in clk_wzrd_register_output_clocks()
1097 ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(is_versal, 0); in clk_wzrd_register_output_clocks()
1098 clk_wzrd->clks_internal[wzrd_clk_mul_div] = devm_clk_hw_register_divider in clk_wzrd_register_output_clocks()
1100 clk_hw_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), in clk_wzrd_register_output_clocks()
1104 if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) { in clk_wzrd_register_output_clocks()
1106 return PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]); in clk_wzrd_register_output_clocks()
1110 for (i = nr_outputs - 1; i >= 0 ; i--) { in clk_wzrd_register_output_clocks()
1113 return -ENOMEM; in clk_wzrd_register_output_clocks()
1116 clk_wzrd->clk_data.hws[i] = clk_wzrd_ver_register_divider in clk_wzrd_register_output_clocks()
1119 clk_wzrd->base, in clk_wzrd_register_output_clocks()
1128 clk_wzrd->clk_data.hws[i] = clk_wzrd_register_divf in clk_wzrd_register_output_clocks()
1129 (dev, clkout_name, clk_name, flags, clk_wzrd->base, in clk_wzrd_register_output_clocks()
1136 clk_wzrd->clk_data.hws[i] = clk_wzrd_register_divider in clk_wzrd_register_output_clocks()
1137 (dev, clkout_name, clk_name, 0, clk_wzrd->base, in clk_wzrd_register_output_clocks()
1144 if (IS_ERR(clk_wzrd->clk_data.hws[i])) { in clk_wzrd_register_output_clocks()
1146 return PTR_ERR(clk_wzrd->clk_data.hws[i]); in clk_wzrd_register_output_clocks()
1155 struct device_node *np = pdev->dev.of_node; in clk_wzrd_probe()
1157 unsigned long rate; in clk_wzrd_probe() local
1161 ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs); in clk_wzrd_probe()
1163 return -EINVAL; in clk_wzrd_probe()
1165 clk_wzrd = devm_kzalloc(&pdev->dev, struct_size(clk_wzrd, clk_data.hws, nr_outputs), in clk_wzrd_probe()
1168 return -ENOMEM; in clk_wzrd_probe()
1171 clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0); in clk_wzrd_probe()
1172 if (IS_ERR(clk_wzrd->base)) in clk_wzrd_probe()
1173 return PTR_ERR(clk_wzrd->base); in clk_wzrd_probe()
1175 clk_wzrd->axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); in clk_wzrd_probe()
1176 if (IS_ERR(clk_wzrd->axi_clk)) in clk_wzrd_probe()
1177 return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk), in clk_wzrd_probe()
1179 rate = clk_get_rate(clk_wzrd->axi_clk); in clk_wzrd_probe()
1180 if (rate > WZRD_ACLK_MAX_FREQ) { in clk_wzrd_probe()
1181 dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n", rate); in clk_wzrd_probe()
1182 return -EINVAL; in clk_wzrd_probe()
1185 if (!of_property_present(np, "xlnx,static-config")) { in clk_wzrd_probe()
1186 ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade); in clk_wzrd_probe()
1188 if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) { in clk_wzrd_probe()
1189 dev_warn(&pdev->dev, "invalid speed grade '%d'\n", in clk_wzrd_probe()
1190 clk_wzrd->speed_grade); in clk_wzrd_probe()
1191 clk_wzrd->speed_grade = 0; in clk_wzrd_probe()
1195 clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1"); in clk_wzrd_probe()
1196 if (IS_ERR(clk_wzrd->clk_in1)) in clk_wzrd_probe()
1197 return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1), in clk_wzrd_probe()
1200 ret = clk_wzrd_register_output_clocks(&pdev->dev, nr_outputs); in clk_wzrd_probe()
1204 clk_wzrd->clk_data.num = nr_outputs; in clk_wzrd_probe()
1205 ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, in clk_wzrd_probe()
1206 &clk_wzrd->clk_data); in clk_wzrd_probe()
1208 dev_err(&pdev->dev, "unable to register clock provider\n"); in clk_wzrd_probe()
1212 if (clk_wzrd->speed_grade) { in clk_wzrd_probe()
1213 clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier; in clk_wzrd_probe()
1215 ret = devm_clk_notifier_register(&pdev->dev, clk_wzrd->clk_in1, in clk_wzrd_probe()
1216 &clk_wzrd->nb); in clk_wzrd_probe()
1218 dev_warn(&pdev->dev, in clk_wzrd_probe()
1221 ret = devm_clk_notifier_register(&pdev->dev, clk_wzrd->axi_clk, in clk_wzrd_probe()
1222 &clk_wzrd->nb); in clk_wzrd_probe()
1224 dev_warn(&pdev->dev, in clk_wzrd_probe()
1233 { .compatible = "xlnx,versal-clk-wizard", .data = &versal_data },
1234 { .compatible = "xlnx,clocking-wizard" },
1235 { .compatible = "xlnx,clocking-wizard-v5.2" },
1236 { .compatible = "xlnx,clocking-wizard-v6.0" },
1243 .name = "clk-wizard",