Lines Matching +full:src +full:- +full:ref +full:- +full:clk +full:- +full:mhz

1 // SPDX-License-Identifier: GPL-2.0+
8 #include <linux/clk-provider.h>
88 #define VC3_DIV_MASK(width) ((1 << (width)) - 1)
131 VC3_SE1_MUX = VC3_SE1 - 1,
132 VC3_SE2_MUX = VC3_SE2 - 1,
133 VC3_SE3_MUX = VC3_SE3 - 1,
134 VC3_DIFF1_MUX = VC3_DIFF1 - 1,
135 VC3_DIFF2_MUX = VC3_DIFF2 - 1,
216 const struct vc3_clk_data *pfd_mux = vc3->data; in vc3_pfd_mux_get_parent()
217 u32 src; in vc3_pfd_mux_get_parent() local
219 regmap_read(vc3->regmap, pfd_mux->offs, &src); in vc3_pfd_mux_get_parent()
221 return !!(src & pfd_mux->bitmsk); in vc3_pfd_mux_get_parent()
227 const struct vc3_clk_data *pfd_mux = vc3->data; in vc3_pfd_mux_set_parent()
229 regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk, in vc3_pfd_mux_set_parent()
230 index ? pfd_mux->bitmsk : 0); in vc3_pfd_mux_set_parent()
244 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_recalc_rate()
249 regmap_read(vc3->regmap, pfd->offs, &prediv); in vc3_pfd_recalc_rate()
250 if (pfd->num == VC3_PFD1) { in vc3_pfd_recalc_rate()
252 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
254 regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul); in vc3_pfd_recalc_rate()
260 } else if (pfd->num == VC3_PFD2) { in vc3_pfd_recalc_rate()
262 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
263 regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul); in vc3_pfd_recalc_rate()
273 if (prediv & pfd->mdiv1_bitmsk) in vc3_pfd_recalc_rate()
279 if (prediv & pfd->mdiv2_bitmsk) in vc3_pfd_recalc_rate()
291 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_round_rate()
294 /* PLL cannot operate with input clock above 50 MHz. */ in vc3_pfd_round_rate()
296 return -EINVAL; in vc3_pfd_round_rate()
303 if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) { in vc3_pfd_round_rate()
305 return -EINVAL; in vc3_pfd_round_rate()
308 return -EINVAL; in vc3_pfd_round_rate()
318 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_set_rate()
324 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, in vc3_pfd_set_rate()
325 pfd->mdiv1_bitmsk); in vc3_pfd_set_rate()
326 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0); in vc3_pfd_set_rate()
331 /* We have dedicated div-2 predivider. */ in vc3_pfd_set_rate()
333 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, in vc3_pfd_set_rate()
334 pfd->mdiv2_bitmsk); in vc3_pfd_set_rate()
335 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0); in vc3_pfd_set_rate()
337 if (pfd->num == VC3_PFD1) in vc3_pfd_set_rate()
339 else if (pfd->num == VC3_PFD2) in vc3_pfd_set_rate()
344 regmap_write(vc3->regmap, pfd->offs, div); in vc3_pfd_set_rate()
360 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_recalc_rate()
364 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_recalc_rate()
366 regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val); in vc3_pll_recalc_rate()
369 if (pll->num == VC3_PLL2) { in vc3_pll_recalc_rate()
370 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val); in vc3_pll_recalc_rate()
372 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val); in vc3_pll_recalc_rate()
387 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_round_rate()
390 if (rate < pll->vco_min) in vc3_pll_round_rate()
391 rate = pll->vco_min; in vc3_pll_round_rate()
392 if (rate > pll->vco_max) in vc3_pll_round_rate()
393 rate = pll->vco_max; in vc3_pll_round_rate()
395 vc3->div_int = rate / *parent_rate; in vc3_pll_round_rate()
397 if (pll->num == VC3_PLL2) { in vc3_pll_round_rate()
398 if (vc3->div_int > 0x7ff) in vc3_pll_round_rate()
403 div_frc *= BIT(16) - 1; in vc3_pll_round_rate()
405 vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX); in vc3_pll_round_rate()
407 (vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16); in vc3_pll_round_rate()
409 rate = *parent_rate * vc3->div_int; in vc3_pll_round_rate()
419 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_set_rate()
422 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_set_rate()
423 val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7); in vc3_pll_set_rate()
424 regmap_write(vc3->regmap, pll->int_div_msb_offs, val); in vc3_pll_set_rate()
425 regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff); in vc3_pll_set_rate()
427 if (pll->num == VC3_PLL2) { in vc3_pll_set_rate()
428 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, in vc3_pll_set_rate()
429 vc3->div_frc >> 8); in vc3_pll_set_rate()
430 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, in vc3_pll_set_rate()
431 vc3->div_frc & 0xff); in vc3_pll_set_rate()
446 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_get_parent()
447 u32 src; in vc3_div_mux_get_parent() local
449 regmap_read(vc3->regmap, div_mux->offs, &src); in vc3_div_mux_get_parent()
451 return !!(src & div_mux->bitmsk); in vc3_div_mux_get_parent()
457 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_set_parent()
459 regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk, in vc3_div_mux_set_parent()
460 index ? div_mux->bitmsk : 0); in vc3_div_mux_set_parent()
476 for (clkt = table; clkt->div; clkt++) in vc3_get_div()
477 if (clkt->val == val) in vc3_get_div()
478 return clkt->div; in vc3_get_div()
487 const struct vc3_div_data *div_data = vc3->data; in vc3_div_recalc_rate()
490 regmap_read(vc3->regmap, div_data->offs, &val); in vc3_div_recalc_rate()
491 val >>= div_data->shift; in vc3_div_recalc_rate()
492 val &= VC3_DIV_MASK(div_data->width); in vc3_div_recalc_rate()
494 return divider_recalc_rate(hw, parent_rate, val, div_data->table, in vc3_div_recalc_rate()
495 div_data->flags, div_data->width); in vc3_div_recalc_rate()
502 const struct vc3_div_data *div_data = vc3->data; in vc3_div_round_rate()
506 if (div_data->flags & CLK_DIVIDER_READ_ONLY) { in vc3_div_round_rate()
507 regmap_read(vc3->regmap, div_data->offs, &bestdiv); in vc3_div_round_rate()
508 bestdiv >>= div_data->shift; in vc3_div_round_rate()
509 bestdiv &= VC3_DIV_MASK(div_data->width); in vc3_div_round_rate()
510 bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags); in vc3_div_round_rate()
514 return divider_round_rate(hw, rate, parent_rate, div_data->table, in vc3_div_round_rate()
515 div_data->width, div_data->flags); in vc3_div_round_rate()
522 const struct vc3_div_data *div_data = vc3->data; in vc3_div_set_rate()
525 value = divider_get_val(rate, parent_rate, div_data->table, in vc3_div_set_rate()
526 div_data->width, div_data->flags); in vc3_div_set_rate()
527 regmap_update_bits(vc3->regmap, div_data->offs, in vc3_div_set_rate()
528 VC3_DIV_MASK(div_data->width) << div_data->shift, in vc3_div_set_rate()
529 value << div_data->shift); in vc3_div_set_rate()
548 if (req->best_parent_rate >= req->rate) { in vc3_clk_mux_determine_rate()
549 frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate, in vc3_clk_mux_determine_rate()
550 req->rate); in vc3_clk_mux_determine_rate()
551 req->rate *= frc; in vc3_clk_mux_determine_rate()
564 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_get_parent()
567 regmap_read(vc3->regmap, clk_mux->offs, &val); in vc3_clk_mux_get_parent()
569 return !!(val & clk_mux->bitmsk); in vc3_clk_mux_get_parent()
575 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_set_parent()
577 regmap_update_bits(vc3->regmap, clk_mux->offs, in vc3_clk_mux_set_parent()
578 clk_mux->bitmsk, index ? clk_mux->bitmsk : 0); in vc3_clk_mux_set_parent()
984 unsigned int idx = clkspec->args[0]; in vc3_of_clk_get()
988 pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np); in vc3_of_clk_get()
989 return ERR_PTR(-EINVAL); in vc3_of_clk_get()
997 struct device *dev = &client->dev; in vc3_probe()
1008 ret = of_property_read_u8_array(dev->of_node, "renesas,settings", in vc3_probe()
1022 } else if (ret == -EOVERFLOW) { in vc3_probe()
1023 dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n", in vc3_probe()
1034 clk_pfd_mux[i].hw.init->name); in vc3_probe()
1043 clk_pfd[i].hw.init->name); in vc3_probe()
1052 clk_pll[i].hw.init->name); in vc3_probe()
1061 clk_div_mux[i].hw.init->name); in vc3_probe()
1070 clk_div[i].hw.init->name); in vc3_probe()
1073 /* Register clk muxes */ in vc3_probe()
1079 clk_mux[i].hw.init->name); in vc3_probe()
1082 /* Register clk outputs */ in vc3_probe()
1101 name = "ref"; in vc3_probe()
1104 return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i); in vc3_probe()
1112 name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); in vc3_probe()
1120 return dev_err_probe(dev, ret, "unable to add clk provider\n"); in vc3_probe()