Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017, Intel Corporation
0004  */
0005 #include <linux/slab.h>
0006 #include <linux/clk-provider.h>
0007 #include <linux/io.h>
0008 
0009 #include "stratix10-clk.h"
0010 #include "clk.h"
0011 
0012 /* Clock Manager offsets */
0013 #define CLK_MGR_PLL_CLK_SRC_SHIFT   16
0014 #define CLK_MGR_PLL_CLK_SRC_MASK    0x3
0015 
0016 /* PLL Clock enable bits */
0017 #define SOCFPGA_PLL_POWER       0
0018 #define SOCFPGA_PLL_RESET_MASK      0x2
0019 #define SOCFPGA_PLL_REFDIV_MASK     0x00003F00
0020 #define SOCFPGA_PLL_REFDIV_SHIFT    8
0021 #define SOCFPGA_PLL_AREFDIV_MASK    0x00000F00
0022 #define SOCFPGA_PLL_DREFDIV_MASK    0x00003000
0023 #define SOCFPGA_PLL_DREFDIV_SHIFT   12
0024 #define SOCFPGA_PLL_MDIV_MASK       0xFF000000
0025 #define SOCFPGA_PLL_MDIV_SHIFT      24
0026 #define SOCFPGA_AGILEX_PLL_MDIV_MASK    0x000003FF
0027 #define SWCTRLBTCLKSEL_MASK     0x200
0028 #define SWCTRLBTCLKSEL_SHIFT        9
0029 
0030 #define SOCFPGA_N5X_PLLDIV_FDIV_MASK    GENMASK(16, 8)
0031 #define SOCFPGA_N5X_PLLDIV_FDIV_SHIFT   8
0032 #define SOCFPGA_N5X_PLLDIV_RDIV_MASK    GENMASK(5, 0)
0033 #define SOCFPGA_N5X_PLLDIV_QDIV_MASK    GENMASK(26, 24)
0034 #define SOCFPGA_N5X_PLLDIV_QDIV_SHIFT   24
0035 
0036 #define SOCFPGA_BOOT_CLK        "boot_clk"
0037 
0038 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
0039 
0040 static unsigned long n5x_clk_pll_recalc_rate(struct clk_hw *hwclk,
0041                         unsigned long parent_rate)
0042 {
0043     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0044     unsigned long fdiv, reg, rdiv, qdiv;
0045     u32 power = 1;
0046 
0047     /* read VCO1 reg for numerator and denominator */
0048     reg = readl(socfpgaclk->hw.reg + 0x8);
0049     fdiv = (reg & SOCFPGA_N5X_PLLDIV_FDIV_MASK) >> SOCFPGA_N5X_PLLDIV_FDIV_SHIFT;
0050     rdiv = (reg & SOCFPGA_N5X_PLLDIV_RDIV_MASK);
0051     qdiv = (reg & SOCFPGA_N5X_PLLDIV_QDIV_MASK) >> SOCFPGA_N5X_PLLDIV_QDIV_SHIFT;
0052 
0053     while (qdiv) {
0054         power *= 2;
0055         qdiv--;
0056     }
0057 
0058     return ((parent_rate * 2 * (fdiv + 1)) / ((rdiv + 1) * power));
0059 }
0060 
0061 static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk,
0062                         unsigned long parent_rate)
0063 {
0064     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0065     unsigned long arefdiv, reg, mdiv;
0066     unsigned long long vco_freq;
0067 
0068     /* read VCO1 reg for numerator and denominator */
0069     reg = readl(socfpgaclk->hw.reg);
0070     arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
0071 
0072     vco_freq = (unsigned long long)parent_rate / arefdiv;
0073 
0074     /* Read mdiv and fdiv from the fdbck register */
0075     reg = readl(socfpgaclk->hw.reg + 0x24);
0076     mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK;
0077 
0078     vco_freq = (unsigned long long)vco_freq * mdiv;
0079     return (unsigned long)vco_freq;
0080 }
0081 
0082 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
0083                      unsigned long parent_rate)
0084 {
0085     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0086     unsigned long mdiv;
0087     unsigned long refdiv;
0088     unsigned long reg;
0089     unsigned long long vco_freq;
0090 
0091     /* read VCO1 reg for numerator and denominator */
0092     reg = readl(socfpgaclk->hw.reg);
0093     refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
0094 
0095     vco_freq = parent_rate;
0096     do_div(vco_freq, refdiv);
0097 
0098     /* Read mdiv and fdiv from the fdbck register */
0099     reg = readl(socfpgaclk->hw.reg + 0x4);
0100     mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
0101     vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
0102 
0103     return (unsigned long)vco_freq;
0104 }
0105 
0106 static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
0107                      unsigned long parent_rate)
0108 {
0109     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0110     u32 div;
0111 
0112     div = ((readl(socfpgaclk->hw.reg) &
0113         SWCTRLBTCLKSEL_MASK) >>
0114         SWCTRLBTCLKSEL_SHIFT);
0115     div += 1;
0116     return parent_rate / div;
0117 }
0118 
0119 
0120 static u8 clk_pll_get_parent(struct clk_hw *hwclk)
0121 {
0122     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0123     u32 pll_src;
0124 
0125     pll_src = readl(socfpgaclk->hw.reg);
0126     return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
0127         CLK_MGR_PLL_CLK_SRC_MASK;
0128 }
0129 
0130 static u8 clk_boot_get_parent(struct clk_hw *hwclk)
0131 {
0132     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0133     u32 pll_src;
0134 
0135     pll_src = readl(socfpgaclk->hw.reg);
0136     return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
0137         SWCTRLBTCLKSEL_MASK;
0138 }
0139 
0140 static int clk_pll_prepare(struct clk_hw *hwclk)
0141 {
0142     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0143     u32 reg;
0144 
0145     /* Bring PLL out of reset */
0146     reg = readl(socfpgaclk->hw.reg);
0147     reg |= SOCFPGA_PLL_RESET_MASK;
0148     writel(reg, socfpgaclk->hw.reg);
0149 
0150     return 0;
0151 }
0152 
0153 static int n5x_clk_pll_prepare(struct clk_hw *hwclk)
0154 {
0155     struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
0156     u32 reg;
0157 
0158     /* Bring PLL out of reset */
0159     reg = readl(socfpgaclk->hw.reg + 0x4);
0160     reg |= SOCFPGA_PLL_RESET_MASK;
0161     writel(reg, socfpgaclk->hw.reg + 0x4);
0162 
0163     return 0;
0164 }
0165 
0166 static const struct clk_ops n5x_clk_pll_ops = {
0167     .recalc_rate = n5x_clk_pll_recalc_rate,
0168     .get_parent = clk_pll_get_parent,
0169     .prepare = n5x_clk_pll_prepare,
0170 };
0171 
0172 static const struct clk_ops agilex_clk_pll_ops = {
0173     .recalc_rate = agilex_clk_pll_recalc_rate,
0174     .get_parent = clk_pll_get_parent,
0175     .prepare = clk_pll_prepare,
0176 };
0177 
0178 static const struct clk_ops clk_pll_ops = {
0179     .recalc_rate = clk_pll_recalc_rate,
0180     .get_parent = clk_pll_get_parent,
0181     .prepare = clk_pll_prepare,
0182 };
0183 
0184 static const struct clk_ops clk_boot_ops = {
0185     .recalc_rate = clk_boot_clk_recalc_rate,
0186     .get_parent = clk_boot_get_parent,
0187     .prepare = clk_pll_prepare,
0188 };
0189 
0190 struct clk_hw *s10_register_pll(const struct stratix10_pll_clock *clks,
0191                  void __iomem *reg)
0192 {
0193     struct clk_hw *hw_clk;
0194     struct socfpga_pll *pll_clk;
0195     struct clk_init_data init;
0196     const char *name = clks->name;
0197     int ret;
0198 
0199     pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
0200     if (WARN_ON(!pll_clk))
0201         return NULL;
0202 
0203     pll_clk->hw.reg = reg + clks->offset;
0204 
0205     if (streq(name, SOCFPGA_BOOT_CLK))
0206         init.ops = &clk_boot_ops;
0207     else
0208         init.ops = &clk_pll_ops;
0209 
0210     init.name = name;
0211     init.flags = clks->flags;
0212 
0213     init.num_parents = clks->num_parents;
0214     init.parent_names = NULL;
0215     init.parent_data = clks->parent_data;
0216     pll_clk->hw.hw.init = &init;
0217 
0218     pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
0219 
0220     hw_clk = &pll_clk->hw.hw;
0221 
0222     ret = clk_hw_register(NULL, hw_clk);
0223     if (ret) {
0224         kfree(pll_clk);
0225         return ERR_PTR(ret);
0226     }
0227     return hw_clk;
0228 }
0229 
0230 struct clk_hw *agilex_register_pll(const struct stratix10_pll_clock *clks,
0231                 void __iomem *reg)
0232 {
0233     struct clk_hw *hw_clk;
0234     struct socfpga_pll *pll_clk;
0235     struct clk_init_data init;
0236     const char *name = clks->name;
0237     int ret;
0238 
0239     pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
0240     if (WARN_ON(!pll_clk))
0241         return NULL;
0242 
0243     pll_clk->hw.reg = reg + clks->offset;
0244 
0245     if (streq(name, SOCFPGA_BOOT_CLK))
0246         init.ops = &clk_boot_ops;
0247     else
0248         init.ops = &agilex_clk_pll_ops;
0249 
0250     init.name = name;
0251     init.flags = clks->flags;
0252 
0253     init.num_parents = clks->num_parents;
0254     init.parent_names = NULL;
0255     init.parent_data = clks->parent_data;
0256     pll_clk->hw.hw.init = &init;
0257 
0258     pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
0259     hw_clk = &pll_clk->hw.hw;
0260 
0261     ret = clk_hw_register(NULL, hw_clk);
0262     if (ret) {
0263         kfree(pll_clk);
0264         return ERR_PTR(ret);
0265     }
0266     return hw_clk;
0267 }
0268 
0269 struct clk_hw *n5x_register_pll(const struct stratix10_pll_clock *clks,
0270                  void __iomem *reg)
0271 {
0272     struct clk_hw *hw_clk;
0273     struct socfpga_pll *pll_clk;
0274     struct clk_init_data init;
0275     const char *name = clks->name;
0276     int ret;
0277 
0278     pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
0279     if (WARN_ON(!pll_clk))
0280         return NULL;
0281 
0282     pll_clk->hw.reg = reg + clks->offset;
0283 
0284     if (streq(name, SOCFPGA_BOOT_CLK))
0285         init.ops = &clk_boot_ops;
0286     else
0287         init.ops = &n5x_clk_pll_ops;
0288 
0289     init.name = name;
0290     init.flags = clks->flags;
0291 
0292     init.num_parents = clks->num_parents;
0293     init.parent_names = NULL;
0294     init.parent_data = clks->parent_data;
0295     pll_clk->hw.hw.init = &init;
0296 
0297     pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
0298     hw_clk = &pll_clk->hw.hw;
0299 
0300     ret = clk_hw_register(NULL, hw_clk);
0301     if (ret) {
0302         kfree(pll_clk);
0303         return ERR_PTR(ret);
0304     }
0305     return hw_clk;
0306 }