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.c765
1 files changed, 765 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..d7926773
--- /dev/null
+++ b/drivers/gpu/nvgpu/pmgr/pwrpolicy.c
@@ -0,0 +1,765 @@
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
232 if (BOARDOBJ_GET_TYPE(board_obj_ptr) ==
233 CTRL_PMGR_PWR_POLICY_TYPE_SW_THRESHOLD) {
234 struct nv_pmu_pmgr_pwr_policy_sw_threshold *pmu_sw_threshold_data;
235 struct pwr_policy_sw_threshold *p_sw_threshold;
236
237 p_sw_threshold = (struct pwr_policy_sw_threshold *)board_obj_ptr;
238 pmu_sw_threshold_data =
239 (struct nv_pmu_pmgr_pwr_policy_sw_threshold *) ppmudata;
240 pmu_sw_threshold_data->event_id =
241 p_sw_threshold->event_id;
242 }
243done:
244 return status;
245}
246
247static struct boardobj *construct_pwr_policy(struct gk20a *g,
248 void *pargs, u16 pargs_size, u8 type)
249{
250 struct boardobj *board_obj_ptr = NULL;
251 u32 status;
252 struct pwr_policy_hw_threshold *pwrpolicyhwthreshold;
253 struct pwr_policy *pwrpolicy;
254 struct pwr_policy *pwrpolicyparams = (struct pwr_policy*)pargs;
255 struct pwr_policy_hw_threshold *hwthreshold = (struct pwr_policy_hw_threshold*)pargs;
256
257 status = boardobj_construct_super(g, &board_obj_ptr,
258 pargs_size, pargs);
259 if (status)
260 return NULL;
261
262 pwrpolicyhwthreshold = (struct pwr_policy_hw_threshold*)board_obj_ptr;
263 pwrpolicy = (struct pwr_policy *)board_obj_ptr;
264
265 /* Set Super class interfaces */
266 board_obj_ptr->pmudatainit = _pwr_domains_pmudatainit_hw_threshold;
267
268 pwrpolicy->ch_idx = pwrpolicyparams->ch_idx;
269 pwrpolicy->num_limit_inputs = 0;
270 pwrpolicy->limit_unit = pwrpolicyparams->limit_unit;
271 pwrpolicy->filter_type = (enum ctrl_pmgr_pwr_policy_filter_type)(pwrpolicyparams->filter_type);
272 pwrpolicy->sample_mult = pwrpolicyparams->sample_mult;
273 switch (pwrpolicy->filter_type)
274 {
275 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_NONE:
276 break;
277
278 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_BLOCK:
279 pwrpolicy->filter_param.block.block_size =
280 pwrpolicyparams->filter_param.block.block_size;
281 break;
282
283 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_MOVING_AVERAGE:
284 pwrpolicy->filter_param.moving_avg.window_size =
285 pwrpolicyparams->filter_param.moving_avg.window_size;
286 break;
287
288 case CTRL_PMGR_PWR_POLICY_FILTER_TYPE_IIR:
289 pwrpolicy->filter_param.iir.divisor = pwrpolicyparams->filter_param.iir.divisor;
290 break;
291
292 default:
293 gk20a_err(g->dev,
294 "Error: unrecognized Power Policy filter type: %d.\n",
295 pwrpolicy->filter_type);
296 }
297
298 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_curr, false);
299
300 pwrpolicy->limit_delta = 0;
301
302 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_min, true);
303 status = _pwr_policy_limitarbinputset(g,
304 pwrpolicy,
305 PWR_POLICY_LIMIT_ID_MIN,
306 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
307 pwrpolicyparams->limit_min);
308
309 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_max, false);
310 status = _pwr_policy_limitarbinputset(g,
311 pwrpolicy,
312 PWR_POLICY_LIMIT_ID_MAX,
313 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
314 pwrpolicyparams->limit_max);
315
316 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_rated, false);
317 status = _pwr_policy_limitarbinputset(g,
318 pwrpolicy,
319 PWR_POLICY_LIMIT_ID_RATED,
320 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
321 pwrpolicyparams->limit_rated);
322
323 _pwr_policy_limitarbconstruct(&pwrpolicy->limit_arb_batt, false);
324 status = _pwr_policy_limitarbinputset(g,
325 pwrpolicy,
326 PWR_POLICY_LIMIT_ID_BATT,
327 CTRL_PMGR_PWR_POLICY_LIMIT_INPUT_CLIENT_IDX_RM,
328 ((pwrpolicyparams->limit_batt != 0) ?
329 pwrpolicyparams->limit_batt:
330 CTRL_PMGR_PWR_POLICY_LIMIT_MAX));
331
332 memcpy(&pwrpolicy->integral, &pwrpolicyparams->integral,
333 sizeof(struct ctrl_pmgr_pwr_policy_info_integral));
334
335 pwrpolicyhwthreshold->threshold_idx = hwthreshold->threshold_idx;
336 pwrpolicyhwthreshold->b_use_low_threshold = hwthreshold->b_use_low_threshold;
337 pwrpolicyhwthreshold->low_threshold_idx = hwthreshold->low_threshold_idx;
338 pwrpolicyhwthreshold->low_threshold_value = hwthreshold->low_threshold_value;
339
340 if (type == CTRL_PMGR_PWR_POLICY_TYPE_SW_THRESHOLD) {
341 struct pwr_policy_sw_threshold *pwrpolicyswthreshold;
342 struct pwr_policy_sw_threshold *swthreshold =
343 (struct pwr_policy_sw_threshold*)pargs;
344
345 pwrpolicyswthreshold = (struct pwr_policy_sw_threshold*)board_obj_ptr;
346 pwrpolicyswthreshold->event_id = swthreshold->event_id;
347 }
348
349 gk20a_dbg_info(" Done");
350
351 return board_obj_ptr;
352}
353
354static u32 _pwr_policy_construct_WAR_policy(struct gk20a *g,
355 struct pmgr_pwr_policy *ppwrpolicyobjs,
356 union pwr_policy_data_union *ppwrpolicydata,
357 u16 pwr_policy_size,
358 u32 hw_threshold_policy_index,
359 u32 obj_index)
360{
361 u32 status = 0;
362 struct boardobj *boardobj;
363
364 if (!(hw_threshold_policy_index & 0x1)) {
365 /* CRIT policy */
366 ppwrpolicydata->pwrpolicy.limit_min = 1000;
367 ppwrpolicydata->pwrpolicy.limit_rated = 20000;
368 ppwrpolicydata->pwrpolicy.limit_max = 20000;
369 ppwrpolicydata->hw_threshold.threshold_idx = 0;
370 } else {
371 /* WARN policy */
372 ppwrpolicydata->pwrpolicy.limit_min = 1000;
373 ppwrpolicydata->pwrpolicy.limit_rated = 11600;
374 ppwrpolicydata->pwrpolicy.limit_max = 11600;
375 ppwrpolicydata->hw_threshold.threshold_idx = 1;
376 }
377
378 boardobj = construct_pwr_policy(g, ppwrpolicydata,
379 pwr_policy_size, ppwrpolicydata->boardobj.type);
380
381 if (!boardobj) {
382 gk20a_err(dev_from_gk20a(g),
383 "unable to create pwr policy for type %d", ppwrpolicydata->boardobj.type);
384 status = -EINVAL;
385 goto done;
386 }
387
388 status = boardobjgrp_objinsert(&ppwrpolicyobjs->pwr_policies.super,
389 boardobj, obj_index);
390
391 if (status) {
392 gk20a_err(dev_from_gk20a(g),
393 "unable to insert pwr policy boardobj for %d", obj_index);
394 status = -EINVAL;
395 goto done;
396 }
397done:
398 return status;
399}
400
401static u32 _pwr_policy_construct_WAR_SW_Threshold_policy(struct gk20a *g,
402 struct pmgr_pwr_policy *ppwrpolicyobjs,
403 union pwr_policy_data_union *ppwrpolicydata,
404 u16 pwr_policy_size,
405 u32 obj_index)
406{
407 u32 status = 0;
408 struct boardobj *boardobj;
409
410 /* WARN policy */
411 ppwrpolicydata->pwrpolicy.limit_unit = 0;
412 ppwrpolicydata->pwrpolicy.limit_min = 10000;
413 ppwrpolicydata->pwrpolicy.limit_rated = 100000;
414 ppwrpolicydata->pwrpolicy.limit_max = 100000;
415 ppwrpolicydata->sw_threshold.threshold_idx = 1;
416 ppwrpolicydata->pwrpolicy.filter_type =
417 CTRL_PMGR_PWR_POLICY_FILTER_TYPE_MOVING_AVERAGE;
418 ppwrpolicydata->pwrpolicy.sample_mult = 5;
419
420 /* Filled the entry.filterParam value in the filterParam */
421 ppwrpolicydata->pwrpolicy.filter_param.moving_avg.window_size = 10;
422
423 ppwrpolicydata->sw_threshold.event_id = 0x01;
424
425 ppwrpolicydata->boardobj.type = CTRL_PMGR_PWR_POLICY_TYPE_SW_THRESHOLD;
426
427 boardobj = construct_pwr_policy(g, ppwrpolicydata,
428 pwr_policy_size, ppwrpolicydata->boardobj.type);
429
430 if (!boardobj) {
431 gk20a_err(dev_from_gk20a(g),
432 "unable to create pwr policy for type %d", ppwrpolicydata->boardobj.type);
433 status = -EINVAL;
434 goto done;
435 }
436
437 status = boardobjgrp_objinsert(&ppwrpolicyobjs->pwr_policies.super,
438 boardobj, obj_index);
439
440 if (status) {
441 gk20a_err(dev_from_gk20a(g),
442 "unable to insert pwr policy boardobj for %d", obj_index);
443 status = -EINVAL;
444 goto done;
445 }
446done:
447 return status;
448}
449
450static u32 devinit_get_pwr_policy_table(struct gk20a *g,
451 struct pmgr_pwr_policy *ppwrpolicyobjs)
452{
453 u32 status = 0;
454 u8 *pwr_policy_table_ptr = NULL;
455 u8 *curr_pwr_policy_table_ptr = NULL;
456 struct boardobj *boardobj;
457 struct pwr_policy_3x_header_struct pwr_policy_table_header = { 0 };
458 struct pwr_policy_3x_entry_struct pwr_policy_table_entry = { 0 };
459 u32 index;
460 u32 obj_index = 0;
461 u16 pwr_policy_size;
462 bool integral_control = false;
463 u32 hw_threshold_policy_index = 0;
464 u32 sw_threshold_policy_index = 0;
465 union pwr_policy_data_union pwr_policy_data;
466
467 gk20a_dbg_info("");
468
469 if (g->ops.bios.get_perf_table_ptrs != NULL) {
470 pwr_policy_table_ptr = (u8 *)g->ops.bios.get_perf_table_ptrs(g,
471 g->bios.perf_token, POWER_CAPPING_TABLE);
472 if (pwr_policy_table_ptr == NULL) {
473 status = -EINVAL;
474 goto done;
475 }
476 }
477
478 memcpy(&pwr_policy_table_header.version,
479 (pwr_policy_table_ptr),
480 14);
481
482 memcpy(&pwr_policy_table_header.d2_limit,
483 (pwr_policy_table_ptr + 14),
484 (VBIOS_POWER_POLICY_3X_ENTRY_SIZE_2E - 14));
485
486 if (pwr_policy_table_header.version !=
487 VBIOS_POWER_POLICY_VERSION_3X) {
488 status = -EINVAL;
489 goto done;
490 }
491
492 if (pwr_policy_table_header.header_size <
493 VBIOS_POWER_POLICY_3X_HEADER_SIZE_25) {
494 status = -EINVAL;
495 goto done;
496 }
497
498 if (pwr_policy_table_header.table_entry_size !=
499 VBIOS_POWER_POLICY_3X_ENTRY_SIZE_2E) {
500 status = -EINVAL;
501 goto done;
502 }
503
504 curr_pwr_policy_table_ptr = (pwr_policy_table_ptr +
505 VBIOS_POWER_POLICY_3X_HEADER_SIZE_25);
506
507 for (index = 0; index < pwr_policy_table_header.num_table_entries;
508 index++) {
509 u8 class_type;
510
511 curr_pwr_policy_table_ptr += (pwr_policy_table_header.table_entry_size * index);
512
513 pwr_policy_table_entry.flags0 = *curr_pwr_policy_table_ptr;
514 pwr_policy_table_entry.ch_idx = *(curr_pwr_policy_table_ptr + 1);
515
516 memcpy(&pwr_policy_table_entry.limit_min,
517 (curr_pwr_policy_table_ptr + 2),
518 35);
519
520 memcpy(&pwr_policy_table_entry.ratio_min,
521 (curr_pwr_policy_table_ptr + 2 + 35),
522 4);
523
524 pwr_policy_table_entry.sample_mult =
525 *(curr_pwr_policy_table_ptr + 2 + 35 + 4);
526
527 memcpy(&pwr_policy_table_entry.filter_param,
528 (curr_pwr_policy_table_ptr + 2 + 35 + 4 + 1),
529 4);
530
531 class_type = (u8)BIOS_GET_FIELD(
532 pwr_policy_table_entry.flags0,
533 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_CLASS);
534
535 if (class_type == NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_CLASS_HW_THRESHOLD) {
536 ppwrpolicyobjs->version = CTRL_PMGR_PWR_POLICY_TABLE_VERSION_3X;
537 ppwrpolicyobjs->base_sample_period = (u16)
538 pwr_policy_table_header.base_sample_period;
539 ppwrpolicyobjs->min_client_sample_period = (u16)
540 pwr_policy_table_header.min_client_sample_period;
541 ppwrpolicyobjs->low_sampling_mult =
542 pwr_policy_table_header.low_sampling_mult;
543
544 ppwrpolicyobjs->policy_idxs[1] =
545 (u8)pwr_policy_table_header.tgp_policy_idx;
546 ppwrpolicyobjs->policy_idxs[0] =
547 (u8)pwr_policy_table_header.rtp_policy_idx;
548 ppwrpolicyobjs->policy_idxs[2] =
549 pwr_policy_table_header.mxm_policy_idx;
550 ppwrpolicyobjs->policy_idxs[3] =
551 pwr_policy_table_header.dnotifier_policy_idx;
552 ppwrpolicyobjs->ext_limits[0].limit =
553 pwr_policy_table_header.d2_limit;
554 ppwrpolicyobjs->ext_limits[1].limit =
555 pwr_policy_table_header.d3_limit;
556 ppwrpolicyobjs->ext_limits[2].limit =
557 pwr_policy_table_header.d4_limit;
558 ppwrpolicyobjs->ext_limits[3].limit =
559 pwr_policy_table_header.d5_limit;
560 ppwrpolicyobjs->policy_idxs[4] =
561 pwr_policy_table_header.pwr_tgt_policy_idx;
562 ppwrpolicyobjs->policy_idxs[5] =
563 pwr_policy_table_header.pwr_tgt_floor_policy_idx;
564 ppwrpolicyobjs->policy_idxs[6] =
565 pwr_policy_table_header.sm_bus_policy_idx;
566
567 integral_control = (bool)BIOS_GET_FIELD(
568 pwr_policy_table_entry.flags1,
569 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS1_INTEGRAL_CONTROL);
570
571 if (integral_control == 0x01) {
572 pwr_policy_data.pwrpolicy.integral.past_sample_count = (u8)
573 pwr_policy_table_entry.past_length;
574 pwr_policy_data.pwrpolicy.integral.next_sample_count = (u8)
575 pwr_policy_table_entry.next_length;
576 pwr_policy_data.pwrpolicy.integral.ratio_limit_max = (u16)
577 pwr_policy_table_entry.ratio_max;
578 pwr_policy_data.pwrpolicy.integral.ratio_limit_min = (u16)
579 pwr_policy_table_entry.ratio_min;
580 } else {
581 memset(&(pwr_policy_data.pwrpolicy.integral), 0x0,
582 sizeof(struct ctrl_pmgr_pwr_policy_info_integral));
583 }
584 pwr_policy_data.hw_threshold.threshold_idx = (u8)
585 BIOS_GET_FIELD(
586 pwr_policy_table_entry.param0,
587 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_THRES_IDX);
588
589 pwr_policy_data.hw_threshold.b_use_low_threshold =
590 BIOS_GET_FIELD(
591 pwr_policy_table_entry.param0,
592 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_LOW_THRESHOLD_USE);
593
594 if (pwr_policy_data.hw_threshold.b_use_low_threshold) {
595 pwr_policy_data.hw_threshold.low_threshold_idx = (u8)
596 BIOS_GET_FIELD(
597 pwr_policy_table_entry.param0,
598 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM0_HW_THRESHOLD_LOW_THRESHOLD_IDX);
599
600 pwr_policy_data.hw_threshold.low_threshold_value = (u16)
601 BIOS_GET_FIELD(
602 pwr_policy_table_entry.param1,
603 NV_VBIOS_POWER_POLICY_3X_ENTRY_PARAM1_HW_THRESHOLD_LOW_THRESHOLD_VAL);
604 }
605
606 pwr_policy_size = sizeof(struct pwr_policy_hw_threshold);
607 } else
608 continue;
609
610 /* Initialize data for the parent class */
611 pwr_policy_data.boardobj.type = CTRL_PMGR_PWR_POLICY_TYPE_HW_THRESHOLD;
612 pwr_policy_data.pwrpolicy.ch_idx = (u8)pwr_policy_table_entry.ch_idx;
613 pwr_policy_data.pwrpolicy.limit_unit = (u8)
614 BIOS_GET_FIELD(
615 pwr_policy_table_entry.flags0,
616 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS0_LIMIT_UNIT);
617 pwr_policy_data.pwrpolicy.filter_type = (u8)
618 BIOS_GET_FIELD(
619 pwr_policy_table_entry.flags1,
620 NV_VBIOS_POWER_POLICY_3X_ENTRY_FLAGS1_FILTER_TYPE);
621 pwr_policy_data.pwrpolicy.limit_min = pwr_policy_table_entry.limit_min;
622 pwr_policy_data.pwrpolicy.limit_rated = pwr_policy_table_entry.limit_rated;
623 pwr_policy_data.pwrpolicy.limit_max = pwr_policy_table_entry.limit_max;
624 pwr_policy_data.pwrpolicy.limit_batt = pwr_policy_table_entry.limit_batt;
625
626 pwr_policy_data.pwrpolicy.sample_mult = (u8)pwr_policy_table_entry.sample_mult;
627
628 /* Filled the entry.filterParam value in the filterParam */
629 pwr_policy_data.pwrpolicy.filter_param.block.block_size = 0;
630 pwr_policy_data.pwrpolicy.filter_param.moving_avg.window_size = 0;
631 pwr_policy_data.pwrpolicy.filter_param.iir.divisor = 0;
632
633 hw_threshold_policy_index |=
634 BIT(pwr_policy_data.hw_threshold.threshold_idx);
635
636 boardobj = construct_pwr_policy(g, &pwr_policy_data,
637 pwr_policy_size, pwr_policy_data.boardobj.type);
638
639 if (!boardobj) {
640 gk20a_err(dev_from_gk20a(g),
641 "unable to create pwr policy for %d type %d", index, pwr_policy_data.boardobj.type);
642 status = -EINVAL;
643 goto done;
644 }
645
646 status = boardobjgrp_objinsert(&ppwrpolicyobjs->pwr_policies.super,
647 boardobj, obj_index);
648
649 if (status) {
650 gk20a_err(dev_from_gk20a(g),
651 "unable to insert pwr policy boardobj for %d", index);
652 status = -EINVAL;
653 goto done;
654 }
655
656 ++obj_index;
657 }
658
659 if (hw_threshold_policy_index &&
660 (hw_threshold_policy_index < 0x3)) {
661 status = _pwr_policy_construct_WAR_policy(g,
662 ppwrpolicyobjs,
663 &pwr_policy_data,
664 pwr_policy_size,
665 hw_threshold_policy_index,
666 obj_index);
667 if (status) {
668 gk20a_err(dev_from_gk20a(g),
669 "unable to construct_WAR_policy");
670 status = -EINVAL;
671 goto done;
672 }
673 ++obj_index;
674 }
675
676 if (!sw_threshold_policy_index) {
677 status = _pwr_policy_construct_WAR_SW_Threshold_policy(g,
678 ppwrpolicyobjs,
679 &pwr_policy_data,
680 sizeof(struct pwr_policy_sw_threshold),
681 obj_index);
682 if (status) {
683 gk20a_err(dev_from_gk20a(g),
684 "unable to construct_WAR_policy");
685 status = -EINVAL;
686 goto done;
687 }
688 ++obj_index;
689 }
690
691done:
692 gk20a_dbg_info(" done status %x", status);
693 return status;
694}
695
696u32 pmgr_policy_sw_setup(struct gk20a *g)
697{
698 u32 status;
699 struct boardobjgrp *pboardobjgrp = NULL;
700 struct pwr_policy *ppolicy;
701 struct pmgr_pwr_policy *ppwrpolicyobjs;
702 u8 indx = 0;
703
704 /* Construct the Super Class and override the Interfaces */
705 status = boardobjgrpconstruct_e32(
706 &g->pmgr_pmu.pmgr_policyobjs.pwr_policies);
707 if (status) {
708 gk20a_err(dev_from_gk20a(g),
709 "error creating boardobjgrp for pmgr policy, status - 0x%x",
710 status);
711 goto done;
712 }
713
714 status = boardobjgrpconstruct_e32(
715 &g->pmgr_pmu.pmgr_policyobjs.pwr_policy_rels);
716 if (status) {
717 gk20a_err(dev_from_gk20a(g),
718 "error creating boardobjgrp for pmgr policy rels, status - 0x%x",
719 status);
720 goto done;
721 }
722
723 status = boardobjgrpconstruct_e32(
724 &g->pmgr_pmu.pmgr_policyobjs.pwr_violations);
725 if (status) {
726 gk20a_err(dev_from_gk20a(g),
727 "error creating boardobjgrp for pmgr violations, status - 0x%x",
728 status);
729 goto done;
730 }
731
732 memset(g->pmgr_pmu.pmgr_policyobjs.policy_idxs, CTRL_PMGR_PWR_POLICY_INDEX_INVALID,
733 sizeof(u8) * CTRL_PMGR_PWR_POLICY_IDX_NUM_INDEXES);
734
735 /* Initialize external power limit policy indexes to _INVALID/0xFF */
736 for (indx = 0; indx < PWR_POLICY_EXT_POWER_STATE_ID_COUNT; indx++) {
737 g->pmgr_pmu.pmgr_policyobjs.ext_limits[indx].policy_table_idx =
738 CTRL_PMGR_PWR_POLICY_INDEX_INVALID;
739 }
740
741 /* Initialize external power state to _D1 */
742 g->pmgr_pmu.pmgr_policyobjs.ext_power_state = 0xFFFFFFFF;
743
744 ppwrpolicyobjs = &(g->pmgr_pmu.pmgr_policyobjs);
745 pboardobjgrp = &(g->pmgr_pmu.pmgr_policyobjs.pwr_policies.super);
746
747 status = devinit_get_pwr_policy_table(g, ppwrpolicyobjs);
748 if (status)
749 goto done;
750
751 g->pmgr_pmu.pmgr_policyobjs.b_enabled = true;
752
753 BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct pwr_policy *, ppolicy, indx) {
754 PMGR_PWR_POLICY_INCREMENT_LIMIT_INPUT_COUNT(ppolicy);
755 }
756
757 g->pmgr_pmu.pmgr_policyobjs.global_ceiling.values[0] =
758 0xFF;
759
760 g->pmgr_pmu.pmgr_policyobjs.client_work_item.b_pending = false;
761
762done:
763 gk20a_dbg_info(" done status %x", status);
764 return status;
765}