summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c5
-rw-r--r--drivers/gpu/nvgpu/gm20b/clk_gm20b.c92
2 files changed, 77 insertions, 20 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
index 1b4d2c07..978ad5aa 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
@@ -18,12 +18,17 @@
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */ 19 */
20 20
21#include <linux/version.h>
21#include <linux/device.h> 22#include <linux/device.h>
22#include <linux/pm_runtime.h> 23#include <linux/pm_runtime.h>
23#include <linux/kernel.h> 24#include <linux/kernel.h>
24#include <linux/fb.h> 25#include <linux/fb.h>
25#include <linux/gk20a.h> 26#include <linux/gk20a.h>
27#include <mach/clk.h>
26#include <linux/clk/tegra.h> 28#include <linux/clk/tegra.h>
29#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
30#include <soc/tegra/tegra-dvfs.h>
31#endif
27 32
28#include "gk20a.h" 33#include "gk20a.h"
29#include "gr_gk20a.h" 34#include "gr_gk20a.h"
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
index 501be537..060a5775 100644
--- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
@@ -372,6 +372,18 @@ static void clk_config_dvfs_ndiv(int mv, u32 n_eff, struct na_dvfs *d)
372 d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff; 372 d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff;
373} 373}
374 374
375static void gm20b_calc_dvfs_safe_max_freq(struct clk *c)
376{
377 unsigned long safe_rate;
378
379 if (dvfs_safe_max_freq)
380 return;
381
382 safe_rate = tegra_dvfs_get_fmax_at_vmin_safe_t(c);
383 safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100;
384 dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate);
385}
386
375/* Voltage dependent configuration */ 387/* Voltage dependent configuration */
376static void clk_config_dvfs(struct gk20a *g, struct pll *gpll) 388static void clk_config_dvfs(struct gk20a *g, struct pll *gpll)
377{ 389{
@@ -383,6 +395,7 @@ static void clk_config_dvfs(struct gk20a *g, struct pll *gpll)
383 clk = clk_get_parent(clk); 395 clk = clk_get_parent(clk);
384#endif 396#endif
385 397
398 gm20b_calc_dvfs_safe_max_freq(clk);
386 d->mv = tegra_dvfs_predict_mv_at_hz_cur_tfloor(clk, 399 d->mv = tegra_dvfs_predict_mv_at_hz_cur_tfloor(clk,
387 rate_gpc2clk_to_gpu(gpll->freq)); 400 rate_gpc2clk_to_gpu(gpll->freq));
388 401
@@ -1120,32 +1133,23 @@ static int gm20b_init_clk_reset_enable_hw(struct gk20a *g)
1120 return 0; 1133 return 0;
1121} 1134}
1122 1135
1123static int gm20b_init_clk_setup_sw(struct gk20a *g) 1136#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
1137static int gm20b_init_gpc_pll(struct gk20a *g)
1124{ 1138{
1125 struct clk_gk20a *clk = &g->clk; 1139 struct clk_gk20a *clk = &g->clk;
1126 unsigned long safe_rate; 1140 struct clk *c, *ref;
1127 struct clk *ref, *c;
1128
1129 gk20a_dbg_fn("");
1130
1131 if (clk->sw_ready) {
1132 gk20a_dbg_fn("skip init");
1133 return 0;
1134 }
1135 1141
1136 if (!gk20a_clk_get(g)) 1142 if (!gk20a_clk_get(g))
1137 return -EINVAL; 1143 return -EINVAL;
1138 1144
1139 c = clk->tegra_clk;
1140#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
1141 /* 1145 /*
1142 * On Tegra GPU clock exposed to frequency governor is a shared user on 1146 * On Tegra GPU clock exposed to frequency governor is a shared user on
1143 * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent. 1147 * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent.
1144 * Respectively the grandparent is PLL reference clock. 1148 * Respectively the grandparent is PLL reference clock.
1145 */ 1149 */
1146 c = clk_get_parent(c); 1150 c = clk_get_parent(clk->tegra_clk);
1147#endif
1148 ref = clk_get_parent(c); 1151 ref = clk_get_parent(c);
1152
1149 if (IS_ERR(ref)) { 1153 if (IS_ERR(ref)) {
1150 gk20a_err(dev_from_gk20a(g), 1154 gk20a_err(dev_from_gk20a(g),
1151 "failed to get GPCPLL reference clock"); 1155 "failed to get GPCPLL reference clock");
@@ -1155,9 +1159,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1155 clk->gpc_pll.id = GK20A_GPC_PLL; 1159 clk->gpc_pll.id = GK20A_GPC_PLL;
1156 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ; 1160 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ;
1157 1161
1158 safe_rate = tegra_dvfs_get_fmax_at_vmin_safe_t(c); 1162 gm20b_calc_dvfs_safe_max_freq(c);
1159 safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100;
1160 dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate);
1161 clk->gpc_pll.PL = (dvfs_safe_max_freq == 0) ? 0 : 1163 clk->gpc_pll.PL = (dvfs_safe_max_freq == 0) ? 0 :
1162 DIV_ROUND_UP(gpc_pll_params.min_vco, dvfs_safe_max_freq); 1164 DIV_ROUND_UP(gpc_pll_params.min_vco, dvfs_safe_max_freq);
1163 1165
@@ -1169,7 +1171,51 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1169 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; 1171 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
1170 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL); 1172 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL);
1171 1173
1172 /* 1174 return 0;
1175}
1176
1177#else /*COMMON_CLOCK_FRAMEWORK*/
1178static int gm20b_init_gpc_pll(struct gk20a *g)
1179{
1180 struct clk_gk20a *clk = &g->clk;
1181 struct clk *ref;
1182
1183 ref = clk_get_sys("gpu_ref", "gpu_ref");
1184 if (IS_ERR(ref)) {
1185 gk20a_err(dev_from_gk20a(g),
1186 "failed to get GPCPLL reference clock");
1187 return -EINVAL;
1188 }
1189 clk->gpc_pll.id = GK20A_GPC_PLL;
1190 clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ;
1191
1192 /* Initial freq: low enough to be safe at Vmin (default 1/3 VCO min) */
1193 clk->gpc_pll.M = 1;
1194 clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco,
1195 clk->gpc_pll.clk_in);
1196 clk->gpc_pll.PL = 3;
1197 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
1198 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL);
1199
1200 return 0;
1201}
1202#endif
1203
1204static int gm20b_init_clk_setup_sw(struct gk20a *g)
1205{
1206 struct clk_gk20a *clk = &g->clk;
1207
1208 gk20a_dbg_fn("");
1209
1210 if (clk->sw_ready) {
1211 gk20a_dbg_fn("skip init");
1212 return 0;
1213 }
1214
1215 if (gm20b_init_gpc_pll(g))
1216 return -EINVAL;
1217
1218 /*
1173 * All production parts should have ADC fuses burnt. Therefore, check 1219 * All production parts should have ADC fuses burnt. Therefore, check
1174 * ADC fuses always, regardless of whether NA mode is selected; and if 1220 * ADC fuses always, regardless of whether NA mode is selected; and if
1175 * NA mode is indeed selected, and part can support it, switch to NA 1221 * NA mode is indeed selected, and part can support it, switch to NA
@@ -1187,7 +1233,6 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
1187#endif 1233#endif
1188 1234
1189 mutex_init(&clk->clk_mutex); 1235 mutex_init(&clk->clk_mutex);
1190
1191 clk->sw_ready = true; 1236 clk->sw_ready = true;
1192 1237
1193 gk20a_dbg_fn("done"); 1238 gk20a_dbg_fn("done");
@@ -1293,6 +1338,11 @@ int gm20b_register_gpcclk(struct gk20a *g) {
1293 struct clk_gk20a *clk = &g->clk; 1338 struct clk_gk20a *clk = &g->clk;
1294 struct clk_init_data init; 1339 struct clk_init_data init;
1295 struct clk *c; 1340 struct clk *c;
1341 int err = 0;
1342
1343 err = gm20b_init_clk_setup_sw(g);
1344 if (err)
1345 return err;
1296 1346
1297 init.name = "gpcclk"; 1347 init.name = "gpcclk";
1298 init.ops = &gk20a_clk_ops; 1348 init.ops = &gk20a_clk_ops;
@@ -1312,7 +1362,7 @@ int gm20b_register_gpcclk(struct gk20a *g) {
1312 clk->tegra_clk = c; 1362 clk->tegra_clk = c;
1313 clk_register_clkdev(c, "gpcclk", "gpcclk"); 1363 clk_register_clkdev(c, "gpcclk", "gpcclk");
1314 1364
1315 return 0; 1365 return err;
1316} 1366}
1317#endif /* CONFIG_COMMON_CLK */ 1367#endif /* CONFIG_COMMON_CLK */
1318 1368
@@ -1522,9 +1572,11 @@ static int gm20b_init_clk_support(struct gk20a *g)
1522 if (err) 1572 if (err)
1523 return err; 1573 return err;
1524 1574
1575#ifdef CONFIG_TEGRA_CLK_FRAMEWORK
1525 err = gm20b_init_clk_setup_sw(g); 1576 err = gm20b_init_clk_setup_sw(g);
1526 if (err) 1577 if (err)
1527 return err; 1578 return err;
1579#endif
1528 1580
1529 mutex_lock(&clk->clk_mutex); 1581 mutex_lock(&clk->clk_mutex);
1530 clk->clk_hw_on = true; 1582 clk->clk_hw_on = true;