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.c326
1 files changed, 318 insertions, 8 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
index 2e3d96ac..6f7d04dd 100644
--- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
@@ -22,6 +22,7 @@
22#include <linux/debugfs.h> 22#include <linux/debugfs.h>
23#include <linux/uaccess.h> 23#include <linux/uaccess.h>
24#include <linux/clk/tegra.h> 24#include <linux/clk/tegra.h>
25#include <linux/tegra-fuse.h>
25 26
26#include "gk20a/gk20a.h" 27#include "gk20a/gk20a.h"
27#include "hw_trim_gm20b.h" 28#include "hw_trim_gm20b.h"
@@ -29,10 +30,19 @@
29#include "hw_therm_gm20b.h" 30#include "hw_therm_gm20b.h"
30#include "clk_gm20b.h" 31#include "clk_gm20b.h"
31 32
33#define ALLOW_NON_CALIBRATED_NA_MODE 1
34
32#define gk20a_dbg_clk(fmt, arg...) \ 35#define gk20a_dbg_clk(fmt, arg...) \
33 gk20a_dbg(gpu_dbg_clk, fmt, ##arg) 36 gk20a_dbg(gpu_dbg_clk, fmt, ##arg)
34 37
35/* from vbios PLL info table */ 38#define DFS_DET_RANGE 6 /* -2^6 ... 2^6-1 */
39#define SDM_DIN_RANGE 12 /* -2^12 ... 2^12-1 */
40#define DFS_EXT_CAL_EN BIT(9)
41#define DFS_EXT_STROBE BIT(16)
42
43#define BOOT_GPU_UV 1000000 /* gpu rail boot voltage 1.0V */
44#define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */
45
36static struct pll_parms gpc_pll_params = { 46static struct pll_parms gpc_pll_params = {
37 128000, 2600000, /* freq */ 47 128000, 2600000, /* freq */
38 1300000, 2600000, /* vco */ 48 1300000, 2600000, /* vco */
@@ -40,6 +50,7 @@ static struct pll_parms gpc_pll_params = {
40 1, 255, /* M */ 50 1, 255, /* M */
41 8, 255, /* N */ 51 8, 255, /* N */
42 1, 31, /* PL */ 52 1, 31, /* PL */
53 -58700, 86789, /* DFS_COEFF */
43}; 54};
44 55
45#ifdef CONFIG_DEBUG_FS 56#ifdef CONFIG_DEBUG_FS
@@ -218,6 +229,244 @@ found_match:
218 return 0; 229 return 0;
219} 230}
220 231
232/* GPCPLL NA/DVFS mode methods */
233
234/*
235 * Read ADC characteristic parmeters from fuses.
236 * Determine clibration settings.
237 */
238static int clk_config_calibration_params(struct gk20a *g)
239{
240 int slope, offs;
241 struct pll_parms *p = &gpc_pll_params;
242
243 if (!tegra_fuse_calib_gpcpll_get_adc(&slope, &offs)) {
244 p->uvdet_slope = slope;
245 p->uvdet_offs = offs;
246 }
247
248 if (!p->uvdet_slope || !p->uvdet_offs) {
249 /*
250 * If ADC conversion slope/offset parameters are not fused
251 * (non-production config), report error, but allow to use
252 * boot internal calibration with default slope.
253 */
254 gk20a_err(dev_from_gk20a(g), "ADC coeff are not fused\n");
255 return -EINVAL;
256 }
257 return 0;
258}
259
260/*
261 * Determine DFS_COEFF for the requested voltage. Always select external
262 * calibration override equal to the voltage, and set maximum detection
263 * limit "0" (to make sure that PLL output remains under F/V curve when
264 * voltage increases).
265 */
266static void clk_config_dvfs_detection(int mv, struct na_dvfs *d)
267{
268 u32 coeff, coeff_max;
269 struct pll_parms *p = &gpc_pll_params;
270
271 coeff_max = trim_sys_gpcpll_dvfs0_dfs_coeff_v(
272 trim_sys_gpcpll_dvfs0_dfs_coeff_m());
273 coeff = DIV_ROUND_CLOSEST(mv * p->coeff_slope, 1000) + p->coeff_offs;
274 coeff = DIV_ROUND_CLOSEST(coeff, 1000);
275 coeff = min(coeff, coeff_max);
276 d->dfs_coeff = coeff;
277
278 d->dfs_ext_cal = DIV_ROUND_CLOSEST(mv * 1000 - p->uvdet_offs,
279 p->uvdet_slope);
280 BUG_ON(abs(d->dfs_ext_cal) >= (1 << DFS_DET_RANGE));
281 d->uv_cal = p->uvdet_offs + d->dfs_ext_cal * p->uvdet_slope;
282 d->dfs_det_max = 0;
283}
284
285/*
286 * Solve equation for integer and fractional part of the effective NDIV:
287 *
288 * n_eff = n_int + 1/2 + SDM_DIN / 2^(SDM_DIN_RANGE + 1) +
289 * DVFS_COEFF * DVFS_DET_DELTA / 2^DFS_DET_RANGE
290 *
291 * The SDM_DIN LSB is finally shifted out, since it is not accessible by s/w.
292 */
293static void clk_config_dvfs_ndiv(int mv, u32 n_eff, struct na_dvfs *d)
294{
295 int n, det_delta;
296 u32 rem, rem_range;
297 struct pll_parms *p = &gpc_pll_params;
298
299 det_delta = (mv * 1000 - d->uv_cal);
300 det_delta = min(det_delta, d->dfs_det_max * p->uvdet_slope);
301 det_delta = det_delta * d->dfs_coeff;
302 det_delta = DIV_ROUND_CLOSEST(det_delta, p->uvdet_slope);
303
304 n = (int)(n_eff << DFS_DET_RANGE) - det_delta;
305 BUG_ON((n < 0) || (n > (p->max_N << DFS_DET_RANGE)));
306 d->n_int = ((u32)n) >> DFS_DET_RANGE;
307
308 rem = ((u32)n) & ((1 << DFS_DET_RANGE) - 1);
309 rem_range = SDM_DIN_RANGE + 1 - DFS_DET_RANGE;
310 d->sdm_din = (rem << rem_range) - (1 << SDM_DIN_RANGE);
311 d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff;
312}
313
314/* Voltage dependent configuration */
315static void clk_config_dvfs(struct gk20a *g, struct pll *gpll)
316{
317 struct na_dvfs *d = &gpll->dvfs;
318
319 d->mv = tegra_dvfs_predict_millivolts_t(
320 clk_get_parent(g->clk.tegra_clk),
321 rate_gpc2clk_to_gpu(gpll->freq));
322 clk_config_dvfs_detection(d->mv, d);
323 clk_config_dvfs_ndiv(d->mv, gpll->N, d);
324}
325
326/* Update DVFS detection settings in flight */
327static void clk_set_dfs_coeff(struct gk20a *g, u32 dfs_coeff)
328{
329 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
330 data |= DFS_EXT_STROBE;
331 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
332
333 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
334 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_coeff_m(),
335 trim_sys_gpcpll_dvfs0_dfs_coeff_f(dfs_coeff));
336 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
337
338 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
339 udelay(1);
340 data &= ~DFS_EXT_STROBE;
341 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
342}
343
344static void __maybe_unused clk_set_dfs_det_max(struct gk20a *g, u32 dfs_det_max)
345{
346 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
347 data |= DFS_EXT_STROBE;
348 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
349
350 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
351 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_det_max_m(),
352 trim_sys_gpcpll_dvfs0_dfs_det_max_f(dfs_det_max));
353 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
354
355 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
356 udelay(1);
357 data &= ~DFS_EXT_STROBE;
358 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
359}
360
361static void clk_set_dfs_ext_cal(struct gk20a *g, u32 dfs_det_cal)
362{
363 u32 data;
364
365 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
366 data &= ~(BIT(DFS_DET_RANGE + 1) - 1);
367 data |= dfs_det_cal;
368 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
369
370 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
371 udelay(1);
372 if (~trim_sys_gpcpll_dvfs1_dfs_ctrl_v(data) & DFS_EXT_CAL_EN) {
373 data = set_field(data, trim_sys_gpcpll_dvfs1_dfs_ctrl_m(),
374 trim_sys_gpcpll_dvfs1_dfs_ctrl_f(DFS_EXT_CAL_EN));
375 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
376 }
377}
378
379static void clk_setup_dvfs_detection(struct gk20a *g, struct pll *gpll)
380{
381 struct na_dvfs *d = &gpll->dvfs;
382
383 u32 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
384 data |= DFS_EXT_STROBE;
385 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
386
387 data = gk20a_readl(g, trim_sys_gpcpll_dvfs0_r());
388 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_coeff_m(),
389 trim_sys_gpcpll_dvfs0_dfs_coeff_f(d->dfs_coeff));
390 data = set_field(data, trim_sys_gpcpll_dvfs0_dfs_det_max_m(),
391 trim_sys_gpcpll_dvfs0_dfs_det_max_f(d->dfs_det_max));
392 gk20a_writel(g, trim_sys_gpcpll_dvfs0_r(), data);
393
394 data = gk20a_readl(g, trim_gpc_bcast_gpcpll_dvfs2_r());
395 udelay(1);
396 data &= ~DFS_EXT_STROBE;
397 gk20a_writel(g, trim_gpc_bcast_gpcpll_dvfs2_r(), data);
398
399 clk_set_dfs_ext_cal(g, d->dfs_ext_cal);
400}
401
402/* Enable NA/DVFS mode */
403static int clk_enbale_pll_dvfs(struct gk20a *g)
404{
405 u32 data;
406 int delay = 5; /* use for iddq exit delay & calib timeout */
407 struct pll_parms *p = &gpc_pll_params;
408 bool calibrated = p->uvdet_slope && p->uvdet_offs;
409
410 /* FIXME: Set VCO_CTRL */
411
412 /* Enable NA DVFS */
413 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
414 data |= trim_sys_gpcpll_dvfs1_en_dfs_m();
415 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
416
417 /*
418 * If calibration parameters are known (either from fuses, or from
419 * internal calibration on boot) - use them. Internal calibration is
420 * started anyway; it will complete, but results will not be used.
421 */
422 if (calibrated) {
423 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
424 data |= trim_sys_gpcpll_dvfs1_en_dfs_cal_m();
425 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
426 }
427
428 /* Exit IDDQ mode */
429 data = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
430 data = set_field(data, trim_sys_gpcpll_cfg_iddq_m(),
431 trim_sys_gpcpll_cfg_iddq_power_on_v());
432 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), data);
433 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
434 udelay(delay);
435
436 if (calibrated)
437 return 0;
438
439 /*
440 * If calibration parameters are not fused, start internal calibration,
441 * wait for completion, and use results along with default slope to
442 * calculate ADC offset during boot.
443 */
444 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
445 data |= trim_sys_gpcpll_dvfs1_en_dfs_cal_m();
446 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
447
448 /* Wait for internal calibration done (spec < 2us). */
449 do {
450 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
451 if (trim_sys_gpcpll_dvfs1_dfs_cal_done_v(data))
452 break;
453 udelay(1);
454 delay--;
455 } while (delay > 0);
456
457 if (delay <= 0) {
458 gk20a_err(dev_from_gk20a(g), "GPCPLL calibration timeout");
459 return -ETIMEDOUT;
460 }
461
462 data = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
463 data = trim_sys_gpcpll_cfg3_dfs_testout_v(data);
464 p->uvdet_offs = BOOT_GPU_UV - data * ADC_SLOPE_UV;
465 p->uvdet_slope = ADC_SLOPE_UV;
466 return 0;
467}
468
469/* GPCPLL slide methods */
221static void clk_setup_slide(struct gk20a *g, u32 clk_u) 470static void clk_setup_slide(struct gk20a *g, u32 clk_u)
222{ 471{
223 u32 data, step_a, step_b; 472 u32 data, step_a, step_b;
@@ -320,6 +569,7 @@ static int clk_slide_gpc_pll(struct gk20a *g, struct pll *gpll)
320 return 0; 569 return 0;
321} 570}
322 571
572/* GPCPLL bypass methods */
323static int clk_change_pldiv_under_bypass(struct gk20a *g, struct pll *gpll) 573static int clk_change_pldiv_under_bypass(struct gk20a *g, struct pll *gpll)
324{ 574{
325 u32 data, coeff; 575 u32 data, coeff;
@@ -381,10 +631,24 @@ static int clk_lock_gpc_pll_under_bypass(struct gk20a *g, struct pll *gpll)
381 } 631 }
382 632
383 /* change coefficients */ 633 /* change coefficients */
384 coeff = trim_sys_gpcpll_coeff_mdiv_f(gpll->M) | 634 if (gpll->mode == GPC_PLL_MODE_DVFS) {
385 trim_sys_gpcpll_coeff_ndiv_f(gpll->N) | 635 clk_setup_dvfs_detection(g, gpll);
386 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL); 636
387 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff); 637 coeff = gk20a_readl(g, trim_sys_gpcpll_cfg2_r());
638 coeff = set_field(coeff, trim_sys_gpcpll_cfg2_sdm_din_m(),
639 trim_sys_gpcpll_cfg2_sdm_din_f(gpll->dvfs.sdm_din));
640 gk20a_writel(g, trim_sys_gpcpll_cfg2_r(), coeff);
641
642 coeff = trim_sys_gpcpll_coeff_mdiv_f(gpll->M) |
643 trim_sys_gpcpll_coeff_ndiv_f(gpll->dvfs.n_int) |
644 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL);
645 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
646 } else {
647 coeff = trim_sys_gpcpll_coeff_mdiv_f(gpll->M) |
648 trim_sys_gpcpll_coeff_ndiv_f(gpll->N) |
649 trim_sys_gpcpll_coeff_pldiv_f(gpll->PL);
650 gk20a_writel(g, trim_sys_gpcpll_coeff_r(), coeff);
651 }
388 652
389 /* enable PLL after changing coefficients */ 653 /* enable PLL after changing coefficients */
390 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r()); 654 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
@@ -392,6 +656,13 @@ static int clk_lock_gpc_pll_under_bypass(struct gk20a *g, struct pll *gpll)
392 trim_sys_gpcpll_cfg_enable_yes_f()); 656 trim_sys_gpcpll_cfg_enable_yes_f());
393 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg); 657 gk20a_writel(g, trim_sys_gpcpll_cfg_r(), cfg);
394 658
659 /* just delay in DVFS mode (lock cannot be used) */
660 if (gpll->mode == GPC_PLL_MODE_DVFS) {
661 gk20a_readl(g, trim_sys_gpcpll_cfg_r());
662 udelay(g->clk.na_pll_delay);
663 goto pll_locked;
664 }
665
395 /* lock pll */ 666 /* lock pll */
396 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r()); 667 cfg = gk20a_readl(g, trim_sys_gpcpll_cfg_r());
397 if (cfg & trim_sys_gpcpll_cfg_enb_lckdet_power_off_f()){ 668 if (cfg & trim_sys_gpcpll_cfg_enb_lckdet_power_off_f()){
@@ -434,6 +705,7 @@ pll_locked:
434 return 0; 705 return 0;
435} 706}
436 707
708/* GPCPLL programming in legacy (non-DVFS) mode */
437static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new, 709static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new,
438 int allow_slide) 710 int allow_slide)
439{ 711{
@@ -549,6 +821,16 @@ set_pldiv:
549 return clk_slide_gpc_pll(g, gpll_new); 821 return clk_slide_gpc_pll(g, gpll_new);
550} 822}
551 823
824/* GPCPLL programming in DVFS mode */
825static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new,
826 int allow_slide)
827{
828 clk_config_dvfs(g, gpll_new);
829
830 /* always under bypass, for now */
831 return clk_program_gpc_pll(g, gpll_new, 0);
832}
833
552static int clk_disable_gpcpll(struct gk20a *g, int allow_slide) 834static int clk_disable_gpcpll(struct gk20a *g, int allow_slide)
553{ 835{
554 u32 cfg, coeff; 836 u32 cfg, coeff;
@@ -617,6 +899,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
617 static int initialized; 899 static int initialized;
618 struct clk *ref; 900 struct clk *ref;
619 unsigned long ref_rate; 901 unsigned long ref_rate;
902 bool calibrated;
620 903
621 gk20a_dbg_fn(""); 904 gk20a_dbg_fn("");
622 905
@@ -636,7 +919,14 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
636 } 919 }
637 ref_rate = clk_get_rate(ref); 920 ref_rate = clk_get_rate(ref);
638 921
922 /*
923 * Locking time in both legacy and DVFS mode is 40us. However, in legacy
924 * mode we rely on lock detection signal, and delay is just timeout
925 * limit, so we can afford set it longer. In DVFS mode each lock inserts
926 * specified delay, so it should be set as short as h/w allows.
927 */
639 clk->pll_delay = 300; /* usec */ 928 clk->pll_delay = 300; /* usec */
929 clk->na_pll_delay = 40; /* usec*/
640 930
641 clk->gpc_pll.id = GK20A_GPC_PLL; 931 clk->gpc_pll.id = GK20A_GPC_PLL;
642 clk->gpc_pll.clk_in = ref_rate / KHZ; 932 clk->gpc_pll.clk_in = ref_rate / KHZ;
@@ -652,6 +942,17 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
652 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL); 942 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL);
653 } 943 }
654 944
945 calibrated = !clk_config_calibration_params(g);
946#ifdef CONFIG_TEGRA_USE_NA_GPCPLL
947 if (ALLOW_NON_CALIBRATED_NA_MODE || calibrated) {
948 /* NA mode is supported only at max update rate 38.4 MHz */
949 if (clk->gpc_pll.clk_in == gpc_pll_params.max_u) {
950 clk->gpc_pll.mode = GPC_PLL_MODE_DVFS;
951 gpc_pll_params.min_u = gpc_pll_params.max_u;
952 }
953 }
954#endif
955
655 mutex_init(&clk->clk_mutex); 956 mutex_init(&clk->clk_mutex);
656 957
657 clk->sw_ready = true; 958 clk->sw_ready = true;
@@ -693,6 +994,9 @@ static int gm20b_init_clk_setup_hw(struct gk20a *g)
693 gk20a_writel(g, therm_clk_slowdown_r(0), data); 994 gk20a_writel(g, therm_clk_slowdown_r(0), data);
694 gk20a_readl(g, therm_clk_slowdown_r(0)); 995 gk20a_readl(g, therm_clk_slowdown_r(0));
695 996
997 if (g->clk.gpc_pll.mode == GPC_PLL_MODE_DVFS)
998 return clk_enbale_pll_dvfs(g);
999
696 return 0; 1000 return 0;
697} 1001}
698 1002
@@ -726,9 +1030,15 @@ static int set_pll_freq(struct gk20a *g, int allow_slide)
726 clk->gpc_pll_last.freq, clk->gpc_pll.freq); 1030 clk->gpc_pll_last.freq, clk->gpc_pll.freq);
727 1031
728 /* If programming with dynamic sliding failed, re-try under bypass */ 1032 /* If programming with dynamic sliding failed, re-try under bypass */
729 err = clk_program_gpc_pll(g, &clk->gpc_pll, allow_slide); 1033 if (clk->gpc_pll.mode == GPC_PLL_MODE_DVFS) {
730 if (err && allow_slide) 1034 err = clk_program_na_gpc_pll(g, &clk->gpc_pll, allow_slide);
731 err = clk_program_gpc_pll(g, &clk->gpc_pll, 0); 1035 if (err && allow_slide)
1036 err = clk_program_na_gpc_pll(g, &clk->gpc_pll, 0);
1037 } else {
1038 err = clk_program_gpc_pll(g, &clk->gpc_pll, allow_slide);
1039 if (err && allow_slide)
1040 err = clk_program_gpc_pll(g, &clk->gpc_pll, 0);
1041 }
732 1042
733 if (!err) { 1043 if (!err) {
734 clk->gpc_pll.enabled = true; 1044 clk->gpc_pll.enabled = true;