1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Western Digital Corporation or its affiliates. 4 * 5 * Copyright (C) 2018 SiFive, Inc. 6 * Wesley Terpstra 7 * Paul Walmsley 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * This library supports configuration parsing and reprogramming of 19 * the CLN28HPC variant of the Analog Bits Wide Range PLL. The 20 * intention is for this library to be reusable for any device that 21 * integrates this PLL; thus the register structure and programming 22 * details are expected to be provided by a separate IP block driver. 23 * 24 * The bulk of this code is primarily useful for clock configurations 25 * that must operate at arbitrary rates, as opposed to clock configurations 26 * that are restricted by software or manufacturer guidance to a small, 27 * pre-determined set of performance points. 28 * 29 * References: 30 * - Analog Bits "Wide Range PLL Datasheet", version 2015.10.01 31 * - SiFive FU540-C000 Manual v1p0, Chapter 7 "Clocking and Reset" 32 */ 33 34 #include <linux/bug.h> 35 #include <linux/err.h> 36 #include <linux/log2.h> 37 #include <linux/math64.h> 38 39 #include "analogbits-wrpll-cln28hpc.h" 40 41 /* MIN_INPUT_FREQ: minimum input clock frequency, in Hz (Fref_min) */ 42 #define MIN_INPUT_FREQ 7000000 43 44 /* MAX_INPUT_FREQ: maximum input clock frequency, in Hz (Fref_max) */ 45 #define MAX_INPUT_FREQ 600000000 46 47 /* MIN_POST_DIVIDE_REF_FREQ: minimum post-divider reference frequency, in Hz */ 48 #define MIN_POST_DIVR_FREQ 7000000 49 50 /* MAX_POST_DIVIDE_REF_FREQ: maximum post-divider reference frequency, in Hz */ 51 #define MAX_POST_DIVR_FREQ 200000000 52 53 /* MIN_VCO_FREQ: minimum VCO frequency, in Hz (Fvco_min) */ 54 #define MIN_VCO_FREQ 2400000000UL 55 56 /* MAX_VCO_FREQ: maximum VCO frequency, in Hz (Fvco_max) */ 57 #define MAX_VCO_FREQ 4800000000ULL 58 59 /* MAX_DIVQ_DIVISOR: maximum output divisor. Selected by DIVQ = 6 */ 60 #define MAX_DIVQ_DIVISOR 64 61 62 /* MAX_DIVR_DIVISOR: maximum reference divisor. Selected by DIVR = 63 */ 63 #define MAX_DIVR_DIVISOR 64 64 65 /* MAX_LOCK_US: maximum PLL lock time, in microseconds (tLOCK_max) */ 66 #define MAX_LOCK_US 70 67 68 /* 69 * ROUND_SHIFT: number of bits to shift to avoid precision loss in the rounding 70 * algorithm 71 */ 72 #define ROUND_SHIFT 20 73 74 /* 75 * Private functions 76 */ 77 78 /** 79 * __wrpll_calc_filter_range() - determine PLL loop filter bandwidth 80 * @post_divr_freq: input clock rate after the R divider 81 * 82 * Select the value to be presented to the PLL RANGE input signals, based 83 * on the input clock frequency after the post-R-divider @post_divr_freq. 84 * This code follows the recommendations in the PLL datasheet for filter 85 * range selection. 86 * 87 * Return: The RANGE value to be presented to the PLL configuration inputs, 88 * or -1 upon error. 89 */ 90 static int __wrpll_calc_filter_range(unsigned long post_divr_freq) 91 { 92 u8 range; 93 94 if (post_divr_freq < MIN_POST_DIVR_FREQ || 95 post_divr_freq > MAX_POST_DIVR_FREQ) { 96 WARN(1, "%s: post-divider reference freq out of range: %lu", 97 __func__, post_divr_freq); 98 return -1; 99 } 100 101 if (post_divr_freq < 11000000) 102 range = 1; 103 else if (post_divr_freq < 18000000) 104 range = 2; 105 else if (post_divr_freq < 30000000) 106 range = 3; 107 else if (post_divr_freq < 50000000) 108 range = 4; 109 else if (post_divr_freq < 80000000) 110 range = 5; 111 else if (post_divr_freq < 130000000) 112 range = 6; 113 else 114 range = 7; 115 116 return range; 117 } 118 119 /** 120 * __wrpll_calc_fbdiv() - return feedback fixed divide value 121 * @c: ptr to a struct analogbits_wrpll_cfg record to read from 122 * 123 * The internal feedback path includes a fixed by-two divider; the 124 * external feedback path does not. Return the appropriate divider 125 * value (2 or 1) depending on whether internal or external feedback 126 * is enabled. This code doesn't test for invalid configurations 127 * (e.g. both or neither of WRPLL_FLAGS_*_FEEDBACK are set); it relies 128 * on the caller to do so. 129 * 130 * Context: Any context. Caller must protect the memory pointed to by 131 * @c from simultaneous modification. 132 * 133 * Return: 2 if internal feedback is enabled or 1 if external feedback 134 * is enabled. 135 */ 136 static u8 __wrpll_calc_fbdiv(struct analogbits_wrpll_cfg *c) 137 { 138 return (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK) ? 2 : 1; 139 } 140 141 /** 142 * __wrpll_calc_divq() - determine DIVQ based on target PLL output clock rate 143 * @target_rate: target PLL output clock rate 144 * @vco_rate: pointer to a u64 to store the computed VCO rate into 145 * 146 * Determine a reasonable value for the PLL Q post-divider, based on the 147 * target output rate @target_rate for the PLL. Along with returning the 148 * computed Q divider value as the return value, this function stores the 149 * desired target VCO rate into the variable pointed to by @vco_rate. 150 * 151 * Context: Any context. Caller must protect the memory pointed to by 152 * @vco_rate from simultaneous access or modification. 153 * 154 * Return: a positive integer DIVQ value to be programmed into the hardware 155 * upon success, or 0 upon error (since 0 is an invalid DIVQ value) 156 */ 157 static u8 __wrpll_calc_divq(u32 target_rate, u64 *vco_rate) 158 { 159 u64 s; 160 u8 divq = 0; 161 162 if (!vco_rate) { 163 WARN_ON(1); 164 goto wcd_out; 165 } 166 167 s = div_u64(MAX_VCO_FREQ, target_rate); 168 if (s <= 1) { 169 divq = 1; 170 *vco_rate = MAX_VCO_FREQ; 171 } else if (s > MAX_DIVQ_DIVISOR) { 172 divq = ilog2(MAX_DIVQ_DIVISOR); 173 *vco_rate = MIN_VCO_FREQ; 174 } else { 175 divq = ilog2(s); 176 *vco_rate = target_rate << divq; 177 } 178 179 wcd_out: 180 return divq; 181 } 182 183 /** 184 * __wrpll_update_parent_rate() - update PLL data when parent rate changes 185 * @c: ptr to a struct analogbits_wrpll_cfg record to write PLL data to 186 * @parent_rate: PLL input refclk rate (pre-R-divider) 187 * 188 * Pre-compute some data used by the PLL configuration algorithm when 189 * the PLL's reference clock rate changes. The intention is to avoid 190 * computation when the parent rate remains constant - expected to be 191 * the common case. 192 * 193 * Returns: 0 upon success or -1 if the reference clock rate is out of range. 194 */ 195 static int __wrpll_update_parent_rate(struct analogbits_wrpll_cfg *c, 196 unsigned long parent_rate) 197 { 198 u8 max_r_for_parent; 199 200 if (parent_rate > MAX_INPUT_FREQ || parent_rate < MIN_POST_DIVR_FREQ) 201 return -1; 202 203 c->_parent_rate = parent_rate; 204 max_r_for_parent = div_u64(parent_rate, MIN_POST_DIVR_FREQ); 205 c->_max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent); 206 207 /* Round up */ 208 c->_init_r = div_u64(parent_rate + MAX_POST_DIVR_FREQ - 1, 209 MAX_POST_DIVR_FREQ); 210 211 return 0; 212 } 213 214 /* 215 * Public functions 216 */ 217 218 /** 219 * analogbits_wrpll_configure() - compute PLL configuration for a target rate 220 * @c: ptr to a struct analogbits_wrpll_cfg record to write into 221 * @target_rate: target PLL output clock rate (post-Q-divider) 222 * @parent_rate: PLL input refclk rate (pre-R-divider) 223 * 224 * Given a pointer to a PLL context @c, a desired PLL target output 225 * rate @target_rate, and a reference clock input rate @parent_rate, 226 * compute the appropriate PLL signal configuration values. PLL 227 * reprogramming is not glitchless, so the caller should switch any 228 * downstream logic to a different clock source or clock-gate it 229 * before presenting these values to the PLL configuration signals. 230 * 231 * The caller must pass this function a pre-initialized struct 232 * analogbits_wrpll_cfg record: either initialized to zero (with the 233 * exception of the .name and .flags fields) or read from the PLL. 234 * 235 * Context: Any context. Caller must protect the memory pointed to by @c 236 * from simultaneous access or modification. 237 * 238 * Return: 0 upon success; anything else upon failure. 239 */ 240 int analogbits_wrpll_configure_for_rate(struct analogbits_wrpll_cfg *c, 241 u32 target_rate, 242 unsigned long parent_rate) 243 { 244 unsigned long ratio; 245 u64 target_vco_rate, delta, best_delta, f_pre_div, vco, vco_pre; 246 u32 best_f, f, post_divr_freq, fbcfg; 247 u8 fbdiv, divq, best_r, r; 248 249 if (!c) 250 return -1; 251 252 if (c->flags == 0) { 253 WARN(1, "%s called with uninitialized PLL config", __func__); 254 return -1; 255 } 256 257 fbcfg = WRPLL_FLAGS_INT_FEEDBACK_MASK | WRPLL_FLAGS_EXT_FEEDBACK_MASK; 258 if ((c->flags & fbcfg) == fbcfg) { 259 WARN(1, "%s called with invalid PLL config", __func__); 260 return -1; 261 } 262 263 if (c->flags == WRPLL_FLAGS_EXT_FEEDBACK_MASK) { 264 WARN(1, "%s: external feedback mode not currently supported", 265 __func__); 266 return -1; 267 } 268 269 /* Initialize rounding data if it hasn't been initialized already */ 270 if (parent_rate != c->_parent_rate) { 271 if (__wrpll_update_parent_rate(c, parent_rate)) { 272 pr_err("%s: PLL input rate is out of range\n", 273 __func__); 274 return -1; 275 } 276 } 277 278 c->flags &= ~WRPLL_FLAGS_RESET_MASK; 279 280 /* Put the PLL into bypass if the user requests the parent clock rate */ 281 if (target_rate == parent_rate) { 282 c->flags |= WRPLL_FLAGS_BYPASS_MASK; 283 return 0; 284 } 285 c->flags &= ~WRPLL_FLAGS_BYPASS_MASK; 286 287 /* Calculate the Q shift and target VCO rate */ 288 divq = __wrpll_calc_divq(target_rate, &target_vco_rate); 289 if (divq == 0) 290 return -1; 291 c->divq = divq; 292 293 /* Precalculate the pre-Q divider target ratio */ 294 ratio = div64_u64((target_vco_rate << ROUND_SHIFT), parent_rate); 295 296 fbdiv = __wrpll_calc_fbdiv(c); 297 best_r = 0; 298 best_f = 0; 299 best_delta = MAX_VCO_FREQ; 300 301 /* 302 * Consider all values for R which land within 303 * [MIN_POST_DIVR_FREQ, MAX_POST_DIVR_FREQ]; prefer smaller R 304 */ 305 for (r = c->_init_r; r <= c->_max_r; ++r) { 306 /* What is the best F we can pick in this case? */ 307 f_pre_div = ratio * r; 308 f = (f_pre_div + (1 << ROUND_SHIFT)) >> ROUND_SHIFT; 309 f >>= (fbdiv - 1); 310 311 post_divr_freq = div_u64(parent_rate, r); 312 vco_pre = fbdiv * post_divr_freq; 313 vco = vco_pre * f; 314 315 /* Ensure rounding didn't take us out of range */ 316 if (vco > target_vco_rate) { 317 --f; 318 vco = vco_pre * f; 319 } else if (vco < MIN_VCO_FREQ) { 320 ++f; 321 vco = vco_pre * f; 322 } 323 324 delta = abs(target_rate - vco); 325 if (delta < best_delta) { 326 best_delta = delta; 327 best_r = r; 328 best_f = f; 329 } 330 } 331 332 c->divr = best_r - 1; 333 c->divf = best_f - 1; 334 335 post_divr_freq = div_u64(parent_rate, best_r); 336 337 /* Pick the best PLL jitter filter */ 338 c->range = __wrpll_calc_filter_range(post_divr_freq); 339 340 return 0; 341 } 342 343 /** 344 * analogbits_wrpll_calc_output_rate() - calculate the PLL's target output rate 345 * @c: ptr to a struct analogbits_wrpll_cfg record to read from 346 * @parent_rate: PLL refclk rate 347 * 348 * Given a pointer to the PLL's current input configuration @c and the 349 * PLL's input reference clock rate @parent_rate (before the R 350 * pre-divider), calculate the PLL's output clock rate (after the Q 351 * post-divider) 352 * 353 * Context: Any context. Caller must protect the memory pointed to by @c 354 * from simultaneous modification. 355 * 356 * Return: the PLL's output clock rate, in Hz. 357 */ 358 unsigned long analogbits_wrpll_calc_output_rate(struct analogbits_wrpll_cfg *c, 359 unsigned long parent_rate) 360 { 361 u8 fbdiv; 362 u64 n; 363 364 WARN(c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK, 365 "external feedback mode not yet supported"); 366 367 fbdiv = __wrpll_calc_fbdiv(c); 368 n = parent_rate * fbdiv * (c->divf + 1); 369 n = div_u64(n, (c->divr + 1)); 370 n >>= c->divq; 371 372 return n; 373 } 374 375 /** 376 * analogbits_wrpll_calc_max_lock_us() - return the time for the PLL to lock 377 * @c: ptr to a struct analogbits_wrpll_cfg record to read from 378 * 379 * Return the minimum amount of time (in microseconds) that the caller 380 * must wait after reprogramming the PLL to ensure that it is locked 381 * to the input frequency and stable. This is likely to depend on the DIVR 382 * value; this is under discussion with the manufacturer. 383 * 384 * Return: the minimum amount of time the caller must wait for the PLL 385 * to lock (in microseconds) 386 */ 387 unsigned int analogbits_wrpll_calc_max_lock_us(struct analogbits_wrpll_cfg *c) 388 { 389 return MAX_LOCK_US; 390 } 391