• Home
  • Raw
  • Download

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

1 // SPDX-License-Identifier: GPL-2.0
7 * Based on renesas-cpg-mssr.c
16 #include <linux/clk-provider.h>
28 #include <linux/reset-controller.h>
32 #include <dt-bindings/clock/renesas-cpg-mssr.h>
34 #include "rzg2l-cpg.h"
64 * struct clk_hw_data - clock hardware data
68 * @priv: CPG private data structure
80 * struct sd_mux_hw_data - SD MUX clock hardware data
107 * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
110 * @dev: CPG device
111 * @base: CPG register block base address
113 * @clks: Array containing all Core and Module Clocks
114 * @num_core_clks: Number of Core Clocks in clks[]
115 * @num_mod_clks: Number of Module Clocks in clks[]
116 * @num_resets: Number of Module Resets in info->resets[]
149 u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf); in rzg2l_cpg_wait_clk_update_done()
160 struct clk_hw *hw = __clk_get_hw(cnd->clk); in rzg2l_cpg_sd_clk_mux_notifier()
162 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_notifier()
163 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_notifier()
164 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_notifier()
169 if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266)) in rzg2l_cpg_sd_clk_mux_notifier()
172 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_notifier()
182 * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and in rzg2l_cpg_sd_clk_mux_notifier()
186 writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off); in rzg2l_cpg_sd_clk_mux_notifier()
189 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg2l_cpg_sd_clk_mux_notifier()
191 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_notifier()
194 dev_err(priv->dev, "failed to switch to safe clk source\n"); in rzg2l_cpg_sd_clk_mux_notifier()
204 if (!core->notifier) in rzg2l_register_notifier()
207 nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL); in rzg2l_register_notifier()
209 return -ENOMEM; in rzg2l_register_notifier()
211 nb->notifier_call = core->notifier; in rzg2l_register_notifier()
213 return clk_notifier_register(hw->clk, nb); in rzg2l_register_notifier()
222 struct device *dev = priv->dev; in rzg2l_cpg_div_clk_register()
227 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_div_clk_register()
233 if (core->dtable) in rzg2l_cpg_div_clk_register()
234 clk_hw = clk_hw_register_divider_table(dev, core->name, in rzg2l_cpg_div_clk_register()
236 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
237 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
238 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
239 core->flag, in rzg2l_cpg_div_clk_register()
240 core->dtable, in rzg2l_cpg_div_clk_register()
241 &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
243 clk_hw = clk_hw_register_divider(dev, core->name, in rzg2l_cpg_div_clk_register()
245 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
246 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
247 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
248 core->flag, &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
253 return clk_hw->clk; in rzg2l_cpg_div_clk_register()
263 clk_hw = devm_clk_hw_register_mux(priv->dev, core->name, in rzg2l_cpg_mux_clk_register()
264 core->parent_names, core->num_parents, in rzg2l_cpg_mux_clk_register()
265 core->flag, in rzg2l_cpg_mux_clk_register()
266 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_mux_clk_register()
267 GET_SHIFT(core->conf), in rzg2l_cpg_mux_clk_register()
268 GET_WIDTH(core->conf), in rzg2l_cpg_mux_clk_register()
269 core->mux_flags, &priv->rmw_lock); in rzg2l_cpg_mux_clk_register()
273 return clk_hw->clk; in rzg2l_cpg_mux_clk_register()
280 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_set_parent()
281 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_set_parent()
282 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_set_parent()
287 val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index); in rzg2l_cpg_sd_clk_mux_set_parent()
289 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_set_parent()
291 writel((CPG_WEN_BIT | val) << shift, priv->base + off); in rzg2l_cpg_sd_clk_mux_set_parent()
294 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg2l_cpg_sd_clk_mux_set_parent()
296 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_set_parent()
299 dev_err(priv->dev, "Failed to switch parent\n"); in rzg2l_cpg_sd_clk_mux_set_parent()
308 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_get_parent()
311 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); in rzg2l_cpg_sd_clk_mux_get_parent()
312 val >>= GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_get_parent()
313 val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); in rzg2l_cpg_sd_clk_mux_get_parent()
315 return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val); in rzg2l_cpg_sd_clk_mux_get_parent()
334 sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL); in rzg2l_cpg_sd_mux_clk_register()
336 return ERR_PTR(-ENOMEM); in rzg2l_cpg_sd_mux_clk_register()
338 sd_mux_hw_data->hw_data.priv = priv; in rzg2l_cpg_sd_mux_clk_register()
339 sd_mux_hw_data->hw_data.conf = core->conf; in rzg2l_cpg_sd_mux_clk_register()
340 sd_mux_hw_data->hw_data.sconf = core->sconf; in rzg2l_cpg_sd_mux_clk_register()
341 sd_mux_hw_data->mtable = core->mtable; in rzg2l_cpg_sd_mux_clk_register()
343 init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0"; in rzg2l_cpg_sd_mux_clk_register()
345 init.flags = core->flag; in rzg2l_cpg_sd_mux_clk_register()
346 init.num_parents = core->num_parents; in rzg2l_cpg_sd_mux_clk_register()
347 init.parent_names = core->parent_names; in rzg2l_cpg_sd_mux_clk_register()
349 clk_hw = &sd_mux_hw_data->hw_data.hw; in rzg2l_cpg_sd_mux_clk_register()
350 clk_hw->init = &init; in rzg2l_cpg_sd_mux_clk_register()
352 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_sd_mux_clk_register()
358 dev_err(priv->dev, "Failed to register notifier for %s\n", in rzg2l_cpg_sd_mux_clk_register()
359 core->name); in rzg2l_cpg_sd_mux_clk_register()
363 return clk_hw->clk; in rzg2l_cpg_sd_mux_clk_register()
372 params->pl5_intin = rate / MEGA; in rzg2l_cpg_get_foutpostdiv_rate()
373 params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA); in rzg2l_cpg_get_foutpostdiv_rate()
374 params->pl5_refdiv = 2; in rzg2l_cpg_get_foutpostdiv_rate()
375 params->pl5_postdiv1 = 1; in rzg2l_cpg_get_foutpostdiv_rate()
376 params->pl5_postdiv2 = 1; in rzg2l_cpg_get_foutpostdiv_rate()
377 params->pl5_spread = 0x16; in rzg2l_cpg_get_foutpostdiv_rate()
380 (params->pl5_intin << 24) + params->pl5_fracin), in rzg2l_cpg_get_foutpostdiv_rate()
381 params->pl5_refdiv) >> 24; in rzg2l_cpg_get_foutpostdiv_rate()
383 params->pl5_postdiv1 * params->pl5_postdiv2); in rzg2l_cpg_get_foutpostdiv_rate()
401 unsigned long rate = dsi_div->rate; in rzg2l_cpg_dsi_div_recalc_rate()
413 struct rzg2l_cpg_priv *priv = dsi_div->priv; in rzg2l_cpg_get_vclk_parent_rate()
419 if (priv->mux_dsi_div_params.clksrc) in rzg2l_cpg_get_vclk_parent_rate()
428 if (req->rate > MAX_VCLK_FREQ) in rzg2l_cpg_dsi_div_determine_rate()
429 req->rate = MAX_VCLK_FREQ; in rzg2l_cpg_dsi_div_determine_rate()
431 req->best_parent_rate = rzg2l_cpg_get_vclk_parent_rate(hw, req->rate); in rzg2l_cpg_dsi_div_determine_rate()
441 struct rzg2l_cpg_priv *priv = dsi_div->priv; in rzg2l_cpg_dsi_div_set_rate()
444 * MUX -->DIV_DSI_{A,B} -->M3 -->VCLK in rzg2l_cpg_dsi_div_set_rate()
452 return -EINVAL; in rzg2l_cpg_dsi_div_set_rate()
454 dsi_div->rate = rate; in rzg2l_cpg_dsi_div_set_rate()
456 (priv->mux_dsi_div_params.dsi_div_a << 0) | in rzg2l_cpg_dsi_div_set_rate()
457 (priv->mux_dsi_div_params.dsi_div_b << 8), in rzg2l_cpg_dsi_div_set_rate()
458 priv->base + CPG_PL5_SDIV); in rzg2l_cpg_dsi_div_set_rate()
481 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_dsi_div_clk_register()
485 clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); in rzg2l_cpg_dsi_div_clk_register()
487 return ERR_PTR(-ENOMEM); in rzg2l_cpg_dsi_div_clk_register()
489 clk_hw_data->priv = priv; in rzg2l_cpg_dsi_div_clk_register()
492 init.name = core->name; in rzg2l_cpg_dsi_div_clk_register()
498 clk_hw = &clk_hw_data->hw; in rzg2l_cpg_dsi_div_clk_register()
499 clk_hw->init = &init; in rzg2l_cpg_dsi_div_clk_register()
501 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_dsi_div_clk_register()
505 return clk_hw->clk; in rzg2l_cpg_dsi_div_clk_register()
522 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
524 parent = clk_hw_get_parent_by_index(hw, priv->mux_dsi_div_params.clksrc); in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
525 req->best_parent_hw = parent; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
526 req->best_parent_rate = req->rate; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
534 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_set_parent()
537 * FOUTPOSTDIV--->| in rzg2l_cpg_pll5_4_clk_mux_set_parent()
538 * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK in rzg2l_cpg_pll5_4_clk_mux_set_parent()
539 * |--FOUT1PH0-->| in rzg2l_cpg_pll5_4_clk_mux_set_parent()
547 priv->base + CPG_OTHERFUNC1_REG); in rzg2l_cpg_pll5_4_clk_mux_set_parent()
555 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_get_parent()
557 return readl(priv->base + GET_REG_OFFSET(hwdata->conf)); in rzg2l_cpg_pll5_4_clk_mux_get_parent()
575 clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); in rzg2l_cpg_pll5_4_mux_clk_register()
577 return ERR_PTR(-ENOMEM); in rzg2l_cpg_pll5_4_mux_clk_register()
579 clk_hw_data->priv = priv; in rzg2l_cpg_pll5_4_mux_clk_register()
580 clk_hw_data->conf = core->conf; in rzg2l_cpg_pll5_4_mux_clk_register()
582 init.name = core->name; in rzg2l_cpg_pll5_4_mux_clk_register()
585 init.num_parents = core->num_parents; in rzg2l_cpg_pll5_4_mux_clk_register()
586 init.parent_names = core->parent_names; in rzg2l_cpg_pll5_4_mux_clk_register()
588 clk_hw = &clk_hw_data->hw; in rzg2l_cpg_pll5_4_mux_clk_register()
589 clk_hw->init = &init; in rzg2l_cpg_pll5_4_mux_clk_register()
591 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_pll5_4_mux_clk_register()
595 return clk_hw->clk; in rzg2l_cpg_pll5_4_mux_clk_register()
611 struct rzg2l_cpg_priv *priv = sipll5->priv; in rzg2l_cpg_get_vclk_rate()
614 vclk = rate / ((1 << priv->mux_dsi_div_params.dsi_div_a) * in rzg2l_cpg_get_vclk_rate()
615 (priv->mux_dsi_div_params.dsi_div_b + 1)); in rzg2l_cpg_get_vclk_rate()
617 if (priv->mux_dsi_div_params.clksrc) in rzg2l_cpg_get_vclk_rate()
627 unsigned long pll5_rate = sipll5->foutpostdiv_rate; in rzg2l_cpg_sipll5_recalc_rate()
647 struct rzg2l_cpg_priv *priv = sipll5->priv; in rzg2l_cpg_sipll5_set_rate()
654 * OSC --> PLL5 --> FOUTPOSTDIV-->| in rzg2l_cpg_sipll5_set_rate()
655 * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK in rzg2l_cpg_sipll5_set_rate()
656 * |--FOUT1PH0-->| in rzg2l_cpg_sipll5_set_rate()
662 * OSC --> PLL5 --> FOUTPOSTDIV in rzg2l_cpg_sipll5_set_rate()
666 return -EINVAL; in rzg2l_cpg_sipll5_set_rate()
669 sipll5->foutpostdiv_rate = in rzg2l_cpg_sipll5_set_rate()
673 writel(CPG_SIPLL5_STBY_RESETB_WEN, priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_set_rate()
674 ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, in rzg2l_cpg_sipll5_set_rate()
677 dev_err(priv->dev, "failed to release pll5 lock"); in rzg2l_cpg_sipll5_set_rate()
683 (params.pl5_refdiv << 8), priv->base + CPG_SIPLL5_CLK1); in rzg2l_cpg_sipll5_set_rate()
686 writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3); in rzg2l_cpg_sipll5_set_rate()
690 priv->base + CPG_SIPLL5_CLK4); in rzg2l_cpg_sipll5_set_rate()
693 writel(params.pl5_spread, priv->base + CPG_SIPLL5_CLK5); in rzg2l_cpg_sipll5_set_rate()
698 priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_set_rate()
701 ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, in rzg2l_cpg_sipll5_set_rate()
704 dev_err(priv->dev, "failed to lock pll5"); in rzg2l_cpg_sipll5_set_rate()
729 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_sipll5_register()
733 sipll5 = devm_kzalloc(priv->dev, sizeof(*sipll5), GFP_KERNEL); in rzg2l_cpg_sipll5_register()
735 return ERR_PTR(-ENOMEM); in rzg2l_cpg_sipll5_register()
737 init.name = core->name; in rzg2l_cpg_sipll5_register()
744 sipll5->hw.init = &init; in rzg2l_cpg_sipll5_register()
745 sipll5->conf = core->conf; in rzg2l_cpg_sipll5_register()
746 sipll5->priv = priv; in rzg2l_cpg_sipll5_register()
749 CPG_SIPLL5_STBY_RESETB, priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_register()
751 clk_hw = &sipll5->hw; in rzg2l_cpg_sipll5_register()
752 clk_hw->init = &init; in rzg2l_cpg_sipll5_register()
754 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_sipll5_register()
758 priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */ in rzg2l_cpg_sipll5_register()
759 priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */ in rzg2l_cpg_sipll5_register()
760 priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */ in rzg2l_cpg_sipll5_register()
762 return clk_hw->clk; in rzg2l_cpg_sipll5_register()
779 struct rzg2l_cpg_priv *priv = pll_clk->priv; in rzg2l_cpg_pll_clk_recalc_rate()
783 if (pll_clk->type != CLK_TYPE_SAM_PLL) in rzg2l_cpg_pll_clk_recalc_rate()
786 val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
787 val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
805 struct device *dev = priv->dev; in rzg2l_cpg_pll_clk_register()
811 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_pll_clk_register()
817 return ERR_PTR(-ENOMEM); in rzg2l_cpg_pll_clk_register()
820 init.name = core->name; in rzg2l_cpg_pll_clk_register()
826 pll_clk->hw.init = &init; in rzg2l_cpg_pll_clk_register()
827 pll_clk->conf = core->conf; in rzg2l_cpg_pll_clk_register()
828 pll_clk->base = base; in rzg2l_cpg_pll_clk_register()
829 pll_clk->priv = priv; in rzg2l_cpg_pll_clk_register()
830 pll_clk->type = core->type; in rzg2l_cpg_pll_clk_register()
832 return clk_register(NULL, &pll_clk->hw); in rzg2l_cpg_pll_clk_register()
839 unsigned int clkidx = clkspec->args[1]; in rzg2l_cpg_clk_src_twocell_get()
841 struct device *dev = priv->dev; in rzg2l_cpg_clk_src_twocell_get()
845 switch (clkspec->args[0]) { in rzg2l_cpg_clk_src_twocell_get()
848 if (clkidx > priv->last_dt_core_clk) { in rzg2l_cpg_clk_src_twocell_get()
850 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
852 clk = priv->clks[clkidx]; in rzg2l_cpg_clk_src_twocell_get()
857 if (clkidx >= priv->num_mod_clks) { in rzg2l_cpg_clk_src_twocell_get()
860 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
862 clk = priv->clks[priv->num_core_clks + clkidx]; in rzg2l_cpg_clk_src_twocell_get()
866 dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); in rzg2l_cpg_clk_src_twocell_get()
867 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
875 clkspec->args[0], clkspec->args[1], clk, in rzg2l_cpg_clk_src_twocell_get()
885 struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; in rzg2l_cpg_register_core_clk()
886 struct device *dev = priv->dev; in rzg2l_cpg_register_core_clk()
887 unsigned int id = core->id, div = core->div; in rzg2l_cpg_register_core_clk()
890 WARN_DEBUG(id >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
891 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_core_clk()
893 if (!core->name) { in rzg2l_cpg_register_core_clk()
898 switch (core->type) { in rzg2l_cpg_register_core_clk()
900 clk = of_clk_get_by_name(priv->dev->of_node, core->name); in rzg2l_cpg_register_core_clk()
903 WARN_DEBUG(core->parent >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
904 parent = priv->clks[core->parent]; in rzg2l_cpg_register_core_clk()
911 clk = clk_register_fixed_factor(NULL, core->name, in rzg2l_cpg_register_core_clk()
913 core->mult, div); in rzg2l_cpg_register_core_clk()
916 clk = rzg2l_cpg_pll_clk_register(core, priv->clks, in rzg2l_cpg_register_core_clk()
917 priv->base, priv); in rzg2l_cpg_register_core_clk()
920 clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv); in rzg2l_cpg_register_core_clk()
923 clk = rzg2l_cpg_div_clk_register(core, priv->clks, in rzg2l_cpg_register_core_clk()
924 priv->base, priv); in rzg2l_cpg_register_core_clk()
927 clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv); in rzg2l_cpg_register_core_clk()
930 clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv); in rzg2l_cpg_register_core_clk()
936 clk = rzg2l_cpg_dsi_div_clk_register(core, priv->clks, priv); in rzg2l_cpg_register_core_clk()
946 priv->clks[id] = clk; in rzg2l_cpg_register_core_clk()
951 core->name, PTR_ERR(clk)); in rzg2l_cpg_register_core_clk()
955 * struct mstp_clock - MSTP gating clock
957 * @hw: handle between common and hardware-specific interfaces
961 * @priv: CPG/MSTP private data
978 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_endisable()
979 unsigned int reg = clock->off; in rzg2l_mod_clock_endisable()
980 struct device *dev = priv->dev; in rzg2l_mod_clock_endisable()
982 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_endisable()
986 if (!clock->off) { in rzg2l_mod_clock_endisable()
987 dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_endisable()
991 dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk, in rzg2l_mod_clock_endisable()
993 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_endisable()
999 writel(value, priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
1001 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_endisable()
1006 if (!priv->info->has_clk_mon_regs) in rzg2l_mod_clock_endisable()
1009 error = readl_poll_timeout_atomic(priv->base + CLK_MON_R(reg), value, in rzg2l_mod_clock_endisable()
1013 priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
1022 if (clock->sibling) { in rzg2l_mod_clock_enable()
1023 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_enable()
1027 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_enable()
1028 enabled = clock->sibling->enabled; in rzg2l_mod_clock_enable()
1029 clock->enabled = true; in rzg2l_mod_clock_enable()
1030 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_enable()
1042 if (clock->sibling) { in rzg2l_mod_clock_disable()
1043 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_disable()
1047 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_disable()
1048 enabled = clock->sibling->enabled; in rzg2l_mod_clock_disable()
1049 clock->enabled = false; in rzg2l_mod_clock_disable()
1050 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_disable()
1061 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_is_enabled()
1062 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_is_enabled()
1065 if (!clock->off) { in rzg2l_mod_clock_is_enabled()
1066 dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_is_enabled()
1070 if (clock->sibling) in rzg2l_mod_clock_is_enabled()
1071 return clock->enabled; in rzg2l_mod_clock_is_enabled()
1073 if (priv->info->has_clk_mon_regs) in rzg2l_mod_clock_is_enabled()
1074 value = readl(priv->base + CLK_MON_R(clock->off)); in rzg2l_mod_clock_is_enabled()
1076 value = readl(priv->base + clock->off); in rzg2l_mod_clock_is_enabled()
1094 for (i = 0; i < priv->num_mod_clks; i++) { in rzg2l_mod_clock_get_sibling()
1097 if (priv->clks[priv->num_core_clks + i] == ERR_PTR(-ENOENT)) in rzg2l_mod_clock_get_sibling()
1100 hw = __clk_get_hw(priv->clks[priv->num_core_clks + i]); in rzg2l_mod_clock_get_sibling()
1102 if (clock->off == clk->off && clock->bit == clk->bit) in rzg2l_mod_clock_get_sibling()
1115 struct device *dev = priv->dev; in rzg2l_cpg_register_mod_clk()
1116 unsigned int id = mod->id; in rzg2l_cpg_register_mod_clk()
1122 WARN_DEBUG(id < priv->num_core_clks); in rzg2l_cpg_register_mod_clk()
1123 WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
1124 WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
1125 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_mod_clk()
1127 if (!mod->name) { in rzg2l_cpg_register_mod_clk()
1132 parent = priv->clks[mod->parent]; in rzg2l_cpg_register_mod_clk()
1140 clk = ERR_PTR(-ENOMEM); in rzg2l_cpg_register_mod_clk()
1144 init.name = mod->name; in rzg2l_cpg_register_mod_clk()
1147 for (i = 0; i < info->num_crit_mod_clks; i++) in rzg2l_cpg_register_mod_clk()
1148 if (id == info->crit_mod_clks[i]) { in rzg2l_cpg_register_mod_clk()
1149 dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n", in rzg2l_cpg_register_mod_clk()
1150 mod->name); in rzg2l_cpg_register_mod_clk()
1159 clock->off = mod->off; in rzg2l_cpg_register_mod_clk()
1160 clock->bit = mod->bit; in rzg2l_cpg_register_mod_clk()
1161 clock->priv = priv; in rzg2l_cpg_register_mod_clk()
1162 clock->hw.init = &init; in rzg2l_cpg_register_mod_clk()
1164 clk = clk_register(NULL, &clock->hw); in rzg2l_cpg_register_mod_clk()
1169 priv->clks[id] = clk; in rzg2l_cpg_register_mod_clk()
1171 if (mod->is_coupled) { in rzg2l_cpg_register_mod_clk()
1174 clock->enabled = rzg2l_mod_clock_is_enabled(&clock->hw); in rzg2l_cpg_register_mod_clk()
1177 clock->sibling = sibling; in rzg2l_cpg_register_mod_clk()
1178 sibling->sibling = clock; in rzg2l_cpg_register_mod_clk()
1186 mod->name, PTR_ERR(clk)); in rzg2l_cpg_register_mod_clk()
1195 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_assert()
1196 unsigned int reg = info->resets[id].off; in rzg2l_cpg_assert()
1197 u32 mask = BIT(info->resets[id].bit); in rzg2l_cpg_assert()
1198 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_assert()
1201 dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg)); in rzg2l_cpg_assert()
1203 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_assert()
1205 if (info->has_clk_mon_regs) { in rzg2l_cpg_assert()
1216 return readl_poll_timeout_atomic(priv->base + reg, value, in rzg2l_cpg_assert()
1224 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_deassert()
1225 unsigned int reg = info->resets[id].off; in rzg2l_cpg_deassert()
1226 u32 mask = BIT(info->resets[id].bit); in rzg2l_cpg_deassert()
1227 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_deassert()
1230 dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id, in rzg2l_cpg_deassert()
1233 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_deassert()
1235 if (info->has_clk_mon_regs) { in rzg2l_cpg_deassert()
1246 return readl_poll_timeout_atomic(priv->base + reg, value, in rzg2l_cpg_deassert()
1266 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_status()
1267 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_status()
1271 if (info->has_clk_mon_regs) { in rzg2l_cpg_status()
1272 reg = CLK_MRST_R(info->resets[id].off); in rzg2l_cpg_status()
1273 bitmask = BIT(info->resets[id].bit); in rzg2l_cpg_status()
1278 return -ENOTSUPP; in rzg2l_cpg_status()
1281 return !!(readl(priv->base + reg) & bitmask); in rzg2l_cpg_status()
1295 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_reset_xlate()
1296 unsigned int id = reset_spec->args[0]; in rzg2l_cpg_reset_xlate()
1298 if (id >= rcdev->nr_resets || !info->resets[id].off) { in rzg2l_cpg_reset_xlate()
1299 dev_err(rcdev->dev, "Invalid reset index %u\n", id); in rzg2l_cpg_reset_xlate()
1300 return -EINVAL; in rzg2l_cpg_reset_xlate()
1308 priv->rcdev.ops = &rzg2l_cpg_reset_ops; in rzg2l_cpg_reset_controller_register()
1309 priv->rcdev.of_node = priv->dev->of_node; in rzg2l_cpg_reset_controller_register()
1310 priv->rcdev.dev = priv->dev; in rzg2l_cpg_reset_controller_register()
1311 priv->rcdev.of_reset_n_cells = 1; in rzg2l_cpg_reset_controller_register()
1312 priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate; in rzg2l_cpg_reset_controller_register()
1313 priv->rcdev.nr_resets = priv->num_resets; in rzg2l_cpg_reset_controller_register()
1315 return devm_reset_controller_register(priv->dev, &priv->rcdev); in rzg2l_cpg_reset_controller_register()
1321 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_is_pm_clk()
1325 if (clkspec->args_count != 2) in rzg2l_cpg_is_pm_clk()
1328 if (clkspec->args[0] != CPG_MOD) in rzg2l_cpg_is_pm_clk()
1331 id = clkspec->args[1] + info->num_total_core_clks; in rzg2l_cpg_is_pm_clk()
1332 for (i = 0; i < info->num_no_pm_mod_clks; i++) { in rzg2l_cpg_is_pm_clk()
1333 if (info->no_pm_mod_clks[i] == id) in rzg2l_cpg_is_pm_clk()
1343 struct device_node *np = dev->of_node; in rzg2l_cpg_attach_dev()
1350 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, in rzg2l_cpg_attach_dev()
1404 struct device *dev = priv->dev; in rzg2l_cpg_add_clk_domain()
1405 struct device_node *np = dev->of_node; in rzg2l_cpg_add_clk_domain()
1406 struct generic_pm_domain *genpd = &priv->genpd; in rzg2l_cpg_add_clk_domain()
1409 genpd->name = np->name; in rzg2l_cpg_add_clk_domain()
1410 genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | in rzg2l_cpg_add_clk_domain()
1412 genpd->attach_dev = rzg2l_cpg_attach_dev; in rzg2l_cpg_add_clk_domain()
1413 genpd->detach_dev = rzg2l_cpg_detach_dev; in rzg2l_cpg_add_clk_domain()
1427 struct device *dev = &pdev->dev; in rzg2l_cpg_probe()
1428 struct device_node *np = dev->of_node; in rzg2l_cpg_probe()
1439 return -ENOMEM; in rzg2l_cpg_probe()
1441 priv->dev = dev; in rzg2l_cpg_probe()
1442 priv->info = info; in rzg2l_cpg_probe()
1443 spin_lock_init(&priv->rmw_lock); in rzg2l_cpg_probe()
1445 priv->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_cpg_probe()
1446 if (IS_ERR(priv->base)) in rzg2l_cpg_probe()
1447 return PTR_ERR(priv->base); in rzg2l_cpg_probe()
1449 nclks = info->num_total_core_clks + info->num_hw_mod_clks; in rzg2l_cpg_probe()
1452 return -ENOMEM; in rzg2l_cpg_probe()
1455 priv->clks = clks; in rzg2l_cpg_probe()
1456 priv->num_core_clks = info->num_total_core_clks; in rzg2l_cpg_probe()
1457 priv->num_mod_clks = info->num_hw_mod_clks; in rzg2l_cpg_probe()
1458 priv->num_resets = info->num_resets; in rzg2l_cpg_probe()
1459 priv->last_dt_core_clk = info->last_dt_core_clk; in rzg2l_cpg_probe()
1462 clks[i] = ERR_PTR(-ENOENT); in rzg2l_cpg_probe()
1464 for (i = 0; i < info->num_core_clks; i++) in rzg2l_cpg_probe()
1465 rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv); in rzg2l_cpg_probe()
1467 for (i = 0; i < info->num_mod_clks; i++) in rzg2l_cpg_probe()
1468 rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv); in rzg2l_cpg_probe()
1492 .compatible = "renesas,r9a07g043-cpg",
1498 .compatible = "renesas,r9a07g044-cpg",
1504 .compatible = "renesas,r9a07g054-cpg",
1510 .compatible = "renesas,r9a09g011-cpg",
1519 .name = "rzg2l-cpg",
1531 MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver");