Lines Matching +full:max +full:- +full:bit +full:- +full:rate
1 // SPDX-License-Identifier: GPL-2.0+
8 #include <linux/clk-provider.h>
17 #define VC3_GENERAL_CTR_DIV1_SRC_SEL BIT(3)
18 #define VC3_GENERAL_CTR_PLL3_REFIN_SEL BIT(2)
21 #define VC3_PLL3_M_DIV1 BIT(7)
22 #define VC3_PLL3_M_DIV2 BIT(6)
29 #define VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL BIT(7)
32 #define VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER BIT(7)
35 #define VC3_PLL1_M_DIV1 BIT(7)
36 #define VC3_PLL1_M_DIV2 BIT(6)
50 #define VC3_PLL2_MDIV_DOUBLER BIT(7)
51 #define VC3_PLL2_M_DIV1 BIT(6)
52 #define VC3_PLL2_M_DIV2 BIT(5)
61 #define VC3_OUTPUT_CTR_DIV4_SRC_SEL BIT(3)
64 #define VC3_SE2_CTRL_REG0_SE2_CLK_SEL BIT(6)
67 #define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL BIT(6)
70 #define VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL BIT(7)
73 #define VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL BIT(7)
76 #define VC3_SE1_DIV4_CTRL_SE1_CLK_SEL BIT(3)
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,
149 unsigned long max; member
222 const struct vc3_clk_data *pfd_mux = vc3->data; in vc3_pfd_mux_get_parent()
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()
251 unsigned long rate; in vc3_pfd_recalc_rate() local
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()
285 rate = parent_rate / 2; in vc3_pfd_recalc_rate()
287 rate = parent_rate / mdiv; in vc3_pfd_recalc_rate()
289 return rate; in vc3_pfd_recalc_rate()
296 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_determine_rate()
300 if (req->rate > 50000000) in vc3_pfd_determine_rate()
301 return -EINVAL; in vc3_pfd_determine_rate()
304 if (req->best_parent_rate <= 50000000) { in vc3_pfd_determine_rate()
305 req->rate = req->best_parent_rate; in vc3_pfd_determine_rate()
310 idiv = DIV_ROUND_UP(req->best_parent_rate, req->rate); in vc3_pfd_determine_rate()
311 if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) { in vc3_pfd_determine_rate()
313 return -EINVAL; in vc3_pfd_determine_rate()
316 return -EINVAL; in vc3_pfd_determine_rate()
319 req->rate = req->best_parent_rate / idiv; in vc3_pfd_determine_rate()
324 static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_pfd_set_rate() argument
328 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_set_rate()
334 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, in vc3_pfd_set_rate()
335 pfd->mdiv1_bitmsk); in vc3_pfd_set_rate()
336 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0); in vc3_pfd_set_rate()
340 idiv = DIV_ROUND_UP(parent_rate, rate); in vc3_pfd_set_rate()
341 /* We have dedicated div-2 predivider. */ in vc3_pfd_set_rate()
343 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, in vc3_pfd_set_rate()
344 pfd->mdiv2_bitmsk); in vc3_pfd_set_rate()
345 regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0); in vc3_pfd_set_rate()
347 if (pfd->num == VC3_PFD1) in vc3_pfd_set_rate()
349 else if (pfd->num == VC3_PFD2) in vc3_pfd_set_rate()
354 regmap_write(vc3->regmap, pfd->offs, div); in vc3_pfd_set_rate()
370 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_recalc_rate()
372 unsigned long rate; in vc3_pll_recalc_rate() local
374 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_recalc_rate()
376 regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val); in vc3_pll_recalc_rate()
379 if (pll->num == VC3_PLL2) { in vc3_pll_recalc_rate()
380 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val); in vc3_pll_recalc_rate()
382 regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val); in vc3_pll_recalc_rate()
384 rate = (parent_rate * in vc3_pll_recalc_rate()
387 rate = parent_rate * div_int; in vc3_pll_recalc_rate()
390 return rate; in vc3_pll_recalc_rate()
397 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_determine_rate()
400 if (req->rate < pll->vco.min) in vc3_pll_determine_rate()
401 req->rate = pll->vco.min; in vc3_pll_determine_rate()
402 if (req->rate > pll->vco.max) in vc3_pll_determine_rate()
403 req->rate = pll->vco.max; in vc3_pll_determine_rate()
405 vc3->div_int = req->rate / req->best_parent_rate; in vc3_pll_determine_rate()
407 if (pll->num == VC3_PLL2) { in vc3_pll_determine_rate()
408 if (vc3->div_int > 0x7ff) in vc3_pll_determine_rate()
409 req->rate = req->best_parent_rate * 0x7ff; in vc3_pll_determine_rate()
411 /* Determine best fractional part, which is 16 bit wide */ in vc3_pll_determine_rate()
412 div_frc = req->rate % req->best_parent_rate; in vc3_pll_determine_rate()
413 div_frc *= BIT(16) - 1; in vc3_pll_determine_rate()
415 vc3->div_frc = min_t(u64, in vc3_pll_determine_rate()
416 div64_ul(div_frc, req->best_parent_rate), in vc3_pll_determine_rate()
418 req->rate = (req->best_parent_rate * in vc3_pll_determine_rate()
419 (vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16); in vc3_pll_determine_rate()
421 req->rate = req->best_parent_rate * vc3->div_int; in vc3_pll_determine_rate()
427 static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_pll_set_rate() argument
431 const struct vc3_pll_data *pll = vc3->data; in vc3_pll_set_rate()
434 regmap_read(vc3->regmap, pll->int_div_msb_offs, &val); in vc3_pll_set_rate()
435 val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7); in vc3_pll_set_rate()
436 regmap_write(vc3->regmap, pll->int_div_msb_offs, val); in vc3_pll_set_rate()
437 regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff); in vc3_pll_set_rate()
439 if (pll->num == VC3_PLL2) { in vc3_pll_set_rate()
440 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, in vc3_pll_set_rate()
441 vc3->div_frc >> 8); in vc3_pll_set_rate()
442 regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, in vc3_pll_set_rate()
443 vc3->div_frc & 0xff); in vc3_pll_set_rate()
458 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_get_parent()
461 regmap_read(vc3->regmap, div_mux->offs, &src); in vc3_div_mux_get_parent()
463 return !!(src & div_mux->bitmsk); in vc3_div_mux_get_parent()
469 const struct vc3_clk_data *div_mux = vc3->data; in vc3_div_mux_set_parent()
471 return regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk, in vc3_div_mux_set_parent()
472 index ? div_mux->bitmsk : 0); in vc3_div_mux_set_parent()
486 for (clkt = table; clkt->div; clkt++) in vc3_get_div()
487 if (clkt->val == val) in vc3_get_div()
488 return clkt->div; in vc3_get_div()
497 const struct vc3_div_data *div_data = vc3->data; in vc3_div_recalc_rate()
500 regmap_read(vc3->regmap, div_data->offs, &val); in vc3_div_recalc_rate()
501 val >>= div_data->shift; in vc3_div_recalc_rate()
502 val &= VC3_DIV_MASK(div_data->width); in vc3_div_recalc_rate()
504 return divider_recalc_rate(hw, parent_rate, val, div_data->table, in vc3_div_recalc_rate()
505 div_data->flags, div_data->width); in vc3_div_recalc_rate()
512 const struct vc3_div_data *div_data = vc3->data; in vc3_div_determine_rate()
516 if (div_data->flags & CLK_DIVIDER_READ_ONLY) { in vc3_div_determine_rate()
517 regmap_read(vc3->regmap, div_data->offs, &bestdiv); in vc3_div_determine_rate()
518 bestdiv >>= div_data->shift; in vc3_div_determine_rate()
519 bestdiv &= VC3_DIV_MASK(div_data->width); in vc3_div_determine_rate()
520 bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags); in vc3_div_determine_rate()
521 req->rate = DIV_ROUND_UP(req->best_parent_rate, bestdiv); in vc3_div_determine_rate()
526 req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, in vc3_div_determine_rate()
527 div_data->table, in vc3_div_determine_rate()
528 div_data->width, div_data->flags); in vc3_div_determine_rate()
533 static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_div_set_rate() argument
537 const struct vc3_div_data *div_data = vc3->data; in vc3_div_set_rate()
540 value = divider_get_val(rate, parent_rate, div_data->table, in vc3_div_set_rate()
541 div_data->width, div_data->flags); in vc3_div_set_rate()
542 return regmap_update_bits(vc3->regmap, div_data->offs, in vc3_div_set_rate()
543 VC3_DIV_MASK(div_data->width) << div_data->shift, in vc3_div_set_rate()
544 value << div_data->shift); in vc3_div_set_rate()
559 /* The below check is equivalent to (best_parent_rate/rate) */ in vc3_clk_mux_determine_rate()
560 if (req->best_parent_rate >= req->rate) { in vc3_clk_mux_determine_rate()
561 frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate, in vc3_clk_mux_determine_rate()
562 req->rate); in vc3_clk_mux_determine_rate()
563 req->rate *= frc; in vc3_clk_mux_determine_rate()
575 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_get_parent()
578 regmap_read(vc3->regmap, clk_mux->offs, &val); in vc3_clk_mux_get_parent()
580 return !!(val & clk_mux->bitmsk); in vc3_clk_mux_get_parent()
586 const struct vc3_clk_data *clk_mux = vc3->data; in vc3_clk_mux_set_parent()
588 return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk, in vc3_clk_mux_set_parent()
589 index ? clk_mux->bitmsk : 0); in vc3_clk_mux_set_parent()
616 .bitmsk = BIT(VC3_PLL_OP_CTRL_PLL2_REFIN_SEL)
629 .bitmsk = BIT(VC3_GENERAL_CTR_PLL3_REFIN_SEL)
703 .max = VC3_PLL1_VCO_MAX
739 .max = VC3_PLL3_VCO_MAX
989 unsigned int idx = clkspec->args[0]; in vc3_of_clk_get()
993 pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np); in vc3_of_clk_get()
994 return ERR_PTR(-EINVAL); in vc3_of_clk_get()
1002 struct device *dev = &client->dev; in vc3_probe()
1014 ret = of_property_read_u8_array(dev->of_node, "renesas,settings", in vc3_probe()
1028 } else if (ret == -EOVERFLOW) { in vc3_probe()
1029 dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n", in vc3_probe()
1040 clk_pfd_mux[i].hw.init->name); in vc3_probe()
1049 clk_pfd[i].hw.init->name); in vc3_probe()
1060 pll_data->vco = data->pll2_vco; in vc3_probe()
1065 clk_pll[i].hw.init->name); in vc3_probe()
1074 clk_div_mux[i].hw.init->name); in vc3_probe()
1083 clk_div[i].hw.init->name); in vc3_probe()
1092 clk_data->bitmsk = data->se2_clk_sel_msk; in vc3_probe()
1097 clk_mux[i].hw.init->name); in vc3_probe()
1122 return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i); in vc3_probe()
1130 name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); in vc3_probe()
1144 .pll2_vco = { .min = 400000000UL, .max = 1200000000UL },
1145 .se2_clk_sel_msk = BIT(6),
1149 .pll2_vco = { .min = 30000000UL, .max = 130000000UL },
1150 .se2_clk_sel_msk = BIT(0),