Lines Matching +full:reg +full:- +full:init

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
6 #define pr_fmt(fmt) "k210-clk: " fmt
15 #include <linux/clk-provider.h>
18 #include <soc/canaan/k210-sysctl.h>
20 #include <dt-bindings/clock/k210-clk.h>
291 void __iomem *reg; member
306 u32 reg; member
322 * struct k210_sysclk - sysclk driver data
344 u32 reg = readl(regs + K210_SYSCTL_SEL0); in k210_aclk_set_selector() local
347 reg |= K210_ACLK_SEL; in k210_aclk_set_selector()
349 reg &= K210_ACLK_SEL; in k210_aclk_set_selector()
350 writel(reg, regs + K210_SYSCTL_SEL0); in k210_aclk_set_selector()
356 pll->id = pllid; in k210_init_pll()
357 pll->reg = regs + k210_plls_cfg[pllid].reg; in k210_init_pll()
358 pll->lock = regs + K210_SYSCTL_PLL_LOCK; in k210_init_pll()
359 pll->lock_shift = k210_plls_cfg[pllid].lock_shift; in k210_init_pll()
360 pll->lock_width = k210_plls_cfg[pllid].lock_width; in k210_init_pll()
365 u32 reg, mask = GENMASK(pll->lock_shift + pll->lock_width - 1, in k210_pll_wait_for_lock() local
366 pll->lock_shift); in k210_pll_wait_for_lock()
369 reg = readl(pll->lock); in k210_pll_wait_for_lock()
370 if ((reg & mask) == mask) in k210_pll_wait_for_lock()
373 reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP); in k210_pll_wait_for_lock()
374 writel(reg, pll->lock); in k210_pll_wait_for_lock()
380 u32 reg = readl(pll->reg); in k210_pll_hw_is_enabled() local
383 if (reg & K210_PLL_RESET) in k210_pll_hw_is_enabled()
386 return (reg & mask) == mask; in k210_pll_hw_is_enabled()
391 struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id]; in k210_pll_enable_hw()
392 u32 reg; in k210_pll_enable_hw() local
398 * For PLL0, we need to re-parent ACLK to IN0 to keep the CPU cores and in k210_pll_enable_hw()
401 if (pll->id == K210_PLL0) in k210_pll_enable_hw()
405 reg = readl(pll->reg); in k210_pll_enable_hw()
406 reg &= ~GENMASK(19, 0); in k210_pll_enable_hw()
407 reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r); in k210_pll_enable_hw()
408 reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f); in k210_pll_enable_hw()
409 reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od); in k210_pll_enable_hw()
410 reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj); in k210_pll_enable_hw()
411 reg |= K210_PLL_PWRD; in k210_pll_enable_hw()
412 writel(reg, pll->reg); in k210_pll_enable_hw()
418 reg &= ~K210_PLL_RESET; in k210_pll_enable_hw()
419 writel(reg, pll->reg); in k210_pll_enable_hw()
420 reg |= K210_PLL_RESET; in k210_pll_enable_hw()
421 writel(reg, pll->reg); in k210_pll_enable_hw()
424 reg &= ~K210_PLL_RESET; in k210_pll_enable_hw()
425 writel(reg, pll->reg); in k210_pll_enable_hw()
429 reg &= ~K210_PLL_BYPASS; in k210_pll_enable_hw()
430 reg |= K210_PLL_EN; in k210_pll_enable_hw()
431 writel(reg, pll->reg); in k210_pll_enable_hw()
433 if (pll->id == K210_PLL0) in k210_pll_enable_hw()
440 struct k210_sysclk *ksc = pll->ksc; in k210_pll_enable()
443 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_pll_enable()
445 k210_pll_enable_hw(ksc->regs, pll); in k210_pll_enable()
447 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_pll_enable()
455 struct k210_sysclk *ksc = pll->ksc; in k210_pll_disable()
457 u32 reg; in k210_pll_disable() local
464 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_pll_disable()
465 reg = readl(pll->reg); in k210_pll_disable()
466 reg |= K210_PLL_BYPASS; in k210_pll_disable()
467 writel(reg, pll->reg); in k210_pll_disable()
469 reg &= ~K210_PLL_PWRD; in k210_pll_disable()
470 reg &= ~K210_PLL_EN; in k210_pll_disable()
471 writel(reg, pll->reg); in k210_pll_disable()
472 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_pll_disable()
484 u32 reg = readl(pll->reg); in k210_pll_get_rate() local
487 if (reg & K210_PLL_BYPASS) in k210_pll_get_rate()
490 if (!(reg & K210_PLL_PWRD)) in k210_pll_get_rate()
493 r = FIELD_GET(K210_PLL_CLKR, reg) + 1; in k210_pll_get_rate()
494 f = FIELD_GET(K210_PLL_CLKF, reg) + 1; in k210_pll_get_rate()
495 od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; in k210_pll_get_rate()
510 struct k210_sysclk *ksc = pll->ksc; in k210_pll2_set_parent()
512 u32 reg; in k210_pll2_set_parent() local
514 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_pll2_set_parent()
516 reg = readl(pll->reg); in k210_pll2_set_parent()
517 reg &= ~K210_PLL_SEL; in k210_pll2_set_parent()
518 reg |= FIELD_PREP(K210_PLL_SEL, index); in k210_pll2_set_parent()
519 writel(reg, pll->reg); in k210_pll2_set_parent()
521 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_pll2_set_parent()
529 u32 reg = readl(pll->reg); in k210_pll2_get_parent() local
531 return FIELD_GET(K210_PLL_SEL, reg); in k210_pll2_get_parent()
549 struct k210_pll *pll = &ksc->plls[pllid]; in k210_register_pll()
550 struct clk_init_data init = {}; in k210_register_pll() local
553 { .hw = &ksc->plls[K210_PLL0].hw }, in k210_register_pll()
554 { .hw = &ksc->plls[K210_PLL1].hw }, in k210_register_pll()
557 init.name = name; in k210_register_pll()
558 init.parent_data = parent_data; in k210_register_pll()
559 init.num_parents = num_parents; in k210_register_pll()
560 init.ops = ops; in k210_register_pll()
562 pll->hw.init = &init; in k210_register_pll()
563 pll->ksc = ksc; in k210_register_pll()
565 return of_clk_hw_register(np, &pll->hw); in k210_register_pll()
574 k210_init_pll(ksc->regs, i, &ksc->plls[i]); in k210_register_plls()
603 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_aclk_set_parent()
605 k210_aclk_set_selector(ksc->regs, index); in k210_aclk_set_parent()
607 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_aclk_set_parent()
617 sel = readl(ksc->regs + K210_SYSCTL_SEL0) & K210_ACLK_SEL; in k210_aclk_get_parent()
626 u32 reg = readl(ksc->regs + K210_SYSCTL_SEL0); in k210_aclk_get_rate() local
629 if (!(reg & 0x1)) in k210_aclk_get_rate()
632 shift = FIELD_GET(K210_ACLK_DIV, reg); in k210_aclk_get_rate()
650 struct clk_init_data init = {}; in k210_register_aclk() local
653 { .hw = &ksc->plls[K210_PLL0].hw }, in k210_register_aclk()
657 init.name = "aclk"; in k210_register_aclk()
658 init.parent_data = parent_data; in k210_register_aclk()
659 init.num_parents = 2; in k210_register_aclk()
660 init.ops = &k210_aclk_ops; in k210_register_aclk()
661 ksc->aclk.init = &init; in k210_register_aclk()
663 ret = of_clk_hw_register(np, &ksc->aclk); in k210_register_aclk()
677 struct k210_sysclk *ksc = kclk->ksc; in k210_clk_enable()
678 struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; in k210_clk_enable()
680 u32 reg; in k210_clk_enable() local
682 if (!cfg->gate_reg) in k210_clk_enable()
685 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_clk_enable()
686 reg = readl(ksc->regs + cfg->gate_reg); in k210_clk_enable()
687 reg |= BIT(cfg->gate_bit); in k210_clk_enable()
688 writel(reg, ksc->regs + cfg->gate_reg); in k210_clk_enable()
689 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_clk_enable()
697 struct k210_sysclk *ksc = kclk->ksc; in k210_clk_disable()
698 struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; in k210_clk_disable()
700 u32 reg; in k210_clk_disable() local
702 if (!cfg->gate_reg) in k210_clk_disable()
705 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_clk_disable()
706 reg = readl(ksc->regs + cfg->gate_reg); in k210_clk_disable()
707 reg &= ~BIT(cfg->gate_bit); in k210_clk_disable()
708 writel(reg, ksc->regs + cfg->gate_reg); in k210_clk_disable()
709 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_clk_disable()
715 struct k210_sysclk *ksc = kclk->ksc; in k210_clk_set_parent()
716 struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; in k210_clk_set_parent()
718 u32 reg; in k210_clk_set_parent() local
720 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_clk_set_parent()
721 reg = readl(ksc->regs + cfg->mux_reg); in k210_clk_set_parent()
723 reg |= BIT(cfg->mux_bit); in k210_clk_set_parent()
725 reg &= ~BIT(cfg->mux_bit); in k210_clk_set_parent()
726 writel(reg, ksc->regs + cfg->mux_reg); in k210_clk_set_parent()
727 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_clk_set_parent()
735 struct k210_sysclk *ksc = kclk->ksc; in k210_clk_get_parent()
736 struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; in k210_clk_get_parent()
738 u32 reg, idx; in k210_clk_get_parent() local
740 spin_lock_irqsave(&ksc->clk_lock, flags); in k210_clk_get_parent()
741 reg = readl(ksc->regs + cfg->mux_reg); in k210_clk_get_parent()
742 idx = (reg & BIT(cfg->mux_bit)) ? 1 : 0; in k210_clk_get_parent()
743 spin_unlock_irqrestore(&ksc->clk_lock, flags); in k210_clk_get_parent()
752 struct k210_sysclk *ksc = kclk->ksc; in k210_clk_get_rate()
753 struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; in k210_clk_get_rate()
754 u32 reg, div_val; in k210_clk_get_rate() local
756 if (!cfg->div_reg) in k210_clk_get_rate()
759 reg = readl(ksc->regs + cfg->div_reg); in k210_clk_get_rate()
760 div_val = (reg >> cfg->div_shift) & GENMASK(cfg->div_width - 1, 0); in k210_clk_get_rate()
762 switch (cfg->div_type) { in k210_clk_get_rate()
795 struct k210_clk *kclk = &ksc->clks[id]; in k210_register_clk()
796 struct clk_init_data init = {}; in k210_register_clk() local
799 init.name = k210_clk_cfgs[id].name; in k210_register_clk()
800 init.flags = flags; in k210_register_clk()
801 init.parent_data = parent_data; in k210_register_clk()
802 init.num_parents = num_parents; in k210_register_clk()
804 init.ops = &k210_clk_mux_ops; in k210_register_clk()
806 init.ops = &k210_clk_ops; in k210_register_clk()
808 kclk->id = id; in k210_register_clk()
809 kclk->ksc = ksc; in k210_register_clk()
810 kclk->hw.init = &init; in k210_register_clk()
812 ret = of_clk_hw_register(np, &kclk->hw); in k210_register_clk()
816 kclk->id = -1; in k210_register_clk()
828 { .hw = &ksc->plls[K210_PLL0].hw } in k210_register_mux_clk()
850 .hw = &ksc->plls[pllid].hw, in k210_register_pll_child()
861 .hw = &ksc->aclk, in k210_register_aclk_child()
872 .hw = &ksc->clks[parent_id].hw, in k210_register_clk_child()
882 unsigned int idx = clkspec->args[0]; in k210_clk_hw_onecell_get()
885 return ERR_PTR(-EINVAL); in k210_clk_hw_onecell_get()
887 return &ksc->clks[idx].hw; in k210_clk_hw_onecell_get()
900 spin_lock_init(&ksc->clk_lock); in k210_clk_init()
902 ksc->regs = of_iomap(sysctl_np, 0); in k210_clk_init()
904 if (!ksc->regs) { in k210_clk_init()
981 if (ksc->clks[i].id != i) in k210_clk_init()
992 np, clk_hw_get_rate(&ksc->clks[K210_CLK_CPU].hw) / 1000000); in k210_clk_init()
995 CLK_OF_DECLARE(k210_clk, "canaan,k210-clk", k210_clk_init);