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()
161 req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate, in pbclk_determine_rate()
172 u32 v, div; in pbclk_set_rate() local
176 err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY, in pbclk_set_rate()
182 div = DIV_ROUND_CLOSEST(parent_rate, rate); in pbclk_set_rate()
184 spin_lock_irqsave(&pb->core->reg_lock, flags); in pbclk_set_rate()
186 /* apply new div */ in pbclk_set_rate()
187 v = readl(pb->ctrl_reg); in pbclk_set_rate()
189 v |= (div - 1); in pbclk_set_rate()
193 writel(v, pb->ctrl_reg); in pbclk_set_rate()
195 spin_unlock_irqrestore(&pb->core->reg_lock, flags); in pbclk_set_rate()
198 err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY, in pbclk_set_rate()
203 /* confirm that new div is applied correctly */ in pbclk_set_rate()
204 return (pbclk_read_pbdiv(pb) == div) ? 0 : -EBUSY; in pbclk_set_rate()
216 struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *desc, in pic32_periph_clk_register()
220 struct clk *clk; in pic32_periph_clk_register() local
222 pbclk = devm_kzalloc(core->dev, sizeof(*pbclk), GFP_KERNEL); in pic32_periph_clk_register()
224 return ERR_PTR(-ENOMEM); in pic32_periph_clk_register()
226 pbclk->hw.init = &desc->init_data; in pic32_periph_clk_register()
227 pbclk->core = core; in pic32_periph_clk_register()
228 pbclk->ctrl_reg = desc->ctrl_reg + core->iobase; in pic32_periph_clk_register()
230 clk = devm_clk_register(core->dev, &pbclk->hw); in pic32_periph_clk_register()
231 if (IS_ERR(clk)) { in pic32_periph_clk_register()
232 dev_err(core->dev, "%s: clk_register() failed\n", __func__); in pic32_periph_clk_register()
233 devm_kfree(core->dev, pbclk); in pic32_periph_clk_register()
236 return clk; in pic32_periph_clk_register()
253 return readl(refo->ctrl_reg) & REFO_ON; in roclk_is_enabled()
260 writel(REFO_ON | REFO_OE, PIC32_SET(refo->ctrl_reg)); in roclk_enable()
268 writel(REFO_ON | REFO_OE, PIC32_CLR(refo->ctrl_reg)); in roclk_disable()
284 v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK; in roclk_get_parent()
286 if (!refo->parent_map) in roclk_get_parent()
290 if (refo->parent_map[i] == v) in roclk_get_parent()
293 return -EINVAL; in roclk_get_parent()
301 /* fout = fin / [2 * {div + (trim / 512)}] in roclk_calc_rate()
302 * = fin * 512 / [1024 * div + 2 * trim] in roclk_calc_rate()
303 * = fin * 256 / (512 * div + trim) in roclk_calc_rate()
304 * = (fin << 8) / ((div << 9) + trim) in roclk_calc_rate()
323 u32 div, rotrim, rodiv; in roclk_calc_div_trim() local
326 /* Find integer approximation of floating-point arithmetic. in roclk_calc_div_trim()
328 * i.e. fout = fin / 2 * DIV in roclk_calc_div_trim()
329 * whereas DIV = rodiv + (rotrim / 512) in roclk_calc_div_trim()
331 * Since kernel does not perform floating-point arithmetic so in roclk_calc_div_trim()
332 * (rotrim/512) will be zero. And DIV & rodiv will result same. in roclk_calc_div_trim()
335 * ie. rotrim = ((fin * 256) / fout) - (512 * DIV) in roclk_calc_div_trim()
338 div = 0; in roclk_calc_div_trim()
343 div = parent_rate / (rate << 1); in roclk_calc_div_trim()
347 frac -= (u64)(div << 9); in roclk_calc_div_trim()
349 rodiv = (div > REFO_DIV_MASK) ? REFO_DIV_MASK : div; in roclk_calc_div_trim()
367 v = readl(refo->ctrl_reg); in roclk_recalc_rate()
371 v = readl(refo->ctrl_reg + REFO_TRIM_REG); in roclk_recalc_rate()
381 unsigned int i, delta, best_delta = -1; in roclk_determine_rate()
396 if (req->rate > parent_rate) in roclk_determine_rate()
400 roclk_calc_div_trim(req->rate, req->best_parent_rate, &rodiv, &rotrim); in roclk_determine_rate()
403 nearest_rate = roclk_calc_rate(req->best_parent_rate, rodiv, rotrim); in roclk_determine_rate()
405 delta = abs(nearest_rate - req->rate); in roclk_determine_rate()
406 if ((nearest_rate >= req->rate) && (delta < best_delta)) { in roclk_determine_rate()
420 __func__, clk_hw_get_name(hw), req->rate); in roclk_determine_rate()
425 clk_hw_get_name(hw), req->rate, in roclk_determine_rate()
429 if (req->best_parent_rate) in roclk_determine_rate()
430 req->best_parent_rate = best_parent_rate; in roclk_determine_rate()
432 if (req->best_parent_hw) in roclk_determine_rate()
433 req->best_parent_hw = best_parent_clk; in roclk_determine_rate()
445 if (refo->parent_map) in roclk_set_parent()
446 index = refo->parent_map[index]; in roclk_set_parent()
449 err = readl_poll_timeout(refo->ctrl_reg, v, !(v & REFO_ACTIVE), in roclk_set_parent()
452 pr_err("%s: poll failed, clk active\n", clk_hw_get_name(hw)); in roclk_set_parent()
456 spin_lock_irqsave(&refo->core->reg_lock, flags); in roclk_set_parent()
461 v = readl(refo->ctrl_reg); in roclk_set_parent()
465 writel(v, refo->ctrl_reg); in roclk_set_parent()
467 spin_unlock_irqrestore(&refo->core->reg_lock, flags); in roclk_set_parent()
485 pr_debug("parent_rate = %lu, rate = %lu, div = %d, trim = %d\n", in roclk_set_rate_and_parent()
489 err = readl_poll_timeout(refo->ctrl_reg, v, in roclk_set_rate_and_parent()
497 spin_lock_irqsave(&refo->core->reg_lock, flags); in roclk_set_rate_and_parent()
498 v = readl(refo->ctrl_reg); in roclk_set_rate_and_parent()
503 if (refo->parent_map) in roclk_set_rate_and_parent()
504 index = refo->parent_map[index]; in roclk_set_rate_and_parent()
512 writel(v, refo->ctrl_reg); in roclk_set_rate_and_parent()
515 v = readl(refo->ctrl_reg + REFO_TRIM_REG); in roclk_set_rate_and_parent()
518 writel(v, refo->ctrl_reg + REFO_TRIM_REG); in roclk_set_rate_and_parent()
521 writel(REFO_ON | REFO_DIVSW_EN, PIC32_SET(refo->ctrl_reg)); in roclk_set_rate_and_parent()
523 /* wait till divswen is in-progress */ in roclk_set_rate_and_parent()
524 err = readl_poll_timeout_atomic(refo->ctrl_reg, v, !(v & REFO_DIVSW_EN), in roclk_set_rate_and_parent()
526 /* leave the clk gated as it was */ in roclk_set_rate_and_parent()
527 writel(REFO_ON, PIC32_CLR(refo->ctrl_reg)); in roclk_set_rate_and_parent()
529 spin_unlock_irqrestore(&refo->core->reg_lock, flags); in roclk_set_rate_and_parent()
555 struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data, in pic32_refo_clk_register()
559 struct clk *clk; in pic32_refo_clk_register() local
561 refo = devm_kzalloc(core->dev, sizeof(*refo), GFP_KERNEL); in pic32_refo_clk_register()
563 return ERR_PTR(-ENOMEM); in pic32_refo_clk_register()
565 refo->core = core; in pic32_refo_clk_register()
566 refo->hw.init = &data->init_data; in pic32_refo_clk_register()
567 refo->ctrl_reg = data->ctrl_reg + core->iobase; in pic32_refo_clk_register()
568 refo->parent_map = data->parent_map; in pic32_refo_clk_register()
570 clk = devm_clk_register(core->dev, &refo->hw); in pic32_refo_clk_register()
571 if (IS_ERR(clk)) in pic32_refo_clk_register()
572 dev_err(core->dev, "%s: clk_register() failed\n", __func__); in pic32_refo_clk_register()
574 return clk; in pic32_refo_clk_register()
600 u32 mul, div, best_mul = 1, best_div = 1; in spll_calc_mult_div() local
602 unsigned int best_delta = -1, delta, match_found = 0; in spll_calc_mult_div()
605 parent_rate /= pll->idiv; in spll_calc_mult_div()
608 for (div = PLL_ODIV_MIN; div <= PLL_ODIV_MAX; div++) { in spll_calc_mult_div()
611 do_div(rate64, 1 << div); in spll_calc_mult_div()
613 delta = abs(rate - new_rate); in spll_calc_mult_div()
618 best_div = div; in spll_calc_mult_div()
629 pr_debug("rate %lu, par_rate %lu/mult %u, div %u, best_rate %lu\n", in spll_calc_mult_div()
633 *mult_p = best_mul - 1; in spll_calc_mult_div()
646 u32 mult, odiv, div, v; in spll_clk_recalc_rate() local
649 v = readl(pll->ctrl_reg); in spll_clk_recalc_rate()
652 div = spll_odiv_to_divider(odiv); in spll_clk_recalc_rate()
655 * pll_out_rate = pll_in_rate * mult / div; in spll_clk_recalc_rate()
657 pll_in_rate = parent_rate / pll->idiv; in spll_clk_recalc_rate()
660 do_div(rate64, div); in spll_clk_recalc_rate()
670 req->rate = spll_calc_mult_div(pll, req->rate, req->best_parent_rate, in spll_clk_determine_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()
786 req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate, in sclk_determine_rate()
797 u32 v, div; in sclk_set_rate() local
800 div = parent_rate / rate; in sclk_set_rate()
802 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_set_rate()
804 /* apply new div */ in sclk_set_rate()
805 v = readl(sclk->slew_reg); in sclk_set_rate()
807 v |= (div - 1) << SLEW_SYSDIV_SHIFT; in sclk_set_rate()
811 writel(v, sclk->slew_reg); in sclk_set_rate()
814 err = readl_poll_timeout_atomic(sclk->slew_reg, v, in sclk_set_rate()
817 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_set_rate()
827 v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; in sclk_get_parent()
829 if (!sclk->parent_map) in sclk_get_parent()
833 if (sclk->parent_map[i] == v) in sclk_get_parent()
835 return -EINVAL; in sclk_get_parent()
845 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_set_parent()
848 nosc = sclk->parent_map ? sclk->parent_map[index] : index; in sclk_set_parent()
851 v = readl(sclk->mux_reg); in sclk_set_parent()
857 writel(v, sclk->mux_reg); in sclk_set_parent()
860 writel(OSC_SWEN, PIC32_SET(sclk->mux_reg)); in sclk_set_parent()
863 /* add nop to flush pipeline (as cpu_clk is in-flux) */ in sclk_set_parent()
867 err = readl_poll_timeout_atomic(sclk->slew_reg, v, in sclk_set_parent()
870 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_set_parent()
873 * SCLK clock-switching logic might reject a clock switching request in sclk_set_parent()
874 * if pre-requisites (like new clk_src not present or unstable) are in sclk_set_parent()
878 cosc = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK; in sclk_set_parent()
882 err = -EBUSY; in sclk_set_parent()
894 /* Maintain reference to this clk, required in spll_clk_set_rate() */ in sclk_init()
898 if (sclk->slew_div) { in sclk_init()
899 spin_lock_irqsave(&sclk->core->reg_lock, flags); in sclk_init()
900 v = readl(sclk->slew_reg); in sclk_init()
902 v |= sclk->slew_div << SLEW_DIV_SHIFT; in sclk_init()
904 writel(v, sclk->slew_reg); in sclk_init()
905 spin_unlock_irqrestore(&sclk->core->reg_lock, flags); in sclk_init()
911 /* sclk with post-divider */
922 /* sclk with no slew and no post-divider */
930 struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data, in pic32_sys_clk_register()
934 struct clk *clk; in pic32_sys_clk_register() local
936 sclk = devm_kzalloc(core->dev, sizeof(*sclk), GFP_KERNEL); in pic32_sys_clk_register()
938 return ERR_PTR(-ENOMEM); in pic32_sys_clk_register()
940 sclk->core = core; in pic32_sys_clk_register()
941 sclk->hw.init = &data->init_data; in pic32_sys_clk_register()
942 sclk->mux_reg = data->mux_reg + core->iobase; in pic32_sys_clk_register()
943 sclk->slew_reg = data->slew_reg + core->iobase; in pic32_sys_clk_register()
944 sclk->slew_div = data->slew_div; in pic32_sys_clk_register()
945 sclk->parent_map = data->parent_map; in pic32_sys_clk_register()
947 clk = devm_clk_register(core->dev, &sclk->hw); in pic32_sys_clk_register()
948 if (IS_ERR(clk)) in pic32_sys_clk_register()
949 dev_err(core->dev, "%s: clk register failed\n", __func__); in pic32_sys_clk_register()
951 return clk; in pic32_sys_clk_register()
973 writel(sosc->enable_mask, PIC32_SET(sosc->enable_reg)); in sosc_clk_enable()
975 /* wait till warm-up period expires or ready-status is updated */ in sosc_clk_enable()
976 return readl_poll_timeout_atomic(sosc->status_reg, v, in sosc_clk_enable()
977 v & sosc->status_mask, 1, 100); in sosc_clk_enable()
985 writel(sosc->enable_mask, PIC32_CLR(sosc->enable_reg)); in sosc_clk_disable()
994 enabled = readl(sosc->enable_reg) & sosc->enable_mask; in sosc_clk_is_enabled()
995 ready = readl(sosc->status_reg) & sosc->status_mask; in sosc_clk_is_enabled()
1003 return clkhw_to_sosc(hw)->fixed_rate; in sosc_clk_calc_rate()
1013 struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data, in pic32_sosc_clk_register()
1018 sosc = devm_kzalloc(core->dev, sizeof(*sosc), GFP_KERNEL); in pic32_sosc_clk_register()
1020 return ERR_PTR(-ENOMEM); in pic32_sosc_clk_register()
1022 sosc->core = core; in pic32_sosc_clk_register()
1023 sosc->hw.init = &data->init_data; in pic32_sosc_clk_register()
1024 sosc->fixed_rate = data->fixed_rate; in pic32_sosc_clk_register()
1025 sosc->enable_mask = data->enable_mask; in pic32_sosc_clk_register()
1026 sosc->status_mask = data->status_mask; in pic32_sosc_clk_register()
1027 sosc->enable_reg = data->enable_reg + core->iobase; in pic32_sosc_clk_register()
1028 sosc->status_reg = data->status_reg + core->iobase; in pic32_sosc_clk_register()
1030 return devm_clk_register(core->dev, &sosc->hw); in pic32_sosc_clk_register()