0001
0002
0003
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
0013 #define CLK_MGR_PLL_CLK_SRC_SHIFT 16
0014 #define CLK_MGR_PLL_CLK_SRC_MASK 0x3
0015
0016
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
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
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
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
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
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
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
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 }