diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 92 |
2 files changed, 20 insertions, 76 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index 6611b120..f7e0036f 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | |||
@@ -18,16 +18,12 @@ | |||
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> | ||
22 | #include <linux/device.h> | 21 | #include <linux/device.h> |
23 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/fb.h> | 24 | #include <linux/fb.h> |
26 | #include <linux/gk20a.h> | 25 | #include <linux/gk20a.h> |
27 | #include <linux/clk/tegra.h> | 26 | #include <linux/clk/tegra.h> |
28 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) | ||
29 | #include <soc/tegra/tegra-dvfs.h> | ||
30 | #endif | ||
31 | 27 | ||
32 | #include "gk20a.h" | 28 | #include "gk20a.h" |
33 | #include "gr_gk20a.h" | 29 | #include "gr_gk20a.h" |
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index 05dd455c..be194228 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c | |||
@@ -371,18 +371,6 @@ static void clk_config_dvfs_ndiv(int mv, u32 n_eff, struct na_dvfs *d) | |||
371 | d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff; | 371 | d->sdm_din = (d->sdm_din >> BITS_PER_BYTE) & 0xff; |
372 | } | 372 | } |
373 | 373 | ||
374 | static void gm20b_calc_dvfs_safe_max_freq(struct clk *c) | ||
375 | { | ||
376 | unsigned long safe_rate; | ||
377 | |||
378 | if (dvfs_safe_max_freq) | ||
379 | return; | ||
380 | |||
381 | safe_rate = tegra_dvfs_get_fmax_at_vmin_safe_t(c); | ||
382 | safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100; | ||
383 | dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate); | ||
384 | } | ||
385 | |||
386 | /* Voltage dependent configuration */ | 374 | /* Voltage dependent configuration */ |
387 | static void clk_config_dvfs(struct gk20a *g, struct pll *gpll) | 375 | static void clk_config_dvfs(struct gk20a *g, struct pll *gpll) |
388 | { | 376 | { |
@@ -394,7 +382,6 @@ static void clk_config_dvfs(struct gk20a *g, struct pll *gpll) | |||
394 | clk = clk_get_parent(clk); | 382 | clk = clk_get_parent(clk); |
395 | #endif | 383 | #endif |
396 | 384 | ||
397 | gm20b_calc_dvfs_safe_max_freq(clk); | ||
398 | d->mv = tegra_dvfs_predict_mv_at_hz_cur_tfloor(clk, | 385 | d->mv = tegra_dvfs_predict_mv_at_hz_cur_tfloor(clk, |
399 | rate_gpc2clk_to_gpu(gpll->freq)); | 386 | rate_gpc2clk_to_gpu(gpll->freq)); |
400 | 387 | ||
@@ -1132,23 +1119,32 @@ static int gm20b_init_clk_reset_enable_hw(struct gk20a *g) | |||
1132 | return 0; | 1119 | return 0; |
1133 | } | 1120 | } |
1134 | 1121 | ||
1135 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | 1122 | static int gm20b_init_clk_setup_sw(struct gk20a *g) |
1136 | static int gm20b_init_gpc_pll(struct gk20a *g) | ||
1137 | { | 1123 | { |
1138 | struct clk_gk20a *clk = &g->clk; | 1124 | struct clk_gk20a *clk = &g->clk; |
1139 | struct clk *c, *ref; | 1125 | unsigned long safe_rate; |
1126 | struct clk *ref, *c; | ||
1127 | |||
1128 | gk20a_dbg_fn(""); | ||
1129 | |||
1130 | if (clk->sw_ready) { | ||
1131 | gk20a_dbg_fn("skip init"); | ||
1132 | return 0; | ||
1133 | } | ||
1140 | 1134 | ||
1141 | if (!gk20a_clk_get(g)) | 1135 | if (!gk20a_clk_get(g)) |
1142 | return -EINVAL; | 1136 | return -EINVAL; |
1143 | 1137 | ||
1138 | c = clk->tegra_clk; | ||
1139 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
1144 | /* | 1140 | /* |
1145 | * On Tegra GPU clock exposed to frequency governor is a shared user on | 1141 | * On Tegra GPU clock exposed to frequency governor is a shared user on |
1146 | * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent. | 1142 | * GPCPLL bus (gbus). The latter can be accessed as GPU clock parent. |
1147 | * Respectively the grandparent is PLL reference clock. | 1143 | * Respectively the grandparent is PLL reference clock. |
1148 | */ | 1144 | */ |
1149 | c = clk_get_parent(clk->tegra_clk); | 1145 | c = clk_get_parent(c); |
1146 | #endif | ||
1150 | ref = clk_get_parent(c); | 1147 | ref = clk_get_parent(c); |
1151 | |||
1152 | if (IS_ERR(ref)) { | 1148 | if (IS_ERR(ref)) { |
1153 | gk20a_err(dev_from_gk20a(g), | 1149 | gk20a_err(dev_from_gk20a(g), |
1154 | "failed to get GPCPLL reference clock"); | 1150 | "failed to get GPCPLL reference clock"); |
@@ -1163,7 +1159,9 @@ static int gm20b_init_gpc_pll(struct gk20a *g) | |||
1163 | return -EINVAL; | 1159 | return -EINVAL; |
1164 | } | 1160 | } |
1165 | 1161 | ||
1166 | gm20b_calc_dvfs_safe_max_freq(c); | 1162 | safe_rate = tegra_dvfs_get_fmax_at_vmin_safe_t(c); |
1163 | safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100; | ||
1164 | dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate); | ||
1167 | clk->gpc_pll.PL = (dvfs_safe_max_freq == 0) ? 0 : | 1165 | clk->gpc_pll.PL = (dvfs_safe_max_freq == 0) ? 0 : |
1168 | DIV_ROUND_UP(gpc_pll_params.min_vco, dvfs_safe_max_freq); | 1166 | DIV_ROUND_UP(gpc_pll_params.min_vco, dvfs_safe_max_freq); |
1169 | 1167 | ||
@@ -1175,51 +1173,7 @@ static int gm20b_init_gpc_pll(struct gk20a *g) | |||
1175 | clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; | 1173 | clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; |
1176 | clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL); | 1174 | clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL); |
1177 | 1175 | ||
1178 | return 0; | 1176 | /* |
1179 | } | ||
1180 | |||
1181 | #else /*COMMON_CLOCK_FRAMEWORK*/ | ||
1182 | static int gm20b_init_gpc_pll(struct gk20a *g) | ||
1183 | { | ||
1184 | struct clk_gk20a *clk = &g->clk; | ||
1185 | struct clk *ref; | ||
1186 | |||
1187 | ref = clk_get_sys("gpu_ref", "gpu_ref"); | ||
1188 | if (IS_ERR(ref)) { | ||
1189 | gk20a_err(dev_from_gk20a(g), | ||
1190 | "failed to get GPCPLL reference clock"); | ||
1191 | return -EINVAL; | ||
1192 | } | ||
1193 | clk->gpc_pll.id = GK20A_GPC_PLL; | ||
1194 | clk->gpc_pll.clk_in = clk_get_rate(ref) / KHZ; | ||
1195 | |||
1196 | /* Initial freq: low enough to be safe at Vmin (default 1/3 VCO min) */ | ||
1197 | clk->gpc_pll.M = 1; | ||
1198 | clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco, | ||
1199 | clk->gpc_pll.clk_in); | ||
1200 | clk->gpc_pll.PL = 3; | ||
1201 | clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; | ||
1202 | clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL); | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | #endif | ||
1207 | |||
1208 | static int gm20b_init_clk_setup_sw(struct gk20a *g) | ||
1209 | { | ||
1210 | struct clk_gk20a *clk = &g->clk; | ||
1211 | |||
1212 | gk20a_dbg_fn(""); | ||
1213 | |||
1214 | if (clk->sw_ready) { | ||
1215 | gk20a_dbg_fn("skip init"); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | if (gm20b_init_gpc_pll(g)) | ||
1220 | return -EINVAL; | ||
1221 | |||
1222 | /* | ||
1223 | * All production parts should have ADC fuses burnt. Therefore, check | 1177 | * All production parts should have ADC fuses burnt. Therefore, check |
1224 | * ADC fuses always, regardless of whether NA mode is selected; and if | 1178 | * ADC fuses always, regardless of whether NA mode is selected; and if |
1225 | * NA mode is indeed selected, and part can support it, switch to NA | 1179 | * NA mode is indeed selected, and part can support it, switch to NA |
@@ -1237,6 +1191,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g) | |||
1237 | #endif | 1191 | #endif |
1238 | 1192 | ||
1239 | mutex_init(&clk->clk_mutex); | 1193 | mutex_init(&clk->clk_mutex); |
1194 | |||
1240 | clk->sw_ready = true; | 1195 | clk->sw_ready = true; |
1241 | 1196 | ||
1242 | gk20a_dbg_fn("done"); | 1197 | gk20a_dbg_fn("done"); |
@@ -1346,11 +1301,6 @@ int gm20b_register_gpcclk(struct gk20a *g) { | |||
1346 | struct clk_gk20a *clk = &g->clk; | 1301 | struct clk_gk20a *clk = &g->clk; |
1347 | struct clk_init_data init; | 1302 | struct clk_init_data init; |
1348 | struct clk *c; | 1303 | struct clk *c; |
1349 | int err = 0; | ||
1350 | |||
1351 | err = gm20b_init_clk_setup_sw(g); | ||
1352 | if (err) | ||
1353 | return err; | ||
1354 | 1304 | ||
1355 | init.name = "gpcclk"; | 1305 | init.name = "gpcclk"; |
1356 | init.ops = &gk20a_clk_ops; | 1306 | init.ops = &gk20a_clk_ops; |
@@ -1370,7 +1320,7 @@ int gm20b_register_gpcclk(struct gk20a *g) { | |||
1370 | clk->tegra_clk = c; | 1320 | clk->tegra_clk = c; |
1371 | clk_register_clkdev(c, "gpcclk", "gpcclk"); | 1321 | clk_register_clkdev(c, "gpcclk", "gpcclk"); |
1372 | 1322 | ||
1373 | return err; | 1323 | return 0; |
1374 | } | 1324 | } |
1375 | #endif /* CONFIG_COMMON_CLK */ | 1325 | #endif /* CONFIG_COMMON_CLK */ |
1376 | 1326 | ||
@@ -1580,11 +1530,9 @@ static int gm20b_init_clk_support(struct gk20a *g) | |||
1580 | if (err) | 1530 | if (err) |
1581 | return err; | 1531 | return err; |
1582 | 1532 | ||
1583 | #ifdef CONFIG_TEGRA_CLK_FRAMEWORK | ||
1584 | err = gm20b_init_clk_setup_sw(g); | 1533 | err = gm20b_init_clk_setup_sw(g); |
1585 | if (err) | 1534 | if (err) |
1586 | return err; | 1535 | return err; |
1587 | #endif | ||
1588 | 1536 | ||
1589 | mutex_lock(&clk->clk_mutex); | 1537 | mutex_lock(&clk->clk_mutex); |
1590 | clk->clk_hw_on = true; | 1538 | clk->clk_hw_on = true; |