aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_freq_controller.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/clk/clk_freq_controller.c')
-rw-r--r--include/clk/clk_freq_controller.c462
1 files changed, 0 insertions, 462 deletions
diff --git a/include/clk/clk_freq_controller.c b/include/clk/clk_freq_controller.c
deleted file mode 100644
index f4d09b0..0000000
--- a/include/clk/clk_freq_controller.c
+++ /dev/null
@@ -1,462 +0,0 @@
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 "clk.h"
27#include "clk_fll.h"
28#include "clk_domain.h"
29#include "clk_freq_controller.h"
30#include "boardobj/boardobjgrp.h"
31#include "boardobj/boardobjgrp_e32.h"
32#include "ctrl/ctrlclk.h"
33#include "ctrl/ctrlvolt.h"
34
35static int clk_freq_controller_pmudatainit_super(struct gk20a *g,
36 struct boardobj *board_obj_ptr,
37 struct nv_pmu_boardobj *ppmudata)
38{
39 struct nv_pmu_clk_clk_freq_controller_boardobj_set *pfreq_cntlr_set;
40 struct clk_freq_controller *pfreq_cntlr;
41 int status = 0;
42
43 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
44 if (status) {
45 return status;
46 }
47
48 pfreq_cntlr_set =
49 (struct nv_pmu_clk_clk_freq_controller_boardobj_set *)ppmudata;
50 pfreq_cntlr = (struct clk_freq_controller *)board_obj_ptr;
51
52 pfreq_cntlr_set->controller_id = pfreq_cntlr->controller_id;
53 pfreq_cntlr_set->clk_domain = pfreq_cntlr->clk_domain;
54 pfreq_cntlr_set->parts_freq_mode = pfreq_cntlr->parts_freq_mode;
55 pfreq_cntlr_set->bdisable = pfreq_cntlr->bdisable;
56 pfreq_cntlr_set->freq_cap_noise_unaware_vmin_above =
57 pfreq_cntlr->freq_cap_noise_unaware_vmin_above;
58 pfreq_cntlr_set->freq_cap_noise_unaware_vmin_below =
59 pfreq_cntlr->freq_cap_noise_unaware_vmin_below;
60 pfreq_cntlr_set->freq_hyst_pos_mhz = pfreq_cntlr->freq_hyst_pos_mhz;
61 pfreq_cntlr_set->freq_hyst_neg_mhz = pfreq_cntlr->freq_hyst_neg_mhz;
62
63 return status;
64}
65
66static int clk_freq_controller_pmudatainit_pi(struct gk20a *g,
67 struct boardobj *board_obj_ptr,
68 struct nv_pmu_boardobj *ppmudata)
69{
70 struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set
71 *pfreq_cntlr_pi_set;
72 struct clk_freq_controller_pi *pfreq_cntlr_pi;
73 int status = 0;
74
75 status = clk_freq_controller_pmudatainit_super(g,
76 board_obj_ptr, ppmudata);
77 if (status) {
78 return -1;
79 }
80
81 pfreq_cntlr_pi_set =
82 (struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set *)
83 ppmudata;
84 pfreq_cntlr_pi = (struct clk_freq_controller_pi *)board_obj_ptr;
85
86 pfreq_cntlr_pi_set->prop_gain = pfreq_cntlr_pi->prop_gain;
87 pfreq_cntlr_pi_set->integ_gain = pfreq_cntlr_pi->integ_gain;
88 pfreq_cntlr_pi_set->integ_decay = pfreq_cntlr_pi->integ_decay;
89 pfreq_cntlr_pi_set->volt_delta_min = pfreq_cntlr_pi->volt_delta_min;
90 pfreq_cntlr_pi_set->volt_delta_max = pfreq_cntlr_pi->volt_delta_max;
91 pfreq_cntlr_pi_set->slowdown_pct_min = pfreq_cntlr_pi->slowdown_pct_min;
92 pfreq_cntlr_pi_set->bpoison = pfreq_cntlr_pi->bpoison;
93
94 return status;
95}
96
97static int clk_freq_controller_construct_super(struct gk20a *g,
98 struct boardobj **ppboardobj,
99 u16 size, void *pargs)
100{
101 struct clk_freq_controller *pfreq_cntlr = NULL;
102 struct clk_freq_controller *pfreq_cntlr_tmp = NULL;
103 int status = 0;
104
105 status = boardobj_construct_super(g, ppboardobj, size, pargs);
106 if (status) {
107 return -EINVAL;
108 }
109
110 pfreq_cntlr_tmp = (struct clk_freq_controller *)pargs;
111 pfreq_cntlr = (struct clk_freq_controller *)*ppboardobj;
112
113 pfreq_cntlr->super.pmudatainit = clk_freq_controller_pmudatainit_super;
114
115 pfreq_cntlr->controller_id = pfreq_cntlr_tmp->controller_id;
116 pfreq_cntlr->clk_domain = pfreq_cntlr_tmp->clk_domain;
117 pfreq_cntlr->parts_freq_mode = pfreq_cntlr_tmp->parts_freq_mode;
118 pfreq_cntlr->freq_cap_noise_unaware_vmin_above =
119 pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_above;
120 pfreq_cntlr->freq_cap_noise_unaware_vmin_below =
121 pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_below;
122 pfreq_cntlr->freq_hyst_pos_mhz = pfreq_cntlr_tmp->freq_hyst_pos_mhz;
123 pfreq_cntlr->freq_hyst_neg_mhz = pfreq_cntlr_tmp->freq_hyst_neg_mhz;
124
125 return status;
126}
127
128static int clk_freq_controller_construct_pi(struct gk20a *g,
129 struct boardobj **ppboardobj,
130 u16 size, void *pargs)
131{
132 struct clk_freq_controller_pi *pfreq_cntlr_pi = NULL;
133 struct clk_freq_controller_pi *pfreq_cntlr_pi_tmp = NULL;
134 int status = 0;
135
136 status = clk_freq_controller_construct_super(g, ppboardobj,
137 size, pargs);
138 if (status) {
139 return -EINVAL;
140 }
141
142 pfreq_cntlr_pi = (struct clk_freq_controller_pi *)*ppboardobj;
143 pfreq_cntlr_pi_tmp = (struct clk_freq_controller_pi *)pargs;
144
145 pfreq_cntlr_pi->super.super.pmudatainit =
146 clk_freq_controller_pmudatainit_pi;
147
148 pfreq_cntlr_pi->prop_gain = pfreq_cntlr_pi_tmp->prop_gain;
149 pfreq_cntlr_pi->integ_gain = pfreq_cntlr_pi_tmp->integ_gain;
150 pfreq_cntlr_pi->integ_decay = pfreq_cntlr_pi_tmp->integ_decay;
151 pfreq_cntlr_pi->volt_delta_min = pfreq_cntlr_pi_tmp->volt_delta_min;
152 pfreq_cntlr_pi->volt_delta_max = pfreq_cntlr_pi_tmp->volt_delta_max;
153 pfreq_cntlr_pi->slowdown_pct_min = pfreq_cntlr_pi_tmp->slowdown_pct_min;
154 pfreq_cntlr_pi->bpoison = pfreq_cntlr_pi_tmp->bpoison;
155
156 return status;
157}
158
159static struct clk_freq_controller *clk_clk_freq_controller_construct(
160 struct gk20a *g,
161 void *pargs)
162{
163 struct boardobj *board_obj_ptr = NULL;
164 int status = 0;
165
166 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_PI) {
167 return NULL;
168 }
169
170 status = clk_freq_controller_construct_pi(g, &board_obj_ptr,
171 sizeof(struct clk_freq_controller_pi), pargs);
172 if (status) {
173 return NULL;
174 }
175
176 return (struct clk_freq_controller *)board_obj_ptr;
177}
178
179
180static int clk_get_freq_controller_table(struct gk20a *g,
181 struct clk_freq_controllers *pclk_freq_controllers)
182{
183 int status = 0;
184 u8 *pfreq_controller_table_ptr = NULL;
185 struct vbios_fct_1x_header header = { 0 };
186 struct vbios_fct_1x_entry entry = { 0 };
187 u8 entry_idx;
188 u8 *entry_offset;
189 struct clk_freq_controller *pclk_freq_cntr = NULL;
190 struct clk_freq_controller *ptmp_freq_cntr = NULL;
191 struct clk_freq_controller_pi *ptmp_freq_cntr_pi = NULL;
192 struct clk_domain *pclk_domain;
193
194 struct freq_controller_data_type {
195 union {
196 struct boardobj board_obj;
197 struct clk_freq_controller freq_controller;
198 struct clk_freq_controller_pi freq_controller_pi;
199 };
200 } freq_controller_data;
201
202 pfreq_controller_table_ptr =
203 (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
204 g->bios.clock_token,
205 FREQUENCY_CONTROLLER_TABLE);
206 if (pfreq_controller_table_ptr == NULL) {
207 status = -EINVAL;
208 goto done;
209 }
210
211 memcpy(&header, pfreq_controller_table_ptr,
212 sizeof(struct vbios_fct_1x_header));
213
214 pclk_freq_controllers->sampling_period_ms = header.sampling_period_ms;
215 pclk_freq_controllers->volt_policy_idx = 0;
216
217 /* Read in the entries. */
218 for (entry_idx = 0; entry_idx < header.entry_count; entry_idx++) {
219 entry_offset = (pfreq_controller_table_ptr +
220 header.header_size + (entry_idx * header.entry_size));
221
222 memset(&freq_controller_data, 0x0,
223 sizeof(struct freq_controller_data_type));
224 ptmp_freq_cntr = &freq_controller_data.freq_controller;
225 ptmp_freq_cntr_pi = &freq_controller_data.freq_controller_pi;
226
227 memcpy(&entry, entry_offset,
228 sizeof(struct vbios_fct_1x_entry));
229
230 if (!BIOS_GET_FIELD(entry.flags0,
231 NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE)) {
232 continue;
233 }
234
235 freq_controller_data.board_obj.type = (u8)BIOS_GET_FIELD(
236 entry.flags0, NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE);
237
238 ptmp_freq_cntr->controller_id =
239 (u8)BIOS_GET_FIELD(entry.param0,
240 NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID);
241
242 pclk_domain = CLK_CLK_DOMAIN_GET((&g->clk_pmu),
243 (u32)entry.clk_domain_idx);
244 freq_controller_data.freq_controller.clk_domain =
245 pclk_domain->api_domain;
246
247 ptmp_freq_cntr->parts_freq_mode =
248 (u8)BIOS_GET_FIELD(entry.param0,
249 NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE);
250
251 /* Populate PI specific data */
252 ptmp_freq_cntr_pi->slowdown_pct_min =
253 (u8)BIOS_GET_FIELD(entry.param1,
254 NV_VBIOS_FCT_1X_ENTRY_PARAM1_SLOWDOWN_PCT_MIN);
255
256 ptmp_freq_cntr_pi->bpoison =
257 BIOS_GET_FIELD(entry.param1,
258 NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON);
259
260 ptmp_freq_cntr_pi->prop_gain =
261 (s32)BIOS_GET_FIELD(entry.param2,
262 NV_VBIOS_FCT_1X_ENTRY_PARAM2_PROP_GAIN);
263
264 ptmp_freq_cntr_pi->integ_gain =
265 (s32)BIOS_GET_FIELD(entry.param3,
266 NV_VBIOS_FCT_1X_ENTRY_PARAM3_INTEG_GAIN);
267
268 ptmp_freq_cntr_pi->integ_decay =
269 (s32)BIOS_GET_FIELD(entry.param4,
270 NV_VBIOS_FCT_1X_ENTRY_PARAM4_INTEG_DECAY);
271
272 ptmp_freq_cntr_pi->volt_delta_min =
273 (s32)BIOS_GET_FIELD(entry.param5,
274 NV_VBIOS_FCT_1X_ENTRY_PARAM5_VOLT_DELTA_MIN);
275
276 ptmp_freq_cntr_pi->volt_delta_max =
277 (s32)BIOS_GET_FIELD(entry.param6,
278 NV_VBIOS_FCT_1X_ENTRY_PARAM6_VOLT_DELTA_MAX);
279
280 ptmp_freq_cntr->freq_cap_noise_unaware_vmin_above =
281 (s16)BIOS_GET_FIELD(entry.param7,
282 NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VF);
283
284 ptmp_freq_cntr->freq_cap_noise_unaware_vmin_below =
285 (s16)BIOS_GET_FIELD(entry.param7,
286 NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VMIN);
287
288 ptmp_freq_cntr->freq_hyst_pos_mhz =
289 (s16)BIOS_GET_FIELD(entry.param8,
290 NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_POS);
291 ptmp_freq_cntr->freq_hyst_neg_mhz =
292 (s16)BIOS_GET_FIELD(entry.param8,
293 NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_NEG);
294
295 if (ptmp_freq_cntr_pi->volt_delta_max <
296 ptmp_freq_cntr_pi->volt_delta_min) {
297 goto done;
298 }
299
300 pclk_freq_cntr = clk_clk_freq_controller_construct(g,
301 (void *)&freq_controller_data);
302
303 if (pclk_freq_cntr == NULL) {
304 nvgpu_err(g,
305 "unable to construct clock freq cntlr boardobj for %d",
306 entry_idx);
307 status = -EINVAL;
308 goto done;
309 }
310
311 status = boardobjgrp_objinsert(
312 &pclk_freq_controllers->super.super,
313 (struct boardobj *)pclk_freq_cntr, entry_idx);
314 if (status) {
315 nvgpu_err(g,
316 "unable to insert clock freq cntlr boardobj for");
317 status = -EINVAL;
318 goto done;
319 }
320
321 }
322
323done:
324 return status;
325}
326
327int clk_freq_controller_pmu_setup(struct gk20a *g)
328{
329 int status;
330 struct boardobjgrp *pboardobjgrp = NULL;
331
332 nvgpu_log_info(g, " ");
333
334 pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super;
335
336 if (!pboardobjgrp->bconstructed) {
337 return -EINVAL;
338 }
339
340 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
341
342 nvgpu_log_info(g, "Done");
343 return status;
344}
345
346static int _clk_freq_controller_devgrp_pmudata_instget(struct gk20a *g,
347 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
348 struct nv_pmu_boardobj **ppboardobjpmudata,
349 u8 idx)
350{
351 struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *pgrp_set =
352 (struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *)
353 pmuboardobjgrp;
354
355 nvgpu_log_info(g, " ");
356
357 /*check whether pmuboardobjgrp has a valid boardobj in index*/
358 if (((u32)BIT(idx) &
359 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) {
360 return -EINVAL;
361 }
362
363 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
364 &pgrp_set->objects[idx].data.board_obj;
365 nvgpu_log_info(g, " Done");
366 return 0;
367}
368
369static int _clk_freq_controllers_pmudatainit(struct gk20a *g,
370 struct boardobjgrp *pboardobjgrp,
371 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
372{
373 struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *pset =
374 (struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *)
375 pboardobjgrppmu;
376 struct clk_freq_controllers *pcntrs =
377 (struct clk_freq_controllers *)pboardobjgrp;
378 int status = 0;
379
380 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
381 if (status) {
382 nvgpu_err(g,
383 "error updating pmu boardobjgrp for clk freq ctrs 0x%x",
384 status);
385 goto done;
386 }
387 pset->sampling_period_ms = pcntrs->sampling_period_ms;
388 pset->volt_policy_idx = pcntrs->volt_policy_idx;
389
390done:
391 return status;
392}
393
394int clk_freq_controller_sw_setup(struct gk20a *g)
395{
396 int status = 0;
397 struct boardobjgrp *pboardobjgrp = NULL;
398 struct clk_freq_controllers *pclk_freq_controllers;
399 struct avfsfllobjs *pfllobjs = &(g->clk_pmu.avfs_fllobjs);
400 struct fll_device *pfll;
401 struct clk_freq_controller *pclkfreqctrl;
402 u8 i;
403 u8 j;
404
405 nvgpu_log_info(g, " ");
406
407 pclk_freq_controllers = &g->clk_pmu.clk_freq_controllers;
408 status = boardobjgrpconstruct_e32(g, &pclk_freq_controllers->super);
409 if (status) {
410 nvgpu_err(g,
411 "error creating boardobjgrp for clk FCT, status - 0x%x",
412 status);
413 goto done;
414 }
415
416 pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super;
417
418 pboardobjgrp->pmudatainit = _clk_freq_controllers_pmudatainit;
419 pboardobjgrp->pmudatainstget =
420 _clk_freq_controller_devgrp_pmudata_instget;
421 pboardobjgrp->pmustatusinstget = NULL;
422
423 /* Initialize mask to zero.*/
424 boardobjgrpmask_e32_init(&pclk_freq_controllers->freq_ctrl_load_mask,
425 NULL);
426
427 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_FREQ_CONTROLLER);
428
429 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
430 clk, CLK, clk_freq_controller, CLK_FREQ_CONTROLLER);
431 if (status) {
432 nvgpu_err(g,
433 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
434 status);
435 goto done;
436 }
437
438 status = clk_get_freq_controller_table(g, pclk_freq_controllers);
439 if (status) {
440 nvgpu_err(g, "error reading freq controller table - 0x%x",
441 status);
442 goto done;
443 }
444
445 BOARDOBJGRP_FOR_EACH(&(pclk_freq_controllers->super.super),
446 struct clk_freq_controller *, pclkfreqctrl, i) {
447 pfll = NULL;
448 j = 0;
449 BOARDOBJGRP_FOR_EACH(&(pfllobjs->super.super),
450 struct fll_device *, pfll, j) {
451 if (pclkfreqctrl->controller_id == pfll->id) {
452 pfll->freq_ctrl_idx = i;
453 break;
454 }
455 }
456 boardobjgrpmask_bitset(&pclk_freq_controllers->
457 freq_ctrl_load_mask.super, i);
458 }
459done:
460 nvgpu_log_info(g, " done status %x", status);
461 return status;
462}