Lines Matching +full:parent +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2015 Chen-Yu Tsai
5 * Chen-Yu Tsai <wens@csie.org>
11 #include <linux/clk.h>
12 #include <linux/clk-provider.h>
22 * sun9i_a80_cpus_clk_setup() - Setup function for a80 cpus composite clk
60 reg = readl(cpus->reg); in sun9i_a80_cpus_clk_recalc_rate()
62 /* apply pre-divider first if parent is pll4 */ in sun9i_a80_cpus_clk_recalc_rate()
66 /* clk divider */ in sun9i_a80_cpus_clk_recalc_rate()
73 u8 parent, unsigned long parent_rate) in sun9i_a80_cpus_clk_round() argument
79 * frequencies higher than the parent frequency in sun9i_a80_cpus_clk_round()
86 /* calculate pre-divider if parent is pll4 */ in sun9i_a80_cpus_clk_round()
87 if (parent == SUN9I_CPUS_MUX_PARENT_PLL4 && div > 4) { in sun9i_a80_cpus_clk_round()
88 /* pre-divider is 1 ~ 32 */ in sun9i_a80_cpus_clk_round()
106 *divp = div - 1; in sun9i_a80_cpus_clk_round()
107 *pre_divp = pre_div - 1; in sun9i_a80_cpus_clk_round()
113 static int sun9i_a80_cpus_clk_determine_rate(struct clk_hw *clk, in sun9i_a80_cpus_clk_determine_rate() argument
116 struct clk_hw *parent, *best_parent = NULL; in sun9i_a80_cpus_clk_determine_rate() local
119 unsigned long rate = req->rate; in sun9i_a80_cpus_clk_determine_rate()
121 /* find the parent that can help provide the fastest rate <= rate */ in sun9i_a80_cpus_clk_determine_rate()
122 num_parents = clk_hw_get_num_parents(clk); in sun9i_a80_cpus_clk_determine_rate()
124 parent = clk_hw_get_parent_by_index(clk, i); in sun9i_a80_cpus_clk_determine_rate()
125 if (!parent) in sun9i_a80_cpus_clk_determine_rate()
127 if (clk_hw_get_flags(clk) & CLK_SET_RATE_PARENT) in sun9i_a80_cpus_clk_determine_rate()
128 parent_rate = clk_hw_round_rate(parent, rate); in sun9i_a80_cpus_clk_determine_rate()
130 parent_rate = clk_hw_get_rate(parent); in sun9i_a80_cpus_clk_determine_rate()
136 best_parent = parent; in sun9i_a80_cpus_clk_determine_rate()
143 return -EINVAL; in sun9i_a80_cpus_clk_determine_rate()
145 req->best_parent_hw = best_parent; in sun9i_a80_cpus_clk_determine_rate()
146 req->best_parent_rate = best; in sun9i_a80_cpus_clk_determine_rate()
147 req->rate = best_child_rate; in sun9i_a80_cpus_clk_determine_rate()
157 u8 div, pre_div, parent; in sun9i_a80_cpus_clk_set_rate() local
162 reg = readl(cpus->reg); in sun9i_a80_cpus_clk_set_rate()
164 /* need to know which parent is used to apply pre-divider */ in sun9i_a80_cpus_clk_set_rate()
165 parent = SUN9I_CPUS_MUX_GET_PARENT(reg); in sun9i_a80_cpus_clk_set_rate()
166 sun9i_a80_cpus_clk_round(rate, &div, &pre_div, parent, parent_rate); in sun9i_a80_cpus_clk_set_rate()
170 writel(reg, cpus->reg); in sun9i_a80_cpus_clk_set_rate()
185 const char *clk_name = node->name; in sun9i_a80_cpus_setup()
190 struct clk *clk; in sun9i_a80_cpus_setup() local
197 cpus->reg = of_io_request_and_map(node, 0, of_node_full_name(node)); in sun9i_a80_cpus_setup()
198 if (IS_ERR(cpus->reg)) in sun9i_a80_cpus_setup()
201 of_property_read_string(node, "clock-output-names", &clk_name); in sun9i_a80_cpus_setup()
211 mux->reg = cpus->reg; in sun9i_a80_cpus_setup()
212 mux->shift = SUN9I_CPUS_MUX_SHIFT; in sun9i_a80_cpus_setup()
213 /* un-shifted mask is what mux_clk expects */ in sun9i_a80_cpus_setup()
214 mux->mask = SUN9I_CPUS_MUX_MASK >> SUN9I_CPUS_MUX_SHIFT; in sun9i_a80_cpus_setup()
215 mux->lock = &sun9i_a80_cpus_lock; in sun9i_a80_cpus_setup()
217 clk = clk_register_composite(NULL, clk_name, parents, ret, in sun9i_a80_cpus_setup()
218 &mux->hw, &clk_mux_ops, in sun9i_a80_cpus_setup()
219 &cpus->hw, &sun9i_a80_cpus_clk_ops, in sun9i_a80_cpus_setup()
221 if (IS_ERR(clk)) in sun9i_a80_cpus_setup()
224 ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); in sun9i_a80_cpus_setup()
231 clk_unregister(clk); in sun9i_a80_cpus_setup()
235 iounmap(cpus->reg); in sun9i_a80_cpus_setup()
241 CLK_OF_DECLARE(sun9i_a80_cpus, "allwinner,sun9i-a80-cpus-clk",