Lines Matching +full:cpg +full:- +full:mstp +full:- +full:clocks

1 // SPDX-License-Identifier: GPL-2.0
7 * Based on renesas-cpg-mssr.c
15 #include <linux/clk-provider.h>
27 #include <linux/reset-controller.h>
30 #include <dt-bindings/clock/renesas-cpg-mssr.h>
32 #include "rzg2l-cpg.h"
59 * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
62 * @dev: CPG device
63 * @base: CPG register block base address
65 * @clks: Array containing all Core and Module Clocks
66 * @num_core_clks: Number of Core Clocks in clks[]
67 * @num_mod_clks: Number of Module Clocks in clks[]
99 struct device *dev = priv->dev; in rzg2l_cpg_div_clk_register()
104 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_div_clk_register()
110 if (core->dtable) in rzg2l_cpg_div_clk_register()
111 clk_hw = clk_hw_register_divider_table(dev, core->name, in rzg2l_cpg_div_clk_register()
113 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
114 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
115 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
116 core->flag, in rzg2l_cpg_div_clk_register()
117 core->dtable, in rzg2l_cpg_div_clk_register()
118 &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
120 clk_hw = clk_hw_register_divider(dev, core->name, in rzg2l_cpg_div_clk_register()
122 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
123 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
124 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
125 core->flag, &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
130 return clk_hw->clk; in rzg2l_cpg_div_clk_register()
147 struct rzg2l_cpg_priv *priv = pll_clk->priv; in rzg2l_cpg_pll_clk_recalc_rate()
152 if (pll_clk->type != CLK_TYPE_SAM_PLL) in rzg2l_cpg_pll_clk_recalc_rate()
155 val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
156 val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
173 struct device *dev = priv->dev; in rzg2l_cpg_pll_clk_register()
179 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_pll_clk_register()
185 return ERR_PTR(-ENOMEM); in rzg2l_cpg_pll_clk_register()
188 init.name = core->name; in rzg2l_cpg_pll_clk_register()
194 pll_clk->hw.init = &init; in rzg2l_cpg_pll_clk_register()
195 pll_clk->conf = core->conf; in rzg2l_cpg_pll_clk_register()
196 pll_clk->base = base; in rzg2l_cpg_pll_clk_register()
197 pll_clk->priv = priv; in rzg2l_cpg_pll_clk_register()
198 pll_clk->type = core->type; in rzg2l_cpg_pll_clk_register()
200 return clk_register(NULL, &pll_clk->hw); in rzg2l_cpg_pll_clk_register()
207 unsigned int clkidx = clkspec->args[1]; in rzg2l_cpg_clk_src_twocell_get()
209 struct device *dev = priv->dev; in rzg2l_cpg_clk_src_twocell_get()
213 switch (clkspec->args[0]) { in rzg2l_cpg_clk_src_twocell_get()
216 if (clkidx > priv->last_dt_core_clk) { in rzg2l_cpg_clk_src_twocell_get()
218 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
220 clk = priv->clks[clkidx]; in rzg2l_cpg_clk_src_twocell_get()
225 if (clkidx >= priv->num_mod_clks) { in rzg2l_cpg_clk_src_twocell_get()
228 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
230 clk = priv->clks[priv->num_core_clks + clkidx]; in rzg2l_cpg_clk_src_twocell_get()
234 dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); in rzg2l_cpg_clk_src_twocell_get()
235 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
243 clkspec->args[0], clkspec->args[1], clk, in rzg2l_cpg_clk_src_twocell_get()
253 struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; in rzg2l_cpg_register_core_clk()
254 struct device *dev = priv->dev; in rzg2l_cpg_register_core_clk()
255 unsigned int id = core->id, div = core->div; in rzg2l_cpg_register_core_clk()
258 WARN_DEBUG(id >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
259 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_core_clk()
261 if (!core->name) { in rzg2l_cpg_register_core_clk()
266 switch (core->type) { in rzg2l_cpg_register_core_clk()
268 clk = of_clk_get_by_name(priv->dev->of_node, core->name); in rzg2l_cpg_register_core_clk()
271 WARN_DEBUG(core->parent >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
272 parent = priv->clks[core->parent]; in rzg2l_cpg_register_core_clk()
279 clk = clk_register_fixed_factor(NULL, core->name, in rzg2l_cpg_register_core_clk()
281 core->mult, div); in rzg2l_cpg_register_core_clk()
284 clk = rzg2l_cpg_pll_clk_register(core, priv->clks, in rzg2l_cpg_register_core_clk()
285 priv->base, priv); in rzg2l_cpg_register_core_clk()
288 clk = rzg2l_cpg_div_clk_register(core, priv->clks, in rzg2l_cpg_register_core_clk()
289 priv->base, priv); in rzg2l_cpg_register_core_clk()
299 priv->clks[id] = clk; in rzg2l_cpg_register_core_clk()
304 core->name, PTR_ERR(clk)); in rzg2l_cpg_register_core_clk()
308 * struct mstp_clock - MSTP gating clock
310 * @hw: handle between common and hardware-specific interfaces
313 * @priv: CPG/MSTP private data
327 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_endisable()
328 unsigned int reg = clock->off; in rzg2l_mod_clock_endisable()
329 struct device *dev = priv->dev; in rzg2l_mod_clock_endisable()
332 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_endisable()
335 if (!clock->off) { in rzg2l_mod_clock_endisable()
336 dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_endisable()
340 dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk, in rzg2l_mod_clock_endisable()
342 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_endisable()
348 writel(value, priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
350 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_endisable()
355 for (i = 1000; i > 0; --i) { in rzg2l_mod_clock_endisable()
356 if (((readl(priv->base + CLK_MON_R(reg))) & bitmask)) in rzg2l_mod_clock_endisable()
363 priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
364 return -ETIMEDOUT; in rzg2l_mod_clock_endisable()
383 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_is_enabled()
384 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_is_enabled()
387 if (!clock->off) { in rzg2l_mod_clock_is_enabled()
388 dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_is_enabled()
392 value = readl(priv->base + CLK_MON_R(clock->off)); in rzg2l_mod_clock_is_enabled()
409 struct device *dev = priv->dev; in rzg2l_cpg_register_mod_clk()
410 unsigned int id = mod->id; in rzg2l_cpg_register_mod_clk()
416 WARN_DEBUG(id < priv->num_core_clks); in rzg2l_cpg_register_mod_clk()
417 WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
418 WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
419 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_mod_clk()
421 if (!mod->name) { in rzg2l_cpg_register_mod_clk()
426 parent = priv->clks[mod->parent]; in rzg2l_cpg_register_mod_clk()
434 clk = ERR_PTR(-ENOMEM); in rzg2l_cpg_register_mod_clk()
438 init.name = mod->name; in rzg2l_cpg_register_mod_clk()
441 for (i = 0; i < info->num_crit_mod_clks; i++) in rzg2l_cpg_register_mod_clk()
442 if (id == info->crit_mod_clks[i]) { in rzg2l_cpg_register_mod_clk()
443 dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n", in rzg2l_cpg_register_mod_clk()
444 mod->name); in rzg2l_cpg_register_mod_clk()
453 clock->off = mod->off; in rzg2l_cpg_register_mod_clk()
454 clock->bit = mod->bit; in rzg2l_cpg_register_mod_clk()
455 clock->priv = priv; in rzg2l_cpg_register_mod_clk()
456 clock->hw.init = &init; in rzg2l_cpg_register_mod_clk()
458 clk = clk_register(NULL, &clock->hw); in rzg2l_cpg_register_mod_clk()
463 priv->clks[id] = clk; in rzg2l_cpg_register_mod_clk()
468 mod->name, PTR_ERR(clk)); in rzg2l_cpg_register_mod_clk()
477 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_reset()
478 unsigned int reg = info->resets[id].off; in rzg2l_cpg_reset()
479 u32 dis = BIT(info->resets[id].bit); in rzg2l_cpg_reset()
482 dev_dbg(rcdev->dev, "reset id:%ld offset:0x%x\n", id, CLK_RST_R(reg)); in rzg2l_cpg_reset()
485 writel(we, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_reset()
491 writel(we | dis, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_reset()
500 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_assert()
501 unsigned int reg = info->resets[id].off; in rzg2l_cpg_assert()
502 u32 value = BIT(info->resets[id].bit) << 16; in rzg2l_cpg_assert()
504 dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg)); in rzg2l_cpg_assert()
506 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_assert()
514 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_deassert()
515 unsigned int reg = info->resets[id].off; in rzg2l_cpg_deassert()
516 u32 dis = BIT(info->resets[id].bit); in rzg2l_cpg_deassert()
519 dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id, in rzg2l_cpg_deassert()
522 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_deassert()
530 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_status()
531 unsigned int reg = info->resets[id].off; in rzg2l_cpg_status()
532 u32 bitmask = BIT(info->resets[id].bit); in rzg2l_cpg_status()
534 return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask); in rzg2l_cpg_status()
548 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_reset_xlate()
549 unsigned int id = reset_spec->args[0]; in rzg2l_cpg_reset_xlate()
551 if (id >= rcdev->nr_resets || !info->resets[id].off) { in rzg2l_cpg_reset_xlate()
552 dev_err(rcdev->dev, "Invalid reset index %u\n", id); in rzg2l_cpg_reset_xlate()
553 return -EINVAL; in rzg2l_cpg_reset_xlate()
561 priv->rcdev.ops = &rzg2l_cpg_reset_ops; in rzg2l_cpg_reset_controller_register()
562 priv->rcdev.of_node = priv->dev->of_node; in rzg2l_cpg_reset_controller_register()
563 priv->rcdev.dev = priv->dev; in rzg2l_cpg_reset_controller_register()
564 priv->rcdev.of_reset_n_cells = 1; in rzg2l_cpg_reset_controller_register()
565 priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate; in rzg2l_cpg_reset_controller_register()
566 priv->rcdev.nr_resets = priv->num_resets; in rzg2l_cpg_reset_controller_register()
568 return devm_reset_controller_register(priv->dev, &priv->rcdev); in rzg2l_cpg_reset_controller_register()
573 if (clkspec->args_count != 2) in rzg2l_cpg_is_pm_clk()
576 switch (clkspec->args[0]) { in rzg2l_cpg_is_pm_clk()
587 struct device_node *np = dev->of_node; in rzg2l_cpg_attach_dev()
594 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, in rzg2l_cpg_attach_dev()
643 struct device_node *np = dev->of_node; in rzg2l_cpg_add_clk_domain()
648 return -ENOMEM; in rzg2l_cpg_add_clk_domain()
650 genpd->name = np->name; in rzg2l_cpg_add_clk_domain()
651 genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | in rzg2l_cpg_add_clk_domain()
653 genpd->attach_dev = rzg2l_cpg_attach_dev; in rzg2l_cpg_add_clk_domain()
654 genpd->detach_dev = rzg2l_cpg_detach_dev; in rzg2l_cpg_add_clk_domain()
663 struct device *dev = &pdev->dev; in rzg2l_cpg_probe()
664 struct device_node *np = dev->of_node; in rzg2l_cpg_probe()
675 return -ENOMEM; in rzg2l_cpg_probe()
677 priv->dev = dev; in rzg2l_cpg_probe()
678 priv->info = info; in rzg2l_cpg_probe()
679 spin_lock_init(&priv->rmw_lock); in rzg2l_cpg_probe()
681 priv->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_cpg_probe()
682 if (IS_ERR(priv->base)) in rzg2l_cpg_probe()
683 return PTR_ERR(priv->base); in rzg2l_cpg_probe()
685 nclks = info->num_total_core_clks + info->num_hw_mod_clks; in rzg2l_cpg_probe()
688 return -ENOMEM; in rzg2l_cpg_probe()
691 priv->clks = clks; in rzg2l_cpg_probe()
692 priv->num_core_clks = info->num_total_core_clks; in rzg2l_cpg_probe()
693 priv->num_mod_clks = info->num_hw_mod_clks; in rzg2l_cpg_probe()
694 priv->num_resets = info->num_resets; in rzg2l_cpg_probe()
695 priv->last_dt_core_clk = info->last_dt_core_clk; in rzg2l_cpg_probe()
698 clks[i] = ERR_PTR(-ENOENT); in rzg2l_cpg_probe()
700 for (i = 0; i < info->num_core_clks; i++) in rzg2l_cpg_probe()
701 rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv); in rzg2l_cpg_probe()
703 for (i = 0; i < info->num_mod_clks; i++) in rzg2l_cpg_probe()
704 rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv); in rzg2l_cpg_probe()
728 .compatible = "renesas,r9a07g044-cpg",
737 .name = "rzg2l-cpg",
749 MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver");