1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2017, Intel Corporation 4 */ 5 #include <linux/slab.h> 6 #include <linux/clk-provider.h> 7 #include <linux/io.h> 8 9 #include "stratix10-clk.h" 10 #include "clk.h" 11 12 /* Clock Manager offsets */ 13 #define CLK_MGR_PLL_CLK_SRC_SHIFT 16 14 #define CLK_MGR_PLL_CLK_SRC_MASK 0x3 15 16 /* PLL Clock enable bits */ 17 #define SOCFPGA_PLL_POWER 0 18 #define SOCFPGA_PLL_RESET_MASK 0x2 19 #define SOCFPGA_PLL_REFDIV_MASK 0x00003F00 20 #define SOCFPGA_PLL_REFDIV_SHIFT 8 21 #define SOCFPGA_PLL_AREFDIV_MASK 0x00000F00 22 #define SOCFPGA_PLL_DREFDIV_MASK 0x00003000 23 #define SOCFPGA_PLL_DREFDIV_SHIFT 12 24 #define SOCFPGA_PLL_MDIV_MASK 0xFF000000 25 #define SOCFPGA_PLL_MDIV_SHIFT 24 26 #define SOCFPGA_AGILEX_PLL_MDIV_MASK 0x000003FF 27 #define SWCTRLBTCLKSEL_MASK 0x200 28 #define SWCTRLBTCLKSEL_SHIFT 9 29 30 #define SOCFPGA_N5X_PLLDIV_FDIV_MASK GENMASK(16, 8) 31 #define SOCFPGA_N5X_PLLDIV_FDIV_SHIFT 8 32 #define SOCFPGA_N5X_PLLDIV_RDIV_MASK GENMASK(5, 0) 33 #define SOCFPGA_N5X_PLLDIV_QDIV_MASK GENMASK(26, 24) 34 #define SOCFPGA_N5X_PLLDIV_QDIV_SHIFT 24 35 36 #define SOCFPGA_BOOT_CLK "boot_clk" 37 38 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) 39 40 static unsigned long n5x_clk_pll_recalc_rate(struct clk_hw *hwclk, 41 unsigned long parent_rate) 42 { 43 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 44 unsigned long fdiv, reg, rdiv, qdiv; 45 u32 power = 1; 46 47 /* read VCO1 reg for numerator and denominator */ 48 reg = readl(socfpgaclk->hw.reg + 0x8); 49 fdiv = (reg & SOCFPGA_N5X_PLLDIV_FDIV_MASK) >> SOCFPGA_N5X_PLLDIV_FDIV_SHIFT; 50 rdiv = (reg & SOCFPGA_N5X_PLLDIV_RDIV_MASK); 51 qdiv = (reg & SOCFPGA_N5X_PLLDIV_QDIV_MASK) >> SOCFPGA_N5X_PLLDIV_QDIV_SHIFT; 52 53 while (qdiv) { 54 power *= 2; 55 qdiv--; 56 } 57 58 return ((parent_rate * 2 * (fdiv + 1)) / ((rdiv + 1) * power)); 59 } 60 61 static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk, 62 unsigned long parent_rate) 63 { 64 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 65 unsigned long arefdiv, reg, mdiv; 66 unsigned long long vco_freq; 67 68 /* read VCO1 reg for numerator and denominator */ 69 reg = readl(socfpgaclk->hw.reg); 70 arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT; 71 72 vco_freq = (unsigned long long)parent_rate / arefdiv; 73 74 /* Read mdiv and fdiv from the fdbck register */ 75 reg = readl(socfpgaclk->hw.reg + 0x24); 76 mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK; 77 78 vco_freq = (unsigned long long)vco_freq * mdiv; 79 return (unsigned long)vco_freq; 80 } 81 82 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, 83 unsigned long parent_rate) 84 { 85 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 86 unsigned long mdiv; 87 unsigned long refdiv; 88 unsigned long reg; 89 unsigned long long vco_freq; 90 91 /* read VCO1 reg for numerator and denominator */ 92 reg = readl(socfpgaclk->hw.reg); 93 refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT; 94 95 vco_freq = parent_rate; 96 do_div(vco_freq, refdiv); 97 98 /* Read mdiv and fdiv from the fdbck register */ 99 reg = readl(socfpgaclk->hw.reg + 0x4); 100 mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT; 101 vco_freq = (unsigned long long)vco_freq * (mdiv + 6); 102 103 return (unsigned long)vco_freq; 104 } 105 106 static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk, 107 unsigned long parent_rate) 108 { 109 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 110 u32 div; 111 112 div = ((readl(socfpgaclk->hw.reg) & 113 SWCTRLBTCLKSEL_MASK) >> 114 SWCTRLBTCLKSEL_SHIFT); 115 div += 1; 116 return parent_rate /= div; 117 } 118 119 120 static u8 clk_pll_get_parent(struct clk_hw *hwclk) 121 { 122 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 123 u32 pll_src; 124 125 pll_src = readl(socfpgaclk->hw.reg); 126 return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) & 127 CLK_MGR_PLL_CLK_SRC_MASK; 128 } 129 130 static u8 clk_boot_get_parent(struct clk_hw *hwclk) 131 { 132 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 133 u32 pll_src; 134 135 pll_src = readl(socfpgaclk->hw.reg); 136 return (pll_src >> SWCTRLBTCLKSEL_SHIFT) & 137 SWCTRLBTCLKSEL_MASK; 138 } 139 140 static int clk_pll_prepare(struct clk_hw *hwclk) 141 { 142 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 143 u32 reg; 144 145 /* Bring PLL out of reset */ 146 reg = readl(socfpgaclk->hw.reg); 147 reg |= SOCFPGA_PLL_RESET_MASK; 148 writel(reg, socfpgaclk->hw.reg); 149 150 return 0; 151 } 152 153 static int n5x_clk_pll_prepare(struct clk_hw *hwclk) 154 { 155 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 156 u32 reg; 157 158 /* Bring PLL out of reset */ 159 reg = readl(socfpgaclk->hw.reg + 0x4); 160 reg |= SOCFPGA_PLL_RESET_MASK; 161 writel(reg, socfpgaclk->hw.reg + 0x4); 162 163 return 0; 164 } 165 166 static const struct clk_ops n5x_clk_pll_ops = { 167 .recalc_rate = n5x_clk_pll_recalc_rate, 168 .get_parent = clk_pll_get_parent, 169 .prepare = n5x_clk_pll_prepare, 170 }; 171 172 static const struct clk_ops agilex_clk_pll_ops = { 173 .recalc_rate = agilex_clk_pll_recalc_rate, 174 .get_parent = clk_pll_get_parent, 175 .prepare = clk_pll_prepare, 176 }; 177 178 static const struct clk_ops clk_pll_ops = { 179 .recalc_rate = clk_pll_recalc_rate, 180 .get_parent = clk_pll_get_parent, 181 .prepare = clk_pll_prepare, 182 }; 183 184 static const struct clk_ops clk_boot_ops = { 185 .recalc_rate = clk_boot_clk_recalc_rate, 186 .get_parent = clk_boot_get_parent, 187 .prepare = clk_pll_prepare, 188 }; 189 190 struct clk_hw *s10_register_pll(const struct stratix10_pll_clock *clks, 191 void __iomem *reg) 192 { 193 struct clk_hw *hw_clk; 194 struct socfpga_pll *pll_clk; 195 struct clk_init_data init; 196 const char *name = clks->name; 197 int ret; 198 199 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 200 if (WARN_ON(!pll_clk)) 201 return NULL; 202 203 pll_clk->hw.reg = reg + clks->offset; 204 205 if (streq(name, SOCFPGA_BOOT_CLK)) 206 init.ops = &clk_boot_ops; 207 else 208 init.ops = &clk_pll_ops; 209 210 init.name = name; 211 init.flags = clks->flags; 212 213 init.num_parents = clks->num_parents; 214 init.parent_names = NULL; 215 init.parent_data = clks->parent_data; 216 pll_clk->hw.hw.init = &init; 217 218 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 219 220 hw_clk = &pll_clk->hw.hw; 221 222 ret = clk_hw_register(NULL, hw_clk); 223 if (ret) { 224 kfree(pll_clk); 225 return ERR_PTR(ret); 226 } 227 return hw_clk; 228 } 229 230 struct clk_hw *agilex_register_pll(const struct stratix10_pll_clock *clks, 231 void __iomem *reg) 232 { 233 struct clk_hw *hw_clk; 234 struct socfpga_pll *pll_clk; 235 struct clk_init_data init; 236 const char *name = clks->name; 237 int ret; 238 239 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 240 if (WARN_ON(!pll_clk)) 241 return NULL; 242 243 pll_clk->hw.reg = reg + clks->offset; 244 245 if (streq(name, SOCFPGA_BOOT_CLK)) 246 init.ops = &clk_boot_ops; 247 else 248 init.ops = &agilex_clk_pll_ops; 249 250 init.name = name; 251 init.flags = clks->flags; 252 253 init.num_parents = clks->num_parents; 254 init.parent_names = NULL; 255 init.parent_data = clks->parent_data; 256 pll_clk->hw.hw.init = &init; 257 258 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 259 hw_clk = &pll_clk->hw.hw; 260 261 ret = clk_hw_register(NULL, hw_clk); 262 if (ret) { 263 kfree(pll_clk); 264 return ERR_PTR(ret); 265 } 266 return hw_clk; 267 } 268 269 struct clk_hw *n5x_register_pll(const struct stratix10_pll_clock *clks, 270 void __iomem *reg) 271 { 272 struct clk_hw *hw_clk; 273 struct socfpga_pll *pll_clk; 274 struct clk_init_data init; 275 const char *name = clks->name; 276 int ret; 277 278 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 279 if (WARN_ON(!pll_clk)) 280 return NULL; 281 282 pll_clk->hw.reg = reg + clks->offset; 283 284 if (streq(name, SOCFPGA_BOOT_CLK)) 285 init.ops = &clk_boot_ops; 286 else 287 init.ops = &n5x_clk_pll_ops; 288 289 init.name = name; 290 init.flags = clks->flags; 291 292 init.num_parents = clks->num_parents; 293 init.parent_names = NULL; 294 init.parent_data = clks->parent_data; 295 pll_clk->hw.hw.init = &init; 296 297 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 298 hw_clk = &pll_clk->hw.hw; 299 300 ret = clk_hw_register(NULL, hw_clk); 301 if (ret) { 302 kfree(pll_clk); 303 return ERR_PTR(ret); 304 } 305 return hw_clk; 306 } 307