Lines Matching +full:bt1 +full:- +full:ccu +full:- +full:pll

1 // SPDX-License-Identifier: GPL-2.0-only
9 * Baikal-T1 CCU PLL interface driver
12 #define pr_fmt(fmt) "bt1-ccu-pll: " fmt
20 #include <linux/clk-provider.h>
29 #include "ccu-pll.h"
88 static int ccu_pll_reset(struct ccu_pll *pll, unsigned long ref_clk, in ccu_pll_reset() argument
97 regmap_update_bits(pll->sys_regs, pll->reg_ctl, in ccu_pll_reset()
100 return regmap_read_poll_timeout_atomic(pll->sys_regs, pll->reg_ctl, val, in ccu_pll_reset()
107 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_enable() local
114 return -EINVAL; in ccu_pll_enable()
117 regmap_read(pll->sys_regs, pll->reg_ctl, &val); in ccu_pll_enable()
121 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_enable()
122 regmap_write(pll->sys_regs, pll->reg_ctl, val | CCU_PLL_CTL_EN); in ccu_pll_enable()
123 ret = ccu_pll_reset(pll, clk_hw_get_rate(parent_hw), in ccu_pll_enable()
125 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_enable()
127 pr_err("PLL '%s' reset timed out\n", clk_hw_get_name(hw)); in ccu_pll_enable()
134 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_disable() local
137 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_disable()
138 regmap_update_bits(pll->sys_regs, pll->reg_ctl, CCU_PLL_CTL_EN, 0); in ccu_pll_disable()
139 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_disable()
144 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_is_enabled() local
147 regmap_read(pll->sys_regs, pll->reg_ctl, &val); in ccu_pll_is_enabled()
155 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_recalc_rate() local
159 regmap_read(pll->sys_regs, pll->reg_ctl, &val); in ccu_pll_recalc_rate()
176 * Make sure PLL is working with valid input signal (Fdiv). If in ccu_pll_calc_factors()
185 * limitations like: 1) 700MHz <= Fvco <= 3.5GHz, 2) PLL Od is in ccu_pll_calc_factors()
205 * Bypass the out-of-bound values, which can't be properly in ccu_pll_calc_factors()
221 err = abs((int64_t)freq - num); in ccu_pll_calc_factors()
242 * This method is used for PLLs, which support the on-the-fly dividers
248 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_set_rate_reset() local
258 val = FIELD_PREP(CCU_PLL_CTL_CLKR_MASK, nr - 1) | in ccu_pll_set_rate_reset()
259 FIELD_PREP(CCU_PLL_CTL_CLKF_MASK, nf - 1) | in ccu_pll_set_rate_reset()
260 FIELD_PREP(CCU_PLL_CTL_CLKOD_MASK, od - 1); in ccu_pll_set_rate_reset()
262 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_set_rate_reset()
263 regmap_update_bits(pll->sys_regs, pll->reg_ctl, mask, val); in ccu_pll_set_rate_reset()
264 ret = ccu_pll_reset(pll, parent_rate, nr); in ccu_pll_set_rate_reset()
265 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_set_rate_reset()
267 pr_err("PLL '%s' reset timed out\n", clk_hw_get_name(hw)); in ccu_pll_set_rate_reset()
273 * This method is used for PLLs, which don't support the on-the-fly dividers
279 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_set_rate_norst() local
287 * Disable PLL if it was enabled by default or left enabled by the in ccu_pll_set_rate_norst()
292 val = FIELD_PREP(CCU_PLL_CTL_CLKR_MASK, nr - 1) | in ccu_pll_set_rate_norst()
293 FIELD_PREP(CCU_PLL_CTL_CLKF_MASK, nf - 1) | in ccu_pll_set_rate_norst()
294 FIELD_PREP(CCU_PLL_CTL_CLKOD_MASK, od - 1); in ccu_pll_set_rate_norst()
296 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_set_rate_norst()
297 regmap_update_bits(pll->sys_regs, pll->reg_ctl, mask, val); in ccu_pll_set_rate_norst()
298 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_set_rate_norst()
306 struct ccu_pll *pll; member
313 struct ccu_pll *pll; member
362 * It can be dangerous to change the PLL settings behind clock framework back,
372 struct ccu_pll *pll = bit->pll; in ccu_pll_dbgfs_bit_set() local
375 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_dbgfs_bit_set()
376 regmap_update_bits(pll->sys_regs, pll->reg_ctl + bit->reg, in ccu_pll_dbgfs_bit_set()
377 bit->mask, val ? bit->mask : 0); in ccu_pll_dbgfs_bit_set()
378 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_dbgfs_bit_set()
386 struct ccu_pll *pll = fld->pll; in ccu_pll_dbgfs_fld_set() local
390 val = clamp_t(u64, val, fld->min, fld->max); in ccu_pll_dbgfs_fld_set()
391 data = ((val - 1) << fld->lsb) & fld->mask; in ccu_pll_dbgfs_fld_set()
393 spin_lock_irqsave(&pll->lock, flags); in ccu_pll_dbgfs_fld_set()
394 regmap_update_bits(pll->sys_regs, pll->reg_ctl + fld->reg, fld->mask, in ccu_pll_dbgfs_fld_set()
396 spin_unlock_irqrestore(&pll->lock, flags); in ccu_pll_dbgfs_fld_set()
414 struct ccu_pll *pll = bit->pll; in ccu_pll_dbgfs_bit_get() local
417 regmap_read(pll->sys_regs, pll->reg_ctl + bit->reg, &data); in ccu_pll_dbgfs_bit_get()
418 *val = !!(data & bit->mask); in ccu_pll_dbgfs_bit_get()
428 struct ccu_pll *pll = fld->pll; in ccu_pll_dbgfs_fld_get() local
431 regmap_read(pll->sys_regs, pll->reg_ctl + fld->reg, &data); in ccu_pll_dbgfs_fld_get()
432 *val = ((data & fld->mask) >> fld->lsb) + 1; in ccu_pll_dbgfs_fld_get()
441 struct ccu_pll *pll = to_ccu_pll(hw); in ccu_pll_debug_init() local
452 bits[idx].pll = pll; in ccu_pll_debug_init()
465 flds[idx].pll = pll; in ccu_pll_debug_init()
503 struct ccu_pll *pll; in ccu_pll_hw_register() local
507 return ERR_PTR(-EINVAL); in ccu_pll_hw_register()
509 pll = kzalloc(sizeof(*pll), GFP_KERNEL); in ccu_pll_hw_register()
510 if (!pll) in ccu_pll_hw_register()
511 return ERR_PTR(-ENOMEM); in ccu_pll_hw_register()
514 * Note since Baikal-T1 System Controller registers are MMIO-backed in ccu_pll_hw_register()
518 pll->hw.init = &hw_init; in ccu_pll_hw_register()
519 pll->reg_ctl = pll_init->base + CCU_PLL_CTL; in ccu_pll_hw_register()
520 pll->reg_ctl1 = pll_init->base + CCU_PLL_CTL1; in ccu_pll_hw_register()
521 pll->sys_regs = pll_init->sys_regs; in ccu_pll_hw_register()
522 pll->id = pll_init->id; in ccu_pll_hw_register()
523 spin_lock_init(&pll->lock); in ccu_pll_hw_register()
525 hw_init.name = pll_init->name; in ccu_pll_hw_register()
526 hw_init.flags = pll_init->flags; in ccu_pll_hw_register()
533 if (!pll_init->parent_name) { in ccu_pll_hw_register()
534 ret = -EINVAL; in ccu_pll_hw_register()
537 parent_data.fw_name = pll_init->parent_name; in ccu_pll_hw_register()
541 ret = of_clk_hw_register(pll_init->np, &pll->hw); in ccu_pll_hw_register()
545 return pll; in ccu_pll_hw_register()
548 kfree(pll); in ccu_pll_hw_register()
553 void ccu_pll_hw_unregister(struct ccu_pll *pll) in ccu_pll_hw_unregister() argument
555 clk_hw_unregister(&pll->hw); in ccu_pll_hw_unregister()
557 kfree(pll); in ccu_pll_hw_unregister()