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>
85 #define VC3_DIV_MASK(width) ((1 << (width)) - 1)
128 VC3_SE1_MUX = VC3_SE1 - 1,
129 VC3_SE2_MUX = VC3_SE2 - 1,
130 VC3_SE3_MUX = VC3_SE3 - 1,
131 VC3_DIFF1_MUX = VC3_DIFF1 - 1,
132 VC3_DIFF2_MUX = VC3_DIFF2 - 1,
222 const struct vc3_clk_data *pfd_mux = vc3->data; in vc3_pfd_mux_get_parent()
223 u32 src; in vc3_pfd_mux_get_parent() local
225 regmap_read(vc3->regmap, pfd_mux->offs, &src); in vc3_pfd_mux_get_parent()
227 return !!(src & pfd_mux->bitmsk); in vc3_pfd_mux_get_parent()
233 const struct vc3_clk_data *pfd_mux = vc3->data; in vc3_pfd_mux_set_parent()
235 return regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk, in vc3_pfd_mux_set_parent()
236 index ? pfd_mux->bitmsk : 0); in vc3_pfd_mux_set_parent()
249 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_recalc_rate()
254 regmap_read(vc3->regmap, pfd->offs, &prediv); in vc3_pfd_recalc_rate()
255 if (pfd->num == VC3_PFD1) { in vc3_pfd_recalc_rate()
257 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
259 regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul); in vc3_pfd_recalc_rate()
265 } else if (pfd->num == VC3_PFD2) { in vc3_pfd_recalc_rate()
267 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
268 regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul); in vc3_pfd_recalc_rate()
278 if (prediv & pfd->mdiv1_bitmsk) in vc3_pfd_recalc_rate()
284 if (prediv & pfd->mdiv2_bitmsk) in vc3_pfd_recalc_rate()
296 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_round_rate()
299 /* PLL cannot operate with input clock above 50 MHz. */ in vc3_pfd_round_rate()
301 return -EINVAL; in vc3_pfd_round_rate()
308 if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) { in vc3_pfd_round_rate()
310 return -EINVAL; in vc3_pfd_round_rate()
313 return -EINVAL; in vc3_pfd_round_rate()
323 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_set_rate()
329 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, in vc3_pfd_set_rate()
330 pfd->mdiv1_bitmsk); in vc3_pfd_set_rate()
331 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0); in vc3_pfd_set_rate()
336 /* We have dedicated div-2 predivider. */ in vc3_pfd_set_rate()
338 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, in vc3_pfd_set_rate()
339 pfd->mdiv2_bitmsk); in vc3_pfd_set_rate()
340 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0); in vc3_pfd_set_rate()
342 if (pfd->num == VC3_PFD1) in vc3_pfd_set_rate()
344 else if (pfd->num == VC3_PFD2) in vc3_pfd_set_rate()
349 regmap_write(vc3->regmap, pfd->offs, div); in vc3_pfd_set_rate()
365 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_recalc_rate()
369 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_recalc_rate()
371 regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val); in vc3_pll_recalc_rate()
374 if (pll->num == VC3_PLL2) { in vc3_pll_recalc_rate()
375 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val); in vc3_pll_recalc_rate()
377 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val); in vc3_pll_recalc_rate()
392 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_round_rate()
395 if (rate < pll->vco.min) in vc3_pll_round_rate()
396 rate = pll->vco.min; in vc3_pll_round_rate()
397 if (rate > pll->vco.max) in vc3_pll_round_rate()
398 rate = pll->vco.max; in vc3_pll_round_rate()
400 vc3->div_int = rate / *parent_rate; in vc3_pll_round_rate()
402 if (pll->num == VC3_PLL2) { in vc3_pll_round_rate()
403 if (vc3->div_int > 0x7ff) in vc3_pll_round_rate()
408 div_frc *= BIT(16) - 1; in vc3_pll_round_rate()
410 vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX); in vc3_pll_round_rate()
412 (vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16); in vc3_pll_round_rate()
414 rate = *parent_rate * vc3->div_int; in vc3_pll_round_rate()
424 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_set_rate()
427 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_set_rate()
428 val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7); in vc3_pll_set_rate()
429 regmap_write(vc3->regmap, pll->int_div_msb_offs, val); in vc3_pll_set_rate()
430 regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff); in vc3_pll_set_rate()
432 if (pll->num == VC3_PLL2) { in vc3_pll_set_rate()
433 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, in vc3_pll_set_rate()
434 vc3->div_frc >> 8); in vc3_pll_set_rate()
435 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, in vc3_pll_set_rate()
436 vc3->div_frc & 0xff); in vc3_pll_set_rate()
451 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_get_parent()
452 u32 src; in vc3_div_mux_get_parent() local
454 regmap_read(vc3->regmap, div_mux->offs, &src); in vc3_div_mux_get_parent()
456 return !!(src & div_mux->bitmsk); in vc3_div_mux_get_parent()
462 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_set_parent()
464 return regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk, in vc3_div_mux_set_parent()
465 index ? div_mux->bitmsk : 0); in vc3_div_mux_set_parent()
479 for (clkt = table; clkt->div; clkt++) in vc3_get_div()
480 if (clkt->val == val) in vc3_get_div()
481 return clkt->div; in vc3_get_div()
490 const struct vc3_div_data *div_data = vc3->data; in vc3_div_recalc_rate()
493 regmap_read(vc3->regmap, div_data->offs, &val); in vc3_div_recalc_rate()
494 val >>= div_data->shift; in vc3_div_recalc_rate()
495 val &= VC3_DIV_MASK(div_data->width); in vc3_div_recalc_rate()
497 return divider_recalc_rate(hw, parent_rate, val, div_data->table, in vc3_div_recalc_rate()
498 div_data->flags, div_data->width); in vc3_div_recalc_rate()
505 const struct vc3_div_data *div_data = vc3->data; in vc3_div_round_rate()
509 if (div_data->flags & CLK_DIVIDER_READ_ONLY) { in vc3_div_round_rate()
510 regmap_read(vc3->regmap, div_data->offs, &bestdiv); in vc3_div_round_rate()
511 bestdiv >>= div_data->shift; in vc3_div_round_rate()
512 bestdiv &= VC3_DIV_MASK(div_data->width); in vc3_div_round_rate()
513 bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags); in vc3_div_round_rate()
517 return divider_round_rate(hw, rate, parent_rate, div_data->table, in vc3_div_round_rate()
518 div_data->width, div_data->flags); in vc3_div_round_rate()
525 const struct vc3_div_data *div_data = vc3->data; in vc3_div_set_rate()
528 value = divider_get_val(rate, parent_rate, div_data->table, in vc3_div_set_rate()
529 div_data->width, div_data->flags); in vc3_div_set_rate()
530 return regmap_update_bits(vc3->regmap, div_data->offs, in vc3_div_set_rate()
531 VC3_DIV_MASK(div_data->width) << div_data->shift, in vc3_div_set_rate()
532 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()
563 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_get_parent()
566 regmap_read(vc3->regmap, clk_mux->offs, &val); in vc3_clk_mux_get_parent()
568 return !!(val & clk_mux->bitmsk); in vc3_clk_mux_get_parent()
574 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_set_parent()
576 return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk, in vc3_clk_mux_set_parent()
577 index ? clk_mux->bitmsk : 0); in vc3_clk_mux_set_parent()
977 unsigned int idx = clkspec->args[0]; in vc3_of_clk_get()
981 pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np); in vc3_of_clk_get()
982 return ERR_PTR(-EINVAL); in vc3_of_clk_get()
990 struct device *dev = &client->dev; in vc3_probe()
1002 ret = of_property_read_u8_array(dev->of_node, "renesas,settings", in vc3_probe()
1016 } else if (ret == -EOVERFLOW) { in vc3_probe()
1017 dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n", in vc3_probe()
1028 clk_pfd_mux[i].hw.init->name); in vc3_probe()
1037 clk_pfd[i].hw.init->name); in vc3_probe()
1048 pll_data->vco = data->pll2_vco; in vc3_probe()
1053 clk_pll[i].hw.init->name); in vc3_probe()
1062 clk_div_mux[i].hw.init->name); in vc3_probe()
1071 clk_div[i].hw.init->name); in vc3_probe()
1074 /* Register clk muxes */ in vc3_probe()
1080 clk_data->bitmsk = data->se2_clk_sel_msk; in vc3_probe()
1085 clk_mux[i].hw.init->name); in vc3_probe()
1088 /* Register clk outputs */ in vc3_probe()
1107 name = "ref"; in vc3_probe()
1110 return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i); in vc3_probe()
1118 name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); in vc3_probe()
1126 return dev_err_probe(dev, ret, "unable to add clk provider\n"); in vc3_probe()