1 /* 2 * Copyright (C) 2014 Google, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 */ 8 9 #include <linux/clk-provider.h> 10 #include <linux/io.h> 11 #include <linux/kernel.h> 12 #include <linux/slab.h> 13 14 #include "clk.h" 15 16 #define PLL_STATUS 0x0 17 #define PLL_STATUS_LOCK BIT(0) 18 19 #define PLL_CTRL1 0x4 20 #define PLL_CTRL1_REFDIV_SHIFT 0 21 #define PLL_CTRL1_REFDIV_MASK 0x3f 22 #define PLL_CTRL1_FBDIV_SHIFT 6 23 #define PLL_CTRL1_FBDIV_MASK 0xfff 24 #define PLL_INT_CTRL1_POSTDIV1_SHIFT 18 25 #define PLL_INT_CTRL1_POSTDIV1_MASK 0x7 26 #define PLL_INT_CTRL1_POSTDIV2_SHIFT 21 27 #define PLL_INT_CTRL1_POSTDIV2_MASK 0x7 28 #define PLL_INT_CTRL1_PD BIT(24) 29 #define PLL_INT_CTRL1_DSMPD BIT(25) 30 #define PLL_INT_CTRL1_FOUTPOSTDIVPD BIT(26) 31 #define PLL_INT_CTRL1_FOUTVCOPD BIT(27) 32 33 #define PLL_CTRL2 0x8 34 #define PLL_FRAC_CTRL2_FRAC_SHIFT 0 35 #define PLL_FRAC_CTRL2_FRAC_MASK 0xffffff 36 #define PLL_FRAC_CTRL2_POSTDIV1_SHIFT 24 37 #define PLL_FRAC_CTRL2_POSTDIV1_MASK 0x7 38 #define PLL_FRAC_CTRL2_POSTDIV2_SHIFT 27 39 #define PLL_FRAC_CTRL2_POSTDIV2_MASK 0x7 40 #define PLL_INT_CTRL2_BYPASS BIT(28) 41 42 #define PLL_CTRL3 0xc 43 #define PLL_FRAC_CTRL3_PD BIT(0) 44 #define PLL_FRAC_CTRL3_DACPD BIT(1) 45 #define PLL_FRAC_CTRL3_DSMPD BIT(2) 46 #define PLL_FRAC_CTRL3_FOUTPOSTDIVPD BIT(3) 47 #define PLL_FRAC_CTRL3_FOUT4PHASEPD BIT(4) 48 #define PLL_FRAC_CTRL3_FOUTVCOPD BIT(5) 49 50 #define PLL_CTRL4 0x10 51 #define PLL_FRAC_CTRL4_BYPASS BIT(28) 52 53 struct pistachio_clk_pll { 54 struct clk_hw hw; 55 void __iomem *base; 56 struct pistachio_pll_rate_table *rates; 57 unsigned int nr_rates; 58 }; 59 60 static inline u32 pll_readl(struct pistachio_clk_pll *pll, u32 reg) 61 { 62 return readl(pll->base + reg); 63 } 64 65 static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg) 66 { 67 writel(val, pll->base + reg); 68 } 69 70 static inline u32 do_div_round_closest(u64 dividend, u32 divisor) 71 { 72 dividend += divisor / 2; 73 do_div(dividend, divisor); 74 75 return dividend; 76 } 77 78 static inline struct pistachio_clk_pll *to_pistachio_pll(struct clk_hw *hw) 79 { 80 return container_of(hw, struct pistachio_clk_pll, hw); 81 } 82 83 static struct pistachio_pll_rate_table * 84 pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref, 85 unsigned long fout) 86 { 87 unsigned int i; 88 89 for (i = 0; i < pll->nr_rates; i++) { 90 if (pll->rates[i].fref == fref && pll->rates[i].fout == fout) 91 return &pll->rates[i]; 92 } 93 94 return NULL; 95 } 96 97 static long pll_round_rate(struct clk_hw *hw, unsigned long rate, 98 unsigned long *parent_rate) 99 { 100 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 101 unsigned int i; 102 103 for (i = 0; i < pll->nr_rates; i++) { 104 if (i > 0 && pll->rates[i].fref == *parent_rate && 105 pll->rates[i].fout <= rate) 106 return pll->rates[i - 1].fout; 107 } 108 109 return pll->rates[0].fout; 110 } 111 112 static int pll_gf40lp_frac_enable(struct clk_hw *hw) 113 { 114 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 115 u32 val; 116 117 val = pll_readl(pll, PLL_CTRL3); 118 val &= ~(PLL_FRAC_CTRL3_PD | PLL_FRAC_CTRL3_DACPD | 119 PLL_FRAC_CTRL3_DSMPD | PLL_FRAC_CTRL3_FOUTPOSTDIVPD | 120 PLL_FRAC_CTRL3_FOUT4PHASEPD | PLL_FRAC_CTRL3_FOUTVCOPD); 121 pll_writel(pll, val, PLL_CTRL3); 122 123 val = pll_readl(pll, PLL_CTRL4); 124 val &= ~PLL_FRAC_CTRL4_BYPASS; 125 pll_writel(pll, val, PLL_CTRL4); 126 127 return 0; 128 } 129 130 static void pll_gf40lp_frac_disable(struct clk_hw *hw) 131 { 132 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 133 u32 val; 134 135 val = pll_readl(pll, PLL_CTRL3); 136 val |= PLL_FRAC_CTRL3_PD; 137 pll_writel(pll, val, PLL_CTRL3); 138 } 139 140 static int pll_gf40lp_frac_is_enabled(struct clk_hw *hw) 141 { 142 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 143 144 return !(pll_readl(pll, PLL_CTRL3) & PLL_FRAC_CTRL3_PD); 145 } 146 147 static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate, 148 unsigned long parent_rate) 149 { 150 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 151 struct pistachio_pll_rate_table *params; 152 bool was_enabled; 153 u32 val; 154 155 params = pll_get_params(pll, parent_rate, rate); 156 if (!params) 157 return -EINVAL; 158 159 was_enabled = pll_gf40lp_frac_is_enabled(hw); 160 if (!was_enabled) 161 pll_gf40lp_frac_enable(hw); 162 163 val = pll_readl(pll, PLL_CTRL1); 164 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | 165 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT)); 166 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | 167 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT); 168 pll_writel(pll, val, PLL_CTRL1); 169 170 val = pll_readl(pll, PLL_CTRL2); 171 val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) | 172 (PLL_FRAC_CTRL2_POSTDIV1_MASK << 173 PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | 174 (PLL_FRAC_CTRL2_POSTDIV2_MASK << 175 PLL_FRAC_CTRL2_POSTDIV2_SHIFT)); 176 val |= (params->frac << PLL_FRAC_CTRL2_FRAC_SHIFT) | 177 (params->postdiv1 << PLL_FRAC_CTRL2_POSTDIV1_SHIFT) | 178 (params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT); 179 pll_writel(pll, val, PLL_CTRL2); 180 181 while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK)) 182 cpu_relax(); 183 184 if (!was_enabled) 185 pll_gf40lp_frac_disable(hw); 186 187 return 0; 188 } 189 190 static unsigned long pll_gf40lp_frac_recalc_rate(struct clk_hw *hw, 191 unsigned long parent_rate) 192 { 193 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 194 u32 val, prediv, fbdiv, frac, postdiv1, postdiv2; 195 u64 rate = parent_rate; 196 197 val = pll_readl(pll, PLL_CTRL1); 198 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; 199 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; 200 201 val = pll_readl(pll, PLL_CTRL2); 202 postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) & 203 PLL_FRAC_CTRL2_POSTDIV1_MASK; 204 postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) & 205 PLL_FRAC_CTRL2_POSTDIV2_MASK; 206 frac = (val >> PLL_FRAC_CTRL2_FRAC_SHIFT) & PLL_FRAC_CTRL2_FRAC_MASK; 207 208 rate *= (fbdiv << 24) + frac; 209 rate = do_div_round_closest(rate, (prediv * postdiv1 * postdiv2) << 24); 210 211 return rate; 212 } 213 214 static struct clk_ops pll_gf40lp_frac_ops = { 215 .enable = pll_gf40lp_frac_enable, 216 .disable = pll_gf40lp_frac_disable, 217 .is_enabled = pll_gf40lp_frac_is_enabled, 218 .recalc_rate = pll_gf40lp_frac_recalc_rate, 219 .round_rate = pll_round_rate, 220 .set_rate = pll_gf40lp_frac_set_rate, 221 }; 222 223 static struct clk_ops pll_gf40lp_frac_fixed_ops = { 224 .enable = pll_gf40lp_frac_enable, 225 .disable = pll_gf40lp_frac_disable, 226 .is_enabled = pll_gf40lp_frac_is_enabled, 227 .recalc_rate = pll_gf40lp_frac_recalc_rate, 228 }; 229 230 static int pll_gf40lp_laint_enable(struct clk_hw *hw) 231 { 232 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 233 u32 val; 234 235 val = pll_readl(pll, PLL_CTRL1); 236 val &= ~(PLL_INT_CTRL1_PD | PLL_INT_CTRL1_DSMPD | 237 PLL_INT_CTRL1_FOUTPOSTDIVPD | PLL_INT_CTRL1_FOUTVCOPD); 238 pll_writel(pll, val, PLL_CTRL1); 239 240 val = pll_readl(pll, PLL_CTRL2); 241 val &= ~PLL_INT_CTRL2_BYPASS; 242 pll_writel(pll, val, PLL_CTRL2); 243 244 return 0; 245 } 246 247 static void pll_gf40lp_laint_disable(struct clk_hw *hw) 248 { 249 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 250 u32 val; 251 252 val = pll_readl(pll, PLL_CTRL1); 253 val |= PLL_INT_CTRL1_PD; 254 pll_writel(pll, val, PLL_CTRL1); 255 } 256 257 static int pll_gf40lp_laint_is_enabled(struct clk_hw *hw) 258 { 259 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 260 261 return !(pll_readl(pll, PLL_CTRL1) & PLL_INT_CTRL1_PD); 262 } 263 264 static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate, 265 unsigned long parent_rate) 266 { 267 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 268 struct pistachio_pll_rate_table *params; 269 bool was_enabled; 270 u32 val; 271 272 params = pll_get_params(pll, parent_rate, rate); 273 if (!params) 274 return -EINVAL; 275 276 was_enabled = pll_gf40lp_laint_is_enabled(hw); 277 if (!was_enabled) 278 pll_gf40lp_laint_enable(hw); 279 280 val = pll_readl(pll, PLL_CTRL1); 281 val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) | 282 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) | 283 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) | 284 (PLL_INT_CTRL1_POSTDIV2_MASK << PLL_INT_CTRL1_POSTDIV2_SHIFT)); 285 val |= (params->refdiv << PLL_CTRL1_REFDIV_SHIFT) | 286 (params->fbdiv << PLL_CTRL1_FBDIV_SHIFT) | 287 (params->postdiv1 << PLL_INT_CTRL1_POSTDIV1_SHIFT) | 288 (params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT); 289 pll_writel(pll, val, PLL_CTRL1); 290 291 while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK)) 292 cpu_relax(); 293 294 if (!was_enabled) 295 pll_gf40lp_laint_disable(hw); 296 297 return 0; 298 } 299 300 static unsigned long pll_gf40lp_laint_recalc_rate(struct clk_hw *hw, 301 unsigned long parent_rate) 302 { 303 struct pistachio_clk_pll *pll = to_pistachio_pll(hw); 304 u32 val, prediv, fbdiv, postdiv1, postdiv2; 305 u64 rate = parent_rate; 306 307 val = pll_readl(pll, PLL_CTRL1); 308 prediv = (val >> PLL_CTRL1_REFDIV_SHIFT) & PLL_CTRL1_REFDIV_MASK; 309 fbdiv = (val >> PLL_CTRL1_FBDIV_SHIFT) & PLL_CTRL1_FBDIV_MASK; 310 postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) & 311 PLL_INT_CTRL1_POSTDIV1_MASK; 312 postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) & 313 PLL_INT_CTRL1_POSTDIV2_MASK; 314 315 rate *= fbdiv; 316 rate = do_div_round_closest(rate, prediv * postdiv1 * postdiv2); 317 318 return rate; 319 } 320 321 static struct clk_ops pll_gf40lp_laint_ops = { 322 .enable = pll_gf40lp_laint_enable, 323 .disable = pll_gf40lp_laint_disable, 324 .is_enabled = pll_gf40lp_laint_is_enabled, 325 .recalc_rate = pll_gf40lp_laint_recalc_rate, 326 .round_rate = pll_round_rate, 327 .set_rate = pll_gf40lp_laint_set_rate, 328 }; 329 330 static struct clk_ops pll_gf40lp_laint_fixed_ops = { 331 .enable = pll_gf40lp_laint_enable, 332 .disable = pll_gf40lp_laint_disable, 333 .is_enabled = pll_gf40lp_laint_is_enabled, 334 .recalc_rate = pll_gf40lp_laint_recalc_rate, 335 }; 336 337 static struct clk *pll_register(const char *name, const char *parent_name, 338 unsigned long flags, void __iomem *base, 339 enum pistachio_pll_type type, 340 struct pistachio_pll_rate_table *rates, 341 unsigned int nr_rates) 342 { 343 struct pistachio_clk_pll *pll; 344 struct clk_init_data init; 345 struct clk *clk; 346 347 pll = kzalloc(sizeof(*pll), GFP_KERNEL); 348 if (!pll) 349 return ERR_PTR(-ENOMEM); 350 351 init.name = name; 352 init.flags = flags | CLK_GET_RATE_NOCACHE; 353 init.parent_names = &parent_name; 354 init.num_parents = 1; 355 356 switch (type) { 357 case PLL_GF40LP_FRAC: 358 if (rates) 359 init.ops = &pll_gf40lp_frac_ops; 360 else 361 init.ops = &pll_gf40lp_frac_fixed_ops; 362 break; 363 case PLL_GF40LP_LAINT: 364 if (rates) 365 init.ops = &pll_gf40lp_laint_ops; 366 else 367 init.ops = &pll_gf40lp_laint_fixed_ops; 368 break; 369 default: 370 pr_err("Unrecognized PLL type %u\n", type); 371 kfree(pll); 372 return ERR_PTR(-EINVAL); 373 } 374 375 pll->hw.init = &init; 376 pll->base = base; 377 pll->rates = rates; 378 pll->nr_rates = nr_rates; 379 380 clk = clk_register(NULL, &pll->hw); 381 if (IS_ERR(clk)) 382 kfree(pll); 383 384 return clk; 385 } 386 387 void pistachio_clk_register_pll(struct pistachio_clk_provider *p, 388 struct pistachio_pll *pll, 389 unsigned int num) 390 { 391 struct clk *clk; 392 unsigned int i; 393 394 for (i = 0; i < num; i++) { 395 clk = pll_register(pll[i].name, pll[i].parent, 396 0, p->base + pll[i].reg_base, 397 pll[i].type, pll[i].rates, 398 pll[i].nr_rates); 399 p->clk_data.clks[pll[i].id] = clk; 400 } 401 } 402