summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/clk_vgpu.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/clk_vgpu.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/clk_vgpu.c b/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
new file mode 100644
index 00000000..fe5533b6
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
@@ -0,0 +1,130 @@
1/*
2 * Virtualized GPU Clock Interface
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16#include "vgpu/vgpu.h"
17#include "vgpu/clk_vgpu.h"
18
19static unsigned long
20vgpu_freq_table[TEGRA_VGPU_GPU_FREQ_TABLE_SIZE];
21
22static unsigned long vgpu_clk_get_rate(struct gk20a *g, u32 api_domain)
23{
24 struct tegra_vgpu_cmd_msg msg = {};
25 struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate;
26 int err;
27 unsigned long ret = 0;
28
29 gk20a_dbg_fn("");
30
31 switch (api_domain) {
32 case CTRL_CLK_DOMAIN_GPCCLK:
33 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_CLK_RATE;
34 msg.handle = vgpu_get_handle(g);
35 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
36 err = err ? err : msg.ret;
37 if (err)
38 nvgpu_err(g, "%s failed - %d", __func__, err);
39 else
40 /* return frequency in Hz */
41 ret = p->rate * 1000;
42 break;
43 case CTRL_CLK_DOMAIN_PWRCLK:
44 nvgpu_err(g, "unsupported clock: %u", api_domain);
45 break;
46 default:
47 nvgpu_err(g, "unknown clock: %u", api_domain);
48 break;
49 }
50
51 return ret;
52}
53
54static int vgpu_clk_set_rate(struct gk20a *g,
55 u32 api_domain, unsigned long rate)
56{
57 struct tegra_vgpu_cmd_msg msg = {};
58 struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate;
59 int err = -EINVAL;
60
61 gk20a_dbg_fn("");
62
63 switch (api_domain) {
64 case CTRL_CLK_DOMAIN_GPCCLK:
65 msg.cmd = TEGRA_VGPU_CMD_SET_GPU_CLK_RATE;
66 msg.handle = vgpu_get_handle(g);
67
68 /* server dvfs framework requires frequency in kHz */
69 p->rate = (u32)(rate / 1000);
70 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
71 err = err ? err : msg.ret;
72 if (err)
73 nvgpu_err(g, "%s failed - %d", __func__, err);
74 break;
75 case CTRL_CLK_DOMAIN_PWRCLK:
76 nvgpu_err(g, "unsupported clock: %u", api_domain);
77 break;
78 default:
79 nvgpu_err(g, "unknown clock: %u", api_domain);
80 break;
81 }
82
83 return err;
84}
85
86void vgpu_init_clk_support(struct gk20a *g)
87{
88 g->ops.clk.get_rate = vgpu_clk_get_rate;
89 g->ops.clk.set_rate = vgpu_clk_set_rate;
90}
91
92long vgpu_clk_round_rate(struct device *dev, unsigned long rate)
93{
94 /* server will handle frequency rounding */
95 return rate;
96}
97
98int vgpu_clk_get_freqs(struct device *dev,
99 unsigned long **freqs, int *num_freqs)
100{
101 struct gk20a_platform *platform = gk20a_get_platform(dev);
102 struct gk20a *g = platform->g;
103 struct tegra_vgpu_cmd_msg msg = {};
104 struct tegra_vgpu_get_gpu_freq_table_params *p =
105 &msg.params.get_gpu_freq_table;
106 unsigned int i;
107 int err;
108
109 gk20a_dbg_fn("");
110
111 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_FREQ_TABLE;
112 msg.handle = vgpu_get_handle(g);
113
114 p->num_freqs = TEGRA_VGPU_GPU_FREQ_TABLE_SIZE;
115 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
116 err = err ? err : msg.ret;
117 if (err) {
118 nvgpu_err(g, "%s failed - %d", __func__, err);
119 return err;
120 }
121
122 /* return frequency in Hz */
123 for (i = 0; i < p->num_freqs; i++)
124 vgpu_freq_table[i] = p->freqs[i] * 1000;
125
126 *freqs = vgpu_freq_table;
127 *num_freqs = p->num_freqs;
128
129 return 0;
130}