summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/pstate
diff options
context:
space:
mode:
authorThomas Fleury <tfleury@nvidia.com>2016-09-08 20:35:13 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commitdb529935a5f50e9e683d44d2eb01d0d76a915792 (patch)
tree6d1b3f63aaa5e5abd937cf0c3aec733b9e2e0d08 /drivers/gpu/nvgpu/pstate
parent776ab920a7a4d31c6180e7dcb9f3fcea611e92bd (diff)
gpu: nvgpu: parse performance table
Parse VBIOS performance table to retrieve clock ranges. Jira DNVGPU-125 Change-Id: Ia8e4ede158de5c5374205a510099d00b497fe1a6 Signed-off-by: Thomas Fleury <tfleury@nvidia.com> Reviewed-on: http://git-master/r/1218935 (cherry picked from commit b5b7c789e98a20eb4cc5c30f0e2eb45d4a882cc4) Reviewed-on: http://git-master/r/1232593 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/pstate')
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.c204
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.h32
2 files changed, 236 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c
index da1a49db..f4cc50ab 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.c
+++ b/drivers/gpu/nvgpu/pstate/pstate.c
@@ -17,6 +17,10 @@
17#include "clk/clk.h" 17#include "clk/clk.h"
18#include "perf/perf.h" 18#include "perf/perf.h"
19#include "pmgr/pmgr.h" 19#include "pmgr/pmgr.h"
20#include "include/bios.h"
21#include "pstate/pstate.h"
22
23static int pstate_sw_setup(struct gk20a *g);
20 24
21/*sw setup for pstate components*/ 25/*sw setup for pstate components*/
22int gk20a_init_pstate_support(struct gk20a *g) 26int gk20a_init_pstate_support(struct gk20a *g)
@@ -53,6 +57,10 @@ int gk20a_init_pstate_support(struct gk20a *g)
53 if (err) 57 if (err)
54 return err; 58 return err;
55 59
60 err = pstate_sw_setup(g);
61 if (err)
62 return err;
63
56 err = pmgr_domain_sw_setup(g); 64 err = pmgr_domain_sw_setup(g);
57 return err; 65 return err;
58} 66}
@@ -112,3 +120,199 @@ int gk20a_init_pstate_pmu_support(struct gk20a *g)
112 return err; 120 return err;
113} 121}
114 122
123int pstate_construct_super(struct gk20a *g, struct boardobj **ppboardobj,
124 u16 size, void *args)
125{
126 struct pstate *ptmppstate = (struct pstate *)args;
127 struct pstate *pstate;
128 int err;
129
130 err = boardobj_construct_super(g, ppboardobj, size, args);
131 if (err)
132 return err;
133
134 pstate = (struct pstate *)*ppboardobj;
135
136 pstate->num = ptmppstate->num;
137 pstate->clklist = ptmppstate->clklist;
138
139 return 0;
140}
141
142int pstate_construct_3x(struct gk20a *g, struct boardobj **ppboardobj,
143 u16 size, void *args)
144{
145 struct boardobj *ptmpobj = (struct boardobj *)args;
146
147 ptmpobj->type_mask |= BIT(CTRL_PERF_PSTATE_TYPE_3X);
148 return pstate_construct_super(g, ppboardobj, size, args);
149}
150
151struct pstate *pstate_construct(struct gk20a *g, void *args)
152{
153 struct pstate *pstate = NULL;
154 struct pstate *tmp = (struct pstate *)args;
155
156 if ((tmp->super.type != CTRL_PERF_PSTATE_TYPE_3X) ||
157 (pstate_construct_3x(g, (struct boardobj **)&pstate,
158 sizeof(struct pstate), args)))
159 gk20a_err(dev_from_gk20a(g),
160 "error constructing pstate num=%u", tmp->num);
161
162 return pstate;
163}
164
165int pstate_insert(struct gk20a *g, struct pstate *pstate, int index)
166{
167 struct pstates *pstates = &(g->perf_pmu.pstatesobjs);
168 int err;
169
170 err = boardobjgrp_objinsert(&pstates->super.super,
171 (struct boardobj *)pstate, index);
172 if (err) {
173 gk20a_err(dev_from_gk20a(g),
174 "error adding pstate boardobj %d", index);
175 return err;
176 }
177
178 pstates->num_levels++;
179
180 return err;
181}
182
183static int parse_pstate_entry_5x(struct gk20a *g,
184 struct vbios_pstate_header_5x *hdr,
185 struct vbios_pstate_entry_5x *entry,
186 struct pstate *pstate)
187{
188 u8 *p = (u8 *)entry;
189 u32 clkidx;
190
191 p += hdr->base_entry_size;
192
193 memset(pstate, 0, sizeof(struct pstate));
194 pstate->super.type = CTRL_PERF_PSTATE_TYPE_3X;
195 pstate->num = 0x0F - entry->pstate_level;
196 pstate->clklist.clksetinfolistsize = hdr->clock_entry_count;
197
198 gk20a_dbg_info("pstate P%u", pstate->num);
199
200 for (clkidx = 0; clkidx < hdr->clock_entry_count; clkidx++) {
201 struct clk_set_info *pclksetinfo;
202 struct vbios_pstate_entry_clock_5x *clk_entry;
203 struct clk_domain *clk_domain;
204
205 clk_domain = (struct clk_domain *)BOARDOBJGRP_OBJ_GET_BY_IDX(
206 &g->clk_pmu.clk_domainobjs.super.super, clkidx);
207
208 pclksetinfo = &pstate->clklist.clksetinfo[clkidx];
209 clk_entry = (struct vbios_pstate_entry_clock_5x *)p;
210
211 pclksetinfo->clkwhich = clk_domain->domain;
212 pclksetinfo->nominal_mhz =
213 BIOS_GET_FIELD(clk_entry->param0,
214 VBIOS_PSTATE_5X_CLOCK_PROG_PARAM0_NOM_FREQ_MHZ);
215 pclksetinfo->min_mhz =
216 BIOS_GET_FIELD(clk_entry->param1,
217 VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MIN_FREQ_MHZ);
218 pclksetinfo->max_mhz =
219 BIOS_GET_FIELD(clk_entry->param1,
220 VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MAX_FREQ_MHZ);
221
222 gk20a_dbg_info(
223 "clk_domain=%u nominal_mhz=%u min_mhz=%u max_mhz=%u",
224 pclksetinfo->clkwhich, pclksetinfo->nominal_mhz,
225 pclksetinfo->min_mhz, pclksetinfo->max_mhz);
226
227 p += hdr->clock_entry_size;
228 }
229
230 return 0;
231}
232
233static int parse_pstate_table_5x(struct gk20a *g,
234 struct vbios_pstate_header_5x *hdr)
235{
236 struct pstate _pstate, *pstate = &_pstate;
237 struct vbios_pstate_entry_5x *entry;
238 u32 entry_size;
239 u8 i;
240 u8 *p = (u8 *)hdr;
241 int err = 0;
242
243 if ((hdr->header_size != VBIOS_PSTATE_HEADER_5X_SIZE_10) ||
244 (hdr->base_entry_count == 0) ||
245 ((hdr->base_entry_size != VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_2) &&
246 (hdr->base_entry_size != VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_3)) ||
247 (hdr->clock_entry_size != VBIOS_PSTATE_CLOCK_ENTRY_5X_SIZE_6) ||
248 (hdr->clock_entry_count > CLK_SET_INFO_MAX_SIZE))
249 return -EINVAL;
250
251 p += hdr->header_size;
252
253 entry_size = hdr->base_entry_size +
254 hdr->clock_entry_count * hdr->clock_entry_size;
255
256 for (i = 0; i < hdr->base_entry_count; i++, p += entry_size) {
257 entry = (struct vbios_pstate_entry_5x *)p;
258
259 if (entry->pstate_level == VBIOS_PERFLEVEL_SKIP_ENTRY)
260 continue;
261
262 err = parse_pstate_entry_5x(g, hdr, entry, pstate);
263 if (err)
264 goto done;
265
266 pstate = pstate_construct(g, pstate);
267 if (!pstate)
268 goto done;
269
270 err = pstate_insert(g, pstate, i);
271 if (err)
272 goto done;
273 }
274
275done:
276 return err;
277}
278
279static int pstate_sw_setup(struct gk20a *g)
280{
281 struct vbios_pstate_header_5x *hdr = NULL;
282 int err = 0;
283
284 gk20a_dbg_fn("");
285
286 err = boardobjgrpconstruct_e32(&g->perf_pmu.pstatesobjs.super);
287 if (err) {
288 gk20a_err(dev_from_gk20a(g),
289 "error creating boardobjgrp for pstates, err=%d",
290 err);
291 goto done;
292 }
293
294 if (g->ops.bios.get_perf_table_ptrs) {
295 hdr = (struct vbios_pstate_header_5x *)
296 g->ops.bios.get_perf_table_ptrs(g,
297 g->bios.perf_token, PERFORMANCE_TABLE);
298 }
299
300 if (!hdr) {
301 gk20a_err(dev_from_gk20a(g),
302 "performance table not found");
303 err = -EINVAL;
304 goto done;
305 }
306
307 if (hdr->version != VBIOS_PSTATE_TABLE_VERSION_5X) {
308 gk20a_err(dev_from_gk20a(g),
309 "unknown/unsupported clocks table version=0x%02x",
310 hdr->version);
311 err = -EINVAL;
312 goto done;
313 }
314
315 err = parse_pstate_table_5x(g, hdr);
316done:
317 return err;
318}
diff --git a/drivers/gpu/nvgpu/pstate/pstate.h b/drivers/gpu/nvgpu/pstate/pstate.h
index fb49adf3..11fa4c77 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.h
+++ b/drivers/gpu/nvgpu/pstate/pstate.h
@@ -12,8 +12,40 @@
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details. 13 * more details.
14 */ 14 */
15#ifndef __PSTATE_H__
16#define __PSTATE_H__
15 17
16#include "gk20a/gk20a.h" 18#include "gk20a/gk20a.h"
19#include "clk/clk.h"
20
21#define CTRL_PERF_PSTATE_TYPE_3X 0x3
22
23#define CLK_SET_INFO_MAX_SIZE (32)
24
25struct clk_set_info {
26 enum nv_pmu_clk_clkwhich clkwhich;
27 u32 nominal_mhz;
28 u32 min_mhz;
29 u32 max_mhz;
30};
31
32struct clk_set_info_list {
33 u32 clksetinfolistsize;
34 struct clk_set_info clksetinfo[CLK_SET_INFO_MAX_SIZE];
35};
36
37struct pstate {
38 struct boardobj super;
39 u32 num;
40 struct clk_set_info_list clklist;
41};
42
43struct pstates {
44 struct boardobjgrp_e32 super;
45 u32 num_levels;
46};
17 47
18int gk20a_init_pstate_support(struct gk20a *g); 48int gk20a_init_pstate_support(struct gk20a *g);
19int gk20a_init_pstate_pmu_support(struct gk20a *g); 49int gk20a_init_pstate_pmu_support(struct gk20a *g);
50
51#endif /* __PSTATE_H__ */