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>
24 if (!((common->features & CCU_FEATURE_FIXED_PREDIV) || in ccu_mux_get_prediv()
25 (common->features & CCU_FEATURE_VARIABLE_PREDIV) || in ccu_mux_get_prediv()
26 (common->features & CCU_FEATURE_ALL_PREDIV))) in ccu_mux_get_prediv()
29 if (common->features & CCU_FEATURE_ALL_PREDIV) in ccu_mux_get_prediv()
30 return common->prediv; in ccu_mux_get_prediv()
32 reg = readl(common->base + common->reg); in ccu_mux_get_prediv()
34 parent_index = reg >> cm->shift; in ccu_mux_get_prediv()
35 parent_index &= (1 << cm->width) - 1; in ccu_mux_get_prediv()
38 if (common->features & CCU_FEATURE_FIXED_PREDIV) { in ccu_mux_get_prediv()
41 for (i = 0; i < cm->n_predivs; i++) in ccu_mux_get_prediv()
42 if (parent_index == cm->fixed_predivs[i].index) in ccu_mux_get_prediv()
43 prediv = cm->fixed_predivs[i].div; in ccu_mux_get_prediv()
46 if (common->features & CCU_FEATURE_VARIABLE_PREDIV) { in ccu_mux_get_prediv()
49 for (i = 0; i < cm->n_var_predivs; i++) in ccu_mux_get_prediv()
50 if (parent_index == cm->var_predivs[i].index) { in ccu_mux_get_prediv()
53 div = reg >> cm->var_predivs[i].shift; in ccu_mux_get_prediv()
54 div &= (1 << cm->var_predivs[i].width) - 1; in ccu_mux_get_prediv()
90 struct clk_hw *best_parent, *hw = &common->hw; in ccu_mux_helper_determine_rate()
98 adj_parent_rate = ccu_mux_helper_apply_prediv(common, cm, -1, in ccu_mux_helper_determine_rate()
102 req->rate, data); in ccu_mux_helper_determine_rate()
106 * Unapply the pre-divider if there's one, and give in ccu_mux_helper_determine_rate()
107 * the actual frequency the parent needs to run at. in ccu_mux_helper_determine_rate()
109 best_parent_rate = ccu_mux_helper_unapply_prediv(common, cm, -1, in ccu_mux_helper_determine_rate()
112 goto out; in ccu_mux_helper_determine_rate()
126 tmp_rate = round(cm, parent, &parent_rate, req->rate, data); in ccu_mux_helper_determine_rate()
130 * Unapply the pre-divider if there's one, and give in ccu_mux_helper_determine_rate()
131 * the actual frequency the parent needs to run at. in ccu_mux_helper_determine_rate()
135 if (tmp_rate == req->rate) { in ccu_mux_helper_determine_rate()
139 goto out; in ccu_mux_helper_determine_rate()
142 if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) { in ccu_mux_helper_determine_rate()
150 return -EINVAL; in ccu_mux_helper_determine_rate()
152 out: in ccu_mux_helper_determine_rate()
153 req->best_parent_hw = best_parent; in ccu_mux_helper_determine_rate()
154 req->best_parent_rate = best_parent_rate; in ccu_mux_helper_determine_rate()
155 req->rate = best_rate; in ccu_mux_helper_determine_rate()
166 reg = readl(common->base + common->reg); in ccu_mux_helper_get_parent()
167 parent = reg >> cm->shift; in ccu_mux_helper_get_parent()
168 parent &= (1 << cm->width) - 1; in ccu_mux_helper_get_parent()
170 if (cm->table) { in ccu_mux_helper_get_parent()
171 int num_parents = clk_hw_get_num_parents(&common->hw); in ccu_mux_helper_get_parent()
175 if (cm->table[i] == parent) in ccu_mux_helper_get_parent()
190 if (cm->table) in ccu_mux_helper_set_parent()
191 index = cm->table[index]; in ccu_mux_helper_set_parent()
193 spin_lock_irqsave(common->lock, flags); in ccu_mux_helper_set_parent()
195 reg = readl(common->base + common->reg); in ccu_mux_helper_set_parent()
198 if (common->features & CCU_FEATURE_KEY_FIELD) in ccu_mux_helper_set_parent()
201 reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift); in ccu_mux_helper_set_parent()
202 writel(reg | (index << cm->shift), common->base + common->reg); in ccu_mux_helper_set_parent()
204 spin_unlock_irqrestore(common->lock, flags); in ccu_mux_helper_set_parent()
214 return ccu_gate_helper_disable(&cm->common, cm->enable); in ccu_mux_disable()
221 return ccu_gate_helper_enable(&cm->common, cm->enable); in ccu_mux_enable()
228 return ccu_gate_helper_is_enabled(&cm->common, cm->enable); in ccu_mux_is_enabled()
235 return ccu_mux_helper_get_parent(&cm->common, &cm->mux); in ccu_mux_get_parent()
242 return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index); in ccu_mux_set_parent()
250 if (cm->common.features & CCU_FEATURE_CLOSEST_RATE) in ccu_mux_determine_rate()
261 return ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1, in ccu_mux_recalc_rate()
279 * This clock notifier is called when the frequency of the of the parent
281 * stable clock, such as the main oscillator, while the PLL frequency
291 mux->original_index = ccu_mux_helper_get_parent(mux->common, in ccu_mux_notifier_cb()
292 mux->cm); in ccu_mux_notifier_cb()
293 ret = ccu_mux_helper_set_parent(mux->common, mux->cm, in ccu_mux_notifier_cb()
294 mux->bypass_index); in ccu_mux_notifier_cb()
296 ret = ccu_mux_helper_set_parent(mux->common, mux->cm, in ccu_mux_notifier_cb()
297 mux->original_index); in ccu_mux_notifier_cb()
300 udelay(mux->delay_us); in ccu_mux_notifier_cb()
305 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb) in ccu_mux_notifier_register() argument
307 mux_nb->clk_nb.notifier_call = ccu_mux_notifier_cb; in ccu_mux_notifier_register()
309 return clk_notifier_register(clk, &mux_nb->clk_nb); in ccu_mux_notifier_register()