Lines Matching +full:clk +full:- +full:div

1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <linux/clk-provider.h>
12 #include <asm/mach-pic32/pic32.h>
15 #include "clk-core.h"
78 /* add instruction pipeline delay while CPU clock is in-transition. */
101 return readl(pb->ctrl_reg) & PB_DIV_ENABLE; in pbclk_is_enabled()
108 writel(PB_DIV_ENABLE, PIC32_SET(pb->ctrl_reg)); in pbclk_enable()
116 writel(PB_DIV_ENABLE, PIC32_CLR(pb->ctrl_reg)); in pbclk_disable()
125 unsigned long div, div_up; in calc_best_divided_rate() local
131 div = parent_rate / rate; in calc_best_divided_rate()
132 div = clamp_val(div, divider_min, divider_max); in calc_best_divided_rate()
133 div_up = clamp_val(div + 1, divider_min, divider_max); in calc_best_divided_rate()
135 divided_rate = parent_rate / div; in calc_best_divided_rate()
137 if (abs(rate - divided_rate_down) < abs(rate - divided_rate)) in calc_best_divided_rate()
147 return ((readl(pb->ctrl_reg) >> PB_DIV_SHIFT) & PB_DIV_MASK) + 1; in pbclk_read_pbdiv()
170 u32 v, div; in pbclk_set_rate() local
174 err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY, in pbclk_set_rate()
180 div = DIV_ROUND_CLOSEST(parent_rate, rate); in pbclk_set_rate()
182 spin_lock_irqsave(&pb->core->reg_lock, flags); in pbclk_set_rate()
184 /* apply new div */ in pbclk_set_rate()
185 v = readl(pb->ctrl_reg); in pbclk_set_rate()
187 v |= (div - 1); in pbclk_set_rate()
191 writel(v, pb->ctrl_reg); in pbclk_set_rate()
193 spin_unlock_irqrestore(&pb->core->reg_lock, flags); in pbclk_set_rate()
196 err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY, in pbclk_set_rate()
201 /* confirm that new div is applied correctly */ in pbclk_set_rate()
202 return (pbclk_read_pbdiv(pb) == div) ? 0 : -EBUSY; in pbclk_set_rate()
214 struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *desc, in pic32_periph_clk_register()
218 struct clk *clk; in pic32_periph_clk_register() local
220 pbclk = devm_kzalloc(core->dev, sizeof(*pbclk), GFP_KERNEL); in pic32_periph_clk_register()
222 return ERR_PTR(-ENOMEM); in pic32_periph_clk_register()
224 pbclk->hw.init = &desc->init_data; in pic32_periph_clk_register()
225 pbclk->core = core; in pic32_periph_clk_register()
226 pbclk->ctrl_reg = desc->ctrl_reg + core->iobase; in pic32_periph_clk_register()
228 clk = devm_clk_register(core->dev, &pbclk->hw); in pic32_periph_clk_register()
229 if (IS_ERR(clk)) { in pic32_periph_clk_register()
230 dev_err(core->dev, "%s: clk_register() failed\n", __func__); in pic32_periph_clk_register()
231 devm_kfree(core->dev, pbclk); in pic32_periph_clk_register()
234 return clk; in pic32_periph_clk_register()
251 return readl(refo->ctrl_reg) & REFO_ON; in roclk_is_enabled()
258 writel(REFO_ON | REFO_OE, PIC32_SET(refo->ctrl_reg)); in roclk_enable()
266 writel(REFO_ON | REFO_OE, PIC32_CLR(refo->ctrl_reg)); in roclk_disable()
282 v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK; in roclk_get_parent()
284 if (!refo->parent_map) in roclk_get_parent()
288 if (refo->parent_map[i] == v) in roclk_get_parent()
291 return -EINVAL; in roclk_get_parent()
299 /* fout = fin / [2 * {div + (trim / 512)}] in roclk_calc_rate()
300 * = fin * 512 / [1024 * div + 2 * trim] in roclk_calc_rate()
301 * = fin * 256 / (512 * div + trim) in roclk_calc_rate()
302 * = (fin << 8) / ((div << 9) + trim) in roclk_calc_rate()
321 u32 div, rotrim, rodiv; in roclk_calc_div_trim() local
324 /* Find integer approximation of floating-point arithmetic. in roclk_calc_div_trim()
326 * i.e. fout = fin / 2 * DIV in roclk_calc_div_trim()
327 * whereas DIV = rodiv + (rotrim / 512) in roclk_calc_div_trim()
329 * Since kernel does not perform floating-point arithmatic so in roclk_calc_div_trim()
330 * (rotrim/512) will be zero. And DIV & rodiv will result same. in roclk_calc_div_trim()
333 * ie. rotrim = ((fin * 256) / fout) - (512 * DIV) in roclk_calc_div_trim()
336 div = 0; in roclk_calc_div_trim()
341 div = parent_rate / (rate << 1); in roclk_calc_div_trim()
345 frac -= (u64)(div << 9); in roclk_calc_div_trim()
347 rodiv = (div > REFO_DIV_MASK) ? REFO_DIV_MASK : div; in roclk_calc_div_trim()
365 v = readl(refo->ctrl_reg); in roclk_recalc_rate()
369 v = readl(refo->ctrl_reg + REFO_TRIM_REG); in roclk_recalc_rate()
391 unsigned int i, delta, best_delta = -1; in roclk_determine_rate()
404 if (req->rate > parent_rate) in roclk_determine_rate()
407 nearest_rate = roclk_round_rate(hw, req->rate, &parent_rate); in roclk_determine_rate()
408 delta = abs(nearest_rate - req->rate); in roclk_determine_rate()
409 if ((nearest_rate >= req->rate) && (delta < best_delta)) { in roclk_determine_rate()
423 __func__, clk_hw_get_name(hw), req->rate); in roclk_determine_rate()
428 clk_hw_get_name(hw), req->rate, in roclk_determine_rate()
432 if (req->best_parent_rate) in roclk_determine_rate()
433 req->best_parent_rate = best_parent_rate; in roclk_determine_rate()
435 if (req->best_parent_hw) in roclk_determine_rate()
436 req->best_parent_hw = best_parent_clk; in roclk_determine_rate()
448 if (refo->parent_map) in roclk_set_parent()
449 index = refo->parent_map[index]; in roclk_set_parent()
452 err = readl_poll_timeout(refo->ctrl_reg, v, !(v & REFO_ACTIVE), in roclk_set_parent()
455 pr_err("%s: poll failed, clk active\n", clk_hw_get_name(hw)); in roclk_set_parent()
459 spin_lock_irqsave(&refo->core->reg_lock, flags); in roclk_set_parent()
464 v = readl(refo->ctrl_reg); in roclk_set_parent()
468 writel(v, refo->ctrl_reg); in roclk_set_parent()
470 spin_unlock_irqrestore(&refo->core->reg_lock, flags); in roclk_set_parent()
488 pr_debug("parent_rate = %lu, rate = %lu, div = %d, trim = %d\n", in roclk_set_rate_and_parent()
492 err = readl_poll_timeout(refo->ctrl_reg, v, in roclk_set_rate_and_parent()
500 spin_lock_irqsave(&refo->core->reg_lock, flags); in roclk_set_rate_and_parent()
501 v = readl(refo->ctrl_reg); in roclk_set_rate_and_parent()
506 if (refo->parent_map) in roclk_set_rate_and_parent()
507 index = refo->parent_map[index]; in roclk_set_rate_and_parent()
515 writel(v, refo->ctrl_reg); in roclk_set_rate_and_parent()
518 v = readl(refo->ctrl_reg + REFO_TRIM_REG); in roclk_set_rate_and_parent()
521 writel(v, refo->ctrl_reg + REFO_TRIM_REG); in roclk_set_rate_and_parent()
524 writel(REFO_ON | REFO_DIVSW_EN, PIC32_SET(refo->ctrl_reg)); in roclk_set_rate_and_parent()
526 /* wait till divswen is in-progress */ in roclk_set_rate_and_parent()
527 err = readl_poll_timeout_atomic(refo->ctrl_reg, v, !(v & REFO_DIVSW_EN), in roclk_set_rate_and_parent()
529 /* leave the clk gated as it was */ in roclk_set_rate_and_parent()
530 writel(REFO_ON, PIC32_CLR(refo->ctrl_reg)); in roclk_set_rate_and_parent()
532 spin_unlock_irqrestore(&refo->core->reg_lock, flags); in roclk_set_rate_and_parent()
558 struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data, in pic32_refo_clk_register()
562 struct clk *clk; in pic32_refo_clk_register() local
564 refo = devm_kzalloc(core->dev, sizeof(*refo), GFP_KERNEL); in pic32_refo_clk_register()
566 return ERR_PTR(-ENOMEM); in pic32_refo_clk_register()
568 refo->core = core; in pic32_refo_clk_register()
569 refo->hw.init = &data->init_data; in pic32_refo_clk_register()
570 refo->ctrl_reg = data->ctrl_reg + core->iobase; in pic32_refo_clk_register()
571 refo->parent_map = data->parent_map; in pic32_refo_clk_register()
573 clk = devm_clk_register(core->dev, &refo->hw); in pic32_refo_clk_register()
574 if (IS_ERR(clk)) in pic32_refo_clk_register()
575 dev_err(core->dev, "%s: clk_register() failed\n", __func__); in pic32_refo_clk_register()
577 return clk; in pic32_refo_clk_register()
603 u32 mul, div, best_mul = 1, best_div = 1; in spll_calc_mult_div() local
605 unsigned int best_delta = -1, delta, match_found = 0; in spll_calc_mult_div()
608 parent_rate /= pll->idiv; in spll_calc_mult_div()
611 for (div = PLL_ODIV_MIN; div <= PLL_ODIV_MAX; div++) { in spll_calc_mult_div()
614 do_div(rate64, 1 << div); in spll_calc_mult_div()
616 delta = abs(rate - new_rate); in spll_calc_mult_div()
621 best_div = div; in spll_calc_mult_div()
632 pr_debug("rate %lu, par_rate %lu/mult %u, div %u, best_rate %lu\n", in spll_calc_mult_div()
636 *mult_p = best_mul - 1; in spll_calc_mult_div()
649 u32 mult, odiv, div, v; in spll_clk_recalc_rate() local
652 v = readl(pll->ctrl_reg); in spll_clk_recalc_rate()
655 div = spll_odiv_to_divider(odiv); in spll_clk_recalc_rate()
658 * pll_out_rate = pll_in_rate * mult / div; in spll_clk_recalc_rate()
660 pll_in_rate = parent_rate / pll->idiv; in spll_clk_recalc_rate()
663 do_div(rate64, div); in spll_clk_recalc_rate()
686 return -EINVAL; in spll_clk_set_rate()
689 * We can't change SPLL counters when it is in-active use in spll_clk_set_rate()
695 pr_err("%s: failed, clk in-use\n", __func__); in spll_clk_set_rate()
696 return -EBUSY; in spll_clk_set_rate()
699 spin_lock_irqsave(&pll->core->reg_lock, flags); in spll_clk_set_rate()
702 v = readl(pll->ctrl_reg); in spll_clk_set_rate()
710 writel(v, pll->ctrl_reg); in spll_clk_set_rate()
713 /* insert few nops (5-stage) to ensure CPU does not hang */ in spll_clk_set_rate()
718 err = readl_poll_timeout_atomic(pll->status_reg, v, in spll_clk_set_rate()
719 v & pll->lock_mask, 1, 100); in spll_clk_set_rate()
720 spin_unlock_irqrestore(&pll->core->reg_lock, flags); in spll_clk_set_rate()
732 struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data, in pic32_spll_clk_register()
736 struct clk *clk; in pic32_spll_clk_register() local
738 spll = devm_kzalloc(core->dev, sizeof(*spll), GFP_KERNEL); in pic32_spll_clk_register()
740 return ERR_PTR(-ENOMEM); in pic32_spll_clk_register()
742 spll->core = core; in pic32_spll_clk_register()
743 spll->hw.init = &data->init_data; in pic32_spll_clk_register()
744 spll->ctrl_reg = data->ctrl_reg + core->iobase; in pic32_spll_clk_register()
745 spll->status_reg = data->status_reg + core->iobase; in pic32_spll_clk_register()
746 spll->lock_mask = data->lock_mask; in pic32_spll_clk_register()
749 spll->idiv = (readl(spll->ctrl_reg) >> PLL_IDIV_SHIFT) & PLL_IDIV_MASK; in pic32_spll_clk_register()
750 spll->idiv += 1; in pic32_spll_clk_register()
752 clk = devm_clk_register(core->dev, &spll->hw); in pic32_spll_clk_register()
753 if (IS_ERR(clk)) in pic32_spll_clk_register()
754 dev_err(core->dev, "sys_pll: clk_register() failed\n"); in pic32_spll_clk_register()
756 return clk; in pic32_spll_clk_register()
775 u32 div; in sclk_get_rate() local
777 div = (readl(sclk->slew_reg) >> SLEW_SYSDIV_SHIFT) & SLEW_SYSDIV; in sclk_get_rate()
778 div += 1; /* sys-div to divider */ in sclk_get_rate()
780 return parent_rate / div; in sclk_get_rate()
794 u32 v, div; in sclk_set_rate() local
797 div = parent_rate / rate; in sclk_set_rate()
799 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_set_rate()
801 /* apply new div */ in sclk_set_rate()
802 v = readl(sclk->slew_reg); in sclk_set_rate()
804 v |= (div - 1) << SLEW_SYSDIV_SHIFT; in sclk_set_rate()
808 writel(v, sclk->slew_reg); in sclk_set_rate()
811 err = readl_poll_timeout_atomic(sclk->slew_reg, v, in sclk_set_rate()
814 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_set_rate()
824 v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; in sclk_get_parent()
826 if (!sclk->parent_map) in sclk_get_parent()
830 if (sclk->parent_map[i] == v) in sclk_get_parent()
832 return -EINVAL; in sclk_get_parent()
842 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_set_parent()
845 nosc = sclk->parent_map ? sclk->parent_map[index] : index; in sclk_set_parent()
848 v = readl(sclk->mux_reg); in sclk_set_parent()
854 writel(v, sclk->mux_reg); in sclk_set_parent()
857 writel(OSC_SWEN, PIC32_SET(sclk->mux_reg)); in sclk_set_parent()
860 /* add nop to flush pipeline (as cpu_clk is in-flux) */ in sclk_set_parent()
864 err = readl_poll_timeout_atomic(sclk->slew_reg, v, in sclk_set_parent()
867 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_set_parent()
870 * SCLK clock-switching logic might reject a clock switching request in sclk_set_parent()
871 * if pre-requisites (like new clk_src not present or unstable) are in sclk_set_parent()
875 cosc = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; in sclk_set_parent()
879 err = -EBUSY; in sclk_set_parent()
891 /* Maintain reference to this clk, required in spll_clk_set_rate() */ in sclk_init()
895 if (sclk->slew_div) { in sclk_init()
896 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_init()
897 v = readl(sclk->slew_reg); in sclk_init()
899 v |= sclk->slew_div << SLEW_DIV_SHIFT; in sclk_init()
901 writel(v, sclk->slew_reg); in sclk_init()
902 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_init()
908 /* sclk with post-divider */
919 /* sclk with no slew and no post-divider */
927 struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data, in pic32_sys_clk_register()
931 struct clk *clk; in pic32_sys_clk_register() local
933 sclk = devm_kzalloc(core->dev, sizeof(*sclk), GFP_KERNEL); in pic32_sys_clk_register()
935 return ERR_PTR(-ENOMEM); in pic32_sys_clk_register()
937 sclk->core = core; in pic32_sys_clk_register()
938 sclk->hw.init = &data->init_data; in pic32_sys_clk_register()
939 sclk->mux_reg = data->mux_reg + core->iobase; in pic32_sys_clk_register()
940 sclk->slew_reg = data->slew_reg + core->iobase; in pic32_sys_clk_register()
941 sclk->slew_div = data->slew_div; in pic32_sys_clk_register()
942 sclk->parent_map = data->parent_map; in pic32_sys_clk_register()
944 clk = devm_clk_register(core->dev, &sclk->hw); in pic32_sys_clk_register()
945 if (IS_ERR(clk)) in pic32_sys_clk_register()
946 dev_err(core->dev, "%s: clk register failed\n", __func__); in pic32_sys_clk_register()
948 return clk; in pic32_sys_clk_register()
970 writel(sosc->enable_mask, PIC32_SET(sosc->enable_reg)); in sosc_clk_enable()
972 /* wait till warm-up period expires or ready-status is updated */ in sosc_clk_enable()
973 return readl_poll_timeout_atomic(sosc->status_reg, v, in sosc_clk_enable()
974 v & sosc->status_mask, 1, 100); in sosc_clk_enable()
982 writel(sosc->enable_mask, PIC32_CLR(sosc->enable_reg)); in sosc_clk_disable()
991 enabled = readl(sosc->enable_reg) & sosc->enable_mask; in sosc_clk_is_enabled()
992 ready = readl(sosc->status_reg) & sosc->status_mask; in sosc_clk_is_enabled()
1000 return clkhw_to_sosc(hw)->fixed_rate; in sosc_clk_calc_rate()
1010 struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data, in pic32_sosc_clk_register()
1015 sosc = devm_kzalloc(core->dev, sizeof(*sosc), GFP_KERNEL); in pic32_sosc_clk_register()
1017 return ERR_PTR(-ENOMEM); in pic32_sosc_clk_register()
1019 sosc->core = core; in pic32_sosc_clk_register()
1020 sosc->hw.init = &data->init_data; in pic32_sosc_clk_register()
1021 sosc->fixed_rate = data->fixed_rate; in pic32_sosc_clk_register()
1022 sosc->enable_mask = data->enable_mask; in pic32_sosc_clk_register()
1023 sosc->status_mask = data->status_mask; in pic32_sosc_clk_register()
1024 sosc->enable_reg = data->enable_reg + core->iobase; in pic32_sosc_clk_register()
1025 sosc->status_reg = data->status_reg + core->iobase; in pic32_sosc_clk_register()
1027 return devm_clk_register(core->dev, &sosc->hw); in pic32_sosc_clk_register()