Lines Matching +full:core +full:- +full:clk
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>
23 #include "renesas-cpg-mssr.h"
24 #include "rcar-gen4-cpg.h"
25 #include "rcar-cpg-lib.h"
33 #define CPG_PLLECR_PLLST(n) BIT(8 + ((n) < 3 ? (n) - 1 : \
67 #define CPG_SD0CKCR1 0x8a4 /* SD-IF0 Clock Freq. Control Reg. 1 */
86 u32 cr0 = readl(pll_clk->pllcr0_reg); in cpg_pll_8_25_clk_recalc_rate()
93 nf = FIELD_GET(CPG_PLLxCR1_NF25, readl(pll_clk->pllcr1_reg)); in cpg_pll_8_25_clk_recalc_rate()
105 u32 cr0 = readl(pll_clk->pllcr0_reg); in cpg_pll_8_25_clk_determine_rate()
108 prate = req->best_parent_rate * 2; in cpg_pll_8_25_clk_determine_rate()
109 min_mult = max(div64_ul(req->min_rate, prate), 1ULL); in cpg_pll_8_25_clk_determine_rate()
110 max_mult = min(div64_ul(req->max_rate, prate), 256ULL); in cpg_pll_8_25_clk_determine_rate()
112 return -EINVAL; in cpg_pll_8_25_clk_determine_rate()
115 ni = div64_ul(req->rate, prate); in cpg_pll_8_25_clk_determine_rate()
121 nf = div64_ul((u64)(req->rate - prate * ni) << 24, in cpg_pll_8_25_clk_determine_rate()
122 req->best_parent_rate); in cpg_pll_8_25_clk_determine_rate()
125 ni = DIV_ROUND_CLOSEST_ULL(req->rate, prate); in cpg_pll_8_25_clk_determine_rate()
129 req->rate = prate * ni + mul_u64_u32_shr(req->best_parent_rate, nf, 24); in cpg_pll_8_25_clk_determine_rate()
139 u32 cr0 = readl(pll_clk->pllcr0_reg); in cpg_pll_8_25_clk_set_rate()
150 nf = div64_ul((u64)(rate - prate * ni) << 24, in cpg_pll_8_25_clk_set_rate()
158 if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK) in cpg_pll_8_25_clk_set_rate()
159 return -EBUSY; in cpg_pll_8_25_clk_set_rate()
161 cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI8, in cpg_pll_8_25_clk_set_rate()
162 FIELD_PREP(CPG_PLLxCR0_NI8, ni - 1)); in cpg_pll_8_25_clk_set_rate()
164 cpg_reg_modify(pll_clk->pllcr1_reg, CPG_PLLxCR1_NF25, in cpg_pll_8_25_clk_set_rate()
171 cpg_reg_modify(pll_clk->pllcr0_reg, 0, CPG_PLLxCR0_KICK); in cpg_pll_8_25_clk_set_rate()
182 return readl_poll_timeout(pll_clk->pllecr_reg, val, in cpg_pll_8_25_clk_set_rate()
183 val & pll_clk->pllecr_pllst_mask, 0, 1000); in cpg_pll_8_25_clk_set_rate()
200 u32 cr0 = readl(pll_clk->pllcr0_reg); in cpg_pll_9_24_clk_recalc_rate()
207 nf = FIELD_GET(CPG_PLLxCR1_NF24, readl(pll_clk->pllcr1_reg)); in cpg_pll_9_24_clk_recalc_rate()
220 static struct clk * __init cpg_pll_clk_register(const char *name, in cpg_pll_clk_register()
227 [1 - 1] = { CPG_PLL1CR0, CPG_PLL1CR1 }, in cpg_pll_clk_register()
228 [2 - 1] = { CPG_PLL2CR0, CPG_PLL2CR1 }, in cpg_pll_clk_register()
229 [3 - 1] = { CPG_PLL3CR0, CPG_PLL3CR1 }, in cpg_pll_clk_register()
230 [4 - 1] = { CPG_PLL4CR0, CPG_PLL4CR1 }, in cpg_pll_clk_register()
231 [6 - 1] = { CPG_PLL6CR0, CPG_PLL6CR1 }, in cpg_pll_clk_register()
235 struct clk *clk; in cpg_pll_clk_register() local
239 return ERR_PTR(-ENOMEM); in cpg_pll_clk_register()
246 pll_clk->hw.init = &init; in cpg_pll_clk_register()
247 pll_clk->pllcr0_reg = base + pll_cr_offsets[index - 1].cr0; in cpg_pll_clk_register()
248 pll_clk->pllcr1_reg = base + pll_cr_offsets[index - 1].cr1; in cpg_pll_clk_register()
249 pll_clk->pllecr_reg = base + CPG_PLLECR; in cpg_pll_clk_register()
250 pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index); in cpg_pll_clk_register()
252 clk = clk_register(NULL, &pll_clk->hw); in cpg_pll_clk_register()
253 if (IS_ERR(clk)) in cpg_pll_clk_register()
256 return clk; in cpg_pll_clk_register()
285 val = readl(zclk->reg) & zclk->mask; in cpg_z_clk_recalc_rate()
286 mult = 32 - (val >> __ffs(zclk->mask)); in cpg_z_clk_recalc_rate()
289 32 * zclk->fixed_div); in cpg_z_clk_recalc_rate()
299 rate = min(req->rate, req->max_rate); in cpg_z_clk_determine_rate()
300 if (rate <= zclk->max_rate) { in cpg_z_clk_determine_rate()
302 prate = zclk->max_rate; in cpg_z_clk_determine_rate()
307 req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), in cpg_z_clk_determine_rate()
308 prate * zclk->fixed_div); in cpg_z_clk_determine_rate()
310 prate = req->best_parent_rate / zclk->fixed_div; in cpg_z_clk_determine_rate()
311 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); in cpg_z_clk_determine_rate()
312 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL); in cpg_z_clk_determine_rate()
314 return -EINVAL; in cpg_z_clk_determine_rate()
319 req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); in cpg_z_clk_determine_rate()
330 mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div, in cpg_z_clk_set_rate()
334 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) in cpg_z_clk_set_rate()
335 return -EBUSY; in cpg_z_clk_set_rate()
337 cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask)); in cpg_z_clk_set_rate()
343 cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK); in cpg_z_clk_set_rate()
354 for (i = 1000; i; i--) { in cpg_z_clk_set_rate()
355 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) in cpg_z_clk_set_rate()
361 return -ETIMEDOUT; in cpg_z_clk_set_rate()
370 static struct clk * __init cpg_z_clk_register(const char *name, in cpg_z_clk_register()
378 struct clk *clk; in cpg_z_clk_register() local
382 return ERR_PTR(-ENOMEM); in cpg_z_clk_register()
391 zclk->reg = reg + CPG_FRQCRC0; in cpg_z_clk_register()
393 zclk->reg = reg + CPG_FRQCRC1; in cpg_z_clk_register()
394 offset -= 32; in cpg_z_clk_register()
396 zclk->kick_reg = reg + CPG_FRQCRB; in cpg_z_clk_register()
397 zclk->hw.init = &init; in cpg_z_clk_register()
398 zclk->mask = GENMASK(offset + 4, offset); in cpg_z_clk_register()
399 zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ in cpg_z_clk_register()
401 clk = clk_register(NULL, &zclk->hw); in cpg_z_clk_register()
402 if (IS_ERR(clk)) { in cpg_z_clk_register()
404 return clk; in cpg_z_clk_register()
407 zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) / in cpg_z_clk_register()
408 zclk->fixed_div; in cpg_z_clk_register()
409 return clk; in cpg_z_clk_register()
419 struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev, in rcar_gen4_cpg_clk_register()
420 const struct cpg_core_clk *core, const struct cpg_mssr_info *info, in rcar_gen4_cpg_clk_register() argument
421 struct clk **clks, void __iomem *base, in rcar_gen4_cpg_clk_register()
424 const struct clk *parent; in rcar_gen4_cpg_clk_register()
429 parent = clks[core->parent & 0xffff]; /* some types use high bits */ in rcar_gen4_cpg_clk_register()
433 switch (core->type) { in rcar_gen4_cpg_clk_register()
435 div = cpg_pll_config->extal_div; in rcar_gen4_cpg_clk_register()
439 mult = cpg_pll_config->pll1_mult; in rcar_gen4_cpg_clk_register()
440 div = cpg_pll_config->pll1_div; in rcar_gen4_cpg_clk_register()
444 mult = cpg_pll_config->pll5_mult; in rcar_gen4_cpg_clk_register()
445 div = cpg_pll_config->pll5_div; in rcar_gen4_cpg_clk_register()
449 value = readl(base + core->offset); in rcar_gen4_cpg_clk_register()
454 return cpg_pll_clk_register(core->name, __clk_get_name(parent), in rcar_gen4_cpg_clk_register()
455 base, core->offset, in rcar_gen4_cpg_clk_register()
459 return cpg_pll_clk_register(core->name, __clk_get_name(parent), in rcar_gen4_cpg_clk_register()
460 base, core->offset, in rcar_gen4_cpg_clk_register()
467 return cpg_pll_clk_register(core->name, __clk_get_name(parent), in rcar_gen4_cpg_clk_register()
468 base, core->offset, in rcar_gen4_cpg_clk_register()
472 return cpg_z_clk_register(core->name, __clk_get_name(parent), in rcar_gen4_cpg_clk_register()
473 base, core->div, core->offset); in rcar_gen4_cpg_clk_register()
481 return cpg_sdh_clk_register(core->name, base + core->offset, in rcar_gen4_cpg_clk_register()
485 return cpg_sd_clk_register(core->name, base + core->offset, in rcar_gen4_cpg_clk_register()
493 if (cpg_mode & BIT(core->offset)) { in rcar_gen4_cpg_clk_register()
494 div = core->div & 0xffff; in rcar_gen4_cpg_clk_register()
496 parent = clks[core->parent >> 16]; in rcar_gen4_cpg_clk_register()
499 div = core->div >> 16; in rcar_gen4_cpg_clk_register()
508 div = cpg_pll_config->osc_prediv * core->div; in rcar_gen4_cpg_clk_register()
512 return clk_register_divider_table(NULL, core->name, in rcar_gen4_cpg_clk_register()
519 return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR, in rcar_gen4_cpg_clk_register()
523 return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR, in rcar_gen4_cpg_clk_register()
527 return ERR_PTR(-EINVAL); in rcar_gen4_cpg_clk_register()
530 return clk_register_fixed_factor(NULL, core->name, in rcar_gen4_cpg_clk_register()