diff options
Diffstat (limited to 'include/clk/clk_freq_controller.c')
-rw-r--r-- | include/clk/clk_freq_controller.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/include/clk/clk_freq_controller.c b/include/clk/clk_freq_controller.c new file mode 100644 index 0000000..f4d09b0 --- /dev/null +++ b/include/clk/clk_freq_controller.c | |||
@@ -0,0 +1,462 @@ | |||
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 | |||
35 | static 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 | |||
66 | static 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 | |||
97 | static 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 | |||
128 | static 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 | |||
159 | static 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 | |||
180 | static 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 | |||
323 | done: | ||
324 | return status; | ||
325 | } | ||
326 | |||
327 | int 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 | |||
346 | static 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 | |||
369 | static 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 | |||
390 | done: | ||
391 | return status; | ||
392 | } | ||
393 | |||
394 | int 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 | } | ||
459 | done: | ||
460 | nvgpu_log_info(g, " done status %x", status); | ||
461 | return status; | ||
462 | } | ||