Lines Matching +full:vco +full:- +full:offset
16 #include <linux/clk-provider.h>
23 #include "clk-iproc.h"
29 * PLL MACRO_SELECT modes 0 to 5 choose pre-calculated PLL output frequencies
30 * from a look-up table. Mode 7 allows user to manipulate PLL clock dividers
37 /* number of VCO frequency bands */
100 return -EINVAL; in pll_calc_param()
102 residual = target_rate - (ndiv_int * parent_rate); in pll_calc_param()
112 vco_out->ndiv_int = ndiv_int; in pll_calc_param()
113 vco_out->ndiv_frac = ndiv_frac; in pll_calc_param()
114 vco_out->pdiv = 1; in pll_calc_param()
116 vco_out->rate = vco_out->ndiv_int * parent_rate; in pll_calc_param()
117 residual = (u64)vco_out->ndiv_frac * (u64)parent_rate; in pll_calc_param()
119 vco_out->rate += residual; in pll_calc_param()
125 * Based on the target frequency, find a match from the VCO frequency parameter
132 for (i = 0; i < pll->num_vco_entries; i++) in pll_get_rate_index()
133 if (target_rate == pll->vco_param[i].rate) in pll_get_rate_index()
136 if (i >= pll->num_vco_entries) in pll_get_rate_index()
137 return -EINVAL; in pll_get_rate_index()
147 return -EINVAL; in get_kp()
154 return -EINVAL; in get_kp()
160 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in pll_wait_for_lock()
163 u32 val = readl(pll->status_base + ctrl->status.offset); in pll_wait_for_lock()
165 if (val & (1 << ctrl->status.shift)) in pll_wait_for_lock()
170 return -EIO; in pll_wait_for_lock()
174 const u32 offset, u32 val) in iproc_pll_write() argument
176 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_write()
178 writel(val, base + offset); in iproc_pll_write()
180 if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK && in iproc_pll_write()
181 (base == pll->status_base || base == pll->control_base))) in iproc_pll_write()
182 val = readl(base + offset); in iproc_pll_write()
187 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in __pll_disable()
190 if (ctrl->flags & IPROC_CLK_PLL_ASIU) { in __pll_disable()
191 val = readl(pll->asiu_base + ctrl->asiu.offset); in __pll_disable()
192 val &= ~(1 << ctrl->asiu.en_shift); in __pll_disable()
193 iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val); in __pll_disable()
196 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) { in __pll_disable()
197 val = readl(pll->control_base + ctrl->aon.offset); in __pll_disable()
198 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; in __pll_disable()
199 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val); in __pll_disable()
202 if (pll->pwr_base) { in __pll_disable()
204 val = readl(pll->pwr_base + ctrl->aon.offset); in __pll_disable()
205 val |= 1 << ctrl->aon.iso_shift; in __pll_disable()
206 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val); in __pll_disable()
209 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); in __pll_disable()
210 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val); in __pll_disable()
216 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in __pll_enable()
219 if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) { in __pll_enable()
220 val = readl(pll->control_base + ctrl->aon.offset); in __pll_enable()
221 val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift); in __pll_enable()
222 iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val); in __pll_enable()
225 if (pll->pwr_base) { in __pll_enable()
227 val = readl(pll->pwr_base + ctrl->aon.offset); in __pll_enable()
228 val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift; in __pll_enable()
229 val &= ~(1 << ctrl->aon.iso_shift); in __pll_enable()
230 iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val); in __pll_enable()
234 if (ctrl->flags & IPROC_CLK_PLL_ASIU) { in __pll_enable()
235 val = readl(pll->asiu_base + ctrl->asiu.offset); in __pll_enable()
236 val |= (1 << ctrl->asiu.en_shift); in __pll_enable()
237 iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val); in __pll_enable()
246 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in __pll_put_in_reset()
247 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; in __pll_put_in_reset()
249 val = readl(pll->control_base + reset->offset); in __pll_put_in_reset()
250 if (ctrl->flags & IPROC_CLK_PLL_RESET_ACTIVE_LOW) in __pll_put_in_reset()
251 val |= BIT(reset->reset_shift) | BIT(reset->p_reset_shift); in __pll_put_in_reset()
253 val &= ~(BIT(reset->reset_shift) | BIT(reset->p_reset_shift)); in __pll_put_in_reset()
254 iproc_pll_write(pll, pll->control_base, reset->offset, val); in __pll_put_in_reset()
261 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in __pll_bring_out_reset()
262 const struct iproc_pll_reset_ctrl *reset = &ctrl->reset; in __pll_bring_out_reset()
263 const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter; in __pll_bring_out_reset()
265 val = readl(pll->control_base + dig_filter->offset); in __pll_bring_out_reset()
266 val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift | in __pll_bring_out_reset()
267 bit_mask(dig_filter->kp_width) << dig_filter->kp_shift | in __pll_bring_out_reset()
268 bit_mask(dig_filter->ka_width) << dig_filter->ka_shift); in __pll_bring_out_reset()
269 val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift | in __pll_bring_out_reset()
270 ka << dig_filter->ka_shift; in __pll_bring_out_reset()
271 iproc_pll_write(pll, pll->control_base, dig_filter->offset, val); in __pll_bring_out_reset()
273 val = readl(pll->control_base + reset->offset); in __pll_bring_out_reset()
274 if (ctrl->flags & IPROC_CLK_PLL_RESET_ACTIVE_LOW) in __pll_bring_out_reset()
275 val &= ~(BIT(reset->reset_shift) | BIT(reset->p_reset_shift)); in __pll_bring_out_reset()
277 val |= BIT(reset->reset_shift) | BIT(reset->p_reset_shift); in __pll_bring_out_reset()
278 iproc_pll_write(pll, pll->control_base, reset->offset, val); in __pll_bring_out_reset()
287 struct iproc_pll_vco_param *vco) in pll_fractional_change_only() argument
289 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in pll_fractional_change_only()
295 val = readl(pll->status_base + ctrl->status.offset); in pll_fractional_change_only()
296 if ((val & (1 << ctrl->status.shift)) == 0) in pll_fractional_change_only()
299 val = readl(pll->control_base + ctrl->ndiv_int.offset); in pll_fractional_change_only()
300 ndiv_int = (val >> ctrl->ndiv_int.shift) & in pll_fractional_change_only()
301 bit_mask(ctrl->ndiv_int.width); in pll_fractional_change_only()
303 if (ndiv_int != vco->ndiv_int) in pll_fractional_change_only()
306 val = readl(pll->control_base + ctrl->pdiv.offset); in pll_fractional_change_only()
307 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); in pll_fractional_change_only()
309 if (pdiv != vco->pdiv) in pll_fractional_change_only()
315 static int pll_set_rate(struct iproc_clk *clk, struct iproc_pll_vco_param *vco, in pll_set_rate() argument
318 struct iproc_pll *pll = clk->pll; in pll_set_rate()
319 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in pll_set_rate()
321 unsigned long rate = vco->rate; in pll_set_rate()
325 const char *clk_name = clk_hw_get_name(&clk->hw); in pll_set_rate()
331 if (vco->pdiv == 0) in pll_set_rate()
334 ref_freq = parent_rate / vco->pdiv; in pll_set_rate()
336 /* determine Ki and Kp index based on target VCO frequency */ in pll_set_rate()
349 return -EINVAL; in pll_set_rate()
364 if (pll_fractional_change_only(clk->pll, vco)) { in pll_set_rate()
366 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { in pll_set_rate()
367 val = readl(pll->control_base + ctrl->ndiv_frac.offset); in pll_set_rate()
368 val &= ~(bit_mask(ctrl->ndiv_frac.width) << in pll_set_rate()
369 ctrl->ndiv_frac.shift); in pll_set_rate()
370 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; in pll_set_rate()
371 iproc_pll_write(pll, pll->control_base, in pll_set_rate()
372 ctrl->ndiv_frac.offset, val); in pll_set_rate()
381 if (ctrl->flags & IPROC_CLK_PLL_USER_MODE_ON) { in pll_set_rate()
382 val = readl(pll->control_base + ctrl->macro_mode.offset); in pll_set_rate()
383 val &= ~(bit_mask(ctrl->macro_mode.width) << in pll_set_rate()
384 ctrl->macro_mode.shift); in pll_set_rate()
385 val |= PLL_USER_MODE << ctrl->macro_mode.shift; in pll_set_rate()
386 iproc_pll_write(pll, pll->control_base, in pll_set_rate()
387 ctrl->macro_mode.offset, val); in pll_set_rate()
390 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0); in pll_set_rate()
392 val = readl(pll->control_base + ctrl->vco_ctrl.l_offset); in pll_set_rate()
402 iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val); in pll_set_rate()
405 val = readl(pll->control_base + ctrl->ndiv_int.offset); in pll_set_rate()
406 val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift); in pll_set_rate()
407 val |= vco->ndiv_int << ctrl->ndiv_int.shift; in pll_set_rate()
408 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val); in pll_set_rate()
411 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { in pll_set_rate()
412 val = readl(pll->control_base + ctrl->ndiv_frac.offset); in pll_set_rate()
413 val &= ~(bit_mask(ctrl->ndiv_frac.width) << in pll_set_rate()
414 ctrl->ndiv_frac.shift); in pll_set_rate()
415 val |= vco->ndiv_frac << ctrl->ndiv_frac.shift; in pll_set_rate()
416 iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset, in pll_set_rate()
421 val = readl(pll->control_base + ctrl->pdiv.offset); in pll_set_rate()
422 val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift); in pll_set_rate()
423 val |= vco->pdiv << ctrl->pdiv.shift; in pll_set_rate()
424 iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val); in pll_set_rate()
440 struct iproc_pll *pll = clk->pll; in iproc_pll_enable()
448 struct iproc_pll *pll = clk->pll; in iproc_pll_disable()
449 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_disable()
451 if (ctrl->flags & IPROC_CLK_AON) in iproc_pll_disable()
461 struct iproc_pll *pll = clk->pll; in iproc_pll_recalc_rate()
462 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_recalc_rate()
472 val = readl(pll->status_base + ctrl->status.offset); in iproc_pll_recalc_rate()
473 if ((val & (1 << ctrl->status.shift)) == 0) in iproc_pll_recalc_rate()
481 val = readl(pll->control_base + ctrl->ndiv_int.offset); in iproc_pll_recalc_rate()
482 ndiv_int = (val >> ctrl->ndiv_int.shift) & in iproc_pll_recalc_rate()
483 bit_mask(ctrl->ndiv_int.width); in iproc_pll_recalc_rate()
486 if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { in iproc_pll_recalc_rate()
487 val = readl(pll->control_base + ctrl->ndiv_frac.offset); in iproc_pll_recalc_rate()
488 ndiv_frac = (val >> ctrl->ndiv_frac.shift) & in iproc_pll_recalc_rate()
489 bit_mask(ctrl->ndiv_frac.width); in iproc_pll_recalc_rate()
493 val = readl(pll->control_base + ctrl->pdiv.offset); in iproc_pll_recalc_rate()
494 pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width); in iproc_pll_recalc_rate()
511 struct iproc_pll *pll = clk->pll; in iproc_pll_determine_rate()
512 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_determine_rate()
517 if (req->rate == 0 || req->best_parent_rate == 0) in iproc_pll_determine_rate()
518 return -EINVAL; in iproc_pll_determine_rate()
520 if (ctrl->flags & IPROC_CLK_PLL_CALC_PARAM) { in iproc_pll_determine_rate()
523 ret = pll_calc_param(req->rate, req->best_parent_rate, in iproc_pll_determine_rate()
528 req->rate = vco_param.rate; in iproc_pll_determine_rate()
532 if (!pll->vco_param) in iproc_pll_determine_rate()
533 return -EINVAL; in iproc_pll_determine_rate()
536 for (i = 0; i < pll->num_vco_entries; i++) { in iproc_pll_determine_rate()
537 diff = abs(req->rate - pll->vco_param[i].rate); in iproc_pll_determine_rate()
547 req->rate = pll->vco_param[best_idx].rate; in iproc_pll_determine_rate()
556 struct iproc_pll *pll = clk->pll; in iproc_pll_set_rate()
557 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_set_rate()
561 if (ctrl->flags & IPROC_CLK_PLL_CALC_PARAM) { in iproc_pll_set_rate()
570 vco_param = pll->vco_param[rate_index]; in iproc_pll_set_rate()
588 const struct iproc_clk_ctrl *ctrl = clk->ctrl; in iproc_clk_enable()
589 struct iproc_pll *pll = clk->pll; in iproc_clk_enable()
593 val = readl(pll->control_base + ctrl->enable.offset); in iproc_clk_enable()
594 val &= ~(1 << ctrl->enable.enable_shift); in iproc_clk_enable()
595 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val); in iproc_clk_enable()
598 val = readl(pll->control_base + ctrl->enable.offset); in iproc_clk_enable()
599 val &= ~(1 << ctrl->enable.hold_shift); in iproc_clk_enable()
600 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val); in iproc_clk_enable()
608 const struct iproc_clk_ctrl *ctrl = clk->ctrl; in iproc_clk_disable()
609 struct iproc_pll *pll = clk->pll; in iproc_clk_disable()
612 if (ctrl->flags & IPROC_CLK_AON) in iproc_clk_disable()
615 val = readl(pll->control_base + ctrl->enable.offset); in iproc_clk_disable()
616 val |= 1 << ctrl->enable.enable_shift; in iproc_clk_disable()
617 iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val); in iproc_clk_disable()
624 const struct iproc_clk_ctrl *ctrl = clk->ctrl; in iproc_clk_recalc_rate()
625 struct iproc_pll *pll = clk->pll; in iproc_clk_recalc_rate()
633 val = readl(pll->control_base + ctrl->mdiv.offset); in iproc_clk_recalc_rate()
634 mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width); in iproc_clk_recalc_rate()
638 if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) in iproc_clk_recalc_rate()
651 if (req->rate == 0) in iproc_clk_determine_rate()
652 return -EINVAL; in iproc_clk_determine_rate()
653 if (req->rate == req->best_parent_rate) in iproc_clk_determine_rate()
656 bestdiv = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate); in iproc_clk_determine_rate()
658 req->rate = req->best_parent_rate; in iproc_clk_determine_rate()
663 req->rate = req->best_parent_rate / bestdiv; in iproc_clk_determine_rate()
672 const struct iproc_clk_ctrl *ctrl = clk->ctrl; in iproc_clk_set_rate()
673 struct iproc_pll *pll = clk->pll; in iproc_clk_set_rate()
678 return -EINVAL; in iproc_clk_set_rate()
681 if (ctrl->flags & IPROC_CLK_MCLK_DIV_BY_2) in iproc_clk_set_rate()
685 return -EINVAL; in iproc_clk_set_rate()
687 val = readl(pll->control_base + ctrl->mdiv.offset); in iproc_clk_set_rate()
689 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); in iproc_clk_set_rate()
691 val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift); in iproc_clk_set_rate()
692 val |= div << ctrl->mdiv.shift; in iproc_clk_set_rate()
694 iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val); in iproc_clk_set_rate()
713 const struct iproc_pll_ctrl *ctrl = pll->ctrl; in iproc_pll_sw_cfg()
715 if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) { in iproc_pll_sw_cfg()
718 val = readl(pll->control_base + ctrl->sw_ctrl.offset); in iproc_pll_sw_cfg()
719 val |= BIT(ctrl->sw_ctrl.shift); in iproc_pll_sw_cfg()
720 iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset, in iproc_pll_sw_cfg()
727 const struct iproc_pll_vco_param *vco, in iproc_pll_clk_setup() argument
750 clk_data->num = num_clks; in iproc_pll_clk_setup()
756 pll->control_base = of_iomap(node, 0); in iproc_pll_clk_setup()
757 if (WARN_ON(!pll->control_base)) in iproc_pll_clk_setup()
761 pll->pwr_base = of_iomap(node, 1); in iproc_pll_clk_setup()
764 if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) { in iproc_pll_clk_setup()
765 pll->asiu_base = of_iomap(node, 2); in iproc_pll_clk_setup()
766 if (WARN_ON(!pll->asiu_base)) in iproc_pll_clk_setup()
770 if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) { in iproc_pll_clk_setup()
774 pll->status_base = of_iomap(node, 2); in iproc_pll_clk_setup()
775 if (!pll->status_base) in iproc_pll_clk_setup()
778 pll->status_base = pll->control_base; in iproc_pll_clk_setup()
781 pll->ctrl = pll_ctrl; in iproc_pll_clk_setup()
784 iclk->pll = pll; in iproc_pll_clk_setup()
786 init.name = node->name; in iproc_pll_clk_setup()
792 iclk->hw.init = &init; in iproc_pll_clk_setup()
794 if (vco) { in iproc_pll_clk_setup()
795 pll->num_vco_entries = num_vco_entries; in iproc_pll_clk_setup()
796 pll->vco_param = vco; in iproc_pll_clk_setup()
801 ret = clk_hw_register(NULL, &iclk->hw); in iproc_pll_clk_setup()
805 clk_data->hws[0] = &iclk->hw; in iproc_pll_clk_setup()
812 parent_name = node->name; in iproc_pll_clk_setup()
814 ret = of_property_read_string_index(node, "clock-output-names", in iproc_pll_clk_setup()
820 iclk->pll = pll; in iproc_pll_clk_setup()
821 iclk->ctrl = &clk_ctrl[i]; in iproc_pll_clk_setup()
828 iclk->hw.init = &init; in iproc_pll_clk_setup()
830 ret = clk_hw_register(NULL, &iclk->hw); in iproc_pll_clk_setup()
834 clk_data->hws[i] = &iclk->hw; in iproc_pll_clk_setup()
844 while (--i >= 0) in iproc_pll_clk_setup()
845 clk_hw_unregister(clk_data->hws[i]); in iproc_pll_clk_setup()
848 if (pll->status_base != pll->control_base) in iproc_pll_clk_setup()
849 iounmap(pll->status_base); in iproc_pll_clk_setup()
852 if (pll->asiu_base) in iproc_pll_clk_setup()
853 iounmap(pll->asiu_base); in iproc_pll_clk_setup()
856 if (pll->pwr_base) in iproc_pll_clk_setup()
857 iounmap(pll->pwr_base); in iproc_pll_clk_setup()
859 iounmap(pll->control_base); in iproc_pll_clk_setup()