summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/clk.c
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2018-04-18 15:59:00 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-06-15 20:47:31 -0400
commit2a2c16af5f9f1ccfc93a13e820d5381e5c881e92 (patch)
tree2e5d7b042270a649978e5bb540857012c85fb5b5 /drivers/gpu/nvgpu/os/linux/clk.c
parent98d996f4ffb0137d119b5849cae46d7b7e5693e1 (diff)
gpu: nvgpu: Move Linux files away from common
Move all Linux source code files to drivers/gpu/nvgpu/os/linux from drivers/gpu/nvgpu/common/linux. This changes the meaning of common to be OS independent. JIRA NVGPU-598 JIRA NVGPU-601 Change-Id: Ib7f2a43d3688bb0d0b7dcc48469a6783fd988ce9 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1747714 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/clk.c')
-rw-r--r--drivers/gpu/nvgpu/os/linux/clk.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/clk.c b/drivers/gpu/nvgpu/os/linux/clk.c
new file mode 100644
index 00000000..414b17c4
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/clk.c
@@ -0,0 +1,165 @@
1/*
2 * Linux clock support
3 *
4 * Copyright (c) 2017-2018, 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 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/clk.h>
20
21#include <soc/tegra/tegra-dvfs.h>
22#include <soc/tegra/tegra-bpmp-dvfs.h>
23
24#include "clk.h"
25#include "os_linux.h"
26#include "platform_gk20a.h"
27
28#include "gk20a/gk20a.h"
29
30static unsigned long nvgpu_linux_clk_get_rate(struct gk20a *g, u32 api_domain)
31{
32 struct gk20a_platform *platform = gk20a_get_platform(dev_from_gk20a(g));
33 unsigned long ret;
34
35 switch (api_domain) {
36 case CTRL_CLK_DOMAIN_GPCCLK:
37 if (g->clk.tegra_clk)
38 ret = g->clk.cached_rate ?
39 g->clk.cached_rate :
40 clk_get_rate(g->clk.tegra_clk);
41 else
42 ret = platform->cached_rate ?
43 platform->cached_rate :
44 clk_get_rate(platform->clk[0]);
45 break;
46 case CTRL_CLK_DOMAIN_PWRCLK:
47 ret = clk_get_rate(platform->clk[1]);
48 break;
49 default:
50 nvgpu_err(g, "unknown clock: %u", api_domain);
51 ret = 0;
52 break;
53 }
54
55 return ret;
56}
57
58static int nvgpu_linux_clk_set_rate(struct gk20a *g,
59 u32 api_domain, unsigned long rate)
60{
61 struct gk20a_platform *platform = gk20a_get_platform(dev_from_gk20a(g));
62 int ret;
63
64 switch (api_domain) {
65 case CTRL_CLK_DOMAIN_GPCCLK:
66 if (g->clk.tegra_clk) {
67 ret = clk_set_rate(g->clk.tegra_clk, rate);
68 if (!ret)
69 g->clk.cached_rate = rate;
70 } else {
71 ret = clk_set_rate(platform->clk[0], rate);
72 if (!ret)
73 platform->cached_rate = rate;
74 }
75 break;
76 case CTRL_CLK_DOMAIN_PWRCLK:
77 ret = clk_set_rate(platform->clk[1], rate);
78 break;
79 default:
80 nvgpu_err(g, "unknown clock: %u", api_domain);
81 ret = -EINVAL;
82 break;
83 }
84
85 return ret;
86}
87
88static unsigned long nvgpu_linux_get_fmax_at_vmin_safe(struct gk20a *g)
89{
90 struct gk20a_platform *platform = gk20a_get_platform(dev_from_gk20a(g));
91
92 /*
93 * On Tegra platforms with GPCPLL bus (gbus) GPU tegra_clk clock exposed
94 * to frequency governor is a shared user on the gbus. The latter can be
95 * accessed as GPU clock parent, and incorporate DVFS related data.
96 */
97 if (g->clk.tegra_clk)
98 return tegra_dvfs_get_fmax_at_vmin_safe_t(
99 clk_get_parent(g->clk.tegra_clk));
100
101 if (platform->maxmin_clk_id)
102 return tegra_bpmp_dvfs_get_fmax_at_vmin(
103 platform->maxmin_clk_id);
104
105 return 0;
106}
107
108static u32 nvgpu_linux_get_ref_clock_rate(struct gk20a *g)
109{
110 struct clk *c;
111
112 c = clk_get_sys("gpu_ref", "gpu_ref");
113 if (IS_ERR(c)) {
114 nvgpu_err(g, "failed to get GPCPLL reference clock");
115 return 0;
116 }
117
118 return clk_get_rate(c);
119}
120
121static int nvgpu_linux_predict_mv_at_hz_cur_tfloor(struct clk_gk20a *clk,
122 unsigned long rate)
123{
124 return tegra_dvfs_predict_mv_at_hz_cur_tfloor(
125 clk_get_parent(clk->tegra_clk), rate);
126}
127
128static unsigned long nvgpu_linux_get_maxrate(struct gk20a *g, u32 api_domain)
129{
130 int ret;
131
132 switch (api_domain) {
133 case CTRL_CLK_DOMAIN_GPCCLK:
134 ret = tegra_dvfs_get_maxrate(clk_get_parent(g->clk.tegra_clk));
135 break;
136 default:
137 nvgpu_err(g, "unknown clock: %u", api_domain);
138 ret = 0;
139 break;
140 }
141
142 return ret;
143}
144
145static int nvgpu_linux_prepare_enable(struct clk_gk20a *clk)
146{
147 return clk_prepare_enable(clk->tegra_clk);
148}
149
150static void nvgpu_linux_disable_unprepare(struct clk_gk20a *clk)
151{
152 clk_disable_unprepare(clk->tegra_clk);
153}
154
155void nvgpu_linux_init_clk_support(struct gk20a *g)
156{
157 g->ops.clk.get_rate = nvgpu_linux_clk_get_rate;
158 g->ops.clk.set_rate = nvgpu_linux_clk_set_rate;
159 g->ops.clk.get_fmax_at_vmin_safe = nvgpu_linux_get_fmax_at_vmin_safe;
160 g->ops.clk.get_ref_clock_rate = nvgpu_linux_get_ref_clock_rate;
161 g->ops.clk.predict_mv_at_hz_cur_tfloor = nvgpu_linux_predict_mv_at_hz_cur_tfloor;
162 g->ops.clk.get_maxrate = nvgpu_linux_get_maxrate;
163 g->ops.clk.prepare_enable = nvgpu_linux_prepare_enable;
164 g->ops.clk.disable_unprepare = nvgpu_linux_disable_unprepare;
165}