Lines Matching +full:mac +full:- +full:divider
1 // SPDX-License-Identifier: GPL-2.0-or-later
7 #include <linux/clk-provider.h>
12 #include <dt-bindings/clock/lpc32xx-clock.h>
244 LPC32XX_CLK_DEFINE(MAC, "mac", 0x0, LPC32XX_CLK_HCLK),
253 * divider register does not contain information about selected rate.
393 regmap_read(clk_regmap, clk->reg, &val); in clk_mask_enable()
395 if (clk->busy_mask && (val & clk->busy_mask) == clk->busy) in clk_mask_enable()
396 return -EBUSY; in clk_mask_enable()
398 return regmap_update_bits(clk_regmap, clk->reg, in clk_mask_enable()
399 clk->enable_mask, clk->enable); in clk_mask_enable()
406 regmap_update_bits(clk_regmap, clk->reg, in clk_mask_disable()
407 clk->disable_mask, clk->disable); in clk_mask_disable()
415 regmap_read(clk_regmap, clk->reg, &val); in clk_mask_is_enabled()
417 return ((val & clk->enable_mask) == clk->enable); in clk_mask_is_enabled()
431 regmap_update_bits(clk_regmap, clk->reg, clk->enable, clk->enable); in clk_pll_enable()
434 regmap_read(clk_regmap, clk->reg, &val); in clk_pll_enable()
442 return -ETIMEDOUT; in clk_pll_enable()
449 regmap_update_bits(clk_regmap, clk->reg, clk->enable, 0x0); in clk_pll_disable()
457 regmap_read(clk_regmap, clk->reg, &val); in clk_pll_is_enabled()
459 val &= clk->enable | PLL_CTRL_LOCK; in clk_pll_is_enabled()
460 if (val == (clk->enable | PLL_CTRL_LOCK)) in clk_pll_is_enabled()
480 regmap_read(clk_regmap, clk->reg, &val); in clk_pll_recalc_rate()
485 clk->m_div = ((val & PLL_CTRL_FEEDDIV) >> 1) + 1; in clk_pll_recalc_rate()
486 clk->n_div = ((val & PLL_CTRL_PREDIV) >> 9) + 1; in clk_pll_recalc_rate()
487 clk->p_div = ((val & PLL_CTRL_POSTDIV) >> 11) + 1; in clk_pll_recalc_rate()
490 clk->p_div = 0; in clk_pll_recalc_rate()
491 clk->mode = PLL_DIRECT_BYPASS; in clk_pll_recalc_rate()
495 clk->mode = PLL_BYPASS; in clk_pll_recalc_rate()
496 return parent_rate / (1 << clk->p_div); in clk_pll_recalc_rate()
499 clk->p_div = 0; in clk_pll_recalc_rate()
500 clk->mode = PLL_DIRECT; in clk_pll_recalc_rate()
503 ref_rate = parent_rate / clk->n_div; in clk_pll_recalc_rate()
504 rate = cco_rate = ref_rate * clk->m_div; in clk_pll_recalc_rate()
508 cco_rate *= (1 << clk->p_div); in clk_pll_recalc_rate()
509 clk->mode = PLL_INTEGER; in clk_pll_recalc_rate()
511 rate /= (1 << clk->p_div); in clk_pll_recalc_rate()
512 clk->mode = PLL_NON_INTEGER; in clk_pll_recalc_rate()
519 clk->n_div, clk->m_div, (1 << clk->p_div), rate); in clk_pll_recalc_rate()
540 switch (clk->mode) { in clk_pll_set_rate()
543 val |= (clk->m_div - 1) << 1; in clk_pll_set_rate()
544 val |= (clk->n_div - 1) << 9; in clk_pll_set_rate()
545 new_rate = (parent_rate * clk->m_div) / clk->n_div; in clk_pll_set_rate()
549 val |= (clk->p_div - 1) << 11; in clk_pll_set_rate()
550 new_rate = parent_rate / (1 << (clk->p_div)); in clk_pll_set_rate()
558 val |= (clk->m_div - 1) << 1; in clk_pll_set_rate()
559 val |= (clk->n_div - 1) << 9; in clk_pll_set_rate()
560 val |= (clk->p_div - 1) << 11; in clk_pll_set_rate()
561 new_rate = (parent_rate * clk->m_div) / clk->n_div; in clk_pll_set_rate()
565 val |= (clk->m_div - 1) << 1; in clk_pll_set_rate()
566 val |= (clk->n_div - 1) << 9; in clk_pll_set_rate()
567 val |= (clk->p_div - 1) << 11; in clk_pll_set_rate()
568 new_rate = (parent_rate * clk->m_div) / in clk_pll_set_rate()
569 (clk->n_div * (1 << clk->p_div)); in clk_pll_set_rate()
572 return -EINVAL; in clk_pll_set_rate()
577 return -EINVAL; in clk_pll_set_rate()
579 return regmap_update_bits(clk_regmap, clk->reg, 0x1FFFF, val); in clk_pll_set_rate()
593 return -EINVAL; in clk_hclk_pll_round_rate()
596 for (p_i = 4; p_i >= 0; p_i--) { in clk_hclk_pll_round_rate()
597 for (n_i = 4; n_i > 0; n_i--) { in clk_hclk_pll_round_rate()
608 if (o * n_i * (1 << p_i) - i * m_i <= d) { in clk_hclk_pll_round_rate()
612 d = o * n_i * (1 << p_i) - i * m_i; in clk_hclk_pll_round_rate()
620 return -EINVAL; in clk_hclk_pll_round_rate()
623 clk->m_div = m; in clk_hclk_pll_round_rate()
624 clk->n_div = n; in clk_hclk_pll_round_rate()
625 clk->p_div = p; in clk_hclk_pll_round_rate()
627 /* Set only direct or non-integer mode of PLL */ in clk_hclk_pll_round_rate()
629 clk->mode = PLL_DIRECT; in clk_hclk_pll_round_rate()
631 clk->mode = PLL_NON_INTEGER; in clk_hclk_pll_round_rate()
639 pr_debug("%s: %lu: found closest: %llu/%llu/%llu - %llu\n", in clk_hclk_pll_round_rate()
657 * and post-divider must be 4, this slightly simplifies calculation of in clk_usb_pll_round_rate()
658 * USB divider, USB PLL N and M parameters. in clk_usb_pll_round_rate()
661 return -EINVAL; in clk_usb_pll_round_rate()
663 /* USB divider clock */ in clk_usb_pll_round_rate()
666 return -EINVAL; in clk_usb_pll_round_rate()
671 return -EINVAL; in clk_usb_pll_round_rate()
674 /* Check if valid USB divider and USB PLL parameters exists */ in clk_usb_pll_round_rate()
675 for (d_i = 16; d_i >= 1; d_i--) { in clk_usb_pll_round_rate()
684 clk->n_div = n_i; in clk_usb_pll_round_rate()
685 clk->m_div = m; in clk_usb_pll_round_rate()
686 clk->p_div = 2; in clk_usb_pll_round_rate()
687 clk->mode = PLL_NON_INTEGER; in clk_usb_pll_round_rate()
694 return -EINVAL; in clk_usb_pll_round_rate()
718 regmap_read(clk_regmap, clk->reg, &val); in clk_ddram_is_enabled()
719 val &= clk->enable_mask | clk->busy_mask; in clk_ddram_is_enabled()
730 regmap_read(clk_regmap, clk->reg, &val); in clk_ddram_enable()
731 hclk_div = val & clk->busy_mask; in clk_ddram_enable()
739 return -EINVAL; in clk_ddram_enable()
741 return regmap_update_bits(clk_regmap, clk->reg, in clk_ddram_enable()
742 clk->enable_mask, hclk_div << 7); in clk_ddram_enable()
754 regmap_read(clk_regmap, clk->reg, &val); in clk_ddram_recalc_rate()
755 val &= clk->enable_mask; in clk_ddram_recalc_rate()
773 regmap_read(clk_regmap, clk->reg, &val); in lpc32xx_clk_uart_recalc_rate()
802 pr_debug("%s: 0x%x\n", clk_hw_get_name(hw), clk->enable); in clk_usb_enable()
804 if (clk->ctrl_mask) { in clk_usb_enable()
807 clk->ctrl_mask, clk->ctrl_enable); in clk_usb_enable()
811 if (clk->busy && (val & clk->busy) == clk->busy) { in clk_usb_enable()
812 if (clk->ctrl_mask) in clk_usb_enable()
815 return -EBUSY; in clk_usb_enable()
818 val |= clk->enable; in clk_usb_enable()
823 if ((val & clk->enable) == clk->enable) in clk_usb_enable()
827 if ((val & clk->enable) == clk->enable) in clk_usb_enable()
830 if (clk->ctrl_mask) in clk_usb_enable()
833 return -ETIMEDOUT; in clk_usb_enable()
841 val &= ~clk->enable; in clk_usb_disable()
844 if (clk->ctrl_mask) in clk_usb_disable()
846 clk->ctrl_mask, clk->ctrl_disable); in clk_usb_disable()
854 if (clk->ctrl_mask) { in clk_usb_is_enabled()
856 if ((ctrl_val & clk->ctrl_mask) != clk->ctrl_enable) in clk_usb_is_enabled()
862 return ((val & clk->enable) == clk->enable); in clk_usb_is_enabled()
887 u32 mask = BIT(clk->bit_idx); in lpc32xx_clk_gate_enable()
888 u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? 0x0 : mask); in lpc32xx_clk_gate_enable()
890 return regmap_update_bits(clk_regmap, clk->reg, mask, val); in lpc32xx_clk_gate_enable()
896 u32 mask = BIT(clk->bit_idx); in lpc32xx_clk_gate_disable()
897 u32 val = (clk->flags & CLK_GATE_SET_TO_DISABLE ? mask : 0x0); in lpc32xx_clk_gate_disable()
899 regmap_update_bits(clk_regmap, clk->reg, mask, val); in lpc32xx_clk_gate_disable()
908 regmap_read(clk_regmap, clk->reg, &val); in lpc32xx_clk_gate_is_enabled()
909 is_set = val & BIT(clk->bit_idx); in lpc32xx_clk_gate_is_enabled()
911 return (clk->flags & CLK_GATE_SET_TO_DISABLE ? !is_set : is_set); in lpc32xx_clk_gate_is_enabled()
920 #define div_mask(width) ((1 << (width)) - 1)
927 for (clkt = table; clkt->div; clkt++) in _get_table_div()
928 if (clkt->val == val) in _get_table_div()
929 return clkt->div; in _get_table_div()
946 struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); in clk_divider_recalc_rate() local
949 regmap_read(clk_regmap, divider->reg, &val); in clk_divider_recalc_rate()
951 val >>= divider->shift; in clk_divider_recalc_rate()
952 val &= div_mask(divider->width); in clk_divider_recalc_rate()
954 return divider_recalc_rate(hw, parent_rate, val, divider->table, in clk_divider_recalc_rate()
955 divider->flags, divider->width); in clk_divider_recalc_rate()
961 struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); in clk_divider_round_rate() local
965 if (divider->flags & CLK_DIVIDER_READ_ONLY) { in clk_divider_round_rate()
966 regmap_read(clk_regmap, divider->reg, &bestdiv); in clk_divider_round_rate()
967 bestdiv >>= divider->shift; in clk_divider_round_rate()
968 bestdiv &= div_mask(divider->width); in clk_divider_round_rate()
969 bestdiv = _get_div(divider->table, bestdiv, divider->flags, in clk_divider_round_rate()
970 divider->width); in clk_divider_round_rate()
974 return divider_round_rate(hw, rate, prate, divider->table, in clk_divider_round_rate()
975 divider->width, divider->flags); in clk_divider_round_rate()
981 struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw); in clk_divider_set_rate() local
984 value = divider_get_val(rate, parent_rate, divider->table, in clk_divider_set_rate()
985 divider->width, divider->flags); in clk_divider_set_rate()
987 return regmap_update_bits(clk_regmap, divider->reg, in clk_divider_set_rate()
988 div_mask(divider->width) << divider->shift, in clk_divider_set_rate()
989 value << divider->shift); in clk_divider_set_rate()
1004 regmap_read(clk_regmap, mux->reg, &val); in clk_mux_get_parent()
1005 val >>= mux->shift; in clk_mux_get_parent()
1006 val &= mux->mask; in clk_mux_get_parent()
1008 if (mux->table) { in clk_mux_get_parent()
1012 if (mux->table[i] == val) in clk_mux_get_parent()
1014 return -EINVAL; in clk_mux_get_parent()
1018 return -EINVAL; in clk_mux_get_parent()
1027 if (mux->table) in clk_mux_set_parent()
1028 index = mux->table[index]; in clk_mux_set_parent()
1030 return regmap_update_bits(clk_regmap, mux->reg, in clk_mux_set_parent()
1031 mux->mask << mux->shift, index << mux->shift); in clk_mux_set_parent()
1234 /* Register 3 read-only muxes with a single control PWR_CTRL[2] */
1241 /* Register 2 read-only muxes with a single control PWR_CTRL[10] */
1342 LPC32XX_DEFINE_CLK(MAC, MACCLK_CTRL,
1357 * rtc-->[gate]-->| |
1358 * | mux |--> adc/ts
1359 * pclk-->[div]-->| |
1362 * ADC --- resulting clock must be <= 4.5 MHz
1363 * TS --- resulting clock must be <= 400 KHz
1390 for (i = 0; i < lpc32xx_clk->num_parents; i++) in lpc32xx_clk_register()
1391 parents[i] = clk_proto[lpc32xx_clk->parents[i]].name; in lpc32xx_clk_register()
1393 pr_debug("%s: derived from '%s', clock type %d\n", lpc32xx_clk->name, in lpc32xx_clk_register()
1394 parents[0], clk_hw->type); in lpc32xx_clk_register()
1396 switch (clk_hw->type) { in lpc32xx_clk_register()
1405 .name = lpc32xx_clk->name, in lpc32xx_clk_register()
1407 .num_parents = lpc32xx_clk->num_parents, in lpc32xx_clk_register()
1408 .flags = lpc32xx_clk->flags, in lpc32xx_clk_register()
1409 .ops = clk_hw->hw0.ops, in lpc32xx_clk_register()
1413 if (clk_hw->type == CLK_LPC32XX) in lpc32xx_clk_register()
1414 hw = &clk_hw->hw0.clk.hw; in lpc32xx_clk_register()
1415 else if (clk_hw->type == CLK_LPC32XX_PLL) in lpc32xx_clk_register()
1416 hw = &clk_hw->hw0.pll.hw; in lpc32xx_clk_register()
1417 else if (clk_hw->type == CLK_LPC32XX_USB) in lpc32xx_clk_register()
1418 hw = &clk_hw->hw0.usb_clk.hw; in lpc32xx_clk_register()
1419 else if (clk_hw->type == CLK_MUX) in lpc32xx_clk_register()
1420 hw = &clk_hw->hw0.mux.hw; in lpc32xx_clk_register()
1421 else if (clk_hw->type == CLK_DIV) in lpc32xx_clk_register()
1422 hw = &clk_hw->hw0.div.hw; in lpc32xx_clk_register()
1423 else if (clk_hw->type == CLK_GATE) in lpc32xx_clk_register()
1424 hw = &clk_hw->hw0.gate.hw; in lpc32xx_clk_register()
1426 return ERR_PTR(-EINVAL); in lpc32xx_clk_register()
1428 hw->init = &clk_init; in lpc32xx_clk_register()
1438 mux0 = clk_hw->hw1.mux; in lpc32xx_clk_register()
1439 div0 = clk_hw->hw1.div; in lpc32xx_clk_register()
1440 gate0 = clk_hw->hw1.gate; in lpc32xx_clk_register()
1442 mops = mux0->ops; in lpc32xx_clk_register()
1443 mux_hw = &mux0->clk.hw; in lpc32xx_clk_register()
1446 dops = div0->ops; in lpc32xx_clk_register()
1447 div_hw = &div0->clk.hw; in lpc32xx_clk_register()
1450 gops = gate0->ops; in lpc32xx_clk_register()
1451 gate_hw = &gate0->clk.hw; in lpc32xx_clk_register()
1454 clk = clk_register_composite(NULL, lpc32xx_clk->name, in lpc32xx_clk_register()
1455 parents, lpc32xx_clk->num_parents, in lpc32xx_clk_register()
1457 gate_hw, gops, lpc32xx_clk->flags); in lpc32xx_clk_register()
1462 struct clk_fixed_rate *fixed = &clk_hw->f; in lpc32xx_clk_register()
1464 clk = clk_register_fixed_rate(NULL, lpc32xx_clk->name, in lpc32xx_clk_register()
1465 parents[0], 0, fixed->fixed_rate); in lpc32xx_clk_register()
1469 clk = ERR_PTR(-EINVAL); in lpc32xx_clk_register()
1529 * Divider part of PWM and MS clocks requires a quirk to avoid in lpc32xx_clk_init()
1533 * divider clock is never met in runtime. in lpc32xx_clk_init()
1564 CLK_OF_DECLARE(lpc32xx_clk, "nxp,lpc3220-clk", lpc32xx_clk_init);
1587 CLK_OF_DECLARE(lpc32xx_usb_clk, "nxp,lpc3220-usb-clk", lpc32xx_usb_clk_init);