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()
292 static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate, in vc3_pfd_round_rate() argument
296 const struct vc3_pfd_data *pfd = vc3->data; in vc3_pfd_round_rate()
300 if (rate > 50000000) in vc3_pfd_round_rate()
301 return -EINVAL; in vc3_pfd_round_rate()
307 idiv = DIV_ROUND_UP(*parent_rate, rate); 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()
319 static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_pfd_set_rate() argument
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()
335 idiv = DIV_ROUND_UP(parent_rate, rate); 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()
367 unsigned long rate; in vc3_pll_recalc_rate() local
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()
379 rate = (parent_rate * in vc3_pll_recalc_rate()
382 rate = parent_rate * div_int; in vc3_pll_recalc_rate()
385 return rate; in vc3_pll_recalc_rate()
388 static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate, in vc3_pll_round_rate() argument
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()
404 rate = *parent_rate * 0x7ff; in vc3_pll_round_rate()
406 /* Determine best fractional part, which is 16 bit wide */ in vc3_pll_round_rate()
407 div_frc = rate % *parent_rate; 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()
411 rate = (*parent_rate * 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()
417 return rate; in vc3_pll_round_rate()
420 static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_pll_set_rate() argument
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()
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()
501 static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate, in vc3_div_round_rate() argument
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()
521 static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate, in vc3_div_set_rate() argument
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()
547 /* The below check is equivalent to (best_parent_rate/rate) */ in vc3_clk_mux_determine_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()
604 .bitmsk = BIT(VC3_PLL_OP_CTRL_PLL2_REFIN_SEL)
617 .bitmsk = BIT(VC3_GENERAL_CTR_PLL3_REFIN_SEL)
691 .max = VC3_PLL1_VCO_MAX
727 .max = VC3_PLL3_VCO_MAX
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()
1080 clk_data->bitmsk = data->se2_clk_sel_msk; in vc3_probe()
1085 clk_mux[i].hw.init->name); 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()
1132 .pll2_vco = { .min = 400000000UL, .max = 1200000000UL },
1133 .se2_clk_sel_msk = BIT(6),
1137 .pll2_vco = { .min = 30000000UL, .max = 130000000UL },
1138 .se2_clk_sel_msk = BIT(0),