Lines Matching +full:clk +full:- +full:out +full:- +full:frequency

1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
22 if (!((common->features & CCU_FEATURE_FIXED_PREDIV) || in ccu_mux_get_prediv()
23 (common->features & CCU_FEATURE_VARIABLE_PREDIV) || in ccu_mux_get_prediv()
24 (common->features & CCU_FEATURE_ALL_PREDIV))) in ccu_mux_get_prediv()
27 if (common->features & CCU_FEATURE_ALL_PREDIV) in ccu_mux_get_prediv()
28 return common->prediv; in ccu_mux_get_prediv()
30 reg = readl(common->base + common->reg); in ccu_mux_get_prediv()
32 parent_index = reg >> cm->shift; in ccu_mux_get_prediv()
33 parent_index &= (1 << cm->width) - 1; in ccu_mux_get_prediv()
36 if (common->features & CCU_FEATURE_FIXED_PREDIV) { in ccu_mux_get_prediv()
39 for (i = 0; i < cm->n_predivs; i++) in ccu_mux_get_prediv()
40 if (parent_index == cm->fixed_predivs[i].index) in ccu_mux_get_prediv()
41 prediv = cm->fixed_predivs[i].div; in ccu_mux_get_prediv()
44 if (common->features & CCU_FEATURE_VARIABLE_PREDIV) { in ccu_mux_get_prediv()
47 for (i = 0; i < cm->n_var_predivs; i++) in ccu_mux_get_prediv()
48 if (parent_index == cm->var_predivs[i].index) { in ccu_mux_get_prediv()
51 div = reg >> cm->var_predivs[i].shift; in ccu_mux_get_prediv()
52 div &= (1 << cm->var_predivs[i].width) - 1; in ccu_mux_get_prediv()
87 struct clk_hw *best_parent, *hw = &common->hw; in ccu_mux_helper_determine_rate()
95 adj_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1, in ccu_mux_helper_determine_rate()
99 req->rate, data); in ccu_mux_helper_determine_rate()
103 * Unapply the pre-divider if there's one, and give in ccu_mux_helper_determine_rate()
104 * the actual frequency the parent needs to run at. in ccu_mux_helper_determine_rate()
106 best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1, in ccu_mux_helper_determine_rate()
109 goto out; in ccu_mux_helper_determine_rate()
123 tmp_rate = round(cm, parent, &parent_rate, req->rate, data); in ccu_mux_helper_determine_rate()
127 * Unapply the pre-divider if there's one, and give in ccu_mux_helper_determine_rate()
128 * the actual frequency the parent needs to run at. in ccu_mux_helper_determine_rate()
132 if (tmp_rate == req->rate) { in ccu_mux_helper_determine_rate()
136 goto out; in ccu_mux_helper_determine_rate()
139 if ((req->rate - tmp_rate) < (req->rate - best_rate)) { in ccu_mux_helper_determine_rate()
147 return -EINVAL; in ccu_mux_helper_determine_rate()
149 out: in ccu_mux_helper_determine_rate()
150 req->best_parent_hw = best_parent; in ccu_mux_helper_determine_rate()
151 req->best_parent_rate = best_parent_rate; in ccu_mux_helper_determine_rate()
152 req->rate = best_rate; in ccu_mux_helper_determine_rate()
162 reg = readl(common->base + common->reg); in ccu_mux_helper_get_parent()
163 parent = reg >> cm->shift; in ccu_mux_helper_get_parent()
164 parent &= (1 << cm->width) - 1; in ccu_mux_helper_get_parent()
166 if (cm->table) { in ccu_mux_helper_get_parent()
167 int num_parents = clk_hw_get_num_parents(&common->hw); in ccu_mux_helper_get_parent()
171 if (cm->table[i] == parent) in ccu_mux_helper_get_parent()
185 if (cm->table) in ccu_mux_helper_set_parent()
186 index = cm->table[index]; in ccu_mux_helper_set_parent()
188 spin_lock_irqsave(common->lock, flags); in ccu_mux_helper_set_parent()
190 reg = readl(common->base + common->reg); in ccu_mux_helper_set_parent()
191 reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift); in ccu_mux_helper_set_parent()
192 writel(reg | (index << cm->shift), common->base + common->reg); in ccu_mux_helper_set_parent()
194 spin_unlock_irqrestore(common->lock, flags); in ccu_mux_helper_set_parent()
203 return ccu_gate_helper_disable(&cm->common, cm->enable); in ccu_mux_disable()
210 return ccu_gate_helper_enable(&cm->common, cm->enable); in ccu_mux_enable()
217 return ccu_gate_helper_is_enabled(&cm->common, cm->enable); in ccu_mux_is_enabled()
224 return ccu_mux_helper_get_parent(&cm->common, &cm->mux); in ccu_mux_get_parent()
231 return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index); in ccu_mux_set_parent()
239 return ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1, in ccu_mux_recalc_rate()
256 * This clock notifier is called when the frequency of the of the parent
258 * stable clock, such as the main oscillator, while the PLL frequency
268 mux->original_index = ccu_mux_helper_get_parent(mux->common, in ccu_mux_notifier_cb()
269 mux->cm); in ccu_mux_notifier_cb()
270 ret = ccu_mux_helper_set_parent(mux->common, mux->cm, in ccu_mux_notifier_cb()
271 mux->bypass_index); in ccu_mux_notifier_cb()
273 ret = ccu_mux_helper_set_parent(mux->common, mux->cm, in ccu_mux_notifier_cb()
274 mux->original_index); in ccu_mux_notifier_cb()
277 udelay(mux->delay_us); in ccu_mux_notifier_cb()
282 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb) in ccu_mux_notifier_register() argument
284 mux_nb->clk_nb.notifier_call = ccu_mux_notifier_cb; in ccu_mux_notifier_register()
286 return clk_notifier_register(clk, &mux_nb->clk_nb); in ccu_mux_notifier_register()