summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/pmgr/pwrpolicy.c
diff options
context:
space:
mode:
authorLakshmanan M <lm@nvidia.com>2016-09-08 13:28:19 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commit90f80a282eff04412858361df35c2f88372e88cb (patch)
tree4de1169e9bc3f02416a01c933175b613f9ccbdfd /drivers/gpu/nvgpu/pmgr/pwrpolicy.c
parentcb78f5aa749fcea198851ae4adf6e3acd47b37ac (diff)
gpu: nvgpu: Add pmgr support
This CL covers the following implementation, 1) Power Sensor Table parsing. 2) Power Topology Table parsing. 3) Add debugfs interface to get the current power(mW), current(mA) and voltage(uV) information from PMU. 4) Power Policy Table Parsing 5) Implement PMU boardobj interface for pmgr module. 6) Over current protection. JIRA DNVGPU-47 Change-Id: I7b1eefacc4f0a9824ab94ec8dcebefe81b7660d3 Signed-off-by: Lakshmanan M <lm@nvidia.com> Reviewed-on: http://git-master/r/1217189 (cherry picked from commit ecd0b16316cb4110118c6677f5f03e02921c29b6) Reviewed-on: http://git-master/r/1241953 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> GVS: Gerrit_Virtual_Submit
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}