summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/pmgr/pwrpolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/pmgr/pwrpolicy.c')
-rw-r--r--drivers/gpu/nvgpu/pmgr/pwrpolicy.c680
1 files changed, 680 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/pmgr/pwrpolicy.c b/drivers/gpu/nvgpu/pmgr/pwrpolicy.c
new file mode 100644
index 00000000..bec13b0c
--- /dev/null
+++ b/drivers/gpu/nvgpu/pmgr/pwrpolicy.c
@@ -0,0 +1,680 @@
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#include "pwrpolicy.h"
16#include "include/bios.h"
17#include "boardobj/boardobjgrp.h"
18#include "boardobj/boardobjgrp_e32.h"
19#include "pmuif/gpmuifboardobj.h"
20#include "pmuif/gpmuifpmgr.h"
21#include "gm206/bios_gm206.h"
22#include "gk20a/pmu_gk20a.h"
23
24#define _pwr_policy_limitarboutputget_helper(p_limit_arb) (p_limit_arb)->output
25#define _pwr_policy_limitdeltaapply(limit, delta) ((u32)max(((s32)limit) + (delta), 0))
26
27static u32 _pwr_policy_limitarbinputset_helper(struct gk20a *g,
28 struct ctrl_pmgr_pwr_policy_limit_arbitration *p_limit_arb,
29 u8 client_idx,
30 u32 limit_value)
31{
32 u8 indx;
33 bool b_found = false;
34 u32 status = 0;
35 u32 output = limit_value;
36
37 for (indx = 0; indx< p_limit_arb->num_inputs; indx++) {
38 if (p_limit_arb->inputs[indx].pwr_policy_idx == client_idx) {
39 p_limit_arb->inputs[indx].limit_value = limit_value;
40 b_found = true;
41 } else if (p_limit_arb->b_arb_max) {
42 output = max(output, p_limit_arb->inputs[indx].limit_value);
43 } else {
44 output = min(output, p_limit_arb->inputs[indx].limit_value);
45 }
46 }
47
48 if (!b_found) {
49 if (p_limit_arb->num_inputs <
50 CTRL_PMGR_PWR_POLICY_MAX_LIMIT_INPUTS) {
51 p_limit_arb->inputs[
52 p_limit_arb->num_inputs].pwr_policy_idx = client_idx;
53 p_limit_arb->inputs[
54 p_limit_arb->num_inputs].limit_value = limit_value;
55 p_limit_arb->num_inputs++;
56 } else {
57 gk20a_err(g->dev, "No entries remaining for clientIdx=%d",
58 client_idx);
59 status = -EINVAL;
60 }
61 }
62
63 if (!status) {
64 p_limit_arb->output = output;
65 }
66
67 return status;
68}
69
70static u32 _pwr_policy_limitid_translate(struct gk20a *g,
71 struct pwr_policy *ppolicy,
72 enum pwr_policy_limit_id limit_id,
73 struct ctrl_pmgr_pwr_policy_limit_arbitration **p_limit_arb,
74 struct ctrl_pmgr_pwr_policy_limit_arbitration **p_limit_arb_sec)
75{
76 u32 status = 0;
77
78 switch (limit_id) {
79 case PWR_POLICY_LIMIT_ID_MIN:
80 *p_limit_arb = &ppolicy->limit_arb_min;
81 break;
82
83 case PWR_POLICY_LIMIT_ID_RATED:
84 *p_limit_arb = &ppolicy->limit_arb_rated;
85
86 if (p_limit_arb_sec != NULL) {
87 *p_limit_arb_sec = &ppolicy->limit_arb_curr;
88 }
89 break;
90
91 case PWR_POLICY_LIMIT_ID_MAX:
92 *p_limit_arb = &ppolicy->limit_arb_max;
93 break;
94
95 case PWR_POLICY_LIMIT_ID_CURR:
96 *p_limit_arb = &ppolicy->limit_arb_curr;
97 break;
98
99 case PWR_POLICY_LIMIT_ID_BATT:
100 *p_limit_arb = &ppolicy->limit_arb_batt;
101 break;
102
103 default:
104 gk20a_err(g->dev, "Unsupported limitId=%d",
105 limit_id);
106 status = -EINVAL;
107 break;
108 }
109
110 return status;
111}
112
113static u32 _pwr_policy_limitarbinputset(struct gk20a *g,
114 struct pwr_policy *ppolicy,
115 enum pwr_policy_limit_id limit_id,
116 u8 client_idx,
117 u32 limit)
118{
119 u32 status = 0;
120 struct ctrl_pmgr_pwr_policy_limit_arbitration *p_limit_arb = NULL;
121 struct ctrl_pmgr_pwr_policy_limit_arbitration *p_limit_arb_sec = NULL;
122
123 status = _pwr_policy_limitid_translate(g,
124 ppolicy,
125 limit_id,
126 &p_limit_arb,
127 &p_limit_arb_sec);
128 if (status) {
129 goto exit;
130 }
131
132 status = _pwr_policy_limitarbinputset_helper(g, p_limit_arb, client_idx, limit);
133 if (status) {
134 gk20a_err(g->dev,
135 "Error setting client limit value: status=0x%08x, limitId=0x%x, clientIdx=0x%x, limit=%d",
136 status, limit_id, client_idx, limit);
137 goto exit;
138 }
139
140 if (NULL != p_limit_arb_sec) {
141 status = _pwr_policy_limitarbinputset_helper(g, p_limit_arb_sec,
142 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
143 _pwr_policy_limitarboutputget_helper(p_limit_arb));
144 }
145
146exit:
147 return status;
148}
149
150static inline void _pwr_policy_limitarbconstruct(
151 struct ctrl_pmgr_pwr_policy_limit_arbitration *p_limit_arb,
152 bool b_arb_max)
153{
154 p_limit_arb->num_inputs = 0;
155 p_limit_arb->b_arb_max = b_arb_max;
156}
157
158static u32 _pwr_policy_limitarboutputget(struct gk20a *g,
159 struct pwr_policy *ppolicy,
160 enum pwr_policy_limit_id limit_id)
161{
162 u32 status = 0;
163 struct ctrl_pmgr_pwr_policy_limit_arbitration *p_limit_arb = NULL;
164
165 status = _pwr_policy_limitid_translate(g,
166 ppolicy,
167 limit_id,
168 &p_limit_arb,
169 NULL);
170 if (status) {
171 return 0;
172 }
173
174 return _pwr_policy_limitarboutputget_helper(p_limit_arb);
175}
176
177static u32 _pwr_domains_pmudatainit_hw_threshold(struct gk20a *g,
178 struct boardobj *board_obj_ptr,
179 struct nv_pmu_boardobj *ppmudata)
180{
181 struct nv_pmu_pmgr_pwr_policy_hw_threshold *pmu_hw_threshold_data;
182 struct pwr_policy_hw_threshold *p_hw_threshold;
183 struct pwr_policy *p_pwr_policy;
184 struct nv_pmu_pmgr_pwr_policy *pmu_pwr_policy;
185 u32 status = 0;
186
187 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
188 if (status) {
189 gk20a_err(dev_from_gk20a(g),
190 "error updating pmu boardobjgrp for pwr sensor 0x%x",
191 status);
192 status = -ENOMEM;
193 goto done;
194 }
195
196 p_hw_threshold = (struct pwr_policy_hw_threshold *)board_obj_ptr;
197 pmu_hw_threshold_data = (struct nv_pmu_pmgr_pwr_policy_hw_threshold *) ppmudata;
198 pmu_pwr_policy = (struct nv_pmu_pmgr_pwr_policy *) ppmudata;
199 p_pwr_policy = (struct pwr_policy *)&(p_hw_threshold->super.super);
200
201 pmu_pwr_policy->ch_idx = 0;
202 pmu_pwr_policy->limit_unit = p_pwr_policy->limit_unit;
203 pmu_pwr_policy->num_limit_inputs = p_pwr_policy->num_limit_inputs;
204
205 pmu_pwr_policy->limit_min = _pwr_policy_limitdeltaapply(
206 _pwr_policy_limitarboutputget(g, p_pwr_policy,
207 PWR_POLICY_LIMIT_ID_MIN),
208 p_pwr_policy->limit_delta);
209
210 pmu_pwr_policy->limit_max = _pwr_policy_limitdeltaapply(
211 _pwr_policy_limitarboutputget(g, p_pwr_policy,
212 PWR_POLICY_LIMIT_ID_MAX),
213 p_pwr_policy->limit_delta);
214
215 pmu_pwr_policy->limit_curr = _pwr_policy_limitdeltaapply(
216 _pwr_policy_limitarboutputget(g, p_pwr_policy,
217 PWR_POLICY_LIMIT_ID_CURR),
218 p_pwr_policy->limit_delta);
219
220 memcpy(&pmu_pwr_policy->integral, &p_pwr_policy->integral,
221 sizeof(struct ctrl_pmgr_pwr_policy_info_integral));
222
223 pmu_pwr_policy->sample_mult = p_pwr_policy->sample_mult;
224 pmu_pwr_policy->filter_type = p_pwr_policy->filter_type;
225 pmu_pwr_policy->filter_param = p_pwr_policy->filter_param;
226
227 pmu_hw_threshold_data->threshold_idx = p_hw_threshold->threshold_idx;
228 pmu_hw_threshold_data->low_threshold_idx = p_hw_threshold->low_threshold_idx;
229 pmu_hw_threshold_data->b_use_low_threshold = p_hw_threshold->b_use_low_threshold;
230 pmu_hw_threshold_data->low_threshold_value = p_hw_threshold->low_threshold_value;
231
232done:
233 return status;
234}
235
236static struct boardobj *construct_pwr_policy(struct gk20a *g,
237 void *pargs, u16 pargs_size, u8 type)
238{
239 struct boardobj *board_obj_ptr = NULL;
240 u32 status;
241 struct pwr_policy_hw_threshold *pwrpolicyhwthreshold;
242 struct pwr_policy *pwrpolicy;
243 struct pwr_policy *pwrpolicyparams = (struct pwr_policy*)pargs;
244 struct pwr_policy_hw_threshold *hwthreshold = (struct pwr_policy_hw_threshold*)pargs;
245
246 status = boardobj_construct_super(g, &board_obj_ptr,
247 pargs_size, pargs);
248 if (status)
249 return NULL;
250
251 pwrpolicyhwthreshold = (struct pwr_policy_hw_threshold*)board_obj_ptr;
252 pwrpolicy = (struct pwr_policy *)board_obj_ptr;
253
254 /* Set Super class interfaces */
255 board_obj_ptr->pmudatainit = _pwr_domains_pmudatainit_hw_threshold;
256
257 pwrpolicy->ch_idx = pwrpolicyparams->ch_idx;
258 pwrpolicy->num_limit_inputs = 0;
259 pwrpolicy->limit_unit = pwrpolicyparams->limit_unit;
260 pwrpolicy->filter_type = (enum ctrl_pmgr_pwr_policy_filter_type)(pwrpolicyparams->filter_type);
261 pwrpolicy->sample_mult = pwrpolicyparams->sample_mult;
262 switch (pwrpolicy->filter_type)
263 {
264 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_NONE:
265 break;
266
267 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_BLOCK:
268 pwrpolicy->filter_param.block.block_size =
269 pwrpolicyparams->filter_param.block.block_size;
270 break;
271
272 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_MOVING_AVERAGE:
273 pwrpolicy->filter_param.moving_avg.window_size =
274 pwrpolicyparams->filter_param.moving_avg.window_size;
275 break;
276
277 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_IIR:
278 pwrpolicy->filter_param.iir.divisor = pwrpolicyparams->filter_param.iir.divisor;
279 break;
280
281 default:
282 gk20a_err(g->dev,
283 "Error: unrecognized Power Policy filter type: %d.\n",
284 pwrpolicy->filter_type);
285 }
286
287 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_curr, false);
288
289 pwrpolicy->limit_delta = 0;
290
291 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_min, true);
292 status = _pwr_policy_limitarbinputset(g,
293 pwrpolicy,
294 PWR_POLICY_LIMIT_ID_MIN,
295 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
296 pwrpolicyparams->limit_min);
297
298 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_max, false);
299 status = _pwr_policy_limitarbinputset(g,
300 pwrpolicy,
301 PWR_POLICY_LIMIT_ID_MAX,
302 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
303 pwrpolicyparams->limit_max);
304
305 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_rated, false);
306 status = _pwr_policy_limitarbinputset(g,
307 pwrpolicy,
308 PWR_POLICY_LIMIT_ID_RATED,
309 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
310 pwrpolicyparams->limit_rated);
311
312 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_batt, false);
313 status = _pwr_policy_limitarbinputset(g,
314 pwrpolicy,
315 PWR_POLICY_LIMIT_ID_BATT,
316 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
317 ((pwrpolicyparams->limit_batt != 0) ?
318 pwrpolicyparams->limit_batt:
319 CTRL_PMGR_PWR_POLICY_LIMIT_MAX));
320
321 memcpy(&pwrpolicy->integral, &pwrpolicyparams->integral,
322 sizeof(struct ctrl_pmgr_pwr_policy_info_integral));
323
324 pwrpolicyhwthreshold->threshold_idx = hwthreshold->threshold_idx;
325 pwrpolicyhwthreshold->b_use_low_threshold = hwthreshold->b_use_low_threshold;
326 pwrpolicyhwthreshold->low_threshold_idx = hwthreshold->low_threshold_idx;
327 pwrpolicyhwthreshold->low_threshold_value = hwthreshold->low_threshold_value;
328
329 gk20a_dbg_info(" Done");
330
331 return board_obj_ptr;
332}
333
334static u32 _pwr_policy_construct_WAR_policy(struct gk20a *g,
335 struct pmgr_pwr_policy *ppwrpolicyobjs,
336 union pwr_policy_data_union *ppwrpolicydata,
337 u16 pwr_policy_size,
338 u32 hw_threshold_policy_index,
339 u32 obj_index)
340{
341 u32 status = 0;
342 struct boardobj *boardobj;
343
344 if (!(hw_threshold_policy_index & 0x1)) {
345 /* CRIT policy */
346 ppwrpolicydata->pwrpolicy.limit_min = 1000;
347 ppwrpolicydata->pwrpolicy.limit_rated = 20000;
348 ppwrpolicydata->pwrpolicy.limit_max = 20000;
349 ppwrpolicydata->hw_threshold.threshold_idx = 0;
350 } else {
351 /* WARN policy */
352 ppwrpolicydata->pwrpolicy.limit_min = 1000;
353 ppwrpolicydata->pwrpolicy.limit_rated = 11600;
354 ppwrpolicydata->pwrpolicy.limit_max = 11600;
355 ppwrpolicydata->hw_threshold.threshold_idx = 1;
356 }
357
358 boardobj = construct_pwr_policy(g, ppwrpolicydata,
359 pwr_policy_size, ppwrpolicydata->boardobj.type);
360
361 if (!boardobj) {
362 gk20a_err(dev_from_gk20a(g),
363 "unable to create pwr policy for type %d", ppwrpolicydata->boardobj.type);
364 status = -EINVAL;
365 goto done;
366 }
367
368 status = boardobjgrp_objinsert(&ppwrpolicyobjs->pwr_policies.super,
369 boardobj, obj_index);
370
371 if (status) {
372 gk20a_err(dev_from_gk20a(g),
373 "unable to insert pwr policy boardobj for %d", obj_index);
374 status = -EINVAL;
375 goto done;
376 }
377done:
378 return status;
379}
380
381static u32 devinit_get_pwr_policy_table(struct gk20a *g,
382 struct pmgr_pwr_policy *ppwrpolicyobjs)
383{
384 u32 status = 0;
385 u8 *pwr_policy_table_ptr = NULL;
386 u8 *curr_pwr_policy_table_ptr = NULL;
387 struct boardobj *boardobj;
388 struct pwr_policy_3x_header_struct pwr_policy_table_header = { 0 };
389 struct pwr_policy_3x_entry_struct pwr_policy_table_entry = { 0 };
390 u32 index;
391 u32 obj_index = 0;
392 u16 pwr_policy_size;
393 bool integral_control = false;
394 u32 hw_threshold_policy_index = 0;
395 union pwr_policy_data_union pwr_policy_data;
396
397 gk20a_dbg_info("");
398
399 if (g->ops.bios.get_perf_table_ptrs != NULL) {
400 pwr_policy_table_ptr = (u8 *)g->ops.bios.get_perf_table_ptrs(g,
401 g->bios.perf_token, POWER_CAPPING_TABLE);
402 if (pwr_policy_table_ptr == NULL) {
403 status = -EINVAL;
404 goto done;
405 }
406 }
407
408 memcpy(&pwr_policy_table_header.version,
409 (pwr_policy_table_ptr),
410 14);
411
412 memcpy(&pwr_policy_table_header.d2_limit,
413 (pwr_policy_table_ptr + 14),
414 (VBIOS_POWER_POLICY_3X_ENTRY_SIZE_2E - 14));
415
416 if (pwr_policy_table_header.version !=
417 VBIOS_POWER_POLICY_VERSION_3X) {
418 status = -EINVAL;
419 goto done;
420 }
421
422 if (pwr_policy_table_header.header_size <
423 VBIOS_POWER_POLICY_3X_HEADER_SIZE_25) {
424 status = -EINVAL;
425 goto done;
426 }
427
428 if (pwr_policy_table_header.table_entry_size !=
429 VBIOS_POWER_POLICY_3X_ENTRY_SIZE_2E) {
430 status = -EINVAL;
431 goto done;
432 }
433
434 curr_pwr_policy_table_ptr = (pwr_policy_table_ptr +
435 VBIOS_POWER_POLICY_3X_HEADER_SIZE_25);
436
437 for (index = 0; index < pwr_policy_table_header.num_table_entries;
438 index++) {
439 u8 class_type;
440
441 curr_pwr_policy_table_ptr += (pwr_policy_table_header.table_entry_size * index);
442
443 pwr_policy_table_entry.flags0 = *curr_pwr_policy_table_ptr;
444 pwr_policy_table_entry.ch_idx = *(curr_pwr_policy_table_ptr + 1);
445
446 memcpy(&pwr_policy_table_entry.limit_min,
447 (curr_pwr_policy_table_ptr + 2),
448 35);
449
450 memcpy(&pwr_policy_table_entry.ratio_min,
451 (curr_pwr_policy_table_ptr + 2 + 35),
452 4);
453
454 pwr_policy_table_entry.sample_mult =
455 *(curr_pwr_policy_table_ptr + 2 + 35 + 4);
456
457 memcpy(&pwr_policy_table_entry.filter_param,
458 (curr_pwr_policy_table_ptr + 2 + 35 + 4 + 1),
459 4);
460
461 class_type = (u8)BIOS_GET_FIELD(
462 pwr_policy_table_entry.flags0,
463 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_CLASS);
464
465 if (class_type == NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_CLASS_HW_THRESHOLD) {
466 ppwrpolicyobjs->version = CTRL_PMGR_PWR_POLICY_TABLE_VERSION_3X;
467 ppwrpolicyobjs->base_sample_period = (u16)
468 pwr_policy_table_header.base_sample_period;
469 ppwrpolicyobjs->min_client_sample_period = (u16)
470 pwr_policy_table_header.min_client_sample_period;
471 ppwrpolicyobjs->low_sampling_mult =
472 pwr_policy_table_header.low_sampling_mult;
473
474 ppwrpolicyobjs->policy_idxs[1] =
475 (u8)pwr_policy_table_header.tgp_policy_idx;
476 ppwrpolicyobjs->policy_idxs[0] =
477 (u8)pwr_policy_table_header.rtp_policy_idx;
478 ppwrpolicyobjs->policy_idxs[2] =
479 pwr_policy_table_header.mxm_policy_idx;
480 ppwrpolicyobjs->policy_idxs[3] =
481 pwr_policy_table_header.dnotifier_policy_idx;
482 ppwrpolicyobjs->ext_limits[0].limit =
483 pwr_policy_table_header.d2_limit;
484 ppwrpolicyobjs->ext_limits[1].limit =
485 pwr_policy_table_header.d3_limit;
486 ppwrpolicyobjs->ext_limits[2].limit =
487 pwr_policy_table_header.d4_limit;
488 ppwrpolicyobjs->ext_limits[3].limit =
489 pwr_policy_table_header.d5_limit;
490 ppwrpolicyobjs->policy_idxs[4] =
491 pwr_policy_table_header.pwr_tgt_policy_idx;
492 ppwrpolicyobjs->policy_idxs[5] =
493 pwr_policy_table_header.pwr_tgt_floor_policy_idx;
494 ppwrpolicyobjs->policy_idxs[6] =
495 pwr_policy_table_header.sm_bus_policy_idx;
496
497 integral_control = (bool)BIOS_GET_FIELD(
498 pwr_policy_table_entry.flags1,
499 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS1_INTEGRAL_CONTROL);
500
501 if (integral_control == 0x01) {
502 pwr_policy_data.pwrpolicy.integral.past_sample_count = (u8)
503 pwr_policy_table_entry.past_length;
504 pwr_policy_data.pwrpolicy.integral.next_sample_count = (u8)
505 pwr_policy_table_entry.next_length;
506 pwr_policy_data.pwrpolicy.integral.ratio_limit_max = (u16)
507 pwr_policy_table_entry.ratio_max;
508 pwr_policy_data.pwrpolicy.integral.ratio_limit_min = (u16)
509 pwr_policy_table_entry.ratio_min;
510 } else {
511 memset(&(pwr_policy_data.pwrpolicy.integral), 0x0,
512 sizeof(struct ctrl_pmgr_pwr_policy_info_integral));
513 }
514 pwr_policy_data.hw_threshold.threshold_idx = (u8)
515 BIOS_GET_FIELD(
516 pwr_policy_table_entry.param0,
517 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_THRES_IDX);
518
519 pwr_policy_data.hw_threshold.b_use_low_threshold =
520 BIOS_GET_FIELD(
521 pwr_policy_table_entry.param0,
522 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_LOW_THRESHOLD_USE);
523
524 if (pwr_policy_data.hw_threshold.b_use_low_threshold) {
525 pwr_policy_data.hw_threshold.low_threshold_idx = (u8)
526 BIOS_GET_FIELD(
527 pwr_policy_table_entry.param0,
528 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_LOW_THRESHOLD_IDX);
529
530 pwr_policy_data.hw_threshold.low_threshold_value = (u16)
531 BIOS_GET_FIELD(
532 pwr_policy_table_entry.param1,
533 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM1_HW_THRESHOLD_LOW_THRESHOLD_VAL);
534 }
535
536 pwr_policy_size = sizeof(struct pwr_policy_hw_threshold);
537 } else
538 continue;
539
540 /* Initialize data for the parent class */
541 pwr_policy_data.boardobj.type = CTRL_PMGR_PWR_POLICY_TYPE_HW_THRESHOLD;
542 pwr_policy_data.pwrpolicy.ch_idx = (u8)pwr_policy_table_entry.ch_idx;
543 pwr_policy_data.pwrpolicy.limit_unit = (u8)
544 BIOS_GET_FIELD(
545 pwr_policy_table_entry.flags0,
546 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_LIMIT_UNIT);
547 pwr_policy_data.pwrpolicy.filter_type = (u8)
548 BIOS_GET_FIELD(
549 pwr_policy_table_entry.flags1,
550 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS1_FILTER_TYPE);
551 pwr_policy_data.pwrpolicy.limit_min = pwr_policy_table_entry.limit_min;
552 pwr_policy_data.pwrpolicy.limit_rated = pwr_policy_table_entry.limit_rated;
553 pwr_policy_data.pwrpolicy.limit_max = pwr_policy_table_entry.limit_max;
554 pwr_policy_data.pwrpolicy.limit_batt = pwr_policy_table_entry.limit_batt;
555
556 pwr_policy_data.pwrpolicy.sample_mult = (u8)pwr_policy_table_entry.sample_mult;
557
558 /* Filled the entry.filterParam value in the filterParam */
559 pwr_policy_data.pwrpolicy.filter_param.block.block_size = 0;
560 pwr_policy_data.pwrpolicy.filter_param.moving_avg.window_size = 0;
561 pwr_policy_data.pwrpolicy.filter_param.iir.divisor = 0;
562
563 hw_threshold_policy_index |=
564 BIT(pwr_policy_data.hw_threshold.threshold_idx);
565
566 boardobj = construct_pwr_policy(g, &pwr_policy_data,
567 pwr_policy_size, pwr_policy_data.boardobj.type);
568
569 if (!boardobj) {
570 gk20a_err(dev_from_gk20a(g),
571 "unable to create pwr policy for %d type %d", index, pwr_policy_data.boardobj.type);
572 status = -EINVAL;
573 goto done;
574 }
575
576 status = boardobjgrp_objinsert(&ppwrpolicyobjs->pwr_policies.super,
577 boardobj, obj_index);
578
579 if (status) {
580 gk20a_err(dev_from_gk20a(g),
581 "unable to insert pwr policy boardobj for %d", index);
582 status = -EINVAL;
583 goto done;
584 }
585
586 ++obj_index;
587 }
588
589 if (hw_threshold_policy_index &&
590 (hw_threshold_policy_index < 0x3)) {
591 status = _pwr_policy_construct_WAR_policy(g,
592 ppwrpolicyobjs,
593 &pwr_policy_data,
594 pwr_policy_size,
595 hw_threshold_policy_index,
596 obj_index);
597 if (status) {
598 gk20a_err(dev_from_gk20a(g),
599 "unable to construct_WAR_policy");
600 status = -EINVAL;
601 goto done;
602 }
603 ++obj_index;
604 }
605
606done:
607 gk20a_dbg_info(" done status %x", status);
608 return status;
609}
610
611u32 pmgr_policy_sw_setup(struct gk20a *g)
612{
613 u32 status;
614 struct boardobjgrp *pboardobjgrp = NULL;
615 struct pwr_policy *ppolicy;
616 struct pmgr_pwr_policy *ppwrpolicyobjs;
617 u8 indx = 0;
618
619 /* Construct the Super Class and override the Interfaces */
620 status = boardobjgrpconstruct_e32(
621 &g->pmgr_pmu.pmgr_policyobjs.pwr_policies);
622 if (status) {
623 gk20a_err(dev_from_gk20a(g),
624 "error creating boardobjgrp for pmgr policy, status - 0x%x",
625 status);
626 goto done;
627 }
628
629 status = boardobjgrpconstruct_e32(
630 &g->pmgr_pmu.pmgr_policyobjs.pwr_policy_rels);
631 if (status) {
632 gk20a_err(dev_from_gk20a(g),
633 "error creating boardobjgrp for pmgr policy rels, status - 0x%x",
634 status);
635 goto done;
636 }
637
638 status = boardobjgrpconstruct_e32(
639 &g->pmgr_pmu.pmgr_policyobjs.pwr_violations);
640 if (status) {
641 gk20a_err(dev_from_gk20a(g),
642 "error creating boardobjgrp for pmgr violations, status - 0x%x",
643 status);
644 goto done;
645 }
646
647 memset(g->pmgr_pmu.pmgr_policyobjs.policy_idxs, CTRL_PMGR_PWR_POLICY_INDEX_INVALID,
648 sizeof(u8) * CTRL_PMGR_PWR_POLICY_IDX_NUM_INDEXES);
649
650 /* Initialize external power limit policy indexes to _INVALID/0xFF */
651 for (indx = 0; indx < PWR_POLICY_EXT_POWER_STATE_ID_COUNT; indx++) {
652 g->pmgr_pmu.pmgr_policyobjs.ext_limits[indx].policy_table_idx =
653 CTRL_PMGR_PWR_POLICY_INDEX_INVALID;
654 }
655
656 /* Initialize external power state to _D1 */
657 g->pmgr_pmu.pmgr_policyobjs.ext_power_state = 0xFFFFFFFF;
658
659 ppwrpolicyobjs = &(g->pmgr_pmu.pmgr_policyobjs);
660 pboardobjgrp = &(g->pmgr_pmu.pmgr_policyobjs.pwr_policies.super);
661
662 status = devinit_get_pwr_policy_table(g, ppwrpolicyobjs);
663 if (status)
664 goto done;
665
666 g->pmgr_pmu.pmgr_policyobjs.b_enabled = true;
667
668 BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct pwr_policy *, ppolicy, indx) {
669 PMGR_PWR_POLICY_INCREMENT_LIMIT_INPUT_COUNT(ppolicy);
670 }
671
672 g->pmgr_pmu.pmgr_policyobjs.global_ceiling.values[0] =
673 0xFF;
674
675 g->pmgr_pmu.pmgr_policyobjs.client_work_item.b_pending = false;
676
677done:
678 gk20a_dbg_info(" done status %x", status);
679 return status;
680}