summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/clk_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/clk_gm20b.c1605
1 files changed, 1605 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
new file mode 100644
index 00000000..61d3b6f5
--- /dev/null
+++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
@@ -0,0 +1,1605 @@
1/*
2 * GM20B Clocks
3 *
4 * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include "gk20a/gk20a.h"
26#include "clk_gm20b.h"
27
28#include <nvgpu/soc.h>
29#include <nvgpu/fuse.h>
30#include <nvgpu/bug.h>
31
32#include <nvgpu/hw/gm20b/hw_trim_gm20b.h>
33#include <nvgpu/hw/gm20b/hw_timer_gm20b.h>
34#include <nvgpu/hw/gm20b/hw_therm_gm20b.h>
35#include <nvgpu/hw/gm20b/hw_fuse_gm20b.h>
36
37#define gk20a_dbg_clk(fmt, arg...) \
38 gk20a_dbg(gpu_dbg_clk, fmt, ##arg)
39
40#define DFS_DET_RANGE 6 /* -2^6 ... 2^6-1 */
41#define SDM_DIN_RANGE 12 /* -2^12 ... 2^12-1 */
42#define DFS_TESTOUT_DET BIT(0)
43#define DFS_EXT_CAL_EN BIT(9)
44#define DFS_EXT_STROBE BIT(16)
45
46#define BOOT_GPU_UV_B1 1000000 /* gpu rail boot voltage 1.0V */
47#define BOOT_GPU_UV_C1 800000 /* gpu rail boot voltage 0.8V */
48#define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */
49
50#define DVFS_SAFE_MARGIN 10 /* 10% */
51
52static struct pll_parms gpc_pll_params_b1 = {
53 128000, 2600000, /* freq */
54 1300000, 2600000, /* vco */
55 12000, 38400, /* u */
56 1, 255, /* M */
57 8, 255, /* N */
58 1, 31, /* PL */
59 -165230, 214007, /* DFS_COEFF */
60 0, 0, /* ADC char coeff - to be read from fuses */
61 0x7 << 3, /* vco control in NA mode */
62 500, /* Locking and ramping timeout */
63 40, /* Lock delay in NA mode */
64 5, /* IDDQ mode exit delay */
65};
66
67static struct pll_parms gpc_pll_params_c1 = {
68 76800, 2600000, /* freq */
69 1300000, 2600000, /* vco */
70 19200, 38400, /* u */
71 1, 255, /* M */
72 8, 255, /* N */
73 1, 31, /* PL */
74 -172550, 195374, /* DFS_COEFF */
75 0, 0, /* ADC char coeff - to be read from fuses */
76 (0x1 << 3) | 0x7, /* vco control in NA mode */
77 500, /* Locking and ramping timeout */
78 40, /* Lock delay in NA mode */
79 5, /* IDDQ mode exit delay */
80 0x3 << 10, /* DFS control settings */
81};
82
83static struct pll_parms gpc_pll_params;
84
85static void clk_setup_slide(struct gk20a *g, u32 clk_u);
86
87#define DUMP_REG(addr_func) \
88do { \
89 addr = trim_sys_##addr_func##_r(); \
90 data = gk20a_readl(g, addr); \
91 pr_info(#addr_func "[0x%x] = 0x%x\n", addr, data); \
92} while (0)
93
94static void dump_gpc_pll(struct gk20a *g, struct pll *gpll, u32 last_cfg)
95{
96 u32 addr, data;
97
98 pr_info("**** GPCPLL DUMP ****");
99 pr_info("gpcpll s/w M=%u N=%u P=%u\n", gpll->M, gpll->N, gpll->PL);
100 pr_info("gpcpll_cfg_last = 0x%x\n", last_cfg);
101 DUMP_REG(gpcpll_cfg);
102 DUMP_REG(gpcpll_coeff);
103 DUMP_REG(sel_vco);
104 pr_info("\n");
105}
106
107#define PLDIV_GLITCHLESS 1
108
109#if PLDIV_GLITCHLESS
110/*
111 * Post divider tarnsition is glitchless only if there is common "1" in binary
112 * representation of old and new settings.
113 */
114static u32 get_interim_pldiv(struct gk20a *g, u32 old_pl, u32 new_pl)
115{
116 u32 pl;
117
118 if ((g->clk.gpc_pll.id == GM20B_GPC_PLL_C1) || (old_pl & new_pl))
119 return 0;
120
121 pl = old_pl | BIT(ffs(new_pl) - 1); /* pl never 0 */
122 new_pl |= BIT(ffs(old_pl) - 1);
123
124 return min(pl, new_pl);
125}
126#endif
127
128/* Calculate and update M/N/PL as well as pll->freq
129 ref_clk_f = clk_in_f;
130 u_f = ref_clk_f / M;
131 vco_f = u_f * N = ref_clk_f * N / M;
132 PLL output = gpc2clk = target clock frequency = vco_f / pl_to_pdiv(PL);
133 gpcclk = gpc2clk / 2; */
134static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll,
135 struct pll_parms *pll_params, u32 *target_freq, bool best_fit)
136{
137 u32 min_vco_f, max_vco_f;
138 u32 best_M, best_N;
139 u32 low_PL, high_PL, best_PL;
140 u32 m, n, n2;
141 u32 target_vco_f, vco_f;
142 u32 ref_clk_f, target_clk_f, u_f;
143 u32 delta, lwv, best_delta = ~0;
144 u32 pl;
145
146 BUG_ON(target_freq == NULL);
147
148 gk20a_dbg_fn("request target freq %d MHz", *target_freq);
149
150 ref_clk_f = pll->clk_in;
151 target_clk_f = *target_freq;
152 max_vco_f = pll_params->max_vco;
153 min_vco_f = pll_params->min_vco;
154 best_M = pll_params->max_M;
155 best_N = pll_params->min_N;
156 best_PL = pll_params->min_PL;
157
158 target_vco_f = target_clk_f + target_clk_f / 50;
159 if (max_vco_f < target_vco_f)
160 max_vco_f = target_vco_f;
161
162 /* Set PL search boundaries. */
163 high_PL = nvgpu_div_to_pl((max_vco_f + target_vco_f - 1) / target_vco_f);
164 high_PL = min(high_PL, pll_params->max_PL);
165 high_PL = max(high_PL, pll_params->min_PL);
166
167 low_PL = nvgpu_div_to_pl(min_vco_f / target_vco_f);
168 low_PL = min(low_PL, pll_params->max_PL);
169 low_PL = max(low_PL, pll_params->min_PL);
170
171 gk20a_dbg_info("low_PL %d(div%d), high_PL %d(div%d)",
172 low_PL, nvgpu_pl_to_div(low_PL), high_PL, nvgpu_pl_to_div(high_PL));
173
174 for (pl = low_PL; pl <= high_PL; pl++) {
175 target_vco_f = target_clk_f * nvgpu_pl_to_div(pl);
176
177 for (m = pll_params->min_M; m <= pll_params->max_M; m++) {
178 u_f = ref_clk_f / m;
179
180 if (u_f < pll_params->min_u)
181 break;
182 if (u_f > pll_params->max_u)
183 continue;
184
185 n = (target_vco_f * m) / ref_clk_f;
186 n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
187
188 if (n > pll_params->max_N)
189 break;
190
191 for (; n <= n2; n++) {
192 if (n < pll_params->min_N)
193 continue;
194 if (n > pll_params->max_N)
195 break;
196
197 vco_f = ref_clk_f * n / m;
198
199 if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
200 lwv = (vco_f + (nvgpu_pl_to_div(pl) / 2))
201 / nvgpu_pl_to_div(pl);
202 delta = abs(lwv - target_clk_f);
203
204 if (delta < best_delta) {
205 best_delta = delta;
206 best_M = m;
207 best_N = n;
208 best_PL = pl;
209
210 if (best_delta == 0 ||
211 /* 0.45% for non best fit */
212 (!best_fit && (vco_f / best_delta > 218))) {
213 goto found_match;
214 }
215
216 gk20a_dbg_info("delta %d @ M %d, N %d, PL %d",
217 delta, m, n, pl);
218 }
219 }
220 }
221 }
222 }
223
224found_match:
225 BUG_ON(best_delta == ~0U);
226
227 if (best_fit && best_delta != 0)
228 gk20a_dbg_clk("no best match for target @ %dMHz on gpc_pll",
229 target_clk_f);
230
231 pll->M = best_M;
232 pll->N = best_N;
233 pll->PL = best_PL;
234
235 /* save current frequency */
236 pll->freq = ref_clk_f * pll->N / (pll->M * nvgpu_pl_to_div(pll->PL));
237
238 *target_freq = pll->freq;
239
240 gk20a_dbg_clk("actual target freq %d kHz, M %d, N %d, PL %d(div%d)",
241 *target_freq, pll->M, pll->N, pll->PL, nvgpu_pl_to_div(pll->PL));
242
243 gk20a_dbg_fn("done");
244
245 return 0;
246}
247
248/* GPCPLL NA/DVFS mode methods */
249
250static inline int fuse_get_gpcpll_adc_rev(u32 val)
251{
252 return (val >> 30) & 0x3;
253}
254
255static inline int fuse_get_gpcpll_adc_slope_uv(u32 val)
256{
257 /* Integer part in mV * 1000 + fractional part in uV */
258 return ((val >> 24) & 0x3f) * 1000 + ((val >> 14) & 0x3ff);
259}
260
261static inline int fuse_get_gpcpll_adc_intercept_uv(u32 val)
262{
263 /* Integer part in mV * 1000 + fractional part in 100uV */
264 return ((val >> 4) & 0x3ff) * 1000 + ((val >> 0) & 0xf) * 100;
265}
266
267static int nvgpu_fuse_calib_gpcpll_get_adc(struct gk20a *g,
268 int *slope_uv, int *intercept_uv)
269{
270 u32 val;
271 int ret;
272
273 ret = nvgpu_tegra_fuse_read_reserved_calib(g, &val);
274 if (ret)
275 return ret;
276
277 if (!fuse_get_gpcpll_adc_rev(val))
278 return -EINVAL;
279
280 *slope_uv = fuse_get_gpcpll_adc_slope_uv(val);
281 *intercept_uv = fuse_get_gpcpll_adc_intercept_uv(val);
282 return 0;
283}
284
285#ifdef CONFIG_TEGRA_USE_NA_GPCPLL
286static bool nvgpu_fuse_can_use_na_gpcpll(struct gk20a *g)
287{
288 return nvgpu_tegra_get_gpu_speedo_id(g);
289}
290#endif
291
292/*
293 * Read ADC characteristic parmeters from fuses.
294 * Determine clibration settings.
295 */
296static int clk_config_calibration_params(struct gk20a *g)
297{
298 int slope, offs;
299 struct pll_parms *p = &gpc_pll_params;
300
301 if (!nvgpu_fuse_calib_gpcpll_get_adc(g, &slope, &offs)) {
302 p->uvdet_slope = slope;
303 p->uvdet_offs = offs;
304 }
305
306 if (!p->uvdet_slope || !p->uvdet_offs) {
307 /*
308 * If ADC conversion slope/offset parameters are not fused
309 * (non-production config), report error, but allow to use
310 * boot internal calibration with default slope.
311 */
312 nvgpu_err(g, "ADC coeff are not fused");
313 return -EINVAL;
314 }
315 return 0;
316}
317
318/*
319 * Determine DFS_COEFF for the requested voltage. Always select external
320 * calibration override equal to the voltage, and set maximum detection
321 * limit "0" (to make sure that PLL output remains under F/V curve when
322 * voltage increases).
323 */
324static void clk_config_dvfs_detection(int mv, struct na_dvfs *d)
325{
326 u32 coeff, coeff_max;
327 struct pll_parms *p = &gpc_pll_params;
328
329 coeff_max = trim_sys_gpcpll_dvfs0_dfs_coeff_v(
330 trim_sys_gpcpll_dvfs0_dfs_coeff_m());
331 coeff = DIV_ROUND_CLOSEST(mv * p->coeff_slope, 1000) + p->coeff_offs;
332 coeff = DIV_ROUND_CLOSEST(coeff, 1000);
333 coeff = min(coeff, coeff_max);
334 d->dfs_coeff = coeff;
335
336 d->dfs_ext_cal = DIV_ROUND_CLOSEST(mv * 1000 - p->uvdet_offs,
337 p->uvdet_slope);
338 BUG_ON(abs(d->dfs_ext_cal) >= (1 << DFS_DET_RANGE));
339 d->uv_cal = p->uvdet_offs + d->dfs_ext_cal * p->uvdet_slope;
340 d->dfs_det_max = 0;
341}
342
343/*
344 * Solve equation for integer and fractional part of the effective NDIV:
345 *
346 * n_eff = n_int + 1/2 + SDM_DIN / 2^(SDM_DIN_RANGE + 1) +
347 * DVFS_COEFF * DVFS_DET_DELTA / 2^DFS_DET_RANGE
348 *
349 * The SDM_DIN LSB is finally shifted out, since it is not accessible by s/w.
350 */
351static void clk_config_dvfs_ndiv(int mv, u32 n_eff, struct na_dvfs *d)
352{
353 int n, det_delta;
354 u32 rem, rem_range;
355 struct pll_parms *p = &gpc_pll_params;
356
357 det_delta = DIV_ROUND_CLOSEST(mv * 1000 - p->uvdet_offs,
358 p->uvdet_slope);
359 det_delta -= d->dfs_ext_cal;
360 det_delta = min(det_delta, d->dfs_det_max);
361 det_delta = det_delta * d->dfs_coeff;
362
363 n = (int)(n_eff << DFS_DET_RANGE) - det_delta;
364 BUG_ON((n < 0) || (n > (int)(p->max_N << DFS_DET_RANGE)));
365 d->n_int = ((u32)n) >> DFS_DET_RANGE;
366
367 rem = ((u32)n) & ((1 << DFS_DET_RANGE) - 1);
368 rem_range = SDM_DIN_RANGE + 1 - DFS_DET_RANGE;
369 d->sdm_din = (rem << rem_range) - (1 << SDM_DIN_RANGE);
370 d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff;
371}
372
373/* Voltage dependent configuration */
374static void clk_config_dvfs(struct gk20a *g, struct pll *gpll)
375{
376 struct na_dvfs *d = &gpll->dvfs;
377
378 d->mv = g->ops.clk.predict_mv_at_hz_cur_tfloor(&g->clk,
379 rate_gpc2clk_to_gpu(gpll->freq));
380
381 clk_config_dvfs_detection(d->mv, d);
382 clk_config_dvfs_ndiv(d->mv, gpll->N, d);
383}
384
385/* Update DVFS detection settings in flight */
386static void clk_set_dfs_coeff(struct gk20a *g, u32 dfs_coeff)
387{
388 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
389 data |= DFS_EXT_STROBE;
390 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
391
392 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
393 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_coeff_m(),
394 trim_sys_gpcpll_dvfs0_dfs_coeff_f(dfs_coeff));
395 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
396
397 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
398 nvgpu_udelay(1);
399 data &= ~DFS_EXT_STROBE;
400 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
401}
402
403static void __maybe_unused clk_set_dfs_det_max(struct gk20a *g, u32 dfs_det_max)
404{
405 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
406 data |= DFS_EXT_STROBE;
407 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
408
409 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
410 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_det_max_m(),
411 trim_sys_gpcpll_dvfs0_dfs_det_max_f(dfs_det_max));
412 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
413
414 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
415 nvgpu_udelay(1);
416 data &= ~DFS_EXT_STROBE;
417 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
418}
419
420static void clk_set_dfs_ext_cal(struct gk20a *g, u32 dfs_det_cal)
421{
422 u32 data, ctrl;
423
424 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
425 data &= ~(BIT(DFS_DET_RANGE + 1) - 1);
426 data |= dfs_det_cal & (BIT(DFS_DET_RANGE + 1) - 1);
427 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
428
429 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
430 nvgpu_udelay(1);
431 ctrl = trim_sys_gpcpll_dvfs1_dfs_ctrl_v(data);
432 if (~ctrl & DFS_EXT_CAL_EN) {
433 data = set_field(data, trim_sys_gpcpll_dvfs1_dfs_ctrl_m(),
434 trim_sys_gpcpll_dvfs1_dfs_ctrl_f(
435 ctrl | DFS_EXT_CAL_EN | DFS_TESTOUT_DET));
436 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
437 }
438}
439
440static void clk_setup_dvfs_detection(struct gk20a *g, struct pll *gpll)
441{
442 struct na_dvfs *d = &gpll->dvfs;
443
444 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
445 data |= DFS_EXT_STROBE;
446 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
447
448 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
449 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_coeff_m(),
450 trim_sys_gpcpll_dvfs0_dfs_coeff_f(d->dfs_coeff));
451 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_det_max_m(),
452 trim_sys_gpcpll_dvfs0_dfs_det_max_f(d->dfs_det_max));
453 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
454
455 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
456 nvgpu_udelay(1);
457 data &= ~DFS_EXT_STROBE;
458 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
459
460 clk_set_dfs_ext_cal(g, d->dfs_ext_cal);
461}
462
463/* Enable NA/DVFS mode */
464static int clk_enbale_pll_dvfs(struct gk20a *g)
465{
466 u32 data, cfg = 0;
467 int delay = gpc_pll_params.iddq_exit_delay; /* iddq & calib delay */
468 struct pll_parms *p = &gpc_pll_params;
469 bool calibrated = p->uvdet_slope && p->uvdet_offs;
470
471 /* Enable NA DVFS */
472 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
473 data |= trim_sys_gpcpll_dvfs1_en_dfs_m();
474 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
475
476 /* Set VCO_CTRL */
477 if (p->vco_ctrl) {
478 data = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
479 data = set_field(data, trim_sys_gpcpll_cfg3_vco_ctrl_m(),
480 trim_sys_gpcpll_cfg3_vco_ctrl_f(p->vco_ctrl));
481 gk20a_writel(g, trim_sys_gpcpll_cfg3_r(), data);
482 }
483
484 /* Set NA mode DFS control */
485 if (p->dfs_ctrl) {
486 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
487 data = set_field(data, trim_sys_gpcpll_dvfs1_dfs_ctrl_m(),
488 trim_sys_gpcpll_dvfs1_dfs_ctrl_f(p->dfs_ctrl));
489 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
490 }
491
492 /*
493 * If calibration parameters are known (either from fuses, or from
494 * internal calibration on boot) - use them. Internal calibration is
495 * started anyway; it will complete, but results will not be used.
496 */
497 if (calibrated) {
498 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
499 data |= trim_sys_gpcpll_dvfs1_en_dfs_cal_m();
500 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
501 }
502
503 /* Exit IDDQ mode */
504 data = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
505 data = set_field(data, trim_sys_gpcpll_cfg_iddq_m(),
506 trim_sys_gpcpll_cfg_iddq_power_on_v());
507 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), data);
508 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
509 nvgpu_udelay(delay);
510
511 /*
512 * Dynamic ramp setup based on update rate, which in DVFS mode on GM20b
513 * is always 38.4 MHz, the same as reference clock rate.
514 */
515 clk_setup_slide(g, g->clk.gpc_pll.clk_in);
516
517 if (calibrated)
518 return 0;
519
520 /*
521 * If calibration parameters are not fused, start internal calibration,
522 * wait for completion, and use results along with default slope to
523 * calculate ADC offset during boot.
524 */
525 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
526 data |= trim_sys_gpcpll_dvfs1_en_dfs_cal_m();
527 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
528
529 /* C1 PLL must be enabled to read internal calibration results */
530 if (g->clk.gpc_pll.id == GM20B_GPC_PLL_C1) {
531 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
532 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enable_m(),
533 trim_sys_gpcpll_cfg_enable_yes_f());
534 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
535 }
536
537 /* Wait for internal calibration done (spec < 2us). */
538 do {
539 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
540 if (trim_sys_gpcpll_dvfs1_dfs_cal_done_v(data))
541 break;
542 nvgpu_udelay(1);
543 delay--;
544 } while (delay > 0);
545
546 /* Read calibration results */
547 data = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
548 data = trim_sys_gpcpll_cfg3_dfs_testout_v(data);
549
550 if (g->clk.gpc_pll.id == GM20B_GPC_PLL_C1) {
551 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enable_m(),
552 trim_sys_gpcpll_cfg_enable_no_f());
553 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
554 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
555 }
556
557 if (delay <= 0) {
558 nvgpu_err(g, "GPCPLL calibration timeout");
559 return -ETIMEDOUT;
560 }
561
562 p->uvdet_offs = g->clk.pll_poweron_uv - data * ADC_SLOPE_UV;
563 p->uvdet_slope = ADC_SLOPE_UV;
564 return 0;
565}
566
567/* GPCPLL slide methods */
568static void clk_setup_slide(struct gk20a *g, u32 clk_u)
569{
570 u32 data, step_a, step_b;
571
572 switch (clk_u) {
573 case 12000:
574 case 12800:
575 case 13000: /* only on FPGA */
576 step_a = 0x2B;
577 step_b = 0x0B;
578 break;
579 case 19200:
580 step_a = 0x12;
581 step_b = 0x08;
582 break;
583 case 38400:
584 step_a = 0x04;
585 step_b = 0x05;
586 break;
587 default:
588 nvgpu_err(g, "Unexpected reference rate %u kHz", clk_u);
589 BUG();
590 }
591
592 /* setup */
593 data = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
594 data = set_field(data, trim_sys_gpcpll_cfg2_pll_stepa_m(),
595 trim_sys_gpcpll_cfg2_pll_stepa_f(step_a));
596 gk20a_writel(g, trim_sys_gpcpll_cfg2_r(), data);
597 data = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
598 data = set_field(data, trim_sys_gpcpll_cfg3_pll_stepb_m(),
599 trim_sys_gpcpll_cfg3_pll_stepb_f(step_b));
600 gk20a_writel(g, trim_sys_gpcpll_cfg3_r(), data);
601}
602
603static int clk_slide_gpc_pll(struct gk20a *g, struct pll *gpll)
604{
605 u32 data, coeff;
606 u32 nold, sdm_old;
607 int ramp_timeout = gpc_pll_params.lock_timeout;
608
609 /* get old coefficients */
610 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
611 nold = trim_sys_gpcpll_coeff_ndiv_v(coeff);
612
613 /* do nothing if NDIV is same */
614 if (gpll->mode == GPC_PLL_MODE_DVFS) {
615 /* in DVFS mode check both integer and fraction */
616 coeff = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
617 sdm_old = trim_sys_gpcpll_cfg2_sdm_din_v(coeff);
618 if ((gpll->dvfs.n_int == nold) &&
619 (gpll->dvfs.sdm_din == sdm_old))
620 return 0;
621 } else {
622 if (gpll->N == nold)
623 return 0;
624
625 /* dynamic ramp setup based on update rate */
626 clk_setup_slide(g, gpll->clk_in / gpll->M);
627 }
628
629 /* pll slowdown mode */
630 data = gk20a_readl(g, trim_sys_gpcpll_ndiv_slowdown_r());
631 data = set_field(data,
632 trim_sys_gpcpll_ndiv_slowdown_slowdown_using_pll_m(),
633 trim_sys_gpcpll_ndiv_slowdown_slowdown_using_pll_yes_f());
634 gk20a_writel(g, trim_sys_gpcpll_ndiv_slowdown_r(), data);
635
636 /* new ndiv ready for ramp */
637 if (gpll->mode == GPC_PLL_MODE_DVFS) {
638 /* in DVFS mode SDM is updated via "new" field */
639 coeff = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
640 coeff = set_field(coeff, trim_sys_gpcpll_cfg2_sdm_din_new_m(),
641 trim_sys_gpcpll_cfg2_sdm_din_new_f(gpll->dvfs.sdm_din));
642 gk20a_writel(g, trim_sys_gpcpll_cfg2_r(), coeff);
643
644 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
645 coeff = set_field(coeff, trim_sys_gpcpll_coeff_ndiv_m(),
646 trim_sys_gpcpll_coeff_ndiv_f(gpll->dvfs.n_int));
647 nvgpu_udelay(1);
648 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
649 } else {
650 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
651 coeff = set_field(coeff, trim_sys_gpcpll_coeff_ndiv_m(),
652 trim_sys_gpcpll_coeff_ndiv_f(gpll->N));
653 nvgpu_udelay(1);
654 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
655 }
656
657 /* dynamic ramp to new ndiv */
658 data = gk20a_readl(g, trim_sys_gpcpll_ndiv_slowdown_r());
659 data = set_field(data,
660 trim_sys_gpcpll_ndiv_slowdown_en_dynramp_m(),
661 trim_sys_gpcpll_ndiv_slowdown_en_dynramp_yes_f());
662 nvgpu_udelay(1);
663 gk20a_writel(g, trim_sys_gpcpll_ndiv_slowdown_r(), data);
664
665 do {
666 nvgpu_udelay(1);
667 ramp_timeout--;
668 data = gk20a_readl(
669 g, trim_gpc_bcast_gpcpll_ndiv_slowdown_debug_r());
670 if (trim_gpc_bcast_gpcpll_ndiv_slowdown_debug_pll_dynramp_done_synced_v(data))
671 break;
672 } while (ramp_timeout > 0);
673
674 if ((gpll->mode == GPC_PLL_MODE_DVFS) && (ramp_timeout > 0)) {
675 /* in DVFS mode complete SDM update */
676 coeff = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
677 coeff = set_field(coeff, trim_sys_gpcpll_cfg2_sdm_din_m(),
678 trim_sys_gpcpll_cfg2_sdm_din_f(gpll->dvfs.sdm_din));
679 gk20a_writel(g, trim_sys_gpcpll_cfg2_r(), coeff);
680 }
681
682 /* exit slowdown mode */
683 data = gk20a_readl(g, trim_sys_gpcpll_ndiv_slowdown_r());
684 data = set_field(data,
685 trim_sys_gpcpll_ndiv_slowdown_slowdown_using_pll_m(),
686 trim_sys_gpcpll_ndiv_slowdown_slowdown_using_pll_no_f());
687 data = set_field(data,
688 trim_sys_gpcpll_ndiv_slowdown_en_dynramp_m(),
689 trim_sys_gpcpll_ndiv_slowdown_en_dynramp_no_f());
690 gk20a_writel(g, trim_sys_gpcpll_ndiv_slowdown_r(), data);
691 gk20a_readl(g, trim_sys_gpcpll_ndiv_slowdown_r());
692
693 if (ramp_timeout <= 0) {
694 nvgpu_err(g, "gpcpll dynamic ramp timeout");
695 return -ETIMEDOUT;
696 }
697 return 0;
698}
699
700/* GPCPLL bypass methods */
701static int clk_change_pldiv_under_bypass(struct gk20a *g, struct pll *gpll)
702{
703 u32 data, coeff;
704
705 /* put PLL in bypass before programming it */
706 data = gk20a_readl(g, trim_sys_sel_vco_r());
707 data = set_field(data, trim_sys_sel_vco_gpc2clk_out_m(),
708 trim_sys_sel_vco_gpc2clk_out_bypass_f());
709 gk20a_writel(g, trim_sys_sel_vco_r(), data);
710
711 /* change PLDIV */
712 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
713 nvgpu_udelay(1);
714 coeff = set_field(coeff, trim_sys_gpcpll_coeff_pldiv_m(),
715 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL));
716 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
717
718 /* put PLL back on vco */
719 data = gk20a_readl(g, trim_sys_sel_vco_r());
720 nvgpu_udelay(1);
721 data = set_field(data, trim_sys_sel_vco_gpc2clk_out_m(),
722 trim_sys_sel_vco_gpc2clk_out_vco_f());
723 gk20a_writel(g, trim_sys_sel_vco_r(), data);
724
725 return 0;
726}
727
728static int clk_lock_gpc_pll_under_bypass(struct gk20a *g, struct pll *gpll)
729{
730 u32 data, cfg, coeff, timeout;
731
732 /* put PLL in bypass before programming it */
733 data = gk20a_readl(g, trim_sys_sel_vco_r());
734 data = set_field(data, trim_sys_sel_vco_gpc2clk_out_m(),
735 trim_sys_sel_vco_gpc2clk_out_bypass_f());
736 gk20a_writel(g, trim_sys_sel_vco_r(), data);
737
738 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
739 nvgpu_udelay(1);
740 if (trim_sys_gpcpll_cfg_iddq_v(cfg)) {
741 /* get out from IDDQ (1st power up) */
742 cfg = set_field(cfg, trim_sys_gpcpll_cfg_iddq_m(),
743 trim_sys_gpcpll_cfg_iddq_power_on_v());
744 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
745 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
746 nvgpu_udelay(gpc_pll_params.iddq_exit_delay);
747 } else {
748 /* clear SYNC_MODE before disabling PLL */
749 cfg = set_field(cfg, trim_sys_gpcpll_cfg_sync_mode_m(),
750 trim_sys_gpcpll_cfg_sync_mode_disable_f());
751 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
752 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
753
754 /* disable running PLL before changing coefficients */
755 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enable_m(),
756 trim_sys_gpcpll_cfg_enable_no_f());
757 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
758 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
759 }
760
761 /* change coefficients */
762 if (gpll->mode == GPC_PLL_MODE_DVFS) {
763 clk_setup_dvfs_detection(g, gpll);
764
765 coeff = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
766 coeff = set_field(coeff, trim_sys_gpcpll_cfg2_sdm_din_m(),
767 trim_sys_gpcpll_cfg2_sdm_din_f(gpll->dvfs.sdm_din));
768 gk20a_writel(g, trim_sys_gpcpll_cfg2_r(), coeff);
769
770 coeff = trim_sys_gpcpll_coeff_mdiv_f(gpll->M) |
771 trim_sys_gpcpll_coeff_ndiv_f(gpll->dvfs.n_int) |
772 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL);
773 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
774 } else {
775 coeff = trim_sys_gpcpll_coeff_mdiv_f(gpll->M) |
776 trim_sys_gpcpll_coeff_ndiv_f(gpll->N) |
777 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL);
778 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
779 }
780
781 /* enable PLL after changing coefficients */
782 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
783 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enable_m(),
784 trim_sys_gpcpll_cfg_enable_yes_f());
785 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
786
787 /* just delay in DVFS mode (lock cannot be used) */
788 if (gpll->mode == GPC_PLL_MODE_DVFS) {
789 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
790 nvgpu_udelay(gpc_pll_params.na_lock_delay);
791 gk20a_dbg_clk("NA config_pll under bypass: %u (%u) kHz %d mV",
792 gpll->freq, gpll->freq / 2,
793 (trim_sys_gpcpll_cfg3_dfs_testout_v(
794 gk20a_readl(g, trim_sys_gpcpll_cfg3_r()))
795 * gpc_pll_params.uvdet_slope
796 + gpc_pll_params.uvdet_offs) / 1000);
797 goto pll_locked;
798 }
799
800 /* lock pll */
801 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
802 if (cfg & trim_sys_gpcpll_cfg_enb_lckdet_power_off_f()){
803 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enb_lckdet_m(),
804 trim_sys_gpcpll_cfg_enb_lckdet_power_on_f());
805 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
806 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
807 }
808
809 /* wait pll lock */
810 timeout = gpc_pll_params.lock_timeout + 1;
811 do {
812 nvgpu_udelay(1);
813 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
814 if (cfg & trim_sys_gpcpll_cfg_pll_lock_true_f())
815 goto pll_locked;
816 } while (--timeout > 0);
817
818 /* PLL is messed up. What can we do here? */
819 dump_gpc_pll(g, gpll, cfg);
820 BUG();
821 return -EBUSY;
822
823pll_locked:
824 gk20a_dbg_clk("locked config_pll under bypass r=0x%x v=0x%x",
825 trim_sys_gpcpll_cfg_r(), cfg);
826
827 /* set SYNC_MODE for glitchless switch out of bypass */
828 cfg = set_field(cfg, trim_sys_gpcpll_cfg_sync_mode_m(),
829 trim_sys_gpcpll_cfg_sync_mode_enable_f());
830 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
831 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
832
833 /* put PLL back on vco */
834 data = gk20a_readl(g, trim_sys_sel_vco_r());
835 data = set_field(data, trim_sys_sel_vco_gpc2clk_out_m(),
836 trim_sys_sel_vco_gpc2clk_out_vco_f());
837 gk20a_writel(g, trim_sys_sel_vco_r(), data);
838
839 return 0;
840}
841
842/*
843 * Change GPCPLL frequency:
844 * - in legacy (non-DVFS) mode
845 * - in DVFS mode at constant DVFS detection settings, matching current/lower
846 * voltage; the same procedure can be used in this case, since maximum DVFS
847 * detection limit makes sure that PLL output remains under F/V curve when
848 * voltage increases arbitrary.
849 */
850static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new,
851 int allow_slide)
852{
853 u32 cfg, coeff, data;
854 bool can_slide, pldiv_only;
855 struct pll gpll;
856
857 gk20a_dbg_fn("");
858
859 if (!nvgpu_platform_is_silicon(g))
860 return 0;
861
862 /* get old coefficients */
863 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
864 gpll.M = trim_sys_gpcpll_coeff_mdiv_v(coeff);
865 gpll.N = trim_sys_gpcpll_coeff_ndiv_v(coeff);
866 gpll.PL = trim_sys_gpcpll_coeff_pldiv_v(coeff);
867 gpll.clk_in = gpll_new->clk_in;
868
869 /* combine target dvfs with old coefficients */
870 gpll.dvfs = gpll_new->dvfs;
871 gpll.mode = gpll_new->mode;
872
873 /* do NDIV slide if there is no change in M and PL */
874 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
875 can_slide = allow_slide && trim_sys_gpcpll_cfg_enable_v(cfg);
876
877 if (can_slide && (gpll_new->M == gpll.M) && (gpll_new->PL == gpll.PL))
878 return clk_slide_gpc_pll(g, gpll_new);
879
880 /* slide down to NDIV_LO */
881 if (can_slide) {
882 int ret;
883 gpll.N = DIV_ROUND_UP(gpll.M * gpc_pll_params.min_vco,
884 gpll.clk_in);
885 if (gpll.mode == GPC_PLL_MODE_DVFS)
886 clk_config_dvfs_ndiv(gpll.dvfs.mv, gpll.N, &gpll.dvfs);
887 ret = clk_slide_gpc_pll(g, &gpll);
888 if (ret)
889 return ret;
890 }
891 pldiv_only = can_slide && (gpll_new->M == gpll.M);
892
893 /*
894 * Split FO-to-bypass jump in halfs by setting out divider 1:2.
895 * (needed even if PLDIV_GLITCHLESS is set, since 1:1 <=> 1:2 direct
896 * transition is not really glitch-less - see get_interim_pldiv
897 * function header).
898 */
899 if ((gpll_new->PL < 2) || (gpll.PL < 2)) {
900 data = gk20a_readl(g, trim_sys_gpc2clk_out_r());
901 data = set_field(data, trim_sys_gpc2clk_out_vcodiv_m(),
902 trim_sys_gpc2clk_out_vcodiv_f(2));
903 gk20a_writel(g, trim_sys_gpc2clk_out_r(), data);
904 /* Intentional 2nd write to assure linear divider operation */
905 gk20a_writel(g, trim_sys_gpc2clk_out_r(), data);
906 gk20a_readl(g, trim_sys_gpc2clk_out_r());
907 nvgpu_udelay(2);
908 }
909
910#if PLDIV_GLITCHLESS
911 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
912 if (pldiv_only) {
913 /* Insert interim PLDIV state if necessary */
914 u32 interim_pl = get_interim_pldiv(g, gpll_new->PL, gpll.PL);
915 if (interim_pl) {
916 coeff = set_field(coeff,
917 trim_sys_gpcpll_coeff_pldiv_m(),
918 trim_sys_gpcpll_coeff_pldiv_f(interim_pl));
919 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
920 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
921 }
922 goto set_pldiv; /* path A: no need to bypass */
923 }
924
925 /* path B: bypass if either M changes or PLL is disabled */
926#endif
927 /*
928 * Program and lock pll under bypass. On exit PLL is out of bypass,
929 * enabled, and locked. VCO is at vco_min if sliding is allowed.
930 * Otherwise it is at VCO target (and therefore last slide call below
931 * is effectively NOP). PL is set to target. Output divider is engaged
932 * at 1:2 if either entry, or exit PL setting is 1:1.
933 */
934 gpll = *gpll_new;
935 if (allow_slide) {
936 gpll.N = DIV_ROUND_UP(gpll_new->M * gpc_pll_params.min_vco,
937 gpll_new->clk_in);
938 if (gpll.mode == GPC_PLL_MODE_DVFS)
939 clk_config_dvfs_ndiv(gpll.dvfs.mv, gpll.N, &gpll.dvfs);
940 }
941 if (pldiv_only)
942 clk_change_pldiv_under_bypass(g, &gpll);
943 else
944 clk_lock_gpc_pll_under_bypass(g, &gpll);
945
946#if PLDIV_GLITCHLESS
947 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
948
949set_pldiv:
950 /* coeff must be current from either path A or B */
951 if (trim_sys_gpcpll_coeff_pldiv_v(coeff) != gpll_new->PL) {
952 coeff = set_field(coeff, trim_sys_gpcpll_coeff_pldiv_m(),
953 trim_sys_gpcpll_coeff_pldiv_f(gpll_new->PL));
954 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
955 }
956#endif
957 /* restore out divider 1:1 */
958 data = gk20a_readl(g, trim_sys_gpc2clk_out_r());
959 if ((data & trim_sys_gpc2clk_out_vcodiv_m()) !=
960 trim_sys_gpc2clk_out_vcodiv_by1_f()) {
961 data = set_field(data, trim_sys_gpc2clk_out_vcodiv_m(),
962 trim_sys_gpc2clk_out_vcodiv_by1_f());
963 nvgpu_udelay(2);
964 gk20a_writel(g, trim_sys_gpc2clk_out_r(), data);
965 /* Intentional 2nd write to assure linear divider operation */
966 gk20a_writel(g, trim_sys_gpc2clk_out_r(), data);
967 gk20a_readl(g, trim_sys_gpc2clk_out_r());
968 }
969
970 /* slide up to target NDIV */
971 return clk_slide_gpc_pll(g, gpll_new);
972}
973
974/* Find GPCPLL config safe at DVFS coefficient = 0, matching target frequency */
975static void clk_config_pll_safe_dvfs(struct gk20a *g, struct pll *gpll)
976{
977 u32 nsafe, nmin;
978
979 if (gpll->freq > g->clk.dvfs_safe_max_freq)
980 gpll->freq = gpll->freq * (100 - DVFS_SAFE_MARGIN) / 100;
981
982 nmin = DIV_ROUND_UP(gpll->M * gpc_pll_params.min_vco, gpll->clk_in);
983 nsafe = gpll->M * gpll->freq / gpll->clk_in;
984
985 /*
986 * If safe frequency is above VCOmin, it can be used in safe PLL config
987 * as is. Since safe frequency is below both old and new frequencies,
988 * in this case all three configurations have same post divider 1:1, and
989 * direct old=>safe=>new n-sliding will be used for transitions.
990 *
991 * Otherwise, if safe frequency is below VCO min, post-divider in safe
992 * configuration (and possibly in old and/or new configurations) is
993 * above 1:1, and each old=>safe and safe=>new transitions includes
994 * sliding to/from VCOmin, as well as divider changes. To avoid extra
995 * dynamic ramps from VCOmin during old=>safe transition and to VCOmin
996 * during safe=>new transition, select nmin as safe NDIV, and set safe
997 * post divider to assure PLL output is below safe frequency
998 */
999 if (nsafe < nmin) {
1000 gpll->PL = DIV_ROUND_UP(nmin * gpll->clk_in,
1001 gpll->M * gpll->freq);
1002 nsafe = nmin;
1003 }
1004 gpll->N = nsafe;
1005 clk_config_dvfs_ndiv(gpll->dvfs.mv, gpll->N, &gpll->dvfs);
1006
1007 gk20a_dbg_clk("safe freq %d kHz, M %d, N %d, PL %d(div%d), mV(cal) %d(%d), DC %d",
1008 gpll->freq, gpll->M, gpll->N, gpll->PL, nvgpu_pl_to_div(gpll->PL),
1009 gpll->dvfs.mv, gpll->dvfs.uv_cal / 1000, gpll->dvfs.dfs_coeff);
1010}
1011
1012/* Change GPCPLL frequency and DVFS detection settings in DVFS mode */
1013static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new,
1014 int allow_slide)
1015{
1016 int ret;
1017 struct pll gpll_safe;
1018 struct pll *gpll_old = &g->clk.gpc_pll_last;
1019
1020 BUG_ON(gpll_new->M != 1); /* the only MDIV in NA mode */
1021 clk_config_dvfs(g, gpll_new);
1022
1023 /*
1024 * In cases below no intermediate steps in PLL DVFS configuration are
1025 * necessary because either
1026 * - PLL DVFS will be configured under bypass directly to target, or
1027 * - voltage is not changing, so DVFS detection settings are the same
1028 */
1029 if (!allow_slide || !gpll_new->enabled ||
1030 (gpll_old->dvfs.mv == gpll_new->dvfs.mv))
1031 return clk_program_gpc_pll(g, gpll_new, allow_slide);
1032
1033 /*
1034 * Interim step for changing DVFS detection settings: low enough
1035 * frequency to be safe at at DVFS coeff = 0.
1036 *
1037 * 1. If voltage is increasing:
1038 * - safe frequency target matches the lowest - old - frequency
1039 * - DVFS settings are still old
1040 * - Voltage already increased to new level by tegra DVFS, but maximum
1041 * detection limit assures PLL output remains under F/V curve
1042 *
1043 * 2. If voltage is decreasing:
1044 * - safe frequency target matches the lowest - new - frequency
1045 * - DVFS settings are still old
1046 * - Voltage is also old, it will be lowered by tegra DVFS afterwards
1047 *
1048 * Interim step can be skipped if old frequency is below safe minimum,
1049 * i.e., it is low enough to be safe at any voltage in operating range
1050 * with zero DVFS coefficient.
1051 */
1052 if (gpll_old->freq > g->clk.dvfs_safe_max_freq) {
1053 if (gpll_old->dvfs.mv < gpll_new->dvfs.mv) {
1054 gpll_safe = *gpll_old;
1055 gpll_safe.dvfs.mv = gpll_new->dvfs.mv;
1056 } else {
1057 gpll_safe = *gpll_new;
1058 gpll_safe.dvfs = gpll_old->dvfs;
1059 }
1060 clk_config_pll_safe_dvfs(g, &gpll_safe);
1061
1062 ret = clk_program_gpc_pll(g, &gpll_safe, 1);
1063 if (ret) {
1064 nvgpu_err(g, "Safe dvfs program fail");
1065 return ret;
1066 }
1067 }
1068
1069 /*
1070 * DVFS detection settings transition:
1071 * - Set DVFS coefficient zero (safe, since already at frequency safe
1072 * at DVFS coeff = 0 for the lowest of the old/new end-points)
1073 * - Set calibration level to new voltage (safe, since DVFS coeff = 0)
1074 * - Set DVFS coefficient to match new voltage (safe, since already at
1075 * frequency safe at DVFS coeff = 0 for the lowest of the old/new
1076 * end-points.
1077 */
1078 clk_set_dfs_coeff(g, 0);
1079 clk_set_dfs_ext_cal(g, gpll_new->dvfs.dfs_ext_cal);
1080 clk_set_dfs_coeff(g, gpll_new->dvfs.dfs_coeff);
1081
1082 gk20a_dbg_clk("config_pll %d kHz, M %d, N %d, PL %d(div%d), mV(cal) %d(%d), DC %d",
1083 gpll_new->freq, gpll_new->M, gpll_new->N, gpll_new->PL,
1084 nvgpu_pl_to_div(gpll_new->PL),
1085 max(gpll_new->dvfs.mv, gpll_old->dvfs.mv),
1086 gpll_new->dvfs.uv_cal / 1000, gpll_new->dvfs.dfs_coeff);
1087
1088 /* Finally set target rate (with DVFS detection settings already new) */
1089 return clk_program_gpc_pll(g, gpll_new, 1);
1090}
1091
1092static int clk_disable_gpcpll(struct gk20a *g, int allow_slide)
1093{
1094 u32 cfg, coeff;
1095 struct clk_gk20a *clk = &g->clk;
1096 struct pll gpll = clk->gpc_pll;
1097
1098 /* slide to VCO min */
1099 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
1100 if (allow_slide && trim_sys_gpcpll_cfg_enable_v(cfg)) {
1101 coeff = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
1102 gpll.M = trim_sys_gpcpll_coeff_mdiv_v(coeff);
1103 gpll.N = DIV_ROUND_UP(gpll.M * gpc_pll_params.min_vco,
1104 gpll.clk_in);
1105 if (gpll.mode == GPC_PLL_MODE_DVFS)
1106 clk_config_dvfs_ndiv(gpll.dvfs.mv, gpll.N, &gpll.dvfs);
1107 clk_slide_gpc_pll(g, &gpll);
1108 }
1109
1110 /* put PLL in bypass before disabling it */
1111 cfg = gk20a_readl(g, trim_sys_sel_vco_r());
1112 cfg = set_field(cfg, trim_sys_sel_vco_gpc2clk_out_m(),
1113 trim_sys_sel_vco_gpc2clk_out_bypass_f());
1114 gk20a_writel(g, trim_sys_sel_vco_r(), cfg);
1115
1116 /* clear SYNC_MODE before disabling PLL */
1117 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
1118 cfg = set_field(cfg, trim_sys_gpcpll_cfg_sync_mode_m(),
1119 trim_sys_gpcpll_cfg_sync_mode_disable_f());
1120 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
1121
1122 /* disable PLL */
1123 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
1124 cfg = set_field(cfg, trim_sys_gpcpll_cfg_enable_m(),
1125 trim_sys_gpcpll_cfg_enable_no_f());
1126 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
1127 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
1128
1129 clk->gpc_pll.enabled = false;
1130 clk->gpc_pll_last.enabled = false;
1131 return 0;
1132}
1133
1134struct pll_parms *gm20b_get_gpc_pll_parms(void)
1135{
1136 return &gpc_pll_params;
1137}
1138
1139int gm20b_init_clk_setup_sw(struct gk20a *g)
1140{
1141 struct clk_gk20a *clk = &g->clk;
1142 unsigned long safe_rate;
1143 int err;
1144
1145 gk20a_dbg_fn("");
1146
1147 err = nvgpu_mutex_init(&clk->clk_mutex);
1148 if (err)
1149 return err;
1150
1151 if (clk->sw_ready) {
1152 gk20a_dbg_fn("skip init");
1153 return 0;
1154 }
1155
1156 if (clk->gpc_pll.id == GM20B_GPC_PLL_C1) {
1157 gpc_pll_params = gpc_pll_params_c1;
1158 if (!clk->pll_poweron_uv)
1159 clk->pll_poweron_uv = BOOT_GPU_UV_C1;
1160 } else {
1161 gpc_pll_params = gpc_pll_params_b1;
1162 if (!clk->pll_poweron_uv)
1163 clk->pll_poweron_uv = BOOT_GPU_UV_B1;
1164 }
1165
1166 clk->gpc_pll.clk_in = g->ops.clk.get_ref_clock_rate(g) / KHZ;
1167 if (clk->gpc_pll.clk_in == 0) {
1168 nvgpu_err(g, "GPCPLL reference clock is zero");
1169 err = -EINVAL;
1170 goto fail;
1171 }
1172
1173 safe_rate = g->ops.clk.get_fmax_at_vmin_safe(clk);
1174 safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100;
1175 clk->dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate);
1176 clk->gpc_pll.PL = (clk->dvfs_safe_max_freq == 0) ? 0 :
1177 DIV_ROUND_UP(gpc_pll_params.min_vco, clk->dvfs_safe_max_freq);
1178
1179 /* Initial freq: low enough to be safe at Vmin (default 1/3 VCO min) */
1180 clk->gpc_pll.M = 1;
1181 clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco,
1182 clk->gpc_pll.clk_in);
1183 clk->gpc_pll.PL = max(clk->gpc_pll.PL, 3U);
1184 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
1185 clk->gpc_pll.freq /= nvgpu_pl_to_div(clk->gpc_pll.PL);
1186
1187 /*
1188 * All production parts should have ADC fuses burnt. Therefore, check
1189 * ADC fuses always, regardless of whether NA mode is selected; and if
1190 * NA mode is indeed selected, and part can support it, switch to NA
1191 * mode even when ADC calibration is not fused; less accurate s/w
1192 * self-calibration will be used for those parts.
1193 */
1194 clk_config_calibration_params(g);
1195#ifdef CONFIG_TEGRA_USE_NA_GPCPLL
1196 if (nvgpu_fuse_can_use_na_gpcpll(g)) {
1197 /* NA mode is supported only at max update rate 38.4 MHz */
1198 BUG_ON(clk->gpc_pll.clk_in != gpc_pll_params.max_u);
1199 clk->gpc_pll.mode = GPC_PLL_MODE_DVFS;
1200 gpc_pll_params.min_u = gpc_pll_params.max_u;
1201 }
1202#endif
1203
1204 clk->sw_ready = true;
1205
1206 gk20a_dbg_fn("done");
1207 nvgpu_info(g,
1208 "GPCPLL initial settings:%s M=%u, N=%u, P=%u (id = %u)",
1209 clk->gpc_pll.mode == GPC_PLL_MODE_DVFS ? " NA mode," : "",
1210 clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL,
1211 clk->gpc_pll.id);
1212 return 0;
1213
1214fail:
1215 nvgpu_mutex_destroy(&clk->clk_mutex);
1216 return err;
1217}
1218
1219
1220static int set_pll_freq(struct gk20a *g, int allow_slide);
1221static int set_pll_target(struct gk20a *g, u32 freq, u32 old_freq);
1222
1223int gm20b_clk_prepare(struct clk_gk20a *clk)
1224{
1225 int ret = 0;
1226
1227 nvgpu_mutex_acquire(&clk->clk_mutex);
1228 if (!clk->gpc_pll.enabled && clk->clk_hw_on)
1229 ret = set_pll_freq(clk->g, 1);
1230 nvgpu_mutex_release(&clk->clk_mutex);
1231 return ret;
1232}
1233
1234void gm20b_clk_unprepare(struct clk_gk20a *clk)
1235{
1236 nvgpu_mutex_acquire(&clk->clk_mutex);
1237 if (clk->gpc_pll.enabled && clk->clk_hw_on)
1238 clk_disable_gpcpll(clk->g, 1);
1239 nvgpu_mutex_release(&clk->clk_mutex);
1240}
1241
1242int gm20b_clk_is_prepared(struct clk_gk20a *clk)
1243{
1244 return clk->gpc_pll.enabled && clk->clk_hw_on;
1245}
1246
1247unsigned long gm20b_recalc_rate(struct clk_gk20a *clk, unsigned long parent_rate)
1248{
1249 return rate_gpc2clk_to_gpu(clk->gpc_pll.freq);
1250}
1251
1252int gm20b_gpcclk_set_rate(struct clk_gk20a *clk, unsigned long rate,
1253 unsigned long parent_rate)
1254{
1255 u32 old_freq;
1256 int ret = -ENODATA;
1257
1258 nvgpu_mutex_acquire(&clk->clk_mutex);
1259 old_freq = clk->gpc_pll.freq;
1260 ret = set_pll_target(clk->g, rate_gpu_to_gpc2clk(rate), old_freq);
1261 if (!ret && clk->gpc_pll.enabled && clk->clk_hw_on)
1262 ret = set_pll_freq(clk->g, 1);
1263 nvgpu_mutex_release(&clk->clk_mutex);
1264
1265 return ret;
1266}
1267
1268long gm20b_round_rate(struct clk_gk20a *clk, unsigned long rate,
1269 unsigned long *parent_rate)
1270{
1271 u32 freq;
1272 struct pll tmp_pll;
1273 unsigned long maxrate;
1274 struct gk20a *g = clk->g;
1275
1276 maxrate = g->ops.clk.get_maxrate(g, CTRL_CLK_DOMAIN_GPCCLK);
1277 if (rate > maxrate)
1278 rate = maxrate;
1279
1280 nvgpu_mutex_acquire(&clk->clk_mutex);
1281 freq = rate_gpu_to_gpc2clk(rate);
1282 if (freq > gpc_pll_params.max_freq)
1283 freq = gpc_pll_params.max_freq;
1284 else if (freq < gpc_pll_params.min_freq)
1285 freq = gpc_pll_params.min_freq;
1286
1287 tmp_pll = clk->gpc_pll;
1288 clk_config_pll(clk, &tmp_pll, &gpc_pll_params, &freq, true);
1289 nvgpu_mutex_release(&clk->clk_mutex);
1290
1291 return rate_gpc2clk_to_gpu(tmp_pll.freq);
1292}
1293
1294static int gm20b_init_clk_setup_hw(struct gk20a *g)
1295{
1296 u32 data;
1297
1298 gk20a_dbg_fn("");
1299
1300 /* LDIV: Div4 mode (required); both bypass and vco ratios 1:1 */
1301 data = gk20a_readl(g, trim_sys_gpc2clk_out_r());
1302 data = set_field(data,
1303 trim_sys_gpc2clk_out_sdiv14_m() |
1304 trim_sys_gpc2clk_out_vcodiv_m() |
1305 trim_sys_gpc2clk_out_bypdiv_m(),
1306 trim_sys_gpc2clk_out_sdiv14_indiv4_mode_f() |
1307 trim_sys_gpc2clk_out_vcodiv_by1_f() |
1308 trim_sys_gpc2clk_out_bypdiv_f(0));
1309 gk20a_writel(g, trim_sys_gpc2clk_out_r(), data);
1310
1311 /*
1312 * Clear global bypass control; PLL is still under bypass, since SEL_VCO
1313 * is cleared by default.
1314 */
1315 data = gk20a_readl(g, trim_sys_bypassctrl_r());
1316 data = set_field(data, trim_sys_bypassctrl_gpcpll_m(),
1317 trim_sys_bypassctrl_gpcpll_vco_f());
1318 gk20a_writel(g, trim_sys_bypassctrl_r(), data);
1319
1320 /* If not fused, set RAM SVOP PDP data 0x2, and enable fuse override */
1321 data = gk20a_readl(g, fuse_ctrl_opt_ram_svop_pdp_r());
1322 if (!fuse_ctrl_opt_ram_svop_pdp_data_v(data)) {
1323 data = set_field(data, fuse_ctrl_opt_ram_svop_pdp_data_m(),
1324 fuse_ctrl_opt_ram_svop_pdp_data_f(0x2));
1325 gk20a_writel(g, fuse_ctrl_opt_ram_svop_pdp_r(), data);
1326 data = gk20a_readl(g, fuse_ctrl_opt_ram_svop_pdp_override_r());
1327 data = set_field(data,
1328 fuse_ctrl_opt_ram_svop_pdp_override_data_m(),
1329 fuse_ctrl_opt_ram_svop_pdp_override_data_yes_f());
1330 gk20a_writel(g, fuse_ctrl_opt_ram_svop_pdp_override_r(), data);
1331 }
1332
1333 /* Disable idle slow down */
1334 data = gk20a_readl(g, therm_clk_slowdown_r(0));
1335 data = set_field(data, therm_clk_slowdown_idle_factor_m(),
1336 therm_clk_slowdown_idle_factor_disabled_f());
1337 gk20a_writel(g, therm_clk_slowdown_r(0), data);
1338 gk20a_readl(g, therm_clk_slowdown_r(0));
1339
1340 if (g->clk.gpc_pll.mode == GPC_PLL_MODE_DVFS)
1341 return clk_enbale_pll_dvfs(g);
1342
1343 return 0;
1344}
1345
1346static int set_pll_target(struct gk20a *g, u32 freq, u32 old_freq)
1347{
1348 struct clk_gk20a *clk = &g->clk;
1349
1350 if (freq > gpc_pll_params.max_freq)
1351 freq = gpc_pll_params.max_freq;
1352 else if (freq < gpc_pll_params.min_freq)
1353 freq = gpc_pll_params.min_freq;
1354
1355 if (freq != old_freq) {
1356 /* gpc_pll.freq is changed to new value here */
1357 if (clk_config_pll(clk, &clk->gpc_pll, &gpc_pll_params,
1358 &freq, true)) {
1359 nvgpu_err(g, "failed to set pll target for %d", freq);
1360 return -EINVAL;
1361 }
1362 }
1363 return 0;
1364}
1365
1366static int set_pll_freq(struct gk20a *g, int allow_slide)
1367{
1368 struct clk_gk20a *clk = &g->clk;
1369 int err = 0;
1370
1371 gk20a_dbg_fn("last freq: %dMHz, target freq %dMHz",
1372 clk->gpc_pll_last.freq, clk->gpc_pll.freq);
1373
1374 /* If programming with dynamic sliding failed, re-try under bypass */
1375 if (clk->gpc_pll.mode == GPC_PLL_MODE_DVFS) {
1376 err = clk_program_na_gpc_pll(g, &clk->gpc_pll, allow_slide);
1377 if (err && allow_slide)
1378 err = clk_program_na_gpc_pll(g, &clk->gpc_pll, 0);
1379 } else {
1380 err = clk_program_gpc_pll(g, &clk->gpc_pll, allow_slide);
1381 if (err && allow_slide)
1382 err = clk_program_gpc_pll(g, &clk->gpc_pll, 0);
1383 }
1384
1385 if (!err) {
1386 clk->gpc_pll.enabled = true;
1387 clk->gpc_pll_last = clk->gpc_pll;
1388 return 0;
1389 }
1390
1391 /*
1392 * Just report error but not restore PLL since dvfs could already change
1393 * voltage even when programming failed.
1394 */
1395 nvgpu_err(g, "failed to set pll to %d", clk->gpc_pll.freq);
1396 return err;
1397}
1398
1399int gm20b_init_clk_support(struct gk20a *g)
1400{
1401 struct clk_gk20a *clk = &g->clk;
1402 u32 err;
1403
1404 gk20a_dbg_fn("");
1405
1406 nvgpu_mutex_acquire(&clk->clk_mutex);
1407 clk->clk_hw_on = true;
1408
1409 err = gm20b_init_clk_setup_hw(g);
1410 nvgpu_mutex_release(&clk->clk_mutex);
1411 if (err)
1412 return err;
1413
1414 /* FIXME: this effectively prevents host level clock gating */
1415 err = g->ops.clk.prepare_enable(&g->clk);
1416 if (err)
1417 return err;
1418
1419 /* The prev call may not enable PLL if gbus is unbalanced - force it */
1420 nvgpu_mutex_acquire(&clk->clk_mutex);
1421 if (!clk->gpc_pll.enabled)
1422 err = set_pll_freq(g, 1);
1423 nvgpu_mutex_release(&clk->clk_mutex);
1424 if (err)
1425 return err;
1426
1427 if (!clk->debugfs_set && g->ops.clk.init_debugfs) {
1428 err = g->ops.clk.init_debugfs(g);
1429 if (err)
1430 return err;
1431 clk->debugfs_set = true;
1432 }
1433
1434 return err;
1435}
1436
1437int gm20b_suspend_clk_support(struct gk20a *g)
1438{
1439 int ret = 0;
1440
1441 g->ops.clk.disable_unprepare(&g->clk);
1442
1443 /* The prev call may not disable PLL if gbus is unbalanced - force it */
1444 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1445 if (g->clk.gpc_pll.enabled)
1446 ret = clk_disable_gpcpll(g, 1);
1447 g->clk.clk_hw_on = false;
1448 nvgpu_mutex_release(&g->clk.clk_mutex);
1449
1450 nvgpu_mutex_destroy(&g->clk.clk_mutex);
1451
1452 return ret;
1453}
1454
1455int gm20b_clk_get_voltage(struct clk_gk20a *clk, u64 *val)
1456{
1457 struct gk20a *g = clk->g;
1458 struct pll_parms *gpc_pll_params = gm20b_get_gpc_pll_parms();
1459 u32 det_out;
1460 int err;
1461
1462 if (clk->gpc_pll.mode != GPC_PLL_MODE_DVFS)
1463 return -ENOSYS;
1464
1465 err = gk20a_busy(g);
1466 if (err)
1467 return err;
1468
1469 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1470
1471 det_out = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
1472 det_out = trim_sys_gpcpll_cfg3_dfs_testout_v(det_out);
1473 *val = div64_u64((u64)det_out * gpc_pll_params->uvdet_slope +
1474 gpc_pll_params->uvdet_offs, 1000ULL);
1475
1476 nvgpu_mutex_release(&g->clk.clk_mutex);
1477
1478 gk20a_idle(g);
1479 return 0;
1480}
1481
1482int gm20b_clk_get_gpcclk_clock_counter(struct clk_gk20a *clk, u64 *val)
1483{
1484 struct gk20a *g = clk->g;
1485 u32 clk_slowdown, clk_slowdown_save;
1486 int err;
1487
1488 u32 ncycle = 800; /* count GPCCLK for ncycle of clkin */
1489 u64 freq = clk->gpc_pll.clk_in;
1490 u32 count1, count2;
1491
1492 err = gk20a_busy(g);
1493 if (err)
1494 return err;
1495
1496 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1497
1498 /* Disable clock slowdown during measurements */
1499 clk_slowdown_save = gk20a_readl(g, therm_clk_slowdown_r(0));
1500 clk_slowdown = set_field(clk_slowdown_save,
1501 therm_clk_slowdown_idle_factor_m(),
1502 therm_clk_slowdown_idle_factor_disabled_f());
1503 gk20a_writel(g, therm_clk_slowdown_r(0), clk_slowdown);
1504 gk20a_readl(g, therm_clk_slowdown_r(0));
1505
1506 gk20a_writel(g, trim_gpc_clk_cntr_ncgpcclk_cfg_r(0),
1507 trim_gpc_clk_cntr_ncgpcclk_cfg_reset_asserted_f());
1508 gk20a_writel(g, trim_gpc_clk_cntr_ncgpcclk_cfg_r(0),
1509 trim_gpc_clk_cntr_ncgpcclk_cfg_enable_asserted_f() |
1510 trim_gpc_clk_cntr_ncgpcclk_cfg_write_en_asserted_f() |
1511 trim_gpc_clk_cntr_ncgpcclk_cfg_noofipclks_f(ncycle));
1512 /* start */
1513
1514 /* It should take less than 25us to finish 800 cycle of 38.4MHz.
1515 * But longer than 100us delay is required here.
1516 */
1517 gk20a_readl(g, trim_gpc_clk_cntr_ncgpcclk_cfg_r(0));
1518 nvgpu_udelay(200);
1519
1520 count1 = gk20a_readl(g, trim_gpc_clk_cntr_ncgpcclk_cnt_r(0));
1521 nvgpu_udelay(100);
1522 count2 = gk20a_readl(g, trim_gpc_clk_cntr_ncgpcclk_cnt_r(0));
1523 freq *= trim_gpc_clk_cntr_ncgpcclk_cnt_value_v(count2);
1524 do_div(freq, ncycle);
1525 *val = freq;
1526
1527 /* Restore clock slowdown */
1528 gk20a_writel(g, therm_clk_slowdown_r(0), clk_slowdown_save);
1529 nvgpu_mutex_release(&g->clk.clk_mutex);
1530
1531 gk20a_idle(g);
1532
1533 if (count1 != count2)
1534 return -EBUSY;
1535
1536 return 0;
1537}
1538
1539int gm20b_clk_pll_reg_write(struct gk20a *g, u32 reg, u32 val)
1540{
1541 if (((reg < trim_sys_gpcpll_cfg_r()) ||
1542 (reg > trim_sys_gpcpll_dvfs2_r())) &&
1543 (reg != trim_sys_sel_vco_r()) &&
1544 (reg != trim_sys_gpc2clk_out_r()) &&
1545 (reg != trim_sys_bypassctrl_r()))
1546 return -EPERM;
1547
1548 if (reg == trim_sys_gpcpll_dvfs2_r())
1549 reg = trim_gpc_bcast_gpcpll_dvfs2_r();
1550
1551 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1552 if (!g->clk.clk_hw_on) {
1553 nvgpu_mutex_release(&g->clk.clk_mutex);
1554 return -EINVAL;
1555 }
1556 gk20a_writel(g, reg, val);
1557 nvgpu_mutex_release(&g->clk.clk_mutex);
1558
1559 return 0;
1560}
1561
1562int gm20b_clk_get_pll_debug_data(struct gk20a *g,
1563 struct nvgpu_clk_pll_debug_data *d)
1564{
1565 u32 reg;
1566
1567 nvgpu_mutex_acquire(&g->clk.clk_mutex);
1568 if (!g->clk.clk_hw_on) {
1569 nvgpu_mutex_release(&g->clk.clk_mutex);
1570 return -EINVAL;
1571 }
1572
1573 d->trim_sys_bypassctrl_reg = trim_sys_bypassctrl_r();
1574 d->trim_sys_bypassctrl_val = gk20a_readl(g, trim_sys_bypassctrl_r());
1575 d->trim_sys_sel_vco_reg = trim_sys_sel_vco_r();
1576 d->trim_sys_sel_vco_val = gk20a_readl(g, trim_sys_sel_vco_r());
1577 d->trim_sys_gpc2clk_out_reg = trim_sys_gpc2clk_out_r();
1578 d->trim_sys_gpc2clk_out_val = gk20a_readl(g, trim_sys_gpc2clk_out_r());
1579 d->trim_sys_gpcpll_cfg_reg = trim_sys_gpcpll_cfg_r();
1580 d->trim_sys_gpcpll_dvfs2_reg = trim_gpc_bcast_gpcpll_dvfs2_r();
1581
1582 reg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
1583 d->trim_sys_gpcpll_cfg_val = reg;
1584 d->trim_sys_gpcpll_cfg_enabled = trim_sys_gpcpll_cfg_enable_v(reg);
1585 d->trim_sys_gpcpll_cfg_locked = trim_sys_gpcpll_cfg_pll_lock_v(reg);
1586 d->trim_sys_gpcpll_cfg_sync_on = trim_sys_gpcpll_cfg_sync_mode_v(reg);
1587
1588 reg = gk20a_readl(g, trim_sys_gpcpll_coeff_r());
1589 d->trim_sys_gpcpll_coeff_val = reg;
1590 d->trim_sys_gpcpll_coeff_mdiv = trim_sys_gpcpll_coeff_mdiv_v(reg);
1591 d->trim_sys_gpcpll_coeff_ndiv = trim_sys_gpcpll_coeff_ndiv_v(reg);
1592 d->trim_sys_gpcpll_coeff_pldiv = trim_sys_gpcpll_coeff_pldiv_v(reg);
1593
1594 reg = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
1595 d->trim_sys_gpcpll_dvfs0_val = reg;
1596 d->trim_sys_gpcpll_dvfs0_dfs_coeff =
1597 trim_sys_gpcpll_dvfs0_dfs_coeff_v(reg);
1598 d->trim_sys_gpcpll_dvfs0_dfs_det_max =
1599 trim_sys_gpcpll_dvfs0_dfs_det_max_v(reg);
1600 d->trim_sys_gpcpll_dvfs0_dfs_dc_offset =
1601 trim_sys_gpcpll_dvfs0_dfs_dc_offset_v(reg);
1602
1603 nvgpu_mutex_release(&g->clk.clk_mutex);
1604 return 0;
1605}