Lines Matching +full:dout +full:- +full:default
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright 2012-2013 Analog Devices Inc.
6 * Author: Lars-Peter Clausen <lars@metafoo.de>
10 #include <linux/clk-provider.h>
87 default: in axi_clkgen_lookup_filter()
131 unsigned long f, dout, best_f, fvco; in axi_clkgen_calc_params() local
143 d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1); in axi_clkgen_calc_params()
144 d_max = min_t(unsigned long, fin / limits->fpfd_min, 80); in axi_clkgen_calc_params()
147 fvco_min_fract = limits->fvco_min << fract_shift; in axi_clkgen_calc_params()
148 fvco_max_fract = limits->fvco_max << fract_shift; in axi_clkgen_calc_params()
160 dout = DIV_ROUND_CLOSEST(fvco, fout); in axi_clkgen_calc_params()
161 dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift); in axi_clkgen_calc_params()
162 f = fvco / dout; in axi_clkgen_calc_params()
163 if (abs(f - fout) < abs(best_f - fout)) { in axi_clkgen_calc_params()
166 *best_m = m << (3 - fract_shift); in axi_clkgen_calc_params()
167 *best_dout = dout << (3 - fract_shift); in axi_clkgen_calc_params()
200 params->nocount = 1; in axi_clkgen_calc_clk_params()
205 params->high = divider / 2; in axi_clkgen_calc_clk_params()
206 params->edge = divider % 2; in axi_clkgen_calc_clk_params()
207 params->low = divider - params->high; in axi_clkgen_calc_clk_params()
209 params->frac_en = 1; in axi_clkgen_calc_clk_params()
210 params->frac = frac_divider; in axi_clkgen_calc_clk_params()
212 params->high = divider / 2; in axi_clkgen_calc_clk_params()
213 params->edge = divider % 2; in axi_clkgen_calc_clk_params()
214 params->low = params->high; in axi_clkgen_calc_clk_params()
216 if (params->edge == 0) { in axi_clkgen_calc_clk_params()
217 params->high--; in axi_clkgen_calc_clk_params()
218 params->frac_wf_r = 1; in axi_clkgen_calc_clk_params()
221 if (params->edge == 0 || frac_divider == 1) in axi_clkgen_calc_clk_params()
222 params->low--; in axi_clkgen_calc_clk_params()
223 if (((params->edge == 0) ^ (frac_divider == 1)) || in axi_clkgen_calc_clk_params()
225 params->frac_wf_f = 1; in axi_clkgen_calc_clk_params()
227 params->frac_phase = params->edge * 4 + frac_divider / 2; in axi_clkgen_calc_clk_params()
234 writel(val, axi_clkgen->base + reg); in axi_clkgen_write()
240 *val = readl(axi_clkgen->base + reg); in axi_clkgen_read()
250 } while ((val & AXI_CLKGEN_V2_DRP_STATUS_BUSY) && --timeout); in axi_clkgen_wait_non_busy()
253 return -EIO; in axi_clkgen_wait_non_busy()
325 (params->high << 6) | params->low, 0xefff); in axi_clkgen_set_div()
327 (params->frac << 12) | (params->frac_en << 11) | in axi_clkgen_set_div()
328 (params->frac_wf_r << 10) | (params->edge << 7) | in axi_clkgen_set_div()
329 (params->nocount << 6), 0x7fff); in axi_clkgen_set_div()
332 (params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00); in axi_clkgen_set_div()
340 const struct axi_clkgen_limits *limits = &axi_clkgen->limits; in axi_clkgen_set_rate()
341 unsigned int d, m, dout; in axi_clkgen_set_rate() local
348 return -EINVAL; in axi_clkgen_set_rate()
350 axi_clkgen_calc_params(limits, parent_rate, rate, &d, &m, &dout); in axi_clkgen_set_rate()
352 if (d == 0 || dout == 0 || m == 0) in axi_clkgen_set_rate()
353 return -EINVAL; in axi_clkgen_set_rate()
355 if ((dout & 0x7) != 0 || (m & 0x7) != 0) in axi_clkgen_set_rate()
360 filter = axi_clkgen_lookup_filter(m - 1); in axi_clkgen_set_rate()
361 lock = axi_clkgen_lookup_lock(m - 1); in axi_clkgen_set_rate()
363 axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, ¶ms); in axi_clkgen_set_rate()
391 const struct axi_clkgen_limits *limits = &axi_clkgen->limits; in axi_clkgen_determine_rate()
392 unsigned int d, m, dout; in axi_clkgen_determine_rate() local
395 axi_clkgen_calc_params(limits, req->best_parent_rate, req->rate, in axi_clkgen_determine_rate()
396 &d, &m, &dout); in axi_clkgen_determine_rate()
398 if (d == 0 || dout == 0 || m == 0) in axi_clkgen_determine_rate()
399 return -EINVAL; in axi_clkgen_determine_rate()
401 tmp = (unsigned long long)req->best_parent_rate * m; in axi_clkgen_determine_rate()
402 tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d); in axi_clkgen_determine_rate()
404 req->rate = min_t(unsigned long long, tmp, LONG_MAX); in axi_clkgen_determine_rate()
439 unsigned int d, m, dout; in axi_clkgen_recalc_rate() local
443 dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1, in axi_clkgen_recalc_rate()
454 if (d == 0 || dout == 0) in axi_clkgen_recalc_rate()
458 tmp = DIV_ROUND_CLOSEST_ULL(tmp, dout * d); in axi_clkgen_recalc_rate()
518 dflt_limits = device_get_match_data(&pdev->dev); in axi_clkgen_probe()
520 return -ENODEV; in axi_clkgen_probe()
522 axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); in axi_clkgen_probe()
524 return -ENOMEM; in axi_clkgen_probe()
526 axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0); in axi_clkgen_probe()
527 if (IS_ERR(axi_clkgen->base)) in axi_clkgen_probe()
528 return PTR_ERR(axi_clkgen->base); in axi_clkgen_probe()
530 init.num_parents = of_clk_get_parent_count(pdev->dev.of_node); in axi_clkgen_probe()
532 return -EINVAL; in axi_clkgen_probe()
535 parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i); in axi_clkgen_probe()
537 return -EINVAL; in axi_clkgen_probe()
540 memcpy(&axi_clkgen->limits, dflt_limits, sizeof(axi_clkgen->limits)); in axi_clkgen_probe()
542 clk_name = pdev->dev.of_node->name; in axi_clkgen_probe()
543 of_property_read_string(pdev->dev.of_node, "clock-output-names", in axi_clkgen_probe()
553 axi_clkgen->clk_hw.init = &init; in axi_clkgen_probe()
554 ret = devm_clk_hw_register(&pdev->dev, &axi_clkgen->clk_hw); in axi_clkgen_probe()
558 return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get, in axi_clkgen_probe()
559 &axi_clkgen->clk_hw); in axi_clkgen_probe()
564 .compatible = "adi,zynqmp-axi-clkgen-2.00.a",
568 .compatible = "adi,axi-clkgen-2.00.a",
577 .name = "adi-axi-clkgen",
585 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");