Lines Matching +full:clock +full:- +full:name
1 // SPDX-License-Identifier: GPL-2.0
3 * R-Car Gen3 Clock Pulse Generator
5 * Copyright (C) 2015-2018 Glider bvba
8 * Based on clk-rcar-gen3.c
16 #include <linux/clk-provider.h>
25 #include "renesas-cpg-mssr.h"
26 #include "rcar-gen3-cpg.h"
32 #define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */
63 csn->saved = readl(csn->reg); in cpg_simple_notifier_call()
67 writel(csn->saved, csn->reg); in cpg_simple_notifier_call()
76 csn->nb.notifier_call = cpg_simple_notifier_call; in cpg_simple_notifier_register()
77 raw_notifier_chain_register(notifiers, &csn->nb); in cpg_simple_notifier_register()
81 * Z Clock & Z2 Clock
83 * Traits of this clock:
84 * prepare - clk_prepare only ensures that parents are prepared
85 * enable - clk_enable only ensures that parents are enabled
86 * rate - rate is adjustable. clk->rate = (parent->rate * mult / 32 ) / 2
87 * parent - fixed parent. No clk_set_parent support
110 val = readl(zclk->reg) & zclk->mask; in cpg_z_clk_recalc_rate()
111 mult = 32 - (val >> __ffs(zclk->mask)); in cpg_z_clk_recalc_rate()
114 32 * zclk->fixed_div); in cpg_z_clk_recalc_rate()
124 prate = req->best_parent_rate / zclk->fixed_div; in cpg_z_clk_determine_rate()
125 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); in cpg_z_clk_determine_rate()
126 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL); in cpg_z_clk_determine_rate()
128 return -EINVAL; in cpg_z_clk_determine_rate()
130 mult = div64_ul(req->rate * 32ULL, prate); in cpg_z_clk_determine_rate()
133 req->rate = div_u64((u64)prate * mult, 32); in cpg_z_clk_determine_rate()
144 mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div, in cpg_z_clk_set_rate()
148 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) in cpg_z_clk_set_rate()
149 return -EBUSY; in cpg_z_clk_set_rate()
151 cpg_reg_modify(zclk->reg, zclk->mask, in cpg_z_clk_set_rate()
152 ((32 - mult) << __ffs(zclk->mask)) & zclk->mask); in cpg_z_clk_set_rate()
156 * clock change completion. in cpg_z_clk_set_rate()
158 cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK); in cpg_z_clk_set_rate()
169 for (i = 1000; i; i--) { in cpg_z_clk_set_rate()
170 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) in cpg_z_clk_set_rate()
176 return -ETIMEDOUT; in cpg_z_clk_set_rate()
185 static struct clk * __init cpg_z_clk_register(const char *name, in cpg_z_clk_register() argument
197 return ERR_PTR(-ENOMEM); in cpg_z_clk_register()
199 init.name = name; in cpg_z_clk_register()
205 zclk->reg = reg + CPG_FRQCRC; in cpg_z_clk_register()
206 zclk->kick_reg = reg + CPG_FRQCRB; in cpg_z_clk_register()
207 zclk->hw.init = &init; in cpg_z_clk_register()
208 zclk->mask = GENMASK(offset + 4, offset); in cpg_z_clk_register()
209 zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ in cpg_z_clk_register()
211 clk = clk_register(NULL, &zclk->hw); in cpg_z_clk_register()
219 * SDn Clock
252 *-------------------------------------------------------------------
266 * early ES versions of H3 and M3-W requires a specific setting to work.
286 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_enable() local
288 cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, in cpg_sd_clock_enable()
289 clock->div_table[clock->cur_div_idx].val & in cpg_sd_clock_enable()
297 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_disable() local
299 cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); in cpg_sd_clock_disable()
304 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_is_enabled() local
306 return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); in cpg_sd_clock_is_enabled()
312 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_recalc_rate() local
315 clock->div_table[clock->cur_div_idx].div); in cpg_sd_clock_recalc_rate()
322 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_determine_rate() local
326 for (i = 0; i < clock->div_num; i++) { in cpg_sd_clock_determine_rate()
327 calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, in cpg_sd_clock_determine_rate()
328 clock->div_table[i].div); in cpg_sd_clock_determine_rate()
329 if (calc_rate < req->min_rate || calc_rate > req->max_rate) in cpg_sd_clock_determine_rate()
332 diff = calc_rate > req->rate ? calc_rate - req->rate in cpg_sd_clock_determine_rate()
333 : req->rate - calc_rate; in cpg_sd_clock_determine_rate()
341 return -EINVAL; in cpg_sd_clock_determine_rate()
343 req->rate = best_rate; in cpg_sd_clock_determine_rate()
350 struct sd_clock *clock = to_sd_clock(hw); in cpg_sd_clock_set_rate() local
353 for (i = 0; i < clock->div_num; i++) in cpg_sd_clock_set_rate()
355 clock->div_table[i].div)) in cpg_sd_clock_set_rate()
358 if (i >= clock->div_num) in cpg_sd_clock_set_rate()
359 return -EINVAL; in cpg_sd_clock_set_rate()
361 clock->cur_div_idx = i; in cpg_sd_clock_set_rate()
363 cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, in cpg_sd_clock_set_rate()
364 clock->div_table[i].val & in cpg_sd_clock_set_rate()
381 #define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
383 #define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
385 static struct clk * __init cpg_sd_clk_register(const char *name, in cpg_sd_clk_register() argument
390 struct sd_clock *clock; in cpg_sd_clk_register() local
394 clock = kzalloc(sizeof(*clock), GFP_KERNEL); in cpg_sd_clk_register()
395 if (!clock) in cpg_sd_clk_register()
396 return ERR_PTR(-ENOMEM); in cpg_sd_clk_register()
398 init.name = name; in cpg_sd_clk_register()
404 clock->csn.reg = base + offset; in cpg_sd_clk_register()
405 clock->hw.init = &init; in cpg_sd_clk_register()
406 clock->div_table = cpg_sd_div_table; in cpg_sd_clk_register()
407 clock->div_num = ARRAY_SIZE(cpg_sd_div_table); in cpg_sd_clk_register()
410 clock->div_table++; in cpg_sd_clk_register()
411 clock->div_num--; in cpg_sd_clk_register()
414 val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK; in cpg_sd_clk_register()
415 val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); in cpg_sd_clk_register()
416 writel(val, clock->csn.reg); in cpg_sd_clk_register()
418 clk = clk_register(NULL, &clock->hw); in cpg_sd_clk_register()
422 cpg_simple_notifier_register(notifiers, &clock->csn); in cpg_sd_clk_register()
426 kfree(clock); in cpg_sd_clk_register()
448 static struct clk * __init cpg_rpc_clk_register(const char *name, in cpg_rpc_clk_register() argument
457 return ERR_PTR(-ENOMEM); in cpg_rpc_clk_register()
459 rpc->div.reg = base + CPG_RPCCKCR; in cpg_rpc_clk_register()
460 rpc->div.width = 3; in cpg_rpc_clk_register()
461 rpc->div.table = cpg_rpc_div_table; in cpg_rpc_clk_register()
462 rpc->div.lock = &cpg_lock; in cpg_rpc_clk_register()
464 rpc->gate.reg = base + CPG_RPCCKCR; in cpg_rpc_clk_register()
465 rpc->gate.bit_idx = 8; in cpg_rpc_clk_register()
466 rpc->gate.flags = CLK_GATE_SET_TO_DISABLE; in cpg_rpc_clk_register()
467 rpc->gate.lock = &cpg_lock; in cpg_rpc_clk_register()
469 rpc->csn.reg = base + CPG_RPCCKCR; in cpg_rpc_clk_register()
471 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, in cpg_rpc_clk_register()
472 &rpc->div.hw, &clk_divider_ops, in cpg_rpc_clk_register()
473 &rpc->gate.hw, &clk_gate_ops, in cpg_rpc_clk_register()
480 cpg_simple_notifier_register(notifiers, &rpc->csn); in cpg_rpc_clk_register()
489 static struct clk * __init cpg_rpcd2_clk_register(const char *name, in cpg_rpcd2_clk_register() argument
498 return ERR_PTR(-ENOMEM); in cpg_rpcd2_clk_register()
500 rpcd2->fixed.mult = 1; in cpg_rpcd2_clk_register()
501 rpcd2->fixed.div = 2; in cpg_rpcd2_clk_register()
503 rpcd2->gate.reg = base + CPG_RPCCKCR; in cpg_rpcd2_clk_register()
504 rpcd2->gate.bit_idx = 9; in cpg_rpcd2_clk_register()
505 rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE; in cpg_rpcd2_clk_register()
506 rpcd2->gate.lock = &cpg_lock; in cpg_rpcd2_clk_register()
508 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, in cpg_rpcd2_clk_register()
509 &rpcd2->fixed.hw, &clk_fixed_factor_ops, in cpg_rpcd2_clk_register()
510 &rpcd2->gate.hw, &clk_gate_ops, in cpg_rpcd2_clk_register()
557 parent = clks[core->parent & 0xffff]; /* some types use high bits */ in rcar_gen3_cpg_clk_register()
561 switch (core->type) { in rcar_gen3_cpg_clk_register()
563 div = cpg_pll_config->extal_div; in rcar_gen3_cpg_clk_register()
568 * PLL0 is a configurable multiplier clock. Register it as a in rcar_gen3_cpg_clk_register()
569 * fixed factor clock for now as there's no generic multiplier in rcar_gen3_cpg_clk_register()
570 * clock implementation and we currently have no need to change in rcar_gen3_cpg_clk_register()
580 mult = cpg_pll_config->pll1_mult; in rcar_gen3_cpg_clk_register()
581 div = cpg_pll_config->pll1_div; in rcar_gen3_cpg_clk_register()
586 * PLL2 is a configurable multiplier clock. Register it as a in rcar_gen3_cpg_clk_register()
587 * fixed factor clock for now as there's no generic multiplier in rcar_gen3_cpg_clk_register()
588 * clock implementation and we currently have no need to change in rcar_gen3_cpg_clk_register()
598 mult = cpg_pll_config->pll3_mult; in rcar_gen3_cpg_clk_register()
599 div = cpg_pll_config->pll3_div; in rcar_gen3_cpg_clk_register()
604 * PLL4 is a configurable multiplier clock. Register it as a in rcar_gen3_cpg_clk_register()
605 * fixed factor clock for now as there's no generic multiplier in rcar_gen3_cpg_clk_register()
606 * clock implementation and we currently have no need to change in rcar_gen3_cpg_clk_register()
616 return cpg_sd_clk_register(core->name, base, core->offset, in rcar_gen3_cpg_clk_register()
625 return ERR_PTR(-ENOMEM); in rcar_gen3_cpg_clk_register()
627 csn->reg = base + CPG_RCKCR; in rcar_gen3_cpg_clk_register()
633 value = readl(csn->reg) & 0x3f; in rcar_gen3_cpg_clk_register()
640 writel(value, csn->reg); in rcar_gen3_cpg_clk_register()
645 /* Select parent clock of RCLK by MD28 */ in rcar_gen3_cpg_clk_register()
652 * Clock selectable between two parents and two fixed dividers in rcar_gen3_cpg_clk_register()
655 if (cpg_mode & BIT(core->offset)) { in rcar_gen3_cpg_clk_register()
656 div = core->div & 0xffff; in rcar_gen3_cpg_clk_register()
658 parent = clks[core->parent >> 16]; in rcar_gen3_cpg_clk_register()
661 div = core->div >> 16; in rcar_gen3_cpg_clk_register()
667 return cpg_z_clk_register(core->name, __clk_get_name(parent), in rcar_gen3_cpg_clk_register()
668 base, core->div, core->offset); in rcar_gen3_cpg_clk_register()
672 * Clock combining OSC EXTAL predivider and a fixed divider in rcar_gen3_cpg_clk_register()
674 div = cpg_pll_config->osc_prediv * core->div; in rcar_gen3_cpg_clk_register()
679 * Clock selectable between two parents and two fixed dividers in rcar_gen3_cpg_clk_register()
683 div = core->div & 0xffff; in rcar_gen3_cpg_clk_register()
685 parent = clks[core->parent >> 16]; in rcar_gen3_cpg_clk_register()
688 div = core->div >> 16; in rcar_gen3_cpg_clk_register()
693 return clk_register_divider_table(NULL, core->name, in rcar_gen3_cpg_clk_register()
700 return cpg_rpc_clk_register(core->name, base, in rcar_gen3_cpg_clk_register()
704 return cpg_rpcd2_clk_register(core->name, base, in rcar_gen3_cpg_clk_register()
708 return ERR_PTR(-EINVAL); in rcar_gen3_cpg_clk_register()
711 return clk_register_fixed_factor(NULL, core->name, in rcar_gen3_cpg_clk_register()
725 cpg_quirks = (uintptr_t)attr->data; in rcar_gen3_cpg_init()