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 = 1; 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 *s10_register_pll(const struct stratix10_pll_clock *clks, 191 void __iomem *reg) 192 { 193 struct clk *clk; 194 struct socfpga_pll *pll_clk; 195 struct clk_init_data init; 196 const char *name = clks->name; 197 198 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 199 if (WARN_ON(!pll_clk)) 200 return NULL; 201 202 pll_clk->hw.reg = reg + clks->offset; 203 204 if (streq(name, SOCFPGA_BOOT_CLK)) 205 init.ops = &clk_boot_ops; 206 else 207 init.ops = &clk_pll_ops; 208 209 init.name = name; 210 init.flags = clks->flags; 211 212 init.num_parents = clks->num_parents; 213 init.parent_names = NULL; 214 init.parent_data = clks->parent_data; 215 pll_clk->hw.hw.init = &init; 216 217 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 218 219 clk = clk_register(NULL, &pll_clk->hw.hw); 220 if (WARN_ON(IS_ERR(clk))) { 221 kfree(pll_clk); 222 return NULL; 223 } 224 return clk; 225 } 226 227 struct clk *agilex_register_pll(const struct stratix10_pll_clock *clks, 228 void __iomem *reg) 229 { 230 struct clk *clk; 231 struct socfpga_pll *pll_clk; 232 struct clk_init_data init; 233 const char *name = clks->name; 234 235 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 236 if (WARN_ON(!pll_clk)) 237 return NULL; 238 239 pll_clk->hw.reg = reg + clks->offset; 240 241 if (streq(name, SOCFPGA_BOOT_CLK)) 242 init.ops = &clk_boot_ops; 243 else 244 init.ops = &agilex_clk_pll_ops; 245 246 init.name = name; 247 init.flags = clks->flags; 248 249 init.num_parents = clks->num_parents; 250 init.parent_names = NULL; 251 init.parent_data = clks->parent_data; 252 pll_clk->hw.hw.init = &init; 253 254 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 255 256 clk = clk_register(NULL, &pll_clk->hw.hw); 257 if (WARN_ON(IS_ERR(clk))) { 258 kfree(pll_clk); 259 return NULL; 260 } 261 return clk; 262 } 263 264 struct clk *n5x_register_pll(const struct stratix10_pll_clock *clks, 265 void __iomem *reg) 266 { 267 struct clk *clk; 268 struct socfpga_pll *pll_clk; 269 struct clk_init_data init; 270 const char *name = clks->name; 271 272 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 273 if (WARN_ON(!pll_clk)) 274 return NULL; 275 276 pll_clk->hw.reg = reg + clks->offset; 277 278 if (streq(name, SOCFPGA_BOOT_CLK)) 279 init.ops = &clk_boot_ops; 280 else 281 init.ops = &n5x_clk_pll_ops; 282 283 init.name = name; 284 init.flags = clks->flags; 285 286 init.num_parents = clks->num_parents; 287 init.parent_names = NULL; 288 init.parent_data = clks->parent_data; 289 pll_clk->hw.hw.init = &init; 290 291 pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; 292 293 clk = clk_register(NULL, &pll_clk->hw.hw); 294 if (WARN_ON(IS_ERR(clk))) { 295 kfree(pll_clk); 296 return NULL; 297 } 298 return clk; 299 } 300