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"
69 * struct clk_hw_data - clock hardware data
73 * @priv: CPG private data structure
85 * struct sd_mux_hw_data - SD MUX clock hardware data
97 * struct div_hw_data - divider clock hardware data
130 * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
133 * @dev: CPG device
134 * @base: CPG register block base address
136 * @clks: Array containing all Core and Module Clocks
137 * @num_core_clks: Number of Core Clocks in clks[]
138 * @num_mod_clks: Number of Module Clocks in clks[]
139 * @num_resets: Number of Module Resets in info->resets[]
172 u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf); in rzg2l_cpg_wait_clk_update_done()
183 struct clk_hw *hw = __clk_get_hw(cnd->clk); in rzg2l_cpg_sd_clk_mux_notifier()
185 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_notifier()
186 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_notifier()
187 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_notifier()
192 if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266)) in rzg2l_cpg_sd_clk_mux_notifier()
195 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_notifier()
205 * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and in rzg2l_cpg_sd_clk_mux_notifier()
209 writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off); in rzg2l_cpg_sd_clk_mux_notifier()
212 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg2l_cpg_sd_clk_mux_notifier()
214 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_notifier()
217 dev_err(priv->dev, "failed to switch to safe clk source\n"); in rzg2l_cpg_sd_clk_mux_notifier()
226 struct clk_hw *hw = __clk_get_hw(cnd->clk); in rzg3s_cpg_div_clk_notifier()
229 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg3s_cpg_div_clk_notifier()
230 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg3s_cpg_div_clk_notifier()
231 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg3s_cpg_div_clk_notifier()
236 if (event != PRE_RATE_CHANGE || !div_hw_data->invalid_rate || in rzg3s_cpg_div_clk_notifier()
237 div_hw_data->invalid_rate % cnd->new_rate) in rzg3s_cpg_div_clk_notifier()
240 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg3s_cpg_div_clk_notifier()
242 val = readl(priv->base + off); in rzg3s_cpg_div_clk_notifier()
244 val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); in rzg3s_cpg_div_clk_notifier()
256 writel((CPG_WEN_BIT | 1) << shift, priv->base + off); in rzg3s_cpg_div_clk_notifier()
258 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg3s_cpg_div_clk_notifier()
261 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg3s_cpg_div_clk_notifier()
264 dev_err(priv->dev, "Failed to downgrade the div\n"); in rzg3s_cpg_div_clk_notifier()
274 if (!core->notifier) in rzg2l_register_notifier()
277 nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL); in rzg2l_register_notifier()
279 return -ENOMEM; in rzg2l_register_notifier()
281 nb->notifier_call = core->notifier; in rzg2l_register_notifier()
283 return clk_notifier_register(hw->clk, nb); in rzg2l_register_notifier()
291 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg3s_div_clk_recalc_rate()
294 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); in rzg3s_div_clk_recalc_rate()
295 val >>= GET_SHIFT(clk_hw_data->conf); in rzg3s_div_clk_recalc_rate()
296 val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); in rzg3s_div_clk_recalc_rate()
298 return divider_recalc_rate(hw, parent_rate, val, div_hw_data->dtable, in rzg3s_div_clk_recalc_rate()
299 CLK_DIVIDER_ROUND_CLOSEST, div_hw_data->width); in rzg3s_div_clk_recalc_rate()
307 if (div_hw_data->max_rate && req->rate > div_hw_data->max_rate) in rzg3s_div_clk_determine_rate()
308 req->rate = div_hw_data->max_rate; in rzg3s_div_clk_determine_rate()
310 return divider_determine_rate(hw, req, div_hw_data->dtable, div_hw_data->width, in rzg3s_div_clk_determine_rate()
319 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg3s_div_clk_set_rate()
320 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg3s_div_clk_set_rate()
321 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg3s_div_clk_set_rate()
326 val = divider_get_val(rate, parent_rate, div_hw_data->dtable, div_hw_data->width, in rzg3s_div_clk_set_rate()
329 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg3s_div_clk_set_rate()
330 writel((CPG_WEN_BIT | val) << shift, priv->base + off); in rzg3s_div_clk_set_rate()
332 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg3s_div_clk_set_rate()
333 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg3s_div_clk_set_rate()
357 parent = clks[core->parent & 0xffff]; in rzg3s_cpg_div_clk_register()
363 div_hw_data = devm_kzalloc(priv->dev, sizeof(*div_hw_data), GFP_KERNEL); in rzg3s_cpg_div_clk_register()
365 return ERR_PTR(-ENOMEM); in rzg3s_cpg_div_clk_register()
367 init.name = core->name; in rzg3s_cpg_div_clk_register()
368 init.flags = core->flag; in rzg3s_cpg_div_clk_register()
374 for (clkt = core->dtable; clkt->div; clkt++) { in rzg3s_cpg_div_clk_register()
375 if (max < clkt->div) in rzg3s_cpg_div_clk_register()
376 max = clkt->div; in rzg3s_cpg_div_clk_register()
379 div_hw_data->hw_data.priv = priv; in rzg3s_cpg_div_clk_register()
380 div_hw_data->hw_data.conf = core->conf; in rzg3s_cpg_div_clk_register()
381 div_hw_data->hw_data.sconf = core->sconf; in rzg3s_cpg_div_clk_register()
382 div_hw_data->dtable = core->dtable; in rzg3s_cpg_div_clk_register()
383 div_hw_data->invalid_rate = core->invalid_rate; in rzg3s_cpg_div_clk_register()
384 div_hw_data->max_rate = core->max_rate; in rzg3s_cpg_div_clk_register()
385 div_hw_data->width = fls(max) - 1; in rzg3s_cpg_div_clk_register()
387 clk_hw = &div_hw_data->hw_data.hw; in rzg3s_cpg_div_clk_register()
388 clk_hw->init = &init; in rzg3s_cpg_div_clk_register()
390 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg3s_cpg_div_clk_register()
396 dev_err(priv->dev, "Failed to register notifier for %s\n", in rzg3s_cpg_div_clk_register()
397 core->name); in rzg3s_cpg_div_clk_register()
401 return clk_hw->clk; in rzg3s_cpg_div_clk_register()
410 struct device *dev = priv->dev; in rzg2l_cpg_div_clk_register()
415 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_div_clk_register()
421 if (core->dtable) in rzg2l_cpg_div_clk_register()
422 clk_hw = clk_hw_register_divider_table(dev, core->name, in rzg2l_cpg_div_clk_register()
424 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
425 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
426 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
427 core->flag, in rzg2l_cpg_div_clk_register()
428 core->dtable, in rzg2l_cpg_div_clk_register()
429 &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
431 clk_hw = clk_hw_register_divider(dev, core->name, in rzg2l_cpg_div_clk_register()
433 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_div_clk_register()
434 GET_SHIFT(core->conf), in rzg2l_cpg_div_clk_register()
435 GET_WIDTH(core->conf), in rzg2l_cpg_div_clk_register()
436 core->flag, &priv->rmw_lock); in rzg2l_cpg_div_clk_register()
441 return clk_hw->clk; in rzg2l_cpg_div_clk_register()
451 clk_hw = devm_clk_hw_register_mux(priv->dev, core->name, in rzg2l_cpg_mux_clk_register()
452 core->parent_names, core->num_parents, in rzg2l_cpg_mux_clk_register()
453 core->flag, in rzg2l_cpg_mux_clk_register()
454 base + GET_REG_OFFSET(core->conf), in rzg2l_cpg_mux_clk_register()
455 GET_SHIFT(core->conf), in rzg2l_cpg_mux_clk_register()
456 GET_WIDTH(core->conf), in rzg2l_cpg_mux_clk_register()
457 core->mux_flags, &priv->rmw_lock); in rzg2l_cpg_mux_clk_register()
461 return clk_hw->clk; in rzg2l_cpg_mux_clk_register()
468 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_set_parent()
469 u32 off = GET_REG_OFFSET(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_set_parent()
470 u32 shift = GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_set_parent()
475 val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index); in rzg2l_cpg_sd_clk_mux_set_parent()
477 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_set_parent()
479 writel((CPG_WEN_BIT | val) << shift, priv->base + off); in rzg2l_cpg_sd_clk_mux_set_parent()
482 ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); in rzg2l_cpg_sd_clk_mux_set_parent()
484 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_cpg_sd_clk_mux_set_parent()
487 dev_err(priv->dev, "Failed to switch parent\n"); in rzg2l_cpg_sd_clk_mux_set_parent()
496 struct rzg2l_cpg_priv *priv = clk_hw_data->priv; in rzg2l_cpg_sd_clk_mux_get_parent()
499 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); in rzg2l_cpg_sd_clk_mux_get_parent()
500 val >>= GET_SHIFT(clk_hw_data->conf); in rzg2l_cpg_sd_clk_mux_get_parent()
501 val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); in rzg2l_cpg_sd_clk_mux_get_parent()
503 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()
522 sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL); in rzg2l_cpg_sd_mux_clk_register()
524 return ERR_PTR(-ENOMEM); in rzg2l_cpg_sd_mux_clk_register()
526 sd_mux_hw_data->hw_data.priv = priv; in rzg2l_cpg_sd_mux_clk_register()
527 sd_mux_hw_data->hw_data.conf = core->conf; in rzg2l_cpg_sd_mux_clk_register()
528 sd_mux_hw_data->hw_data.sconf = core->sconf; in rzg2l_cpg_sd_mux_clk_register()
529 sd_mux_hw_data->mtable = core->mtable; in rzg2l_cpg_sd_mux_clk_register()
531 init.name = core->name; in rzg2l_cpg_sd_mux_clk_register()
533 init.flags = core->flag; in rzg2l_cpg_sd_mux_clk_register()
534 init.num_parents = core->num_parents; in rzg2l_cpg_sd_mux_clk_register()
535 init.parent_names = core->parent_names; in rzg2l_cpg_sd_mux_clk_register()
537 clk_hw = &sd_mux_hw_data->hw_data.hw; in rzg2l_cpg_sd_mux_clk_register()
538 clk_hw->init = &init; in rzg2l_cpg_sd_mux_clk_register()
540 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_sd_mux_clk_register()
546 dev_err(priv->dev, "Failed to register notifier for %s\n", in rzg2l_cpg_sd_mux_clk_register()
547 core->name); in rzg2l_cpg_sd_mux_clk_register()
551 return clk_hw->clk; in rzg2l_cpg_sd_mux_clk_register()
560 params->pl5_intin = rate / MEGA; in rzg2l_cpg_get_foutpostdiv_rate()
561 params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA); in rzg2l_cpg_get_foutpostdiv_rate()
562 params->pl5_refdiv = 2; in rzg2l_cpg_get_foutpostdiv_rate()
563 params->pl5_postdiv1 = 1; in rzg2l_cpg_get_foutpostdiv_rate()
564 params->pl5_postdiv2 = 1; in rzg2l_cpg_get_foutpostdiv_rate()
565 params->pl5_spread = 0x16; in rzg2l_cpg_get_foutpostdiv_rate()
568 EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv * in rzg2l_cpg_get_foutpostdiv_rate()
569 ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) / in rzg2l_cpg_get_foutpostdiv_rate()
570 (params->pl5_postdiv1 * params->pl5_postdiv2); in rzg2l_cpg_get_foutpostdiv_rate()
588 unsigned long rate = dsi_div->rate; in rzg2l_cpg_dsi_div_recalc_rate()
600 struct rzg2l_cpg_priv *priv = dsi_div->priv; in rzg2l_cpg_get_vclk_parent_rate()
606 if (priv->mux_dsi_div_params.clksrc) in rzg2l_cpg_get_vclk_parent_rate()
615 if (req->rate > MAX_VCLK_FREQ) in rzg2l_cpg_dsi_div_determine_rate()
616 req->rate = MAX_VCLK_FREQ; in rzg2l_cpg_dsi_div_determine_rate()
618 req->best_parent_rate = rzg2l_cpg_get_vclk_parent_rate(hw, req->rate); in rzg2l_cpg_dsi_div_determine_rate()
628 struct rzg2l_cpg_priv *priv = dsi_div->priv; in rzg2l_cpg_dsi_div_set_rate()
631 * MUX -->DIV_DSI_{A,B} -->M3 -->VCLK in rzg2l_cpg_dsi_div_set_rate()
639 return -EINVAL; in rzg2l_cpg_dsi_div_set_rate()
641 dsi_div->rate = rate; in rzg2l_cpg_dsi_div_set_rate()
643 (priv->mux_dsi_div_params.dsi_div_a << 0) | in rzg2l_cpg_dsi_div_set_rate()
644 (priv->mux_dsi_div_params.dsi_div_b << 8), in rzg2l_cpg_dsi_div_set_rate()
645 priv->base + CPG_PL5_SDIV); in rzg2l_cpg_dsi_div_set_rate()
668 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_dsi_div_clk_register()
672 clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); in rzg2l_cpg_dsi_div_clk_register()
674 return ERR_PTR(-ENOMEM); in rzg2l_cpg_dsi_div_clk_register()
676 clk_hw_data->priv = priv; in rzg2l_cpg_dsi_div_clk_register()
679 init.name = core->name; in rzg2l_cpg_dsi_div_clk_register()
685 clk_hw = &clk_hw_data->hw; in rzg2l_cpg_dsi_div_clk_register()
686 clk_hw->init = &init; in rzg2l_cpg_dsi_div_clk_register()
688 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_dsi_div_clk_register()
692 return clk_hw->clk; in rzg2l_cpg_dsi_div_clk_register()
709 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
711 parent = clk_hw_get_parent_by_index(hw, priv->mux_dsi_div_params.clksrc); in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
712 req->best_parent_hw = parent; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
713 req->best_parent_rate = req->rate; in rzg2l_cpg_pll5_4_clk_mux_determine_rate()
721 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_set_parent()
724 * FOUTPOSTDIV--->| in rzg2l_cpg_pll5_4_clk_mux_set_parent()
725 * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK in rzg2l_cpg_pll5_4_clk_mux_set_parent()
726 * |--FOUT1PH0-->| in rzg2l_cpg_pll5_4_clk_mux_set_parent()
734 priv->base + CPG_OTHERFUNC1_REG); in rzg2l_cpg_pll5_4_clk_mux_set_parent()
742 struct rzg2l_cpg_priv *priv = hwdata->priv; in rzg2l_cpg_pll5_4_clk_mux_get_parent()
744 return readl(priv->base + GET_REG_OFFSET(hwdata->conf)); in rzg2l_cpg_pll5_4_clk_mux_get_parent()
762 clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); in rzg2l_cpg_pll5_4_mux_clk_register()
764 return ERR_PTR(-ENOMEM); in rzg2l_cpg_pll5_4_mux_clk_register()
766 clk_hw_data->priv = priv; in rzg2l_cpg_pll5_4_mux_clk_register()
767 clk_hw_data->conf = core->conf; in rzg2l_cpg_pll5_4_mux_clk_register()
769 init.name = core->name; in rzg2l_cpg_pll5_4_mux_clk_register()
772 init.num_parents = core->num_parents; in rzg2l_cpg_pll5_4_mux_clk_register()
773 init.parent_names = core->parent_names; in rzg2l_cpg_pll5_4_mux_clk_register()
775 clk_hw = &clk_hw_data->hw; in rzg2l_cpg_pll5_4_mux_clk_register()
776 clk_hw->init = &init; in rzg2l_cpg_pll5_4_mux_clk_register()
778 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_pll5_4_mux_clk_register()
782 return clk_hw->clk; in rzg2l_cpg_pll5_4_mux_clk_register()
798 struct rzg2l_cpg_priv *priv = sipll5->priv; in rzg2l_cpg_get_vclk_rate()
801 vclk = rate / ((1 << priv->mux_dsi_div_params.dsi_div_a) * in rzg2l_cpg_get_vclk_rate()
802 (priv->mux_dsi_div_params.dsi_div_b + 1)); in rzg2l_cpg_get_vclk_rate()
804 if (priv->mux_dsi_div_params.clksrc) in rzg2l_cpg_get_vclk_rate()
814 unsigned long pll5_rate = sipll5->foutpostdiv_rate; in rzg2l_cpg_sipll5_recalc_rate()
834 struct rzg2l_cpg_priv *priv = sipll5->priv; in rzg2l_cpg_sipll5_set_rate()
841 * OSC --> PLL5 --> FOUTPOSTDIV-->| in rzg2l_cpg_sipll5_set_rate()
842 * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK in rzg2l_cpg_sipll5_set_rate()
843 * |--FOUT1PH0-->| in rzg2l_cpg_sipll5_set_rate()
849 * OSC --> PLL5 --> FOUTPOSTDIV in rzg2l_cpg_sipll5_set_rate()
853 return -EINVAL; in rzg2l_cpg_sipll5_set_rate()
856 sipll5->foutpostdiv_rate = in rzg2l_cpg_sipll5_set_rate()
860 writel(CPG_SIPLL5_STBY_RESETB_WEN, priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_set_rate()
861 ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, in rzg2l_cpg_sipll5_set_rate()
864 dev_err(priv->dev, "failed to release pll5 lock"); in rzg2l_cpg_sipll5_set_rate()
870 (params.pl5_refdiv << 8), priv->base + CPG_SIPLL5_CLK1); in rzg2l_cpg_sipll5_set_rate()
873 writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3); in rzg2l_cpg_sipll5_set_rate()
877 priv->base + CPG_SIPLL5_CLK4); in rzg2l_cpg_sipll5_set_rate()
880 writel(params.pl5_spread, priv->base + CPG_SIPLL5_CLK5); in rzg2l_cpg_sipll5_set_rate()
885 priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_set_rate()
888 ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, in rzg2l_cpg_sipll5_set_rate()
891 dev_err(priv->dev, "failed to lock pll5"); in rzg2l_cpg_sipll5_set_rate()
916 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_sipll5_register()
920 sipll5 = devm_kzalloc(priv->dev, sizeof(*sipll5), GFP_KERNEL); in rzg2l_cpg_sipll5_register()
922 return ERR_PTR(-ENOMEM); in rzg2l_cpg_sipll5_register()
924 init.name = core->name; in rzg2l_cpg_sipll5_register()
931 sipll5->hw.init = &init; in rzg2l_cpg_sipll5_register()
932 sipll5->conf = core->conf; in rzg2l_cpg_sipll5_register()
933 sipll5->priv = priv; in rzg2l_cpg_sipll5_register()
936 CPG_SIPLL5_STBY_RESETB, priv->base + CPG_SIPLL5_STBY); in rzg2l_cpg_sipll5_register()
938 clk_hw = &sipll5->hw; in rzg2l_cpg_sipll5_register()
939 clk_hw->init = &init; in rzg2l_cpg_sipll5_register()
941 ret = devm_clk_hw_register(priv->dev, clk_hw); in rzg2l_cpg_sipll5_register()
945 priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */ in rzg2l_cpg_sipll5_register()
946 priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */ in rzg2l_cpg_sipll5_register()
947 priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */ in rzg2l_cpg_sipll5_register()
949 return clk_hw->clk; in rzg2l_cpg_sipll5_register()
966 struct rzg2l_cpg_priv *priv = pll_clk->priv; in rzg2l_cpg_pll_clk_recalc_rate()
970 if (pll_clk->type != CLK_TYPE_SAM_PLL) in rzg2l_cpg_pll_clk_recalc_rate()
973 val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
974 val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); in rzg2l_cpg_pll_clk_recalc_rate()
990 struct rzg2l_cpg_priv *priv = pll_clk->priv; in rzg3s_cpg_pll_clk_recalc_rate()
994 if (pll_clk->type != CLK_TYPE_G3S_PLL) in rzg3s_cpg_pll_clk_recalc_rate()
997 val = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); in rzg3s_cpg_pll_clk_recalc_rate()
1024 struct device *dev = priv->dev; in rzg2l_cpg_pll_clk_register()
1030 parent = clks[core->parent & 0xffff]; in rzg2l_cpg_pll_clk_register()
1036 return ERR_PTR(-ENOMEM); in rzg2l_cpg_pll_clk_register()
1039 init.name = core->name; in rzg2l_cpg_pll_clk_register()
1045 pll_clk->hw.init = &init; in rzg2l_cpg_pll_clk_register()
1046 pll_clk->conf = core->conf; in rzg2l_cpg_pll_clk_register()
1047 pll_clk->base = base; in rzg2l_cpg_pll_clk_register()
1048 pll_clk->priv = priv; in rzg2l_cpg_pll_clk_register()
1049 pll_clk->type = core->type; in rzg2l_cpg_pll_clk_register()
1051 return clk_register(NULL, &pll_clk->hw); in rzg2l_cpg_pll_clk_register()
1058 unsigned int clkidx = clkspec->args[1]; in rzg2l_cpg_clk_src_twocell_get()
1060 struct device *dev = priv->dev; in rzg2l_cpg_clk_src_twocell_get()
1064 switch (clkspec->args[0]) { in rzg2l_cpg_clk_src_twocell_get()
1067 if (clkidx > priv->last_dt_core_clk) { in rzg2l_cpg_clk_src_twocell_get()
1069 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
1071 clk = priv->clks[clkidx]; in rzg2l_cpg_clk_src_twocell_get()
1076 if (clkidx >= priv->num_mod_clks) { in rzg2l_cpg_clk_src_twocell_get()
1079 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
1081 clk = priv->clks[priv->num_core_clks + clkidx]; in rzg2l_cpg_clk_src_twocell_get()
1085 dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); in rzg2l_cpg_clk_src_twocell_get()
1086 return ERR_PTR(-EINVAL); in rzg2l_cpg_clk_src_twocell_get()
1094 clkspec->args[0], clkspec->args[1], clk, in rzg2l_cpg_clk_src_twocell_get()
1104 struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; in rzg2l_cpg_register_core_clk()
1105 struct device *dev = priv->dev; in rzg2l_cpg_register_core_clk()
1106 unsigned int id = core->id, div = core->div; in rzg2l_cpg_register_core_clk()
1109 WARN_DEBUG(id >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
1110 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_core_clk()
1112 if (!core->name) { in rzg2l_cpg_register_core_clk()
1117 switch (core->type) { in rzg2l_cpg_register_core_clk()
1119 clk = of_clk_get_by_name(priv->dev->of_node, core->name); in rzg2l_cpg_register_core_clk()
1122 WARN_DEBUG(core->parent >= priv->num_core_clks); in rzg2l_cpg_register_core_clk()
1123 parent = priv->clks[core->parent]; in rzg2l_cpg_register_core_clk()
1130 clk = clk_register_fixed_factor(NULL, core->name, in rzg2l_cpg_register_core_clk()
1132 core->mult, div); in rzg2l_cpg_register_core_clk()
1135 clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv, in rzg2l_cpg_register_core_clk()
1139 clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv, in rzg2l_cpg_register_core_clk()
1143 clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv); in rzg2l_cpg_register_core_clk()
1146 clk = rzg2l_cpg_div_clk_register(core, priv->clks, in rzg2l_cpg_register_core_clk()
1147 priv->base, priv); in rzg2l_cpg_register_core_clk()
1150 clk = rzg3s_cpg_div_clk_register(core, priv->clks, priv->base, priv); in rzg2l_cpg_register_core_clk()
1153 clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv); in rzg2l_cpg_register_core_clk()
1156 clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv); in rzg2l_cpg_register_core_clk()
1162 clk = rzg2l_cpg_dsi_div_clk_register(core, priv->clks, priv); in rzg2l_cpg_register_core_clk()
1172 priv->clks[id] = clk; in rzg2l_cpg_register_core_clk()
1177 core->name, PTR_ERR(clk)); in rzg2l_cpg_register_core_clk()
1181 * struct mstp_clock - MSTP gating clock
1183 * @hw: handle between common and hardware-specific interfaces
1187 * @priv: CPG/MSTP private data
1204 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_endisable()
1205 unsigned int reg = clock->off; in rzg2l_mod_clock_endisable()
1206 struct device *dev = priv->dev; in rzg2l_mod_clock_endisable()
1207 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_endisable()
1211 if (!clock->off) { in rzg2l_mod_clock_endisable()
1212 dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_endisable()
1216 dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk, in rzg2l_mod_clock_endisable()
1223 writel(value, priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
1228 if (!priv->info->has_clk_mon_regs) in rzg2l_mod_clock_endisable()
1231 error = readl_poll_timeout_atomic(priv->base + CLK_MON_R(reg), value, in rzg2l_mod_clock_endisable()
1235 priv->base + CLK_ON_R(reg)); in rzg2l_mod_clock_endisable()
1244 if (clock->sibling) { in rzg2l_mod_clock_enable()
1245 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_enable()
1249 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_enable()
1250 enabled = clock->sibling->enabled; in rzg2l_mod_clock_enable()
1251 clock->enabled = true; in rzg2l_mod_clock_enable()
1252 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_enable()
1264 if (clock->sibling) { in rzg2l_mod_clock_disable()
1265 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_disable()
1269 spin_lock_irqsave(&priv->rmw_lock, flags); in rzg2l_mod_clock_disable()
1270 enabled = clock->sibling->enabled; in rzg2l_mod_clock_disable()
1271 clock->enabled = false; in rzg2l_mod_clock_disable()
1272 spin_unlock_irqrestore(&priv->rmw_lock, flags); in rzg2l_mod_clock_disable()
1283 struct rzg2l_cpg_priv *priv = clock->priv; in rzg2l_mod_clock_is_enabled()
1284 u32 bitmask = BIT(clock->bit); in rzg2l_mod_clock_is_enabled()
1287 if (!clock->off) { in rzg2l_mod_clock_is_enabled()
1288 dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk); in rzg2l_mod_clock_is_enabled()
1292 if (clock->sibling) in rzg2l_mod_clock_is_enabled()
1293 return clock->enabled; in rzg2l_mod_clock_is_enabled()
1295 if (priv->info->has_clk_mon_regs) in rzg2l_mod_clock_is_enabled()
1296 value = readl(priv->base + CLK_MON_R(clock->off)); in rzg2l_mod_clock_is_enabled()
1298 value = readl(priv->base + clock->off); in rzg2l_mod_clock_is_enabled()
1316 for (i = 0; i < priv->num_mod_clks; i++) { in rzg2l_mod_clock_get_sibling()
1319 if (priv->clks[priv->num_core_clks + i] == ERR_PTR(-ENOENT)) in rzg2l_mod_clock_get_sibling()
1322 hw = __clk_get_hw(priv->clks[priv->num_core_clks + i]); in rzg2l_mod_clock_get_sibling()
1324 if (clock->off == clk->off && clock->bit == clk->bit) in rzg2l_mod_clock_get_sibling()
1337 struct device *dev = priv->dev; in rzg2l_cpg_register_mod_clk()
1338 unsigned int id = mod->id; in rzg2l_cpg_register_mod_clk()
1344 WARN_DEBUG(id < priv->num_core_clks); in rzg2l_cpg_register_mod_clk()
1345 WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
1346 WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); in rzg2l_cpg_register_mod_clk()
1347 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); in rzg2l_cpg_register_mod_clk()
1349 if (!mod->name) { in rzg2l_cpg_register_mod_clk()
1354 parent = priv->clks[mod->parent]; in rzg2l_cpg_register_mod_clk()
1362 clk = ERR_PTR(-ENOMEM); in rzg2l_cpg_register_mod_clk()
1366 init.name = mod->name; in rzg2l_cpg_register_mod_clk()
1369 for (i = 0; i < info->num_crit_mod_clks; i++) in rzg2l_cpg_register_mod_clk()
1370 if (id == info->crit_mod_clks[i]) { in rzg2l_cpg_register_mod_clk()
1371 dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n", in rzg2l_cpg_register_mod_clk()
1372 mod->name); in rzg2l_cpg_register_mod_clk()
1381 clock->off = mod->off; in rzg2l_cpg_register_mod_clk()
1382 clock->bit = mod->bit; in rzg2l_cpg_register_mod_clk()
1383 clock->priv = priv; in rzg2l_cpg_register_mod_clk()
1384 clock->hw.init = &init; in rzg2l_cpg_register_mod_clk()
1386 clk = clk_register(NULL, &clock->hw); in rzg2l_cpg_register_mod_clk()
1391 priv->clks[id] = clk; in rzg2l_cpg_register_mod_clk()
1393 if (mod->is_coupled) { in rzg2l_cpg_register_mod_clk()
1396 clock->enabled = rzg2l_mod_clock_is_enabled(&clock->hw); in rzg2l_cpg_register_mod_clk()
1399 clock->sibling = sibling; in rzg2l_cpg_register_mod_clk()
1400 sibling->sibling = clock; in rzg2l_cpg_register_mod_clk()
1408 mod->name, PTR_ERR(clk)); in rzg2l_cpg_register_mod_clk()
1417 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_assert()
1418 unsigned int reg = info->resets[id].off; in rzg2l_cpg_assert()
1419 u32 mask = BIT(info->resets[id].bit); in rzg2l_cpg_assert()
1420 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_assert()
1423 dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg)); in rzg2l_cpg_assert()
1425 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_assert()
1427 if (info->has_clk_mon_regs) { in rzg2l_cpg_assert()
1438 return readl_poll_timeout_atomic(priv->base + reg, value, in rzg2l_cpg_assert()
1446 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_deassert()
1447 unsigned int reg = info->resets[id].off; in rzg2l_cpg_deassert()
1448 u32 mask = BIT(info->resets[id].bit); in rzg2l_cpg_deassert()
1449 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_deassert()
1452 dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id, in rzg2l_cpg_deassert()
1455 writel(value, priv->base + CLK_RST_R(reg)); in rzg2l_cpg_deassert()
1457 if (info->has_clk_mon_regs) { in rzg2l_cpg_deassert()
1468 return readl_poll_timeout_atomic(priv->base + reg, value, in rzg2l_cpg_deassert()
1488 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_status()
1489 s8 monbit = info->resets[id].monbit; in rzg2l_cpg_status()
1493 if (info->has_clk_mon_regs) { in rzg2l_cpg_status()
1494 reg = CLK_MRST_R(info->resets[id].off); in rzg2l_cpg_status()
1495 bitmask = BIT(info->resets[id].bit); in rzg2l_cpg_status()
1500 return -ENOTSUPP; in rzg2l_cpg_status()
1503 return !!(readl(priv->base + reg) & bitmask); in rzg2l_cpg_status()
1517 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_reset_xlate()
1518 unsigned int id = reset_spec->args[0]; in rzg2l_cpg_reset_xlate()
1520 if (id >= rcdev->nr_resets || !info->resets[id].off) { in rzg2l_cpg_reset_xlate()
1521 dev_err(rcdev->dev, "Invalid reset index %u\n", id); in rzg2l_cpg_reset_xlate()
1522 return -EINVAL; in rzg2l_cpg_reset_xlate()
1530 priv->rcdev.ops = &rzg2l_cpg_reset_ops; in rzg2l_cpg_reset_controller_register()
1531 priv->rcdev.of_node = priv->dev->of_node; in rzg2l_cpg_reset_controller_register()
1532 priv->rcdev.dev = priv->dev; in rzg2l_cpg_reset_controller_register()
1533 priv->rcdev.of_reset_n_cells = 1; in rzg2l_cpg_reset_controller_register()
1534 priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate; in rzg2l_cpg_reset_controller_register()
1535 priv->rcdev.nr_resets = priv->num_resets; in rzg2l_cpg_reset_controller_register()
1537 return devm_reset_controller_register(priv->dev, &priv->rcdev); in rzg2l_cpg_reset_controller_register()
1543 const struct rzg2l_cpg_info *info = priv->info; in rzg2l_cpg_is_pm_clk()
1547 if (clkspec->args_count != 2) in rzg2l_cpg_is_pm_clk()
1550 if (clkspec->args[0] != CPG_MOD) in rzg2l_cpg_is_pm_clk()
1553 id = clkspec->args[1] + info->num_total_core_clks; in rzg2l_cpg_is_pm_clk()
1554 for (i = 0; i < info->num_no_pm_mod_clks; i++) { in rzg2l_cpg_is_pm_clk()
1555 if (info->no_pm_mod_clks[i] == id) in rzg2l_cpg_is_pm_clk()
1565 struct device_node *np = dev->of_node; in rzg2l_cpg_attach_dev()
1572 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, in rzg2l_cpg_attach_dev()
1626 struct device *dev = priv->dev; in rzg2l_cpg_add_clk_domain()
1627 struct device_node *np = dev->of_node; in rzg2l_cpg_add_clk_domain()
1628 struct generic_pm_domain *genpd = &priv->genpd; in rzg2l_cpg_add_clk_domain()
1631 genpd->name = np->name; in rzg2l_cpg_add_clk_domain()
1632 genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | in rzg2l_cpg_add_clk_domain()
1634 genpd->attach_dev = rzg2l_cpg_attach_dev; in rzg2l_cpg_add_clk_domain()
1635 genpd->detach_dev = rzg2l_cpg_detach_dev; in rzg2l_cpg_add_clk_domain()
1649 struct device *dev = &pdev->dev; in rzg2l_cpg_probe()
1650 struct device_node *np = dev->of_node; in rzg2l_cpg_probe()
1661 return -ENOMEM; in rzg2l_cpg_probe()
1663 priv->dev = dev; in rzg2l_cpg_probe()
1664 priv->info = info; in rzg2l_cpg_probe()
1665 spin_lock_init(&priv->rmw_lock); in rzg2l_cpg_probe()
1667 priv->base = devm_platform_ioremap_resource(pdev, 0); in rzg2l_cpg_probe()
1668 if (IS_ERR(priv->base)) in rzg2l_cpg_probe()
1669 return PTR_ERR(priv->base); in rzg2l_cpg_probe()
1671 nclks = info->num_total_core_clks + info->num_hw_mod_clks; in rzg2l_cpg_probe()
1674 return -ENOMEM; in rzg2l_cpg_probe()
1677 priv->clks = clks; in rzg2l_cpg_probe()
1678 priv->num_core_clks = info->num_total_core_clks; in rzg2l_cpg_probe()
1679 priv->num_mod_clks = info->num_hw_mod_clks; in rzg2l_cpg_probe()
1680 priv->num_resets = info->num_resets; in rzg2l_cpg_probe()
1681 priv->last_dt_core_clk = info->last_dt_core_clk; in rzg2l_cpg_probe()
1684 clks[i] = ERR_PTR(-ENOENT); in rzg2l_cpg_probe()
1686 for (i = 0; i < info->num_core_clks; i++) in rzg2l_cpg_probe()
1687 rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv); in rzg2l_cpg_probe()
1689 for (i = 0; i < info->num_mod_clks; i++) in rzg2l_cpg_probe()
1690 rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv); in rzg2l_cpg_probe()
1714 .compatible = "renesas,r9a07g043-cpg",
1720 .compatible = "renesas,r9a07g044-cpg",
1726 .compatible = "renesas,r9a07g054-cpg",
1732 .compatible = "renesas,r9a08g045-cpg",
1738 .compatible = "renesas,r9a09g011-cpg",
1747 .name = "rzg2l-cpg",
1759 MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver");