summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/Makefile.nvgpu-t18x2
-rw-r--r--drivers/gpu/nvgpu/clk/clk_arb.c387
-rw-r--r--drivers/gpu/nvgpu/clk/clk_arb.h63
-rw-r--r--drivers/gpu/nvgpu/gp106/clk_arb_gp106.c95
-rw-r--r--drivers/gpu/nvgpu/gp106/clk_arb_gp106.h21
-rw-r--r--drivers/gpu/nvgpu/gp106/clk_gp106.c1
-rw-r--r--drivers/gpu/nvgpu/gp106/hal_gp106.c2
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.c40
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.h9
9 files changed, 618 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
index bb19d595..a096a438 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
@@ -38,11 +38,13 @@ nvgpu-y += \
38 $(nvgpu-t18x)/clk/clk_domain.o \ 38 $(nvgpu-t18x)/clk/clk_domain.o \
39 $(nvgpu-t18x)/clk/clk_prog.o \ 39 $(nvgpu-t18x)/clk/clk_prog.o \
40 $(nvgpu-t18x)/clk/clk_vf_point.o \ 40 $(nvgpu-t18x)/clk/clk_vf_point.o \
41 $(nvgpu-t18x)/clk/clk_arb.o \
41 $(nvgpu-t18x)/perf/vfe_var.o \ 42 $(nvgpu-t18x)/perf/vfe_var.o \
42 $(nvgpu-t18x)/perf/vfe_equ.o \ 43 $(nvgpu-t18x)/perf/vfe_equ.o \
43 $(nvgpu-t18x)/perf/perf.o \ 44 $(nvgpu-t18x)/perf/perf.o \
44 $(nvgpu-t18x)/clk/clk.o \ 45 $(nvgpu-t18x)/clk/clk.o \
45 $(nvgpu-t18x)/gp106/clk_gp106.o \ 46 $(nvgpu-t18x)/gp106/clk_gp106.o \
47 $(nvgpu-t18x)/gp106/clk_arb_gp106.o \
46 $(nvgpu-t18x)/gp106/gp106_gating_reglist.o \ 48 $(nvgpu-t18x)/gp106/gp106_gating_reglist.o \
47 $(nvgpu-t18x)/gp106/xve_gp106.o \ 49 $(nvgpu-t18x)/gp106/xve_gp106.o \
48 $(nvgpu-t18x)/gp106/therm_gp106.o \ 50 $(nvgpu-t18x)/gp106/therm_gp106.o \
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c
new file mode 100644
index 00000000..1d02c7d7
--- /dev/null
+++ b/drivers/gpu/nvgpu/clk/clk_arb.c
@@ -0,0 +1,387 @@
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
14#include "gk20a/gk20a.h"
15
16#include <linux/cdev.h>
17#include <linux/file.h>
18#include <linux/anon_inodes.h>
19#include <linux/nvgpu.h>
20#include <linux/bitops.h>
21
22#include "clk/clk_arb.h"
23
24static int nvgpu_clk_arb_release_session_dev(struct inode *inode, struct file *filp);
25static unsigned int nvgpu_clk_arb_poll_session_dev(struct file *filp, poll_table *wait);
26
27static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work);
28
29struct nvgpu_clk_arb {
30 struct mutex wlock;
31 struct mutex users_lock;
32 struct list_head users;
33 u32 gpc2clk_current_mhz;
34 u32 gpc2clk_target_mhz;
35 u32 gpc2clk_default_mhz;
36 u32 mclk_current_mhz;
37 u32 mclk_target_mhz;
38 u32 mclk_default_mhz;
39 atomic_t usercount;
40 struct work_struct update_fn_work;
41
42 atomic_t req_nr; /* for allocations */
43 atomic_t last_req_nr; /* last completed by arbiter */
44};
45
46struct nvgpu_clk_session {
47 struct gk20a *g;
48 int fd;
49 atomic_t req_nr;
50 struct kref refcount;
51 wait_queue_head_t readout_wq;
52 atomic_t poll_mask;
53 struct list_head user;
54 u32 gpc2clk_target_mhz;
55 u32 mclk_target_mhz;
56};
57
58const struct file_operations clk_dev_ops = {
59 .owner = THIS_MODULE,
60 .release = nvgpu_clk_arb_release_session_dev,
61 .poll = nvgpu_clk_arb_poll_session_dev,
62};
63
64int nvgpu_clk_arb_init_arbiter(struct gk20a *g)
65{
66 struct nvgpu_clk_arb *arb;
67 u16 default_mhz;
68 int err;
69
70 gk20a_dbg_fn("");
71
72 if (!g->ops.clk_arb.get_arbiter_clk_domains)
73 return 0;
74
75 arb = kzalloc(sizeof(struct nvgpu_clk_arb), GFP_KERNEL);
76 if (!arb)
77 return -ENOMEM;
78
79 g->clk_arb = arb;
80
81 mutex_init(&arb->wlock);
82 mutex_init(&arb->users_lock);
83
84 err = g->ops.clk_arb.get_arbiter_clk_default(g,
85 NVGPU_GPU_CLK_DOMAIN_MCLK, &default_mhz);
86 if (err)
87 return -EINVAL;
88
89 arb->mclk_target_mhz = default_mhz;
90 arb->mclk_current_mhz = default_mhz;
91 arb->mclk_default_mhz = default_mhz;
92
93 err = g->ops.clk_arb.get_arbiter_clk_default(g,
94 NVGPU_GPU_CLK_DOMAIN_GPC2CLK, &default_mhz);
95 if (err)
96 return -EINVAL;
97
98 arb->gpc2clk_target_mhz = default_mhz;
99 arb->gpc2clk_current_mhz = default_mhz;
100 arb->gpc2clk_default_mhz = default_mhz;
101
102 atomic_set(&arb->usercount, 0);
103 atomic_set(&arb->req_nr, 0);
104 atomic_set(&arb->last_req_nr, 0);
105
106 INIT_LIST_HEAD(&arb->users);
107 INIT_WORK(&arb->update_fn_work, nvgpu_clk_arb_run_arbiter_cb);
108
109 return 0;
110}
111
112void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g)
113{
114 kfree(g->clk_arb);
115}
116
117
118int nvgpu_clk_arb_install_session_fd(struct gk20a *g,
119 struct nvgpu_clk_session *session)
120{
121 struct file *file;
122 char *name;
123 int fd;
124 int err;
125
126 gk20a_dbg_fn("");
127
128 if (session->fd >= 0)
129 goto done;
130
131 fd = get_unused_fd_flags(O_RDWR);
132 if (fd < 0)
133 return fd;
134
135 name = kasprintf(GFP_KERNEL, "%s-clk-fd%d", dev_name(g->dev), fd);
136 file = anon_inode_getfile(name, &clk_dev_ops, session, O_RDWR);
137 kfree(name);
138 if (IS_ERR(file)) {
139 err = PTR_ERR(file);
140 goto clean_up_fd;
141 }
142
143 BUG_ON(file->private_data != session);
144
145 fd_install(fd, file);
146 kref_get(&session->refcount);
147
148 session->fd = fd;
149done:
150 return session->fd;
151
152clean_up_fd:
153 put_unused_fd(fd);
154
155 return err;
156}
157
158int nvgpu_clk_arb_init_session(struct gk20a *g,
159 struct nvgpu_clk_session **_session)
160{
161 struct nvgpu_clk_arb *arb = g->clk_arb;
162 struct nvgpu_clk_session *session = *(_session);
163
164 gk20a_dbg_fn("");
165
166 *_session = NULL;
167
168 if (!g->ops.clk_arb.get_arbiter_clk_domains)
169 return 0;
170
171 session = kzalloc(sizeof(struct nvgpu_clk_session), GFP_KERNEL);
172 if (!session)
173 return -ENOMEM;
174 session->g = g;
175 session->fd = -1;
176
177 kref_init(&session->refcount);
178 init_waitqueue_head(&session->readout_wq);
179
180 atomic_set(&session->poll_mask, 0);
181 atomic_set(&session->req_nr, 0);
182
183 mutex_lock(&arb->users_lock);
184 list_add_tail(&session->user, &arb->users);
185 mutex_unlock(&arb->users_lock);
186 atomic_inc(&arb->usercount);
187
188 mutex_lock(&arb->wlock);
189 session->mclk_target_mhz = arb->mclk_default_mhz;
190 session->gpc2clk_target_mhz = arb->gpc2clk_default_mhz;
191 mutex_unlock(&arb->wlock);
192
193 *_session = session;
194
195 return 0;
196}
197
198void nvgpu_clk_arb_free_session(struct kref *refcount)
199{
200 struct nvgpu_clk_session *session = container_of(refcount,
201 struct nvgpu_clk_session, refcount);
202 struct gk20a *g = session->g;
203 struct nvgpu_clk_arb *arb = g->clk_arb;
204
205 mutex_lock(&arb->users_lock);
206 list_del_init(&session->user);
207 mutex_unlock(&arb->users_lock);
208
209 if (atomic_dec_and_test(&arb->usercount))
210 nvgpu_clk_arb_apply_session_constraints(g, NULL);
211
212 kfree(session);
213}
214
215void nvgpu_clk_arb_cleanup_session(struct gk20a *g,
216 struct nvgpu_clk_session *session)
217{
218 kref_put(&session->refcount, nvgpu_clk_arb_free_session);
219}
220
221static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work)
222{
223 struct nvgpu_clk_arb *arb =
224 container_of(work, struct nvgpu_clk_arb, update_fn_work);
225 struct nvgpu_clk_session *session;
226
227 mutex_lock(&arb->wlock);
228
229 /* TODO: loop up higher or equal VF points */
230
231 arb->mclk_current_mhz = arb->mclk_target_mhz;
232 arb->gpc2clk_current_mhz = arb->gpc2clk_target_mhz;
233
234 /* TODO: actually program the clocks */
235
236 atomic_set(&arb->last_req_nr, atomic_read(&arb->req_nr));
237 mutex_unlock(&arb->wlock);
238
239 mutex_lock(&arb->users_lock);
240 list_for_each_entry(session, &arb->users, user) {
241 atomic_set(&session->poll_mask, POLLIN | POLLRDNORM);
242 wake_up_interruptible(&session->readout_wq);
243 }
244 mutex_unlock(&arb->users_lock);
245
246}
247
248void nvgpu_clk_arb_apply_session_constraints(struct gk20a *g,
249 struct nvgpu_clk_session *session)
250{
251 struct nvgpu_clk_arb *arb = g->clk_arb;
252
253 mutex_lock(&arb->wlock);
254 atomic_inc(&arb->req_nr);
255
256 /* TODO: arbitration between users.
257 For now, last session to run arbiter wins.
258 */
259
260 if (session) {
261 arb->mclk_target_mhz = session->mclk_target_mhz;
262 arb->gpc2clk_target_mhz = session->gpc2clk_target_mhz;
263
264 atomic_set(&session->req_nr, atomic_read(&arb->req_nr));
265 } else {
266 arb->mclk_target_mhz = arb->mclk_default_mhz;
267 arb->gpc2clk_target_mhz = arb->gpc2clk_default_mhz;
268 }
269 mutex_unlock(&arb->wlock);
270
271 schedule_work(&arb->update_fn_work);
272}
273
274static unsigned int nvgpu_clk_arb_poll_session_dev(struct file *filp, poll_table *wait)
275{
276 struct nvgpu_clk_session *session = filp->private_data;
277
278 gk20a_dbg_fn("");
279
280 poll_wait(filp, &session->readout_wq, wait);
281 return atomic_xchg(&session->poll_mask, 0);
282}
283
284static int nvgpu_clk_arb_release_session_dev(struct inode *inode, struct file *filp)
285{
286 struct nvgpu_clk_session *session = filp->private_data;
287 struct gk20a *g = session->g;
288
289 session->fd = -1;
290 nvgpu_clk_arb_cleanup_session(g, session);
291
292 return 0;
293}
294
295int nvgpu_clk_arb_set_session_target_mhz(struct nvgpu_clk_session *session,
296 u32 api_domain, u16 target_mhz)
297{
298
299 gk20a_dbg_fn("domain=0x%08x target_mhz=%u", api_domain, target_mhz);
300
301 switch (api_domain) {
302 case NVGPU_GPU_CLK_DOMAIN_MCLK:
303 session->mclk_target_mhz = target_mhz;
304 return 0;
305
306 case NVGPU_GPU_CLK_DOMAIN_GPC2CLK:
307 session->gpc2clk_target_mhz = target_mhz;
308 return 0;
309
310 default:
311 return -EINVAL;
312 }
313}
314
315int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session,
316 u32 api_domain, u16 *target_mhz)
317{
318 switch (api_domain) {
319 case NVGPU_GPU_CLK_DOMAIN_MCLK:
320 *target_mhz = session->mclk_target_mhz;
321 return 0;
322
323 case NVGPU_GPU_CLK_DOMAIN_GPC2CLK:
324 *target_mhz = session->gpc2clk_target_mhz;
325 return 0;
326
327 default:
328 *target_mhz = 0;
329 return -EINVAL;
330 }
331}
332
333int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g,
334 u32 api_domain, u16 *actual_mhz)
335{
336 struct nvgpu_clk_arb *arb = g->clk_arb;
337 int err = 0;
338
339 mutex_lock(&arb->wlock);
340 switch (api_domain) {
341 case NVGPU_GPU_CLK_DOMAIN_MCLK:
342 *actual_mhz = arb->mclk_current_mhz;
343 break;
344
345 case NVGPU_GPU_CLK_DOMAIN_GPC2CLK:
346 *actual_mhz = arb->gpc2clk_current_mhz;
347 break;
348
349 default:
350 *actual_mhz = 0;
351 err = -EINVAL;
352 }
353 mutex_unlock(&arb->wlock);
354
355 return err;
356}
357
358u32 nvgpu_clk_arb_get_arbiter_req_nr(struct gk20a *g)
359{
360 struct nvgpu_clk_arb *arb = g->clk_arb;
361
362 return atomic_read(&arb->last_req_nr);
363}
364
365int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain,
366 u16 *min_mhz, u16 *max_mhz)
367{
368 return g->ops.clk_arb.get_arbiter_clk_range(g, api_domain,
369 min_mhz, max_mhz);
370}
371
372u32 nvgpu_clk_arb_get_arbiter_clk_domains(struct gk20a *g)
373{
374 return g->ops.clk_arb.get_arbiter_clk_domains(g);
375}
376
377u32 nvgpu_clk_arb_get_session_req_nr(struct gk20a *g,
378 struct nvgpu_clk_session *session)
379{
380 return atomic_read(&session->req_nr);
381}
382
383int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g,
384 u32 api_domain, u32 *max_points, u16 *fpoints)
385{
386 return (int)clk_domain_get_f_points(g, api_domain, max_points, fpoints);
387}
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.h b/drivers/gpu/nvgpu/clk/clk_arb.h
new file mode 100644
index 00000000..9981041b
--- /dev/null
+++ b/drivers/gpu/nvgpu/clk/clk_arb.h
@@ -0,0 +1,63 @@
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
14#include "gk20a/gk20a.h"
15
16#ifndef _CLK_ARB_H_
17#define _CLK_ARB_H_
18
19struct nvgpu_clk_arb;
20struct nvgpu_clk_session;
21
22int nvgpu_clk_arb_init_arbiter(struct gk20a *g);
23
24int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain,
25 u16 *min_mhz, u16 *max_mhz);
26
27int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g,
28 u32 api_domain, u16 *actual_mhz);
29
30int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g,
31 u32 api_domain, u32 *max_points, u16 *fpoints);
32
33u32 nvgpu_clk_arb_get_arbiter_req_nr(struct gk20a *g);
34
35u32 nvgpu_clk_arb_get_arbiter_clk_domains(struct gk20a *g);
36
37void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g);
38
39int nvgpu_clk_arb_install_session_fd(struct gk20a *g,
40 struct nvgpu_clk_session *session);
41
42int nvgpu_clk_arb_init_session(struct gk20a *g,
43 struct nvgpu_clk_session **_session);
44
45void nvgpu_clk_arb_cleanup_session(struct gk20a *g,
46 struct nvgpu_clk_session *session);
47
48void nvgpu_clk_arb_apply_session_constraints(struct gk20a *g,
49 struct nvgpu_clk_session *session);
50
51int nvgpu_clk_arb_set_session_target_mhz(struct nvgpu_clk_session *session,
52 u32 api_domain, u16 target_mhz);
53
54int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session,
55 u32 api_domain, u16 *target_mhz);
56
57u32 nvgpu_clk_arb_get_session_req_nr(struct gk20a *g,
58 struct nvgpu_clk_session *session);
59
60
61
62#endif /* _CLK_ARB_H_ */
63
diff --git a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c
new file mode 100644
index 00000000..d1cbb32b
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c
@@ -0,0 +1,95 @@
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
14#include "gk20a/gk20a.h"
15
16#include "clk/clk_arb.h"
17#include "clk_arb_gp106.h"
18
19static u32 gp106_get_arbiter_clk_domains(struct gk20a *g)
20{
21 (void)g;
22 return (CTRL_CLK_DOMAIN_MCLK|CTRL_CLK_DOMAIN_GPC2CLK);
23}
24
25static int gp106_get_arbiter_clk_range(struct gk20a *g, u32 api_domain,
26 u16 *min_mhz, u16 *max_mhz)
27{
28 enum nv_pmu_clk_clkwhich clkwhich;
29 struct clk_set_info *p0_info;
30 struct clk_set_info *p5_info;
31
32 switch (api_domain) {
33 case CTRL_CLK_DOMAIN_MCLK:
34 clkwhich = clkwhich_mclk;
35 break;
36
37 case CTRL_CLK_DOMAIN_GPC2CLK:
38 clkwhich = clkwhich_gpc2clk;
39 break;
40
41 default:
42 return -EINVAL;
43 }
44
45 p5_info = pstate_get_clk_set_info(g,
46 CTRL_PERF_PSTATE_P5, clkwhich);
47 if (!p5_info)
48 return -EINVAL;
49
50 p0_info = pstate_get_clk_set_info(g,
51 CTRL_PERF_PSTATE_P0, clkwhich);
52 if (!p0_info)
53 return -EINVAL;
54
55 *min_mhz = p5_info->min_mhz;
56 *max_mhz = p0_info->max_mhz;
57
58 return 0;
59}
60
61static int gp106_get_arbiter_clk_default(struct gk20a *g, u32 api_domain,
62 u16 *default_mhz)
63{
64 enum nv_pmu_clk_clkwhich clkwhich;
65 struct clk_set_info *p0_info;
66
67 switch (api_domain) {
68 case CTRL_CLK_DOMAIN_MCLK:
69 clkwhich = clkwhich_mclk;
70 break;
71
72 case CTRL_CLK_DOMAIN_GPC2CLK:
73 clkwhich = clkwhich_gpc2clk;
74 break;
75
76 default:
77 return -EINVAL;
78 }
79
80 p0_info = pstate_get_clk_set_info(g,
81 CTRL_PERF_PSTATE_P0, clkwhich);
82 if (!p0_info)
83 return -EINVAL;
84
85 *default_mhz = p0_info->max_mhz;
86
87 return 0;
88}
89
90void gp106_init_clk_arb_ops(struct gpu_ops *gops)
91{
92 gops->clk_arb.get_arbiter_clk_domains = gp106_get_arbiter_clk_domains;
93 gops->clk_arb.get_arbiter_clk_range = gp106_get_arbiter_clk_range;
94 gops->clk_arb.get_arbiter_clk_default = gp106_get_arbiter_clk_default;
95}
diff --git a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h
new file mode 100644
index 00000000..a9877199
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h
@@ -0,0 +1,21 @@
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#ifndef CLK_ARB_GP106_H
17#define CLK_ARB_GP106_H
18
19void gp106_init_clk_arb_ops(struct gpu_ops *gops);
20
21#endif /* CLK_ARB_GP106_H */
diff --git a/drivers/gpu/nvgpu/gp106/clk_gp106.c b/drivers/gpu/nvgpu/gp106/clk_gp106.c
index 39c308a3..85dde69f 100644
--- a/drivers/gpu/nvgpu/gp106/clk_gp106.c
+++ b/drivers/gpu/nvgpu/gp106/clk_gp106.c
@@ -27,6 +27,7 @@
27#include "gk20a/gk20a.h" 27#include "gk20a/gk20a.h"
28#include "hw_trim_gp106.h" 28#include "hw_trim_gp106.h"
29#include "clk_gp106.h" 29#include "clk_gp106.h"
30#include "clk/clk_arb.h"
30 31
31#define gk20a_dbg_clk(fmt, arg...) \ 32#define gk20a_dbg_clk(fmt, arg...) \
32 gk20a_dbg(gpu_dbg_clk, fmt, ##arg) 33 gk20a_dbg(gpu_dbg_clk, fmt, ##arg)
diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c
index 0f926be8..dc27cdae 100644
--- a/drivers/gpu/nvgpu/gp106/hal_gp106.c
+++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c
@@ -37,6 +37,7 @@
37#include "gm20b/fifo_gm20b.h" 37#include "gm20b/fifo_gm20b.h"
38#include "gm20b/pmu_gm20b.h" 38#include "gm20b/pmu_gm20b.h"
39#include "gp106/clk_gp106.h" 39#include "gp106/clk_gp106.h"
40#include "gp106/clk_arb_gp106.h"
40 41
41#include "gp106/mm_gp106.h" 42#include "gp106/mm_gp106.h"
42#include "gp106/pmu_gp106.h" 43#include "gp106/pmu_gp106.h"
@@ -210,6 +211,7 @@ int gp106_init_hal(struct gk20a *g)
210 gk20a_init_debug_ops(gops); 211 gk20a_init_debug_ops(gops);
211 gk20a_init_dbg_session_ops(gops); 212 gk20a_init_dbg_session_ops(gops);
212 gp106_init_clk_ops(gops); 213 gp106_init_clk_ops(gops);
214 gp106_init_clk_arb_ops(gops);
213 gp106_init_regops(gops); 215 gp106_init_regops(gops);
214 gp10b_init_cde_ops(gops); 216 gp10b_init_cde_ops(gops);
215 gk20a_init_tsg_ops(gops); 217 gk20a_init_tsg_ops(gops);
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c
index e9b9775e..0dc15201 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.c
+++ b/drivers/gpu/nvgpu/pstate/pstate.c
@@ -234,7 +234,7 @@ static int parse_pstate_entry_5x(struct gk20a *g,
234 memset(pstate, 0, sizeof(struct pstate)); 234 memset(pstate, 0, sizeof(struct pstate));
235 pstate->super.type = CTRL_PERF_PSTATE_TYPE_3X; 235 pstate->super.type = CTRL_PERF_PSTATE_TYPE_3X;
236 pstate->num = 0x0F - entry->pstate_level; 236 pstate->num = 0x0F - entry->pstate_level;
237 pstate->clklist.clksetinfolistsize = hdr->clock_entry_count; 237 pstate->clklist.num_info = hdr->clock_entry_count;
238 238
239 gk20a_dbg_info("pstate P%u", pstate->num); 239 gk20a_dbg_info("pstate P%u", pstate->num);
240 240
@@ -357,3 +357,41 @@ static int pstate_sw_setup(struct gk20a *g)
357done: 357done:
358 return err; 358 return err;
359} 359}
360
361static struct pstate *pstate_find(struct gk20a *g, u32 num)
362{
363 struct pstates *pstates = &(g->perf_pmu.pstatesobjs);
364 struct pstate *pstate;
365 u8 i;
366
367 gk20a_dbg_info("pstates = %p", pstates);
368
369 BOARDOBJGRP_FOR_EACH(&pstates->super.super,
370 struct pstate *, pstate, i) {
371 gk20a_dbg_info("pstate=%p num=%u (looking for num=%u)",
372 pstate, pstate->num, num);
373 if (pstate->num == num)
374 return pstate;
375 }
376 return NULL;
377}
378
379struct clk_set_info *pstate_get_clk_set_info(struct gk20a *g,
380 u32 pstate_num, enum nv_pmu_clk_clkwhich clkwhich)
381{
382 struct pstate *pstate = pstate_find(g, pstate_num);
383 struct clk_set_info *info;
384 u32 clkidx;
385
386 gk20a_dbg_info("pstate = %p", pstate);
387
388 if (!pstate)
389 return NULL;
390
391 for (clkidx = 0; clkidx < pstate->clklist.num_info; clkidx++) {
392 info = &pstate->clklist.clksetinfo[clkidx];
393 if (info->clkwhich == clkwhich)
394 return info;
395 }
396 return NULL;
397}
diff --git a/drivers/gpu/nvgpu/pstate/pstate.h b/drivers/gpu/nvgpu/pstate/pstate.h
index 11fa4c77..4ae72aa9 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.h
+++ b/drivers/gpu/nvgpu/pstate/pstate.h
@@ -20,6 +20,10 @@
20 20
21#define CTRL_PERF_PSTATE_TYPE_3X 0x3 21#define CTRL_PERF_PSTATE_TYPE_3X 0x3
22 22
23#define CTRL_PERF_PSTATE_P0 0
24#define CTRL_PERF_PSTATE_P5 5
25#define CTRL_PERF_PSTATE_P8 8
26
23#define CLK_SET_INFO_MAX_SIZE (32) 27#define CLK_SET_INFO_MAX_SIZE (32)
24 28
25struct clk_set_info { 29struct clk_set_info {
@@ -30,7 +34,7 @@ struct clk_set_info {
30}; 34};
31 35
32struct clk_set_info_list { 36struct clk_set_info_list {
33 u32 clksetinfolistsize; 37 u32 num_info;
34 struct clk_set_info clksetinfo[CLK_SET_INFO_MAX_SIZE]; 38 struct clk_set_info clksetinfo[CLK_SET_INFO_MAX_SIZE];
35}; 39};
36 40
@@ -48,4 +52,7 @@ struct pstates {
48int gk20a_init_pstate_support(struct gk20a *g); 52int gk20a_init_pstate_support(struct gk20a *g);
49int gk20a_init_pstate_pmu_support(struct gk20a *g); 53int gk20a_init_pstate_pmu_support(struct gk20a *g);
50 54
55struct clk_set_info *pstate_get_clk_set_info(struct gk20a *g, u32 pstate_num,
56 enum nv_pmu_clk_clkwhich clkwhich);
57
51#endif /* __PSTATE_H__ */ 58#endif /* __PSTATE_H__ */