summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2014-09-26 01:44:26 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:11:32 -0400
commit83bf2aa83d922080884a9fe547b656e24495e16e (patch)
treef0911d3020da632c9976fbc9df01b111557d77a3 /drivers/gpu/nvgpu/gm20b/clk_gm20b.c
parent6b85e32d6c750c79264455636c2f8f55c409b51a (diff)
gpu: nvgpu: Prepare for GPCPLL NA data integration
In preparation for GM20B GPCPLL NA data integration: - Added VCO control initialization code (no data, yet) - Replaced absolute safe margin with relative percentage (preliminary 8%) - Retrieved maximum safe frequency at minimum voltage from GPU DVFS table, instead of hard-coded macro (also fix the name of the limit: maximum instead of minimum) - Updated comments Bug 1555318 Change-Id: I49a7a90cc4bc29e181065ebd2cf9d214edae6465 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/542462 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Seshendra Gadagottu <sgadagottu@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/clk_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/clk_gm20b.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
index b1d1af4d..6ee7dff9 100644
--- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
@@ -43,9 +43,8 @@
43#define BOOT_GPU_UV 1000000 /* gpu rail boot voltage 1.0V */ 43#define BOOT_GPU_UV 1000000 /* gpu rail boot voltage 1.0V */
44#define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */ 44#define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */
45 45
46/* FIXME: need characterized safe margin constant or table, and minimum */ 46#define DVFS_SAFE_MARGIN 8 /* 8% */
47#define DVFS_SAFE_MARGIN (2*38400) 47static unsigned long dvfs_safe_max_freq;
48#define DVFS_SAFE_MIN_FREQ (2*307200)
49 48
50static struct pll_parms gpc_pll_params = { 49static struct pll_parms gpc_pll_params = {
51 128000, 2600000, /* freq */ 50 128000, 2600000, /* freq */
@@ -55,6 +54,8 @@ static struct pll_parms gpc_pll_params = {
55 8, 255, /* N */ 54 8, 255, /* N */
56 1, 31, /* PL */ 55 1, 31, /* PL */
57 -58700, 86789, /* DFS_COEFF */ 56 -58700, 86789, /* DFS_COEFF */
57 0, 0, /* ADC char coeff - to be read from fuses */
58 0, /* FIXME: vco control data */
58}; 59};
59 60
60#ifdef CONFIG_DEBUG_FS 61#ifdef CONFIG_DEBUG_FS
@@ -412,13 +413,19 @@ static int clk_enbale_pll_dvfs(struct gk20a *g)
412 struct pll_parms *p = &gpc_pll_params; 413 struct pll_parms *p = &gpc_pll_params;
413 bool calibrated = p->uvdet_slope && p->uvdet_offs; 414 bool calibrated = p->uvdet_slope && p->uvdet_offs;
414 415
415 /* FIXME: Set VCO_CTRL */
416
417 /* Enable NA DVFS */ 416 /* Enable NA DVFS */
418 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r()); 417 data = gk20a_readl(g, trim_sys_gpcpll_dvfs1_r());
419 data |= trim_sys_gpcpll_dvfs1_en_dfs_m(); 418 data |= trim_sys_gpcpll_dvfs1_en_dfs_m();
420 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data); 419 gk20a_writel(g, trim_sys_gpcpll_dvfs1_r(), data);
421 420
421 /* Set VCO_CTRL */
422 if (p->vco_ctrl) {
423 data = gk20a_readl(g, trim_sys_gpcpll_cfg3_r());
424 data = set_field(data, trim_sys_gpcpll_cfg3_vco_ctrl_m(),
425 trim_sys_gpcpll_cfg3_vco_ctrl_f(p->vco_ctrl));
426 gk20a_writel(g, trim_sys_gpcpll_cfg3_r(), data);
427 }
428
422 /* 429 /*
423 * If calibration parameters are known (either from fuses, or from 430 * If calibration parameters are known (either from fuses, or from
424 * internal calibration on boot) - use them. Internal calibration is 431 * internal calibration on boot) - use them. Internal calibration is
@@ -884,8 +891,8 @@ static void clk_config_pll_safe_dvfs(struct gk20a *g, struct pll *gpll)
884{ 891{
885 u32 nsafe, nmin; 892 u32 nsafe, nmin;
886 893
887 if (gpll->freq > DVFS_SAFE_MIN_FREQ) 894 if (gpll->freq > dvfs_safe_max_freq)
888 gpll->freq -= DVFS_SAFE_MARGIN; 895 gpll->freq = gpll->freq * (100 - DVFS_SAFE_MARGIN) / 100;
889 896
890 nmin = DIV_ROUND_UP(gpll->M * gpc_pll_params.min_vco, gpll->clk_in); 897 nmin = DIV_ROUND_UP(gpll->M * gpc_pll_params.min_vco, gpll->clk_in);
891 nsafe = gpll->M * gpll->freq / gpll->clk_in; 898 nsafe = gpll->M * gpll->freq / gpll->clk_in;
@@ -956,7 +963,7 @@ static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new,
956 * i.e., it is low enough to be safe at any voltage in operating range 963 * i.e., it is low enough to be safe at any voltage in operating range
957 * with zero DVFS coefficient. 964 * with zero DVFS coefficient.
958 */ 965 */
959 if (gpll_old->freq > DVFS_SAFE_MIN_FREQ) { 966 if (gpll_old->freq > dvfs_safe_max_freq) {
960 if (gpll_old->dvfs.mv < gpll_new->dvfs.mv) { 967 if (gpll_old->dvfs.mv < gpll_new->dvfs.mv) {
961 gpll_safe = *gpll_old; 968 gpll_safe = *gpll_old;
962 gpll_safe.dvfs.mv = gpll_new->dvfs.mv; 969 gpll_safe.dvfs.mv = gpll_new->dvfs.mv;
@@ -1060,7 +1067,6 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1060 struct clk_gk20a *clk = &g->clk; 1067 struct clk_gk20a *clk = &g->clk;
1061 static int initialized; 1068 static int initialized;
1062 struct clk *ref; 1069 struct clk *ref;
1063 unsigned long ref_rate;
1064 bool calibrated; 1070 bool calibrated;
1065 1071
1066 gk20a_dbg_fn(""); 1072 gk20a_dbg_fn("");
@@ -1073,13 +1079,17 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1073 if (!gk20a_clk_get(g)) 1079 if (!gk20a_clk_get(g))
1074 return -EINVAL; 1080 return -EINVAL;
1075 1081
1082 /*
1083 * On Tegra GPU clock exposed to frequency governor is a shared user on
1084 * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent.
1085 * Respectively the grandparent is PLL reference clock.
1086 */
1076 ref = clk_get_parent(clk_get_parent(clk->tegra_clk)); 1087 ref = clk_get_parent(clk_get_parent(clk->tegra_clk));
1077 if (IS_ERR(ref)) { 1088 if (IS_ERR(ref)) {
1078 gk20a_err(dev_from_gk20a(g), 1089 gk20a_err(dev_from_gk20a(g),
1079 "failed to get GPCPLL reference clock"); 1090 "failed to get GPCPLL reference clock");
1080 return -EINVAL; 1091 return -EINVAL;
1081 } 1092 }
1082 ref_rate = clk_get_rate(ref);
1083 1093
1084 /* 1094 /*
1085 * Locking time in both legacy and DVFS mode is 40us. However, in legacy 1095 * Locking time in both legacy and DVFS mode is 40us. However, in legacy
@@ -1091,7 +1101,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1091 clk->na_pll_delay = 40; /* usec*/ 1101 clk->na_pll_delay = 40; /* usec*/
1092 1102
1093 clk->gpc_pll.id = GK20A_GPC_PLL; 1103 clk->gpc_pll.id = GK20A_GPC_PLL;
1094 clk->gpc_pll.clk_in = ref_rate / KHZ; 1104 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ;
1095 1105
1096 /* Initial frequency: 1/3 VCO min (low enough to be safe at Vmin) */ 1106 /* Initial frequency: 1/3 VCO min (low enough to be safe at Vmin) */
1097 if (!initialized) { 1107 if (!initialized) {
@@ -1109,8 +1119,14 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1109 if (ALLOW_NON_CALIBRATED_NA_MODE || calibrated) { 1119 if (ALLOW_NON_CALIBRATED_NA_MODE || calibrated) {
1110 /* NA mode is supported only at max update rate 38.4 MHz */ 1120 /* NA mode is supported only at max update rate 38.4 MHz */
1111 if (clk->gpc_pll.clk_in == gpc_pll_params.max_u) { 1121 if (clk->gpc_pll.clk_in == gpc_pll_params.max_u) {
1122 unsigned long safe_rate;
1112 clk->gpc_pll.mode = GPC_PLL_MODE_DVFS; 1123 clk->gpc_pll.mode = GPC_PLL_MODE_DVFS;
1113 gpc_pll_params.min_u = gpc_pll_params.max_u; 1124 gpc_pll_params.min_u = gpc_pll_params.max_u;
1125
1126 safe_rate = tegra_dvfs_get_therm_safe_fmax(
1127 clk_get_parent(clk->tegra_clk));
1128 safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100;
1129 dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate);
1114 } 1130 }
1115 } 1131 }
1116#endif 1132#endif