Lines Matching +full:div +full:- +full:clk
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;
61 mult = 32 - val;
69 unsigned long prate = req->best_parent_rate;
72 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
73 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
75 return -EINVAL;
77 mult = div64_ul(req->rate * 32ULL, prate);
80 req->rate = div_u64((u64)prate * mult, 32);
95 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
96 return -EBUSY;
98 val = readl(zclk->reg);
100 val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
101 writel(val, zclk->reg);
107 kick = readl(zclk->kick_reg);
109 writel(kick, zclk->kick_reg);
120 for (i = 1000; i; i--) {
121 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
127 return -ETIMEDOUT;
136 static struct clk * __init cpg_z_clk_register(const char *name,
142 struct clk *clk;
146 return ERR_PTR(-ENOMEM);
153 zclk->reg = base + CPG_FRQCRC;
154 zclk->kick_reg = base + CPG_FRQCRB;
155 zclk->hw.init = &init;
157 clk = clk_register(NULL, &zclk->hw);
158 if (IS_ERR(clk))
161 return clk;
164 static struct clk * __init cpg_rcan_clk_register(const char *name,
170 struct clk *clk;
174 return ERR_PTR(-ENOMEM);
176 fixed->mult = 1;
177 fixed->div = 6;
182 return ERR_PTR(-ENOMEM);
185 gate->reg = base + CPG_RCANCKCR;
186 gate->bit_idx = 8;
187 gate->flags = CLK_GATE_SET_TO_DISABLE;
188 gate->lock = &cpg_lock;
190 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
191 &fixed->hw, &clk_fixed_factor_ops,
192 &gate->hw, &clk_gate_ops, 0);
193 if (IS_ERR(clk)) {
198 return clk;
208 static struct clk * __init cpg_adsp_clk_register(const char *name,
212 struct clk_divider *div;
214 struct clk *clk;
216 div = kzalloc(sizeof(*div), GFP_KERNEL);
217 if (!div)
218 return ERR_PTR(-ENOMEM);
220 div->reg = base + CPG_ADSPCKCR;
221 div->width = 4;
222 div->table = cpg_adsp_div_table;
223 div->lock = &cpg_lock;
227 kfree(div);
228 return ERR_PTR(-ENOMEM);
231 gate->reg = base + CPG_ADSPCKCR;
232 gate->bit_idx = 8;
233 gate->flags = CLK_GATE_SET_TO_DISABLE;
234 gate->lock = &cpg_lock;
236 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
237 &div->hw, &clk_divider_ops,
238 &gate->hw, &clk_gate_ops, 0);
239 if (IS_ERR(clk)) {
241 kfree(div);
244 return clk;
275 struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
280 void __iomem *base = pub->base0;
281 struct clk **clks = pub->clks;
282 const struct clk *parent;
285 unsigned int div = 1;
288 parent = clks[core->parent];
294 switch (core->type) {
295 /* R-Car Gen2 */
297 div = cpg_pll_config->extal_div;
302 * PLL0 is a configurable multiplier clock except on R-Car
307 mult = cpg_pll_config->pll0_mult;
308 div = cpg_pll0_div;
318 mult = cpg_pll_config->pll1_mult / 2;
322 mult = cpg_pll_config->pll3_mult;
326 return cpg_z_clk_register(core->name, parent_name, base);
329 div = cpg_mode & BIT(18) ? 36 : 24;
333 return cpg_adsp_clk_register(core->name, parent_name, base);
357 div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
362 return cpg_rcan_clk_register(core->name, parent_name, base);
365 return ERR_PTR(-EINVAL);
369 return clk_register_fixed_factor(NULL, core->name, parent_name,
370 0, mult, div);
372 return clk_register_divider_table(NULL, core->name,
388 cpg_quirks = (uintptr_t)attr->data;