Lines Matching +full:clk +full:- +full:div
1 // SPDX-License-Identifier: GPL-2.0
3 * R-Car Gen2 Clock Pulse Generator
9 #include <linux/clk.h>
10 #include <linux/clk-provider.h>
18 #include "renesas-cpg-mssr.h"
19 #include "rcar-gen2-cpg.h"
39 * prepare - clk_prepare only ensures that parents are prepared
40 * enable - clk_enable only ensures that parents are enabled
41 * rate - rate is adjustable. clk->rate = parent->rate * mult / 32
42 * parent - fixed parent. No clk_set_parent support
60 val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT; in cpg_z_clk_recalc_rate()
61 mult = 32 - val; in cpg_z_clk_recalc_rate()
69 unsigned long prate = req->best_parent_rate; in cpg_z_clk_determine_rate()
72 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); in cpg_z_clk_determine_rate()
73 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL); in cpg_z_clk_determine_rate()
75 return -EINVAL; in cpg_z_clk_determine_rate()
77 mult = div64_ul(req->rate * 32ULL, prate); in cpg_z_clk_determine_rate()
80 req->rate = div_u64((u64)prate * mult, 32); in cpg_z_clk_determine_rate()
95 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) in cpg_z_clk_set_rate()
96 return -EBUSY; in cpg_z_clk_set_rate()
98 val = readl(zclk->reg); in cpg_z_clk_set_rate()
100 val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; in cpg_z_clk_set_rate()
101 writel(val, zclk->reg); in cpg_z_clk_set_rate()
107 kick = readl(zclk->kick_reg); in cpg_z_clk_set_rate()
109 writel(kick, zclk->kick_reg); in cpg_z_clk_set_rate()
120 for (i = 1000; i; i--) { in cpg_z_clk_set_rate()
121 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) in cpg_z_clk_set_rate()
127 return -ETIMEDOUT; in cpg_z_clk_set_rate()
136 static struct clk * __init cpg_z_clk_register(const char *name, in cpg_z_clk_register()
142 struct clk *clk; in cpg_z_clk_register() local
146 return ERR_PTR(-ENOMEM); in cpg_z_clk_register()
154 zclk->reg = base + CPG_FRQCRC; in cpg_z_clk_register()
155 zclk->kick_reg = base + CPG_FRQCRB; in cpg_z_clk_register()
156 zclk->hw.init = &init; in cpg_z_clk_register()
158 clk = clk_register(NULL, &zclk->hw); in cpg_z_clk_register()
159 if (IS_ERR(clk)) in cpg_z_clk_register()
162 return clk; in cpg_z_clk_register()
165 static struct clk * __init cpg_rcan_clk_register(const char *name, in cpg_rcan_clk_register()
171 struct clk *clk; in cpg_rcan_clk_register() local
175 return ERR_PTR(-ENOMEM); in cpg_rcan_clk_register()
177 fixed->mult = 1; in cpg_rcan_clk_register()
178 fixed->div = 6; in cpg_rcan_clk_register()
183 return ERR_PTR(-ENOMEM); in cpg_rcan_clk_register()
186 gate->reg = base + CPG_RCANCKCR; in cpg_rcan_clk_register()
187 gate->bit_idx = 8; in cpg_rcan_clk_register()
188 gate->flags = CLK_GATE_SET_TO_DISABLE; in cpg_rcan_clk_register()
189 gate->lock = &cpg_lock; in cpg_rcan_clk_register()
191 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, in cpg_rcan_clk_register()
192 &fixed->hw, &clk_fixed_factor_ops, in cpg_rcan_clk_register()
193 &gate->hw, &clk_gate_ops, 0); in cpg_rcan_clk_register()
194 if (IS_ERR(clk)) { in cpg_rcan_clk_register()
199 return clk; in cpg_rcan_clk_register()
209 static struct clk * __init cpg_adsp_clk_register(const char *name, in cpg_adsp_clk_register()
213 struct clk_divider *div; in cpg_adsp_clk_register() local
215 struct clk *clk; in cpg_adsp_clk_register() local
217 div = kzalloc(sizeof(*div), GFP_KERNEL); in cpg_adsp_clk_register()
218 if (!div) in cpg_adsp_clk_register()
219 return ERR_PTR(-ENOMEM); in cpg_adsp_clk_register()
221 div->reg = base + CPG_ADSPCKCR; in cpg_adsp_clk_register()
222 div->width = 4; in cpg_adsp_clk_register()
223 div->table = cpg_adsp_div_table; in cpg_adsp_clk_register()
224 div->lock = &cpg_lock; in cpg_adsp_clk_register()
228 kfree(div); in cpg_adsp_clk_register()
229 return ERR_PTR(-ENOMEM); in cpg_adsp_clk_register()
232 gate->reg = base + CPG_ADSPCKCR; in cpg_adsp_clk_register()
233 gate->bit_idx = 8; in cpg_adsp_clk_register()
234 gate->flags = CLK_GATE_SET_TO_DISABLE; in cpg_adsp_clk_register()
235 gate->lock = &cpg_lock; in cpg_adsp_clk_register()
237 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, in cpg_adsp_clk_register()
238 &div->hw, &clk_divider_ops, in cpg_adsp_clk_register()
239 &gate->hw, &clk_gate_ops, 0); in cpg_adsp_clk_register()
240 if (IS_ERR(clk)) { in cpg_adsp_clk_register()
242 kfree(div); in cpg_adsp_clk_register()
245 return clk; in cpg_adsp_clk_register()
276 struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, in rcar_gen2_cpg_clk_register()
278 struct clk **clks, void __iomem *base, in rcar_gen2_cpg_clk_register()
282 const struct clk *parent; in rcar_gen2_cpg_clk_register()
285 unsigned int div = 1; in rcar_gen2_cpg_clk_register() local
288 parent = clks[core->parent]; in rcar_gen2_cpg_clk_register()
294 switch (core->type) { in rcar_gen2_cpg_clk_register()
295 /* R-Car Gen2 */ in rcar_gen2_cpg_clk_register()
297 div = cpg_pll_config->extal_div; in rcar_gen2_cpg_clk_register()
302 * PLL0 is a configurable multiplier clock except on R-Car in rcar_gen2_cpg_clk_register()
307 mult = cpg_pll_config->pll0_mult; in rcar_gen2_cpg_clk_register()
308 div = cpg_pll0_div; in rcar_gen2_cpg_clk_register()
318 mult = cpg_pll_config->pll1_mult / 2; in rcar_gen2_cpg_clk_register()
322 mult = cpg_pll_config->pll3_mult; in rcar_gen2_cpg_clk_register()
326 return cpg_z_clk_register(core->name, parent_name, base); in rcar_gen2_cpg_clk_register()
329 div = cpg_mode & BIT(18) ? 36 : 24; in rcar_gen2_cpg_clk_register()
333 return cpg_adsp_clk_register(core->name, parent_name, base); in rcar_gen2_cpg_clk_register()
357 div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ? in rcar_gen2_cpg_clk_register()
362 return cpg_rcan_clk_register(core->name, parent_name, base); in rcar_gen2_cpg_clk_register()
365 return ERR_PTR(-EINVAL); in rcar_gen2_cpg_clk_register()
369 return clk_register_fixed_factor(NULL, core->name, parent_name, in rcar_gen2_cpg_clk_register()
370 0, mult, div); in rcar_gen2_cpg_clk_register()
372 return clk_register_divider_table(NULL, core->name, in rcar_gen2_cpg_clk_register()
388 cpg_quirks = (uintptr_t)attr->data; in rcar_gen2_cpg_init()