summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp106/xve_gp106.c
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-09-09 19:59:21 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:49 -0500
commit82bbd0cd5d3d82bacc5023830d0eeb21065dd5f2 (patch)
tree50cac71c5516404760b163a7de3675a6b526c797 /drivers/gpu/nvgpu/gp106/xve_gp106.c
parent4afc6a1659ec058fd44953ccff7a1030275bcc92 (diff)
gpu: nvgpu: implement PCIe Gen2 frequency swap
Implement the basic code to swap between PCIe bus speeds for the GPU. Other GPUs are not supported yet. Currently the following speeds can be used: Gen1 (2.5 MTPS) Gen2 (5.0 MTPS) gp106 on DPX2 does not support Gen3. JIRA DNVGPU-89 Change-Id: I8bebfc9d99b682bdcff406fa56e806097dd51499 Reviewed-on: http://git-master/r/1218177 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1227925 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gp106/xve_gp106.c')
-rw-r--r--drivers/gpu/nvgpu/gp106/xve_gp106.c623
1 files changed, 623 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp106/xve_gp106.c b/drivers/gpu/nvgpu/gp106/xve_gp106.c
new file mode 100644
index 00000000..23a02fbd
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/xve_gp106.c
@@ -0,0 +1,623 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/delay.h>
18#include <linux/kernel.h>
19#include <linux/debugfs.h>
20
21#include "gk20a/gk20a.h"
22#include "gm206/bios_gm206.h"
23#include "gp106/xve_gp106.h"
24
25#include "gp106/hw_xp_gp106.h"
26#include "gp106/hw_xve_gp106.h"
27
28/**
29 * Init a timer and place the timeout data in @timeout.
30 */
31static void init_timeout(u32 timeout_ms, u32 *timeout)
32{
33 *timeout = jiffies + msecs_to_jiffies(timeout_ms);
34}
35
36/**
37 * Returns 1 if the current time is after @timeout i.e: the timer timed
38 * out. Returns 0 if the timer still has time left.
39 */
40static int check_timeout(u32 *timeout)
41{
42 unsigned long now = jiffies;
43 unsigned long timeout_l = (unsigned long)*timeout;
44
45 if (time_after(now, timeout_l))
46 return 1;
47
48 return 0;
49}
50
51static void xve_xve_writel_gp106(struct gk20a *g, u32 reg, u32 val)
52{
53 gk20a_writel(g, NV_PCFG + reg, val);
54}
55
56static u32 xve_xve_readl_gp106(struct gk20a *g, u32 reg)
57{
58 return gk20a_readl(g, NV_PCFG + reg);
59}
60
61/**
62 * Places one of:
63 *
64 * %GPU_XVE_SPEED_2P5
65 * %GPU_XVE_SPEED_5P0
66 * %GPU_XVE_SPEED_8P0
67 *
68 * in the u32 pointed to by @xve_link_speed. If for some reason an unknown PCIe
69 * bus speed is detected then *@xve_link_speed is not touched and -ENODEV is
70 * returned.
71 */
72static int xve_get_speed_gp106(struct gk20a *g, u32 *xve_link_speed)
73{
74 u32 status;
75 u32 link_speed, real_link_speed = 0;
76
77 status = g->ops.xve.xve_readl(g, xve_link_control_status_r());
78
79 link_speed = xve_link_control_status_link_speed_v(status);
80
81 /*
82 * Can't use a switch statement becuase switch statements dont work with
83 * function calls.
84 */
85 if (link_speed == xve_link_control_status_link_speed_link_speed_2p5_v())
86 real_link_speed = GPU_XVE_SPEED_2P5;
87 if (link_speed == xve_link_control_status_link_speed_link_speed_5p0_v())
88 real_link_speed = GPU_XVE_SPEED_5P0;
89 if (link_speed == xve_link_control_status_link_speed_link_speed_8p0_v())
90 real_link_speed = GPU_XVE_SPEED_8P0;
91
92 if (!real_link_speed) {
93 pr_warn("%s: Unknown PCIe bus speed!\n", __func__);
94 return -ENODEV;
95 }
96
97 *xve_link_speed = real_link_speed;
98 return 0;
99}
100
101/**
102 * Set the mask for L0s in the XVE.
103 *
104 * When @status is non-zero the mask for L0s is set which _disables_ L0s. When
105 * @status is zero L0s is no longer masked and may be enabled.
106 */
107static void set_xve_l0s_mask(struct gk20a *g, bool status)
108{
109 u32 xve_priv;
110 u32 status_bit = status ? 1 : 0;
111
112 xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r());
113
114 xve_priv = set_field(xve_priv,
115 xve_priv_xv_cya_l0s_enable_m(),
116 xve_priv_xv_cya_l0s_enable_f(status_bit));
117
118 g->ops.xve.xve_writel(g, xve_priv_xv_r(), xve_priv);
119}
120
121/**
122 * Set the mask for L1 in the XVE.
123 *
124 * When @status is non-zero the mask for L1 is set which _disables_ L0s. When
125 * @status is zero L1 is no longer masked and may be enabled.
126 */
127static void set_xve_l1_mask(struct gk20a *g, int status)
128{
129 u32 xve_priv;
130 u32 status_bit = status ? 1 : 0;
131
132 xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r());
133
134 xve_priv = set_field(xve_priv,
135 xve_priv_xv_cya_l1_enable_m(),
136 xve_priv_xv_cya_l1_enable_f(status_bit));
137
138 g->ops.xve.xve_writel(g, xve_priv_xv_r(), xve_priv);
139}
140
141/**
142 * When doing the speed change disable power saving features.
143 */
144static void disable_aspm_gp106(struct gk20a *g)
145{
146 u32 xve_priv;
147
148 xve_priv = g->ops.xve.xve_readl(g, xve_priv_xv_r());
149
150 /*
151 * Store prior ASPM state so we can restore it later on.
152 */
153 g->xve_l0s = xve_priv_xv_cya_l0s_enable_v(xve_priv);
154 g->xve_l1 = xve_priv_xv_cya_l1_enable_v(xve_priv);
155
156 set_xve_l0s_mask(g, true);
157 set_xve_l1_mask(g, true);
158}
159
160/**
161 * Restore the state saved by disable_aspm_gp106().
162 */
163static void enable_aspm_gp106(struct gk20a *g)
164{
165 set_xve_l0s_mask(g, g->xve_l0s);
166 set_xve_l1_mask(g, g->xve_l1);
167}
168
169/*
170 * Error checking is done in xve_set_speed_gp106.
171 */
172static int __do_xve_set_speed_gp106(struct gk20a *g, u32 next_link_speed)
173{
174 u32 current_link_speed, new_link_speed;
175 u32 dl_mgr, saved_dl_mgr;
176 u32 pl_link_config;
177 u32 link_control_status, link_speed_setting, link_width;
178 u32 timeout;
179 int attempts = 10, err_status = 0;
180
181 g->ops.xve.get_speed(g, &current_link_speed);
182 xv_sc_dbg(PRE_CHANGE, "Executing PCIe link change.");
183 xv_sc_dbg(PRE_CHANGE, " Current speed: %s",
184 xve_speed_to_str(current_link_speed));
185 xv_sc_dbg(PRE_CHANGE, " Next speed: %s",
186 xve_speed_to_str(next_link_speed));
187 xv_sc_dbg(PRE_CHANGE, " PL_LINK_CONFIG: 0x%08x",
188 gk20a_readl(g, xp_pl_link_config_r(0)));
189
190 xv_sc_dbg(DISABLE_ASPM, "Disabling ASPM...");
191 disable_aspm_gp106(g);
192 xv_sc_dbg(DISABLE_ASPM, " Done!");
193
194 xv_sc_dbg(DL_SAFE_MODE, "Putting DL in safe mode...");
195 saved_dl_mgr = gk20a_readl(g, xp_dl_mgr_r(0));
196
197 /*
198 * Put the DL in safe mode.
199 */
200 dl_mgr = saved_dl_mgr;
201 dl_mgr |= xp_dl_mgr_safe_timing_f(1);
202 gk20a_writel(g, xp_dl_mgr_r(0), dl_mgr);
203 xv_sc_dbg(DL_SAFE_MODE, " Done!");
204
205 init_timeout(GPU_XVE_TIMEOUT_MS, &timeout);
206
207 xv_sc_dbg(CHECK_LINK, "Checking for link idle...");
208 while (1) {
209 pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0));
210 if ((xp_pl_link_config_ltssm_status_f(pl_link_config) ==
211 xp_pl_link_config_ltssm_status_idle_v()) &&
212 (xp_pl_link_config_ltssm_directive_f(pl_link_config) ==
213 xp_pl_link_config_ltssm_directive_normal_operations_v()))
214 break;
215
216 if (check_timeout(&timeout)) {
217 err_status = -ETIMEDOUT;
218 break;
219 }
220 }
221
222 if (err_status == -ETIMEDOUT)
223 /* TODO: debug message. */
224 goto done;
225
226 xv_sc_dbg(CHECK_LINK, " Done");
227
228 xv_sc_dbg(LINK_SETTINGS, "Preparing next link settings");
229 pl_link_config &= ~xp_pl_link_config_max_link_rate_m();
230 switch (next_link_speed) {
231 case GPU_XVE_SPEED_2P5:
232 link_speed_setting =
233 xve_link_control_status_link_speed_link_speed_2p5_v();
234 pl_link_config |= xp_pl_link_config_max_link_rate_f(
235 xp_pl_link_config_max_link_rate_2500_mtps_v());
236 break;
237 case GPU_XVE_SPEED_5P0:
238 link_speed_setting =
239 xve_link_control_status_link_speed_link_speed_5p0_v();
240 pl_link_config |= xp_pl_link_config_max_link_rate_f(
241 xp_pl_link_config_max_link_rate_5000_mtps_v());
242 break;
243 case GPU_XVE_SPEED_8P0:
244 link_speed_setting =
245 xve_link_control_status_link_speed_link_speed_8p0_v();
246 pl_link_config |= xp_pl_link_config_max_link_rate_f(
247 xp_pl_link_config_max_link_rate_8000_mtps_v());
248 break;
249 default:
250 BUG(); /* Should never be hit. */
251 }
252
253 link_control_status =
254 g->ops.xve.xve_readl(g, xve_link_control_status_r());
255 link_width = xve_link_control_status_link_width_v(link_control_status);
256
257 pl_link_config &= ~xp_pl_link_config_target_tx_width_m();
258
259 /* Can't use a switch due to oddities in register definitions. */
260 if (link_width == xve_link_control_status_link_width_x1_v())
261 pl_link_config |= xp_pl_link_config_target_tx_width_f(
262 xp_pl_link_config_target_tx_width_x1_v());
263 else if (link_width == xve_link_control_status_link_width_x2_v())
264 pl_link_config |= xp_pl_link_config_target_tx_width_f(
265 xp_pl_link_config_target_tx_width_x2_v());
266 else if (link_width == xve_link_control_status_link_width_x4_v())
267 pl_link_config |= xp_pl_link_config_target_tx_width_f(
268 xp_pl_link_config_target_tx_width_x4_v());
269 else if (link_width == xve_link_control_status_link_width_x8_v())
270 pl_link_config |= xp_pl_link_config_target_tx_width_f(
271 xp_pl_link_config_target_tx_width_x8_v());
272 else if (link_width == xve_link_control_status_link_width_x16_v())
273 pl_link_config |= xp_pl_link_config_target_tx_width_f(
274 xp_pl_link_config_target_tx_width_x16_v());
275 else
276 BUG();
277
278 xv_sc_dbg(LINK_SETTINGS, " pl_link_config = 0x%08x", pl_link_config);
279 xv_sc_dbg(LINK_SETTINGS, " Done");
280
281 xv_sc_dbg(EXEC_CHANGE, "Running link speed change...");
282
283 init_timeout(GPU_XVE_TIMEOUT_MS, &timeout);
284 while (1) {
285 gk20a_writel(g, xp_pl_link_config_r(0), pl_link_config);
286 if (pl_link_config ==
287 gk20a_readl(g, xp_pl_link_config_r(0)))
288 break;
289
290 if (check_timeout(&timeout)) {
291 err_status = -ETIMEDOUT;
292 break;
293 }
294 }
295
296 if (err_status == -ETIMEDOUT)
297 goto done;
298
299 xv_sc_dbg(EXEC_CHANGE, " Wrote PL_LINK_CONFIG.");
300
301 pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0));
302
303 do {
304 pl_link_config = set_field(pl_link_config,
305 xp_pl_link_config_ltssm_directive_m(),
306 xp_pl_link_config_ltssm_directive_f(
307 xp_pl_link_config_ltssm_directive_change_speed_v()));
308
309 xv_sc_dbg(EXEC_CHANGE, " Executing change (0x%08x)!",
310 pl_link_config);
311 gk20a_writel(g, xp_pl_link_config_r(0), pl_link_config);
312
313 /*
314 * Read NV_XP_PL_LINK_CONFIG until the link has swapped to
315 * the target speed.
316 */
317 init_timeout(GPU_XVE_TIMEOUT_MS, &timeout);
318 while (1) {
319 pl_link_config = gk20a_readl(g, xp_pl_link_config_r(0));
320 if (pl_link_config != 0xfffffff &&
321 (xp_pl_link_config_ltssm_status_f(pl_link_config) ==
322 xp_pl_link_config_ltssm_status_idle_v()) &&
323 (xp_pl_link_config_ltssm_directive_f(pl_link_config) ==
324 xp_pl_link_config_ltssm_directive_normal_operations_v()))
325 break;
326
327 if (check_timeout(&timeout)) {
328 err_status = -ETIMEDOUT;
329 xv_sc_dbg(EXEC_CHANGE, " timeout; pl_link_config = 0x%x",
330 pl_link_config);
331 break;
332 }
333 }
334
335 xv_sc_dbg(EXEC_CHANGE, " Change done... Checking status");
336
337 if (pl_link_config == 0xffffffff) {
338 WARN(1, "GPU fell of PCI bus!?");
339
340 /*
341 * The rest of the driver is probably about to
342 * explode...
343 */
344 BUG();
345 }
346
347 link_control_status =
348 g->ops.xve.xve_readl(g, xve_link_control_status_r());
349 xv_sc_dbg(EXEC_CHANGE, " target %d vs current %d",
350 link_speed_setting,
351 xve_link_control_status_link_speed_v(link_control_status));
352
353 if (err_status == -ETIMEDOUT)
354 xv_sc_dbg(EXEC_CHANGE, " Oops timed out?");
355 } while (attempts-- > 0 &&
356 link_speed_setting !=
357 xve_link_control_status_link_speed_v(link_control_status));
358
359 xv_sc_dbg(EXEC_VERIF, "Verifying speed change...");
360
361 /*
362 * Check that the new link speed is actually active. If we failed to
363 * change to the new link speed then return to the link speed setting
364 * pre-speed change.
365 */
366 new_link_speed = xve_link_control_status_link_speed_v(
367 link_control_status);
368 if (link_speed_setting != new_link_speed) {
369 u32 link_config = gk20a_readl(g, xp_pl_link_config_r(0));
370
371 xv_sc_dbg(EXEC_VERIF, " Current and target speeds mismatch!");
372 xv_sc_dbg(EXEC_VERIF, " LINK_CONTROL_STATUS: 0x%08x",
373 g->ops.xve.xve_readl(g, xve_link_control_status_r()));
374 xv_sc_dbg(EXEC_VERIF, " Link speed is %s - should be %s",
375 xve_speed_to_str(new_link_speed),
376 xve_speed_to_str(link_speed_setting));
377
378 link_config &= ~xp_pl_link_config_max_link_rate_m();
379 if (new_link_speed ==
380 xve_link_control_status_link_speed_link_speed_2p5_v())
381 link_config |= xp_pl_link_config_max_link_rate_f(
382 xp_pl_link_config_max_link_rate_2500_mtps_v());
383 else if (new_link_speed ==
384 xve_link_control_status_link_speed_link_speed_5p0_v())
385 link_config |= xp_pl_link_config_max_link_rate_f(
386 xp_pl_link_config_max_link_rate_5000_mtps_v());
387 else if (new_link_speed ==
388 xve_link_control_status_link_speed_link_speed_8p0_v())
389 link_config |= xp_pl_link_config_max_link_rate_f(
390 xp_pl_link_config_max_link_rate_8000_mtps_v());
391 else
392 link_config |= xp_pl_link_config_max_link_rate_f(
393 xp_pl_link_config_max_link_rate_2500_mtps_v());
394
395 gk20a_writel(g, xp_pl_link_config_r(0), link_config);
396 err_status = -ENODEV;
397 } else {
398 xv_sc_dbg(EXEC_VERIF, " Current and target speeds match!");
399 err_status = 0;
400 }
401
402done:
403 /* Restore safe timings. */
404 xv_sc_dbg(CLEANUP, "Restoring saved DL settings...");
405 gk20a_writel(g, xp_dl_mgr_r(0), saved_dl_mgr);
406 xv_sc_dbg(CLEANUP, " Done");
407
408 xv_sc_dbg(CLEANUP, "Re-enabling ASPM settings...");
409 enable_aspm_gp106(g);
410 xv_sc_dbg(CLEANUP, " Done");
411
412 return err_status;
413}
414
415/**
416 * Sets the PCIe link speed to @xve_link_speed which must be one of:
417 *
418 * %GPU_XVE_SPEED_2P5
419 * %GPU_XVE_SPEED_5P0
420 * %GPU_XVE_SPEED_8P0
421 *
422 * If an error is encountered an appropriate error will be returned.
423 */
424static int xve_set_speed_gp106(struct gk20a *g, u32 next_link_speed)
425{
426 u32 current_link_speed;
427 int err;
428
429 if ((next_link_speed & GPU_XVE_SPEED_MASK) == 0)
430 return -EINVAL;
431
432 err = g->ops.xve.get_speed(g, &current_link_speed);
433 if (err)
434 return err;
435
436 /* No-op. */
437 if (current_link_speed == next_link_speed)
438 return 0;
439
440 return __do_xve_set_speed_gp106(g, next_link_speed);
441}
442
443/**
444 * Places a bitmask of available speeds for gp106 in @speed_mask.
445 */
446static void xve_available_speeds_gp106(struct gk20a *g, u32 *speed_mask)
447{
448 *speed_mask = GPU_XVE_SPEED_2P5 | GPU_XVE_SPEED_5P0;
449}
450
451static ssize_t xve_link_speed_write(struct file *filp,
452 const char __user *buff,
453 size_t len, loff_t *off)
454{
455 struct gk20a *g = ((struct seq_file *)filp->private_data)->private;
456 char kbuff[16];
457 u32 buff_size, check_len;
458 u32 link_speed = 0;
459 int ret;
460
461 buff_size = min_t(size_t, 16, len);
462
463 memset(kbuff, 0, 16);
464 if (copy_from_user(kbuff, buff, buff_size))
465 return -EFAULT;
466
467 check_len = strlen("Gen1");
468 if (strncmp(kbuff, "Gen1", check_len) == 0)
469 link_speed = GPU_XVE_SPEED_2P5;
470 else if (strncmp(kbuff, "Gen2", check_len) == 0)
471 link_speed = GPU_XVE_SPEED_5P0;
472 else if (strncmp(kbuff, "Gen3", check_len) == 0)
473 link_speed = GPU_XVE_SPEED_8P0;
474 else
475 gk20a_err(g->dev, "%s: Unknown PCIe speed: %s\n",
476 __func__, kbuff);
477
478 if (!link_speed)
479 return -EINVAL;
480
481 /* Brief pause... To help rate limit this. */
482 msleep(250);
483
484 /*
485 * And actually set the speed. Yay.
486 */
487 ret = g->ops.xve.set_speed(g, link_speed);
488 if (ret)
489 return ret;
490
491 return len;
492}
493
494static int xve_link_speed_show(struct seq_file *s, void *unused)
495{
496 struct gk20a *g = s->private;
497 u32 speed;
498 int err;
499
500 err = g->ops.xve.get_speed(g, &speed);
501 if (err)
502 return err;
503
504 seq_printf(s, "Current PCIe speed:\n %s\n", xve_speed_to_str(speed));
505
506 return 0;
507}
508
509static int xve_link_speed_open(struct inode *inode, struct file *file)
510{
511 return single_open(file, xve_link_speed_show, inode->i_private);
512}
513
514static const struct file_operations xve_link_speed_fops = {
515 .open = xve_link_speed_open,
516 .read = seq_read,
517 .write = xve_link_speed_write,
518 .llseek = seq_lseek,
519 .release = single_release,
520};
521
522static int xve_available_speeds_show(struct seq_file *s, void *unused)
523{
524 struct gk20a *g = s->private;
525 u32 available_speeds;
526
527 g->ops.xve.available_speeds(g, &available_speeds);
528
529 seq_puts(s, "Available PCIe bus speeds:\n");
530 if (available_speeds & GPU_XVE_SPEED_2P5)
531 seq_puts(s, " Gen1\n");
532 if (available_speeds & GPU_XVE_SPEED_5P0)
533 seq_puts(s, " Gen2\n");
534 if (available_speeds & GPU_XVE_SPEED_8P0)
535 seq_puts(s, " Gen3\n");
536
537 return 0;
538}
539
540static int xve_available_speeds_open(struct inode *inode, struct file *file)
541{
542 return single_open(file, xve_available_speeds_show, inode->i_private);
543}
544
545static const struct file_operations xve_available_speeds_fops = {
546 .open = xve_available_speeds_open,
547 .read = seq_read,
548 .llseek = seq_lseek,
549 .release = single_release,
550};
551
552static int xve_link_control_status_show(struct seq_file *s, void *unused)
553{
554 struct gk20a *g = s->private;
555 u32 link_status;
556
557 link_status = g->ops.xve.xve_readl(g, xve_link_control_status_r());
558 seq_printf(s, "0x%08x\n", link_status);
559
560 return 0;
561}
562
563static int xve_link_control_status_open(struct inode *inode, struct file *file)
564{
565 return single_open(file, xve_link_control_status_show, inode->i_private);
566}
567
568static const struct file_operations xve_link_control_status_fops = {
569 .open = xve_link_control_status_open,
570 .read = seq_read,
571 .llseek = seq_lseek,
572 .release = single_release,
573};
574
575static int xve_sw_init_gp106(struct device *dev)
576{
577 int err = -ENODEV;
578#ifdef CONFIG_DEBUG_FS
579 struct gk20a *g = get_gk20a(dev);
580 struct gk20a_platform *plat = gk20a_get_platform(dev);
581 struct dentry *gpu_root = plat->debugfs;
582
583 g->debugfs_xve = debugfs_create_dir("xve", gpu_root);
584 if (IS_ERR_OR_NULL(g->debugfs_xve))
585 goto fail;
586
587 /*
588 * These are just debug nodes. If they fail to get made it's not worth
589 * worrying the higher level SW.
590 */
591 debugfs_create_file("link_speed", S_IRUGO,
592 g->debugfs_xve, g,
593 &xve_link_speed_fops);
594 debugfs_create_file("available_speeds", S_IRUGO,
595 g->debugfs_xve, g,
596 &xve_available_speeds_fops);
597 debugfs_create_file("link_control_status", S_IRUGO,
598 g->debugfs_xve, g,
599 &xve_link_control_status_fops);
600
601 err = 0;
602fail:
603 return err;
604#else
605 return err;
606#endif
607}
608
609/*
610 * Init the HAL functions and what not. xve_sw_init_gp106() is for initializing
611 * all the other stuff like debugfs nodes, etc.
612 */
613int gp106_init_xve_ops(struct gpu_ops *gops)
614{
615 gops->xve.sw_init = xve_sw_init_gp106;
616 gops->xve.get_speed = xve_get_speed_gp106;
617 gops->xve.set_speed = xve_set_speed_gp106;
618 gops->xve.available_speeds = xve_available_speeds_gp106;
619 gops->xve.xve_readl = xve_xve_readl_gp106;
620 gops->xve.xve_writel = xve_xve_writel_gp106;
621
622 return 0;
623}