aboutsummaryrefslogtreecommitdiffstats
path: root/include/volt/volt_rail.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
commit01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 (patch)
tree4ef34501728a087be24f4ba0af90f91486bf780b /include/volt/volt_rail.c
parent306a03d18b305e4e573be3b2931978fa10679eb9 (diff)
Include nvgpu headers
These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future.
Diffstat (limited to 'include/volt/volt_rail.c')
-rw-r--r--include/volt/volt_rail.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/include/volt/volt_rail.c b/include/volt/volt_rail.c
new file mode 100644
index 0000000..caf297f
--- /dev/null
+++ b/include/volt/volt_rail.c
@@ -0,0 +1,485 @@
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
33u8 volt_rail_volt_domain_convert_to_idx(struct gk20a *g, u8 volt_domain)
34{
35 switch (g->perf_pmu.volt.volt_rail_metadata.volt_domain_hal) {
36 case CTRL_VOLT_DOMAIN_HAL_GP10X_SINGLE_RAIL:
37 switch (volt_domain) {
38 case CTRL_VOLT_DOMAIN_LOGIC:
39 return 0;
40 }
41 break;
42 case CTRL_VOLT_DOMAIN_HAL_GP10X_SPLIT_RAIL:
43 switch (volt_domain) {
44 case CTRL_VOLT_DOMAIN_LOGIC:
45 return 0;
46 case CTRL_VOLT_DOMAIN_SRAM:
47 return 1;
48 }
49 break;
50 }
51
52 return CTRL_BOARDOBJ_IDX_INVALID;
53}
54
55u32 volt_rail_volt_dev_register(struct gk20a *g, struct voltage_rail
56 *pvolt_rail, u8 volt_dev_idx, u8 operation_type)
57{
58 u32 status = 0;
59
60 if (operation_type == CTRL_VOLT_DEVICE_OPERATION_TYPE_DEFAULT) {
61 if (pvolt_rail->volt_dev_idx_default ==
62 CTRL_BOARDOBJ_IDX_INVALID) {
63 pvolt_rail->volt_dev_idx_default = volt_dev_idx;
64 } else {
65 status = -EINVAL;
66 goto exit;
67 }
68 } else if (operation_type ==
69 CTRL_VOLT_VOLT_DEVICE_OPERATION_TYPE_IPC_VMIN) {
70 if (pvolt_rail->volt_dev_idx_ipc_vmin ==
71 CTRL_BOARDOBJ_IDX_INVALID) {
72 pvolt_rail->volt_dev_idx_ipc_vmin = volt_dev_idx;
73 /*
74 * Exit on purpose as we do not want to register
75 * IPC_VMIN device against the rail to avoid
76 * setting current voltage instead of
77 * IPC Vmin voltage.
78 */
79 goto exit;
80 } else {
81 status = -EINVAL;
82 goto exit;
83 }
84 } else {
85 goto exit;
86 }
87
88 status = boardobjgrpmask_bitset(&pvolt_rail->volt_dev_mask.super,
89 volt_dev_idx);
90
91exit:
92 if (status) {
93 nvgpu_err(g, "Failed to register VOLTAGE_DEVICE");
94 }
95
96 return status;
97}
98
99static u32 volt_rail_state_init(struct gk20a *g,
100 struct voltage_rail *pvolt_rail)
101{
102 u32 status = 0;
103 u32 i;
104
105 pvolt_rail->volt_dev_idx_default = CTRL_BOARDOBJ_IDX_INVALID;
106
107 for (i = 0; i < CTRL_VOLT_RAIL_VOLT_DELTA_MAX_ENTRIES; i++) {
108 pvolt_rail->volt_delta_uv[i] = (int)NV_PMU_VOLT_VALUE_0V_IN_UV;
109 g->perf_pmu.volt.volt_rail_metadata.ext_rel_delta_uv[i] =
110 NV_PMU_VOLT_VALUE_0V_IN_UV;
111 }
112
113 pvolt_rail->volt_margin_limit_vfe_equ_mon_handle =
114 NV_PMU_PERF_RPC_VFE_EQU_MONITOR_COUNT_MAX;
115 pvolt_rail->rel_limit_vfe_equ_mon_handle =
116 NV_PMU_PERF_RPC_VFE_EQU_MONITOR_COUNT_MAX;
117 pvolt_rail->alt_rel_limit_vfe_equ_mon_handle =
118 NV_PMU_PERF_RPC_VFE_EQU_MONITOR_COUNT_MAX;
119 pvolt_rail->ov_limit_vfe_equ_mon_handle =
120 NV_PMU_PERF_RPC_VFE_EQU_MONITOR_COUNT_MAX;
121
122 status = boardobjgrpmask_e32_init(&pvolt_rail->volt_dev_mask, NULL);
123 if (status) {
124 nvgpu_err(g,
125 "Failed to initialize BOARDOBJGRPMASK of VOLTAGE_DEVICEs");
126 }
127
128 return status;
129}
130
131static int volt_rail_init_pmudata_super(struct gk20a *g,
132 struct boardobj *board_obj_ptr, struct nv_pmu_boardobj *ppmudata)
133{
134 int status = 0;
135 struct voltage_rail *prail;
136 struct nv_pmu_volt_volt_rail_boardobj_set *rail_pmu_data;
137 u32 i;
138
139 nvgpu_log_info(g, " ");
140
141 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
142 if (status) {
143 return status;
144 }
145
146 prail = (struct voltage_rail *)board_obj_ptr;
147 rail_pmu_data = (struct nv_pmu_volt_volt_rail_boardobj_set *)
148 ppmudata;
149
150 rail_pmu_data->rel_limit_vfe_equ_idx = prail->rel_limit_vfe_equ_idx;
151 rail_pmu_data->alt_rel_limit_vfe_equ_idx =
152 prail->alt_rel_limit_vfe_equ_idx;
153 rail_pmu_data->ov_limit_vfe_equ_idx = prail->ov_limit_vfe_equ_idx;
154 rail_pmu_data->vmin_limit_vfe_equ_idx = prail->vmin_limit_vfe_equ_idx;
155 rail_pmu_data->volt_margin_limit_vfe_equ_idx =
156 prail->volt_margin_limit_vfe_equ_idx;
157 rail_pmu_data->pwr_equ_idx = prail->pwr_equ_idx;
158 rail_pmu_data->volt_dev_idx_default = prail->volt_dev_idx_default;
159 rail_pmu_data->volt_scale_exp_pwr_equ_idx =
160 prail->volt_scale_exp_pwr_equ_idx;
161 rail_pmu_data->volt_dev_idx_ipc_vmin = prail->volt_dev_idx_ipc_vmin;
162
163 for (i = 0; i < CTRL_VOLT_RAIL_VOLT_DELTA_MAX_ENTRIES; i++) {
164 rail_pmu_data->volt_delta_uv[i] = prail->volt_delta_uv[i] +
165 (int)g->perf_pmu.volt.volt_rail_metadata.ext_rel_delta_uv[i];
166 }
167
168 status = boardobjgrpmask_export(&prail->volt_dev_mask.super,
169 prail->volt_dev_mask.super.bitcount,
170 &rail_pmu_data->volt_dev_mask.super);
171 if (status) {
172 nvgpu_err(g,
173 "Failed to export BOARDOBJGRPMASK of VOLTAGE_DEVICEs");
174 }
175
176 nvgpu_log_info(g, "Done");
177
178 return status;
179}
180
181static struct voltage_rail *construct_volt_rail(struct gk20a *g, void *pargs)
182{
183 struct boardobj *board_obj_ptr = NULL;
184 struct voltage_rail *ptemp_rail = (struct voltage_rail *)pargs;
185 struct voltage_rail *board_obj_volt_rail_ptr = NULL;
186 int status;
187
188 nvgpu_log_info(g, " ");
189 status = boardobj_construct_super(g, &board_obj_ptr,
190 sizeof(struct voltage_rail), pargs);
191 if (status) {
192 return NULL;
193 }
194
195 board_obj_volt_rail_ptr = (struct voltage_rail *)board_obj_ptr;
196 /* override super class interface */
197 board_obj_ptr->pmudatainit = volt_rail_init_pmudata_super;
198
199 board_obj_volt_rail_ptr->boot_voltage_uv =
200 ptemp_rail->boot_voltage_uv;
201 board_obj_volt_rail_ptr->rel_limit_vfe_equ_idx =
202 ptemp_rail->rel_limit_vfe_equ_idx;
203 board_obj_volt_rail_ptr->alt_rel_limit_vfe_equ_idx =
204 ptemp_rail->alt_rel_limit_vfe_equ_idx;
205 board_obj_volt_rail_ptr->ov_limit_vfe_equ_idx =
206 ptemp_rail->ov_limit_vfe_equ_idx;
207 board_obj_volt_rail_ptr->pwr_equ_idx =
208 ptemp_rail->pwr_equ_idx;
209 board_obj_volt_rail_ptr->boot_volt_vfe_equ_idx =
210 ptemp_rail->boot_volt_vfe_equ_idx;
211 board_obj_volt_rail_ptr->vmin_limit_vfe_equ_idx =
212 ptemp_rail->vmin_limit_vfe_equ_idx;
213 board_obj_volt_rail_ptr->volt_margin_limit_vfe_equ_idx =
214 ptemp_rail->volt_margin_limit_vfe_equ_idx;
215 board_obj_volt_rail_ptr->volt_scale_exp_pwr_equ_idx =
216 ptemp_rail->volt_scale_exp_pwr_equ_idx;
217
218 nvgpu_log_info(g, "Done");
219
220 return (struct voltage_rail *)board_obj_ptr;
221}
222
223u8 volt_rail_vbios_volt_domain_convert_to_internal(struct gk20a *g,
224 u8 vbios_volt_domain)
225{
226 switch (g->perf_pmu.volt.volt_rail_metadata.volt_domain_hal) {
227 case CTRL_VOLT_DOMAIN_HAL_GP10X_SINGLE_RAIL:
228 if (vbios_volt_domain == 0U) {
229 return CTRL_VOLT_DOMAIN_LOGIC;
230 }
231 break;
232 case CTRL_VOLT_DOMAIN_HAL_GP10X_SPLIT_RAIL:
233 switch (vbios_volt_domain) {
234 case 0:
235 return CTRL_VOLT_DOMAIN_LOGIC;
236 case 1:
237 return CTRL_VOLT_DOMAIN_SRAM;
238 }
239 break;
240 }
241
242 return CTRL_VOLT_DOMAIN_INVALID;
243}
244
245int volt_rail_pmu_setup(struct gk20a *g)
246{
247 int status;
248 struct boardobjgrp *pboardobjgrp = NULL;
249
250 nvgpu_log_info(g, " ");
251
252 pboardobjgrp = &g->perf_pmu.volt.volt_rail_metadata.volt_rails.super;
253
254 if (!pboardobjgrp->bconstructed) {
255 return -EINVAL;
256 }
257
258 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
259
260 nvgpu_log_info(g, "Done");
261 return status;
262}
263
264static int volt_get_volt_rail_table(struct gk20a *g,
265 struct voltage_rail_metadata *pvolt_rail_metadata)
266{
267 int status = 0;
268 u8 *volt_rail_table_ptr = NULL;
269 struct voltage_rail *prail = NULL;
270 struct vbios_voltage_rail_table_1x_header header = { 0 };
271 struct vbios_voltage_rail_table_1x_entry entry = { 0 };
272 u8 i;
273 u8 volt_domain;
274 u8 *entry_ptr;
275 union rail_type {
276 struct boardobj board_obj;
277 struct voltage_rail volt_rail;
278 } rail_type_data;
279
280 volt_rail_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
281 g->bios.perf_token, VOLTAGE_RAIL_TABLE);
282 if (volt_rail_table_ptr == NULL) {
283 status = -EINVAL;
284 goto done;
285 }
286
287 memcpy(&header, volt_rail_table_ptr,
288 sizeof(struct vbios_voltage_rail_table_1x_header));
289
290 pvolt_rail_metadata->volt_domain_hal = (u8)header.volt_domain_hal;
291
292 for (i = 0; i < header.num_table_entries; i++) {
293 entry_ptr = (volt_rail_table_ptr + header.header_size +
294 (i * header.table_entry_size));
295
296 memset(&rail_type_data, 0x0, sizeof(rail_type_data));
297
298 memcpy(&entry, entry_ptr,
299 sizeof(struct vbios_voltage_rail_table_1x_entry));
300
301 volt_domain = volt_rail_vbios_volt_domain_convert_to_internal(g,
302 i);
303 if (volt_domain == CTRL_VOLT_DOMAIN_INVALID) {
304 continue;
305 }
306
307 rail_type_data.board_obj.type = volt_domain;
308 rail_type_data.volt_rail.boot_voltage_uv =
309 (u32)entry.boot_voltage_uv;
310 rail_type_data.volt_rail.rel_limit_vfe_equ_idx =
311 (u8)entry.rel_limit_vfe_equ_idx;
312 rail_type_data.volt_rail.alt_rel_limit_vfe_equ_idx =
313 (u8)entry.alt_rel_limit_vfe_equidx;
314 rail_type_data.volt_rail.ov_limit_vfe_equ_idx =
315 (u8)entry.ov_limit_vfe_equ_idx;
316
317 if (header.table_entry_size >=
318 NV_VBIOS_VOLTAGE_RAIL_1X_ENTRY_SIZE_0C) {
319 rail_type_data.volt_rail.volt_scale_exp_pwr_equ_idx =
320 (u8)entry.volt_scale_exp_pwr_equ_idx;
321 } else {
322 rail_type_data.volt_rail.volt_scale_exp_pwr_equ_idx =
323 CTRL_BOARDOBJ_IDX_INVALID;
324 }
325
326 if (header.table_entry_size >=
327 NV_VBIOS_VOLTAGE_RAIL_1X_ENTRY_SIZE_0B) {
328 rail_type_data.volt_rail.volt_margin_limit_vfe_equ_idx =
329 (u8)entry.volt_margin_limit_vfe_equ_idx;
330 } else {
331 rail_type_data.volt_rail.volt_margin_limit_vfe_equ_idx =
332 CTRL_BOARDOBJ_IDX_INVALID;
333 }
334
335 if (header.table_entry_size >=
336 NV_VBIOS_VOLTAGE_RAIL_1X_ENTRY_SIZE_0A) {
337 rail_type_data.volt_rail.vmin_limit_vfe_equ_idx =
338 (u8)entry.vmin_limit_vfe_equ_idx;
339 } else {
340 rail_type_data.volt_rail.vmin_limit_vfe_equ_idx =
341 CTRL_BOARDOBJ_IDX_INVALID;
342 }
343
344 if (header.table_entry_size >=
345 NV_VBIOS_VOLTAGE_RAIL_1X_ENTRY_SIZE_09) {
346 rail_type_data.volt_rail.boot_volt_vfe_equ_idx =
347 (u8)entry.boot_volt_vfe_equ_idx;
348 } else {
349 rail_type_data.volt_rail.boot_volt_vfe_equ_idx =
350 CTRL_BOARDOBJ_IDX_INVALID;
351 }
352
353 if (header.table_entry_size >=
354 NV_VBIOS_VOLTAGE_RAIL_1X_ENTRY_SIZE_08) {
355 rail_type_data.volt_rail.pwr_equ_idx =
356 (u8)entry.pwr_equ_idx;
357 } else {
358 rail_type_data.volt_rail.pwr_equ_idx =
359 CTRL_PMGR_PWR_EQUATION_INDEX_INVALID;
360 }
361
362 prail = construct_volt_rail(g, &rail_type_data);
363
364 status = boardobjgrp_objinsert(
365 &pvolt_rail_metadata->volt_rails.super,
366 (struct boardobj *)prail, i);
367 }
368
369done:
370 return status;
371}
372
373static int _volt_rail_devgrp_pmudata_instget(struct gk20a *g,
374 struct nv_pmu_boardobjgrp *pmuboardobjgrp, struct nv_pmu_boardobj
375 **ppboardobjpmudata, u8 idx)
376{
377 struct nv_pmu_volt_volt_rail_boardobj_grp_set *pgrp_set =
378 (struct nv_pmu_volt_volt_rail_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
395static int _volt_rail_devgrp_pmustatus_instget(struct gk20a *g,
396 void *pboardobjgrppmu, struct nv_pmu_boardobj_query
397 **ppboardobjpmustatus, u8 idx)
398{
399 struct nv_pmu_volt_volt_rail_boardobj_grp_get_status *pgrp_get_status =
400 (struct nv_pmu_volt_volt_rail_boardobj_grp_get_status *)
401 pboardobjgrppmu;
402
403 /*check whether pmuboardobjgrp has a valid boardobj in index*/
404 if (((u32)BIT(idx) &
405 pgrp_get_status->hdr.data.super.obj_mask.super.data[0]) == 0U) {
406 return -EINVAL;
407 }
408
409 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
410 &pgrp_get_status->objects[idx].data.board_obj;
411 return 0;
412}
413
414int volt_rail_sw_setup(struct gk20a *g)
415{
416 int status = 0;
417 struct boardobjgrp *pboardobjgrp = NULL;
418 struct voltage_rail *pvolt_rail;
419 u8 i;
420
421 nvgpu_log_info(g, " ");
422
423 status = boardobjgrpconstruct_e32(g,
424 &g->perf_pmu.volt.volt_rail_metadata.volt_rails);
425 if (status) {
426 nvgpu_err(g,
427 "error creating boardobjgrp for volt rail, status - 0x%x",
428 status);
429 goto done;
430 }
431
432 pboardobjgrp = &g->perf_pmu.volt.volt_rail_metadata.volt_rails.super;
433
434 pboardobjgrp->pmudatainstget = _volt_rail_devgrp_pmudata_instget;
435 pboardobjgrp->pmustatusinstget = _volt_rail_devgrp_pmustatus_instget;
436
437 g->perf_pmu.volt.volt_rail_metadata.pct_delta =
438 NV_PMU_VOLT_VALUE_0V_IN_UV;
439
440 /* Obtain Voltage Rail Table from VBIOS */
441 status = volt_get_volt_rail_table(g, &g->perf_pmu.volt.
442 volt_rail_metadata);
443 if (status) {
444 goto done;
445 }
446
447 /* Populate data for the VOLT_RAIL PMU interface */
448 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, VOLT, VOLT_RAIL);
449
450 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
451 volt, VOLT, volt_rail, VOLT_RAIL);
452 if (status) {
453 nvgpu_err(g,
454 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
455 status);
456 goto done;
457 }
458
459 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
460 &g->perf_pmu.volt.volt_rail_metadata.volt_rails.super,
461 volt, VOLT, volt_rail, VOLT_RAIL);
462 if (status) {
463 nvgpu_err(g,
464 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
465 status);
466 goto done;
467 }
468
469 /* update calibration to fuse */
470 BOARDOBJGRP_FOR_EACH(&(g->perf_pmu.volt.volt_rail_metadata.
471 volt_rails.super),
472 struct voltage_rail *, pvolt_rail, i) {
473 status = volt_rail_state_init(g, pvolt_rail);
474 if (status) {
475 nvgpu_err(g,
476 "Failure while executing RAIL's state init railIdx = %d",
477 i);
478 goto done;
479 }
480 }
481
482done:
483 nvgpu_log_info(g, " done status %x", status);
484 return status;
485}