Lines Matching +full:clk +full:- +full:div

1 // SPDX-License-Identifier: GPL-2.0
3 * R-Car Gen4 Clock Pulse Generator
7 * Based on rcar-gen3-cpg.c
9 * Copyright (C) 2015-2018 Glider bvba
14 #include <linux/clk.h>
15 #include <linux/clk-provider.h>
22 #include "renesas-cpg-mssr.h"
23 #include "rcar-gen4-cpg.h"
24 #include "rcar-cpg-lib.h"
55 val = readl(zclk->reg) & zclk->mask; in cpg_z_clk_recalc_rate()
56 mult = 32 - (val >> __ffs(zclk->mask)); in cpg_z_clk_recalc_rate()
59 32 * zclk->fixed_div); in cpg_z_clk_recalc_rate()
69 rate = min(req->rate, req->max_rate); in cpg_z_clk_determine_rate()
70 if (rate <= zclk->max_rate) { in cpg_z_clk_determine_rate()
72 prate = zclk->max_rate; in cpg_z_clk_determine_rate()
77 req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), in cpg_z_clk_determine_rate()
78 prate * zclk->fixed_div); in cpg_z_clk_determine_rate()
80 prate = req->best_parent_rate / zclk->fixed_div; in cpg_z_clk_determine_rate()
81 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); in cpg_z_clk_determine_rate()
82 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL); in cpg_z_clk_determine_rate()
84 return -EINVAL; in cpg_z_clk_determine_rate()
89 req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); in cpg_z_clk_determine_rate()
100 mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div, in cpg_z_clk_set_rate()
104 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) in cpg_z_clk_set_rate()
105 return -EBUSY; in cpg_z_clk_set_rate()
107 cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask)); in cpg_z_clk_set_rate()
113 cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK); in cpg_z_clk_set_rate()
124 for (i = 1000; i; i--) { in cpg_z_clk_set_rate()
125 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) in cpg_z_clk_set_rate()
131 return -ETIMEDOUT; in cpg_z_clk_set_rate()
140 static struct clk * __init cpg_z_clk_register(const char *name, in cpg_z_clk_register()
143 unsigned int div, in cpg_z_clk_register() argument
148 struct clk *clk; in cpg_z_clk_register() local
152 return ERR_PTR(-ENOMEM); in cpg_z_clk_register()
160 zclk->reg = reg + CPG_FRQCRC; in cpg_z_clk_register()
161 zclk->kick_reg = reg + CPG_FRQCRB; in cpg_z_clk_register()
162 zclk->hw.init = &init; in cpg_z_clk_register()
163 zclk->mask = GENMASK(offset + 4, offset); in cpg_z_clk_register()
164 zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ in cpg_z_clk_register()
166 clk = clk_register(NULL, &zclk->hw); in cpg_z_clk_register()
167 if (IS_ERR(clk)) { in cpg_z_clk_register()
169 return clk; in cpg_z_clk_register()
172 zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) / in cpg_z_clk_register()
173 zclk->fixed_div; in cpg_z_clk_register()
174 return clk; in cpg_z_clk_register()
184 struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev, in rcar_gen4_cpg_clk_register()
186 struct clk **clks, void __iomem *base, in rcar_gen4_cpg_clk_register()
189 const struct clk *parent; in rcar_gen4_cpg_clk_register()
191 unsigned int div = 1; in rcar_gen4_cpg_clk_register() local
194 parent = clks[core->parent & 0xffff]; /* some types use high bits */ in rcar_gen4_cpg_clk_register()
198 switch (core->type) { in rcar_gen4_cpg_clk_register()
200 div = cpg_pll_config->extal_div; in rcar_gen4_cpg_clk_register()
204 mult = cpg_pll_config->pll1_mult; in rcar_gen4_cpg_clk_register()
205 div = cpg_pll_config->pll1_div; in rcar_gen4_cpg_clk_register()
209 mult = cpg_pll_config->pll2_mult; in rcar_gen4_cpg_clk_register()
210 div = cpg_pll_config->pll2_div; in rcar_gen4_cpg_clk_register()
214 mult = cpg_pll_config->pll3_mult; in rcar_gen4_cpg_clk_register()
215 div = cpg_pll_config->pll3_div; in rcar_gen4_cpg_clk_register()
219 mult = cpg_pll_config->pll4_mult; in rcar_gen4_cpg_clk_register()
220 div = cpg_pll_config->pll4_div; in rcar_gen4_cpg_clk_register()
224 mult = cpg_pll_config->pll5_mult; in rcar_gen4_cpg_clk_register()
225 div = cpg_pll_config->pll5_div; in rcar_gen4_cpg_clk_register()
229 mult = cpg_pll_config->pll6_mult; in rcar_gen4_cpg_clk_register()
230 div = cpg_pll_config->pll6_div; in rcar_gen4_cpg_clk_register()
234 value = readl(base + core->offset); in rcar_gen4_cpg_clk_register()
239 return cpg_z_clk_register(core->name, __clk_get_name(parent), in rcar_gen4_cpg_clk_register()
240 base, core->div, core->offset); in rcar_gen4_cpg_clk_register()
243 div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 4; in rcar_gen4_cpg_clk_register()
247 return cpg_sdh_clk_register(core->name, base + core->offset, in rcar_gen4_cpg_clk_register()
251 return cpg_sd_clk_register(core->name, base + core->offset, in rcar_gen4_cpg_clk_register()
259 if (cpg_mode & BIT(core->offset)) { in rcar_gen4_cpg_clk_register()
260 div = core->div & 0xffff; in rcar_gen4_cpg_clk_register()
262 parent = clks[core->parent >> 16]; in rcar_gen4_cpg_clk_register()
265 div = core->div >> 16; in rcar_gen4_cpg_clk_register()
274 div = cpg_pll_config->osc_prediv * core->div; in rcar_gen4_cpg_clk_register()
278 return clk_register_divider_table(NULL, core->name, in rcar_gen4_cpg_clk_register()
285 return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR, in rcar_gen4_cpg_clk_register()
289 return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR, in rcar_gen4_cpg_clk_register()
293 return ERR_PTR(-EINVAL); in rcar_gen4_cpg_clk_register()
296 return clk_register_fixed_factor(NULL, core->name, in rcar_gen4_cpg_clk_register()
297 __clk_get_name(parent), 0, mult, div); in rcar_gen4_cpg_clk_register()