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 return 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()
243 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_recalc_rate()
248 regmap_read(vc3->regmap, pfd->offs, &prediv); in vc3_pfd_recalc_rate()
249 if (pfd->num == VC3_PFD1) { in vc3_pfd_recalc_rate()
251 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
253 regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul); in vc3_pfd_recalc_rate()
259 } else if (pfd->num == VC3_PFD2) { in vc3_pfd_recalc_rate()
261 if (prediv & pfd->mdiv1_bitmsk) { in vc3_pfd_recalc_rate()
262 regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul); in vc3_pfd_recalc_rate()
272 if (prediv & pfd->mdiv1_bitmsk) in vc3_pfd_recalc_rate()
278 if (prediv & pfd->mdiv2_bitmsk) in vc3_pfd_recalc_rate()
290 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_round_rate()
293 /* PLL cannot operate with input clock above 50 MHz. */ in vc3_pfd_round_rate()
295 return -EINVAL; in vc3_pfd_round_rate()
302 if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) { in vc3_pfd_round_rate()
304 return -EINVAL; in vc3_pfd_round_rate()
307 return -EINVAL; in vc3_pfd_round_rate()
317 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_set_rate()
323 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, in vc3_pfd_set_rate()
324 pfd->mdiv1_bitmsk); in vc3_pfd_set_rate()
325 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0); in vc3_pfd_set_rate()
330 /* We have dedicated div-2 predivider. */ in vc3_pfd_set_rate()
332 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, in vc3_pfd_set_rate()
333 pfd->mdiv2_bitmsk); in vc3_pfd_set_rate()
334 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0); in vc3_pfd_set_rate()
336 if (pfd->num == VC3_PFD1) in vc3_pfd_set_rate()
338 else if (pfd->num == VC3_PFD2) in vc3_pfd_set_rate()
343 regmap_write(vc3->regmap, pfd->offs, div); in vc3_pfd_set_rate()
359 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_recalc_rate()
363 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_recalc_rate()
365 regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val); in vc3_pll_recalc_rate()
368 if (pll->num == VC3_PLL2) { in vc3_pll_recalc_rate()
369 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val); in vc3_pll_recalc_rate()
371 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val); in vc3_pll_recalc_rate()
386 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_round_rate()
389 if (rate < pll->vco_min) in vc3_pll_round_rate()
390 rate = pll->vco_min; in vc3_pll_round_rate()
391 if (rate > pll->vco_max) in vc3_pll_round_rate()
392 rate = pll->vco_max; in vc3_pll_round_rate()
394 vc3->div_int = rate / *parent_rate; in vc3_pll_round_rate()
396 if (pll->num == VC3_PLL2) { in vc3_pll_round_rate()
397 if (vc3->div_int > 0x7ff) in vc3_pll_round_rate()
402 div_frc *= BIT(16) - 1; in vc3_pll_round_rate()
404 vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX); in vc3_pll_round_rate()
406 (vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16); in vc3_pll_round_rate()
408 rate = *parent_rate * vc3->div_int; in vc3_pll_round_rate()
418 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_set_rate()
421 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_set_rate()
422 val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7); in vc3_pll_set_rate()
423 regmap_write(vc3->regmap, pll->int_div_msb_offs, val); in vc3_pll_set_rate()
424 regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff); in vc3_pll_set_rate()
426 if (pll->num == VC3_PLL2) { in vc3_pll_set_rate()
427 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, in vc3_pll_set_rate()
428 vc3->div_frc >> 8); in vc3_pll_set_rate()
429 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, in vc3_pll_set_rate()
430 vc3->div_frc & 0xff); in vc3_pll_set_rate()
445 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_get_parent()
446 u32 src; in vc3_div_mux_get_parent() local
448 regmap_read(vc3->regmap, div_mux->offs, &src); in vc3_div_mux_get_parent()
450 return !!(src & div_mux->bitmsk); in vc3_div_mux_get_parent()
456 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_set_parent()
458 return regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk, in vc3_div_mux_set_parent()
459 index ? div_mux->bitmsk : 0); in vc3_div_mux_set_parent()
473 for (clkt = table; clkt->div; clkt++) in vc3_get_div()
474 if (clkt->val == val) in vc3_get_div()
475 return clkt->div; in vc3_get_div()
484 const struct vc3_div_data *div_data = vc3->data; in vc3_div_recalc_rate()
487 regmap_read(vc3->regmap, div_data->offs, &val); in vc3_div_recalc_rate()
488 val >>= div_data->shift; in vc3_div_recalc_rate()
489 val &= VC3_DIV_MASK(div_data->width); in vc3_div_recalc_rate()
491 return divider_recalc_rate(hw, parent_rate, val, div_data->table, in vc3_div_recalc_rate()
492 div_data->flags, div_data->width); in vc3_div_recalc_rate()
499 const struct vc3_div_data *div_data = vc3->data; in vc3_div_round_rate()
503 if (div_data->flags & CLK_DIVIDER_READ_ONLY) { in vc3_div_round_rate()
504 regmap_read(vc3->regmap, div_data->offs, &bestdiv); in vc3_div_round_rate()
505 bestdiv >>= div_data->shift; in vc3_div_round_rate()
506 bestdiv &= VC3_DIV_MASK(div_data->width); in vc3_div_round_rate()
507 bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags); in vc3_div_round_rate()
511 return divider_round_rate(hw, rate, parent_rate, div_data->table, in vc3_div_round_rate()
512 div_data->width, div_data->flags); in vc3_div_round_rate()
519 const struct vc3_div_data *div_data = vc3->data; in vc3_div_set_rate()
522 value = divider_get_val(rate, parent_rate, div_data->table, in vc3_div_set_rate()
523 div_data->width, div_data->flags); in vc3_div_set_rate()
524 return regmap_update_bits(vc3->regmap, div_data->offs, in vc3_div_set_rate()
525 VC3_DIV_MASK(div_data->width) << div_data->shift, in vc3_div_set_rate()
526 value << div_data->shift); in vc3_div_set_rate()
542 if (req->best_parent_rate >= req->rate) { in vc3_clk_mux_determine_rate()
543 frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate, in vc3_clk_mux_determine_rate()
544 req->rate); in vc3_clk_mux_determine_rate()
545 req->rate *= frc; in vc3_clk_mux_determine_rate()
557 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_get_parent()
560 regmap_read(vc3->regmap, clk_mux->offs, &val); in vc3_clk_mux_get_parent()
562 return !!(val & clk_mux->bitmsk); in vc3_clk_mux_get_parent()
568 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_set_parent()
570 return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk, in vc3_clk_mux_set_parent()
571 index ? clk_mux->bitmsk : 0); in vc3_clk_mux_set_parent()
970 unsigned int idx = clkspec->args[0]; in vc3_of_clk_get()
974 pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np); in vc3_of_clk_get()
975 return ERR_PTR(-EINVAL); in vc3_of_clk_get()
983 struct device *dev = &client->dev; in vc3_probe()
994 ret = of_property_read_u8_array(dev->of_node, "renesas,settings", in vc3_probe()
1008 } else if (ret == -EOVERFLOW) { in vc3_probe()
1009 dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n", in vc3_probe()
1020 clk_pfd_mux[i].hw.init->name); in vc3_probe()
1029 clk_pfd[i].hw.init->name); in vc3_probe()
1038 clk_pll[i].hw.init->name); in vc3_probe()
1047 clk_div_mux[i].hw.init->name); in vc3_probe()
1056 clk_div[i].hw.init->name); in vc3_probe()
1059 /* Register clk muxes */ in vc3_probe()
1065 clk_mux[i].hw.init->name); in vc3_probe()
1068 /* Register clk outputs */ in vc3_probe()
1087 name = "ref"; in vc3_probe()
1090 return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i); in vc3_probe()
1098 name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); in vc3_probe()
1106 return dev_err_probe(dev, ret, "unable to add clk provider\n"); in vc3_probe()