diff options
Diffstat (limited to 'include/volt/volt_policy.c')
-rw-r--r-- | include/volt/volt_policy.c | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/include/volt/volt_policy.c b/include/volt/volt_policy.c new file mode 100644 index 0000000..cc60730 --- /dev/null +++ b/include/volt/volt_policy.c | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
20 | * DEALINGS IN THE SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <nvgpu/bios.h> | ||
24 | #include <nvgpu/gk20a.h> | ||
25 | |||
26 | #include "boardobj/boardobjgrp.h" | ||
27 | #include "boardobj/boardobjgrp_e32.h" | ||
28 | #include "gp106/bios_gp106.h" | ||
29 | #include "ctrl/ctrlvolt.h" | ||
30 | |||
31 | #include "volt.h" | ||
32 | |||
33 | static int volt_policy_pmu_data_init_super(struct gk20a *g, | ||
34 | struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata) | ||
35 | { | ||
36 | return boardobj_pmudatainit_super(g, pboardobj, ppmudata); | ||
37 | } | ||
38 | |||
39 | static int construct_volt_policy(struct gk20a *g, | ||
40 | struct boardobj **ppboardobj, u16 size, void *pArgs) | ||
41 | { | ||
42 | struct voltage_policy *pvolt_policy = NULL; | ||
43 | int status = 0; | ||
44 | |||
45 | status = boardobj_construct_super(g, ppboardobj, size, pArgs); | ||
46 | if (status) { | ||
47 | return status; | ||
48 | } | ||
49 | |||
50 | pvolt_policy = (struct voltage_policy *)*ppboardobj; | ||
51 | |||
52 | pvolt_policy->super.pmudatainit = volt_policy_pmu_data_init_super; | ||
53 | |||
54 | return status; | ||
55 | } | ||
56 | |||
57 | static int construct_volt_policy_split_rail(struct gk20a *g, | ||
58 | struct boardobj **ppboardobj, u16 size, void *pArgs) | ||
59 | { | ||
60 | struct voltage_policy_split_rail *ptmp_policy = | ||
61 | (struct voltage_policy_split_rail *)pArgs; | ||
62 | struct voltage_policy_split_rail *pvolt_policy = NULL; | ||
63 | int status = 0; | ||
64 | |||
65 | status = construct_volt_policy(g, ppboardobj, size, pArgs); | ||
66 | if (status) { | ||
67 | return status; | ||
68 | } | ||
69 | |||
70 | pvolt_policy = (struct voltage_policy_split_rail *)*ppboardobj; | ||
71 | |||
72 | pvolt_policy->rail_idx_master = ptmp_policy->rail_idx_master; | ||
73 | pvolt_policy->rail_idx_slave = ptmp_policy->rail_idx_slave; | ||
74 | pvolt_policy->delta_min_vfe_equ_idx = | ||
75 | ptmp_policy->delta_min_vfe_equ_idx; | ||
76 | pvolt_policy->delta_max_vfe_equ_idx = | ||
77 | ptmp_policy->delta_max_vfe_equ_idx; | ||
78 | |||
79 | return status; | ||
80 | } | ||
81 | |||
82 | static int construct_volt_policy_single_rail(struct gk20a *g, | ||
83 | struct boardobj **ppboardobj, u16 size, void *pArgs) | ||
84 | { | ||
85 | struct voltage_policy_single_rail *ptmp_policy = | ||
86 | (struct voltage_policy_single_rail *)pArgs; | ||
87 | struct voltage_policy_single_rail *pvolt_policy = NULL; | ||
88 | int status = 0; | ||
89 | |||
90 | status = construct_volt_policy(g, ppboardobj, size, pArgs); | ||
91 | if (status) { | ||
92 | return status; | ||
93 | } | ||
94 | |||
95 | pvolt_policy = (struct voltage_policy_single_rail *)*ppboardobj; | ||
96 | |||
97 | pvolt_policy->rail_idx = ptmp_policy->rail_idx; | ||
98 | |||
99 | return status; | ||
100 | } | ||
101 | |||
102 | static int volt_policy_pmu_data_init_single_rail(struct gk20a *g, | ||
103 | struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata) | ||
104 | { | ||
105 | int status = 0; | ||
106 | struct voltage_policy_single_rail *ppolicy; | ||
107 | struct nv_pmu_volt_volt_policy_sr_boardobj_set *pset; | ||
108 | |||
109 | status = volt_policy_pmu_data_init_super(g, pboardobj, ppmudata); | ||
110 | if (status) { | ||
111 | goto done; | ||
112 | } | ||
113 | |||
114 | ppolicy = (struct voltage_policy_single_rail *)pboardobj; | ||
115 | pset = (struct nv_pmu_volt_volt_policy_sr_boardobj_set *) | ||
116 | ppmudata; | ||
117 | pset->rail_idx = ppolicy->rail_idx; | ||
118 | |||
119 | done: | ||
120 | return status; | ||
121 | } | ||
122 | |||
123 | static int volt_policy_pmu_data_init_sr_multi_step(struct gk20a *g, | ||
124 | struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata) | ||
125 | { | ||
126 | int status = 0; | ||
127 | struct voltage_policy_single_rail_multi_step *ppolicy; | ||
128 | struct nv_pmu_volt_volt_policy_sr_multi_step_boardobj_set *pset; | ||
129 | |||
130 | status = volt_policy_pmu_data_init_single_rail(g, pboardobj, ppmudata); | ||
131 | if (status) { | ||
132 | goto done; | ||
133 | } | ||
134 | |||
135 | ppolicy = (struct voltage_policy_single_rail_multi_step *)pboardobj; | ||
136 | pset = (struct nv_pmu_volt_volt_policy_sr_multi_step_boardobj_set *) | ||
137 | ppmudata; | ||
138 | |||
139 | pset->ramp_up_step_size_uv = ppolicy->ramp_up_step_size_uv; | ||
140 | pset->ramp_down_step_size_uv = ppolicy->ramp_down_step_size_uv; | ||
141 | pset->inter_switch_delay_us = ppolicy->inter_switch_delay_us; | ||
142 | |||
143 | done: | ||
144 | return status; | ||
145 | } | ||
146 | |||
147 | static int volt_construct_volt_policy_single_rail_multi_step(struct gk20a *g, | ||
148 | struct boardobj **ppboardobj, u16 size, void *pargs) | ||
149 | { | ||
150 | struct boardobj *pboardobj = NULL; | ||
151 | struct voltage_policy_single_rail_multi_step *p_volt_policy = NULL; | ||
152 | struct voltage_policy_single_rail_multi_step *tmp_policy = | ||
153 | (struct voltage_policy_single_rail_multi_step *)pargs; | ||
154 | int status = 0; | ||
155 | |||
156 | status = construct_volt_policy_single_rail(g, ppboardobj, size, pargs); | ||
157 | if (status) { | ||
158 | return status; | ||
159 | } | ||
160 | |||
161 | pboardobj = (*ppboardobj); | ||
162 | p_volt_policy = (struct voltage_policy_single_rail_multi_step *) | ||
163 | *ppboardobj; | ||
164 | |||
165 | pboardobj->pmudatainit = volt_policy_pmu_data_init_sr_multi_step; | ||
166 | |||
167 | p_volt_policy->ramp_up_step_size_uv = | ||
168 | tmp_policy->ramp_up_step_size_uv; | ||
169 | p_volt_policy->ramp_down_step_size_uv = | ||
170 | tmp_policy->ramp_down_step_size_uv; | ||
171 | p_volt_policy->inter_switch_delay_us = | ||
172 | tmp_policy->inter_switch_delay_us; | ||
173 | |||
174 | return status; | ||
175 | } | ||
176 | |||
177 | static int volt_policy_pmu_data_init_split_rail(struct gk20a *g, | ||
178 | struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata) | ||
179 | { | ||
180 | int status = 0; | ||
181 | struct voltage_policy_split_rail *ppolicy; | ||
182 | struct nv_pmu_volt_volt_policy_splt_r_boardobj_set *pset; | ||
183 | |||
184 | status = volt_policy_pmu_data_init_super(g, pboardobj, ppmudata); | ||
185 | if (status) { | ||
186 | goto done; | ||
187 | } | ||
188 | |||
189 | ppolicy = (struct voltage_policy_split_rail *)pboardobj; | ||
190 | pset = (struct nv_pmu_volt_volt_policy_splt_r_boardobj_set *) | ||
191 | ppmudata; | ||
192 | |||
193 | pset->rail_idx_master = ppolicy->rail_idx_master; | ||
194 | pset->rail_idx_slave = ppolicy->rail_idx_slave; | ||
195 | pset->delta_min_vfe_equ_idx = ppolicy->delta_min_vfe_equ_idx; | ||
196 | pset->delta_max_vfe_equ_idx = ppolicy->delta_max_vfe_equ_idx; | ||
197 | pset->offset_delta_min_uv = ppolicy->offset_delta_min_uv; | ||
198 | pset->offset_delta_max_uv = ppolicy->offset_delta_max_uv; | ||
199 | |||
200 | done: | ||
201 | return status; | ||
202 | } | ||
203 | |||
204 | static int volt_construct_volt_policy_split_rail_single_step(struct gk20a *g, | ||
205 | struct boardobj **ppboardobj, u16 size, void *pargs) | ||
206 | { | ||
207 | struct boardobj *pboardobj = NULL; | ||
208 | int status = 0; | ||
209 | |||
210 | status = construct_volt_policy_split_rail(g, ppboardobj, size, pargs); | ||
211 | if (status) { | ||
212 | return status; | ||
213 | } | ||
214 | |||
215 | pboardobj = (*ppboardobj); | ||
216 | pboardobj->pmudatainit = volt_policy_pmu_data_init_split_rail; | ||
217 | |||
218 | return status; | ||
219 | } | ||
220 | |||
221 | static struct voltage_policy *volt_volt_policy_construct(struct gk20a *g, void *pargs) | ||
222 | { | ||
223 | struct boardobj *pboard_obj = NULL; | ||
224 | int status = 0; | ||
225 | |||
226 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
227 | case CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP: | ||
228 | status = volt_construct_volt_policy_split_rail_single_step(g, | ||
229 | &pboard_obj, | ||
230 | sizeof(struct voltage_policy_split_rail_single_step), | ||
231 | pargs); | ||
232 | if (status) { | ||
233 | nvgpu_err(g, | ||
234 | "Could not allocate memory for voltage_policy"); | ||
235 | pboard_obj = NULL; | ||
236 | } | ||
237 | break; | ||
238 | case CTRL_VOLT_POLICY_TYPE_SINGLE_RAIL_MULTI_STEP: | ||
239 | status = volt_construct_volt_policy_single_rail_multi_step(g, | ||
240 | &pboard_obj, | ||
241 | sizeof(struct voltage_policy_single_rail_multi_step), | ||
242 | pargs); | ||
243 | if (status) { | ||
244 | nvgpu_err(g, | ||
245 | "Could not allocate memory for voltage_policy"); | ||
246 | pboard_obj = NULL; | ||
247 | } | ||
248 | break; | ||
249 | } | ||
250 | |||
251 | return (struct voltage_policy *)pboard_obj; | ||
252 | } | ||
253 | |||
254 | static u8 volt_policy_type_convert(u8 vbios_type) | ||
255 | { | ||
256 | switch (vbios_type) { | ||
257 | case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SINGLE_RAIL: | ||
258 | return CTRL_VOLT_POLICY_TYPE_SINGLE_RAIL; | ||
259 | |||
260 | case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SR_MULTI_STEP: | ||
261 | return CTRL_VOLT_POLICY_TYPE_SR_MULTI_STEP; | ||
262 | |||
263 | case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SR_SINGLE_STEP: | ||
264 | return CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP; | ||
265 | case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SINGLE_RAIL_MULTI_STEP: | ||
266 | return CTRL_VOLT_POLICY_TYPE_SINGLE_RAIL_MULTI_STEP; | ||
267 | } | ||
268 | |||
269 | return CTRL_VOLT_POLICY_TYPE_INVALID; | ||
270 | } | ||
271 | |||
272 | static int volt_get_volt_policy_table(struct gk20a *g, | ||
273 | struct voltage_policy_metadata *pvolt_policy_metadata) | ||
274 | { | ||
275 | int status = 0; | ||
276 | u8 *voltage_policy_table_ptr = NULL; | ||
277 | struct voltage_policy *ppolicy = NULL; | ||
278 | struct vbios_voltage_policy_table_1x_header header = { 0 }; | ||
279 | struct vbios_voltage_policy_table_1x_entry entry = { 0 }; | ||
280 | u8 i; | ||
281 | u8 policy_type = 0; | ||
282 | u8 *entry_offset; | ||
283 | union policy_type { | ||
284 | struct boardobj board_obj; | ||
285 | struct voltage_policy volt_policy; | ||
286 | struct voltage_policy_split_rail split_rail; | ||
287 | struct voltage_policy_single_rail_multi_step single_rail_ms; | ||
288 | } policy_type_data; | ||
289 | |||
290 | voltage_policy_table_ptr = | ||
291 | (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
292 | g->bios.perf_token, VOLTAGE_POLICY_TABLE); | ||
293 | if (voltage_policy_table_ptr == NULL) { | ||
294 | status = -EINVAL; | ||
295 | goto done; | ||
296 | } | ||
297 | |||
298 | memcpy(&header, voltage_policy_table_ptr, | ||
299 | sizeof(struct vbios_voltage_policy_table_1x_header)); | ||
300 | |||
301 | /* Set Voltage Policy Table Index for Perf Core VF Sequence client. */ | ||
302 | pvolt_policy_metadata->perf_core_vf_seq_policy_idx = | ||
303 | (u8)header.perf_core_vf_seq_policy_idx; | ||
304 | |||
305 | /* Read in the entries. */ | ||
306 | for (i = 0; i < header.num_table_entries; i++) { | ||
307 | entry_offset = (voltage_policy_table_ptr + header.header_size + | ||
308 | i * header.table_entry_size); | ||
309 | |||
310 | memcpy(&entry, entry_offset, | ||
311 | sizeof(struct vbios_voltage_policy_table_1x_entry)); | ||
312 | |||
313 | memset(&policy_type_data, 0x0, sizeof(policy_type_data)); | ||
314 | |||
315 | policy_type = volt_policy_type_convert((u8)entry.type); | ||
316 | |||
317 | switch (policy_type) { | ||
318 | case CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP: | ||
319 | policy_type_data.split_rail.rail_idx_master = | ||
320 | (u8)BIOS_GET_FIELD(entry.param0, | ||
321 | NV_VBIOS_VPT_ENTRY_PARAM0_SR_VD_MASTER); | ||
322 | |||
323 | policy_type_data.split_rail.rail_idx_slave = | ||
324 | (u8)BIOS_GET_FIELD(entry.param0, | ||
325 | NV_VBIOS_VPT_ENTRY_PARAM0_SR_VD_SLAVE); | ||
326 | |||
327 | policy_type_data.split_rail.delta_min_vfe_equ_idx = | ||
328 | (u8)BIOS_GET_FIELD(entry.param0, | ||
329 | NV_VBIOS_VPT_ENTRY_PARAM0_SR_DELTA_SM_MIN); | ||
330 | |||
331 | policy_type_data.split_rail.delta_max_vfe_equ_idx = | ||
332 | (u8)BIOS_GET_FIELD(entry.param0, | ||
333 | NV_VBIOS_VPT_ENTRY_PARAM0_SR_DELTA_SM_MAX); | ||
334 | break; | ||
335 | case CTRL_VOLT_POLICY_TYPE_SINGLE_RAIL_MULTI_STEP: | ||
336 | policy_type_data.single_rail_ms.inter_switch_delay_us = | ||
337 | (u16)BIOS_GET_FIELD(entry.param1, | ||
338 | NV_VBIOS_VPT_ENTRY_PARAM1_SR_SETTLE_TIME_INTERMEDIATE); | ||
339 | policy_type_data.single_rail_ms.ramp_up_step_size_uv = | ||
340 | (u32)BIOS_GET_FIELD(entry.param2, | ||
341 | NV_VBIOS_VPT_ENTRY_PARAM2_SR_RAMP_UP_STEP_SIZE_UV); | ||
342 | policy_type_data.single_rail_ms.ramp_down_step_size_uv = | ||
343 | (u32)BIOS_GET_FIELD(entry.param3, | ||
344 | NV_VBIOS_VPT_ENTRY_PARAM3_SR_RAMP_DOWN_STEP_SIZE_UV); | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | policy_type_data.board_obj.type = policy_type; | ||
349 | |||
350 | ppolicy = volt_volt_policy_construct(g, | ||
351 | (void *)&policy_type_data); | ||
352 | if (ppolicy == NULL) { | ||
353 | nvgpu_err(g, | ||
354 | "Failure to construct VOLT_POLICY object."); | ||
355 | status = -EINVAL; | ||
356 | goto done; | ||
357 | } | ||
358 | |||
359 | status = boardobjgrp_objinsert( | ||
360 | &pvolt_policy_metadata->volt_policies.super, | ||
361 | (struct boardobj *)ppolicy, i); | ||
362 | if (status) { | ||
363 | nvgpu_err(g, | ||
364 | "could not add volt_policy for entry %d into boardobjgrp ", | ||
365 | i); | ||
366 | goto done; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | done: | ||
371 | return status; | ||
372 | } | ||
373 | static int _volt_policy_devgrp_pmudata_instget(struct gk20a *g, | ||
374 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
375 | struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx) | ||
376 | { | ||
377 | struct nv_pmu_volt_volt_policy_boardobj_grp_set *pgrp_set = | ||
378 | (struct nv_pmu_volt_volt_policy_boardobj_grp_set *) | ||
379 | pmuboardobjgrp; | ||
380 | |||
381 | nvgpu_log_info(g, " "); | ||
382 | |||
383 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
384 | if (((u32)BIT(idx) & | ||
385 | pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0U) { | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | |||
389 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
390 | &pgrp_set->objects[idx].data.board_obj; | ||
391 | nvgpu_log_info(g, " Done"); | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int _volt_policy_devgrp_pmustatus_instget(struct gk20a *g, | ||
396 | void *pboardobjgrppmu, | ||
397 | struct nv_pmu_boardobj_query **ppboardobjpmustatus, u8 idx) | ||
398 | { | ||
399 | struct nv_pmu_volt_volt_policy_boardobj_grp_get_status *p_get_status = | ||
400 | (struct nv_pmu_volt_volt_policy_boardobj_grp_get_status *) | ||
401 | pboardobjgrppmu; | ||
402 | |||
403 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
404 | if (((u32)BIT(idx) & | ||
405 | p_get_status->hdr.data.super.obj_mask.super.data[0]) == 0U) { | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
409 | *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *) | ||
410 | &p_get_status->objects[idx].data.board_obj; | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int _volt_policy_grp_pmudatainit_super(struct gk20a *g, | ||
415 | struct boardobjgrp *pboardobjgrp, | ||
416 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
417 | { | ||
418 | struct nv_pmu_volt_volt_policy_boardobjgrp_set_header *pset = | ||
419 | (struct nv_pmu_volt_volt_policy_boardobjgrp_set_header *) | ||
420 | pboardobjgrppmu; | ||
421 | struct obj_volt *volt = (struct obj_volt *)pboardobjgrp; | ||
422 | int status = 0; | ||
423 | |||
424 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
425 | if (status) { | ||
426 | nvgpu_err(g, | ||
427 | "error updating pmu boardobjgrp for volt policy 0x%x", | ||
428 | status); | ||
429 | goto done; | ||
430 | } | ||
431 | pset->perf_core_vf_seq_policy_idx = | ||
432 | volt->volt_policy_metadata.perf_core_vf_seq_policy_idx; | ||
433 | |||
434 | done: | ||
435 | return status; | ||
436 | } | ||
437 | |||
438 | int volt_policy_pmu_setup(struct gk20a *g) | ||
439 | { | ||
440 | int status; | ||
441 | struct boardobjgrp *pboardobjgrp = NULL; | ||
442 | |||
443 | nvgpu_log_info(g, " "); | ||
444 | |||
445 | pboardobjgrp = | ||
446 | &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super; | ||
447 | |||
448 | if (!pboardobjgrp->bconstructed) { | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | |||
452 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
453 | |||
454 | nvgpu_log_info(g, "Done"); | ||
455 | return status; | ||
456 | } | ||
457 | |||
458 | int volt_policy_sw_setup(struct gk20a *g) | ||
459 | { | ||
460 | int status = 0; | ||
461 | struct boardobjgrp *pboardobjgrp = NULL; | ||
462 | |||
463 | nvgpu_log_info(g, " "); | ||
464 | |||
465 | status = boardobjgrpconstruct_e32(g, | ||
466 | &g->perf_pmu.volt.volt_policy_metadata.volt_policies); | ||
467 | if (status) { | ||
468 | nvgpu_err(g, | ||
469 | "error creating boardobjgrp for volt rail, status - 0x%x", | ||
470 | status); | ||
471 | goto done; | ||
472 | } | ||
473 | |||
474 | pboardobjgrp = | ||
475 | &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super; | ||
476 | |||
477 | pboardobjgrp->pmudatainstget = _volt_policy_devgrp_pmudata_instget; | ||
478 | pboardobjgrp->pmustatusinstget = _volt_policy_devgrp_pmustatus_instget; | ||
479 | pboardobjgrp->pmudatainit = _volt_policy_grp_pmudatainit_super; | ||
480 | |||
481 | /* Obtain Voltage Rail Table from VBIOS */ | ||
482 | status = volt_get_volt_policy_table(g, &g->perf_pmu.volt. | ||
483 | volt_policy_metadata); | ||
484 | if (status) { | ||
485 | goto done; | ||
486 | } | ||
487 | |||
488 | /* Populate data for the VOLT_RAIL PMU interface */ | ||
489 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, VOLT, VOLT_POLICY); | ||
490 | |||
491 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
492 | volt, VOLT, volt_policy, VOLT_POLICY); | ||
493 | if (status) { | ||
494 | nvgpu_err(g, | ||
495 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
496 | status); | ||
497 | goto done; | ||
498 | } | ||
499 | |||
500 | status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g, | ||
501 | &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super, | ||
502 | volt, VOLT, volt_policy, VOLT_POLICY); | ||
503 | if (status) { | ||
504 | nvgpu_err(g, | ||
505 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
506 | status); | ||
507 | goto done; | ||
508 | } | ||
509 | |||
510 | done: | ||
511 | nvgpu_log_info(g, " done status %x", status); | ||
512 | return status; | ||
513 | } | ||