aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_fll.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
commit01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 (patch)
tree4ef34501728a087be24f4ba0af90f91486bf780b /include/clk/clk_fll.c
parent306a03d18b305e4e573be3b2931978fa10679eb9 (diff)
Include nvgpu headers
These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future.
Diffstat (limited to 'include/clk/clk_fll.c')
-rw-r--r--include/clk/clk_fll.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/include/clk/clk_fll.c b/include/clk/clk_fll.c
new file mode 100644
index 0000000..e67dd35
--- /dev/null
+++ b/include/clk/clk_fll.c
@@ -0,0 +1,495 @@
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 "boardobj/boardobjgrp.h"
30#include "boardobj/boardobjgrp_e32.h"
31#include "ctrl/ctrlclk.h"
32#include "ctrl/ctrlvolt.h"
33
34static int devinit_get_fll_device_table(struct gk20a *g,
35 struct avfsfllobjs *pfllobjs);
36static struct fll_device *construct_fll_device(struct gk20a *g,
37 void *pargs);
38static int fll_device_init_pmudata_super(struct gk20a *g,
39 struct boardobj *board_obj_ptr,
40 struct nv_pmu_boardobj *ppmudata);
41
42static int _clk_fll_devgrp_pmudatainit_super(struct gk20a *g,
43 struct boardobjgrp *pboardobjgrp,
44 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
45{
46 struct nv_pmu_clk_clk_fll_device_boardobjgrp_set_header *pset =
47 (struct nv_pmu_clk_clk_fll_device_boardobjgrp_set_header *)
48 pboardobjgrppmu;
49 struct avfsfllobjs *pfll_objs = (struct avfsfllobjs *)
50 pboardobjgrp;
51 int status = 0;
52
53 nvgpu_log_info(g, " ");
54
55 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
56 if (status) {
57 nvgpu_err(g, "failed to init fll pmuobjgrp");
58 return status;
59 }
60 pset->lut_num_entries = pfll_objs->lut_num_entries;
61 pset->lut_step_size_uv = pfll_objs->lut_step_size_uv;
62 pset->lut_min_voltage_uv = pfll_objs->lut_min_voltage_uv;
63 pset->max_min_freq_mhz = pfll_objs->max_min_freq_mhz;
64
65 status = boardobjgrpmask_export(
66 &pfll_objs->lut_prog_master_mask.super,
67 pfll_objs->lut_prog_master_mask.super.bitcount,
68 &pset->lut_prog_master_mask.super);
69
70 nvgpu_log_info(g, " Done");
71 return status;
72}
73
74static int _clk_fll_devgrp_pmudata_instget(struct gk20a *g,
75 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
76 struct nv_pmu_boardobj **ppboardobjpmudata,
77 u8 idx)
78{
79 struct nv_pmu_clk_clk_fll_device_boardobj_grp_set *pgrp_set =
80 (struct nv_pmu_clk_clk_fll_device_boardobj_grp_set *)
81 pmuboardobjgrp;
82
83 nvgpu_log_info(g, " ");
84
85 /*check whether pmuboardobjgrp has a valid boardobj in index*/
86 if (((u32)BIT(idx) &
87 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) {
88 return -EINVAL;
89 }
90
91 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
92 &pgrp_set->objects[idx].data.board_obj;
93 nvgpu_log_info(g, " Done");
94 return 0;
95}
96
97static int _clk_fll_devgrp_pmustatus_instget(struct gk20a *g,
98 void *pboardobjgrppmu,
99 struct nv_pmu_boardobj_query **ppboardobjpmustatus,
100 u8 idx)
101{
102 struct nv_pmu_clk_clk_fll_device_boardobj_grp_get_status *pgrp_get_status =
103 (struct nv_pmu_clk_clk_fll_device_boardobj_grp_get_status *)
104 pboardobjgrppmu;
105
106 /*check whether pmuboardobjgrp has a valid boardobj in index*/
107 if (((u32)BIT(idx) &
108 pgrp_get_status->hdr.data.super.obj_mask.super.data[0]) == 0) {
109 return -EINVAL;
110 }
111
112 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
113 &pgrp_get_status->objects[idx].data.board_obj;
114 return 0;
115}
116
117int clk_fll_sw_setup(struct gk20a *g)
118{
119 int status;
120 struct boardobjgrp *pboardobjgrp = NULL;
121 struct avfsfllobjs *pfllobjs;
122 struct fll_device *pfll;
123 struct fll_device *pfll_master;
124 struct fll_device *pfll_local;
125 u8 i;
126 u8 j;
127
128 nvgpu_log_info(g, " ");
129
130 status = boardobjgrpconstruct_e32(g, &g->clk_pmu.avfs_fllobjs.super);
131 if (status) {
132 nvgpu_err(g,
133 "error creating boardobjgrp for fll, status - 0x%x", status);
134 goto done;
135 }
136 pfllobjs = &(g->clk_pmu.avfs_fllobjs);
137 pboardobjgrp = &(g->clk_pmu.avfs_fllobjs.super.super);
138
139 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, FLL_DEVICE);
140
141 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
142 clk, CLK, clk_fll_device, CLK_FLL_DEVICE);
143 if (status) {
144 nvgpu_err(g,
145 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
146 status);
147 goto done;
148 }
149
150 pboardobjgrp->pmudatainit = _clk_fll_devgrp_pmudatainit_super;
151 pboardobjgrp->pmudatainstget = _clk_fll_devgrp_pmudata_instget;
152 pboardobjgrp->pmustatusinstget = _clk_fll_devgrp_pmustatus_instget;
153 pfllobjs = (struct avfsfllobjs *)pboardobjgrp;
154 pfllobjs->lut_num_entries = g->ops.clk.lut_num_entries;
155 pfllobjs->lut_step_size_uv = CTRL_CLK_VIN_STEP_SIZE_UV;
156 pfllobjs->lut_min_voltage_uv = CTRL_CLK_LUT_MIN_VOLTAGE_UV;
157
158 /* Initialize lut prog master mask to zero.*/
159 boardobjgrpmask_e32_init(&pfllobjs->lut_prog_master_mask, NULL);
160
161 status = devinit_get_fll_device_table(g, pfllobjs);
162 if (status) {
163 goto done;
164 }
165
166 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
167 &g->clk_pmu.avfs_fllobjs.super.super,
168 clk, CLK, clk_fll_device, CLK_FLL_DEVICE);
169 if (status) {
170 nvgpu_err(g,
171 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
172 status);
173 goto done;
174 }
175
176 BOARDOBJGRP_FOR_EACH(&(pfllobjs->super.super),
177 struct fll_device *, pfll, i) {
178 pfll_master = NULL;
179 j = 0;
180 BOARDOBJGRP_ITERATOR(&(pfllobjs->super.super),
181 struct fll_device *, pfll_local, j,
182 &pfllobjs->lut_prog_master_mask.super) {
183 if (pfll_local->clk_domain == pfll->clk_domain) {
184 pfll_master = pfll_local;
185 break;
186 }
187 }
188
189 if (pfll_master == NULL) {
190 status = boardobjgrpmask_bitset(
191 &pfllobjs->lut_prog_master_mask.super,
192 BOARDOBJ_GET_IDX(pfll));
193 if (status) {
194 nvgpu_err(g, "err setting lutprogmask");
195 goto done;
196 }
197 pfll_master = pfll;
198 }
199 status = pfll_master->lut_broadcast_slave_register(
200 g, pfllobjs, pfll_master, pfll);
201
202 if (status) {
203 nvgpu_err(g, "err setting lutslavemask");
204 goto done;
205 }
206 }
207done:
208 nvgpu_log_info(g, " done status %x", status);
209 return status;
210}
211
212int clk_fll_pmu_setup(struct gk20a *g)
213{
214 int status;
215 struct boardobjgrp *pboardobjgrp = NULL;
216
217 nvgpu_log_info(g, " ");
218
219 pboardobjgrp = &g->clk_pmu.avfs_fllobjs.super.super;
220
221 if (!pboardobjgrp->bconstructed) {
222 return -EINVAL;
223 }
224
225 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
226
227 nvgpu_log_info(g, "Done");
228 return status;
229}
230
231static int devinit_get_fll_device_table(struct gk20a *g,
232 struct avfsfllobjs *pfllobjs)
233{
234 int status = 0;
235 u8 *fll_table_ptr = NULL;
236 struct fll_descriptor_header fll_desc_table_header_sz = { 0 };
237 struct fll_descriptor_header_10 fll_desc_table_header = { 0 };
238 struct fll_descriptor_entry_10 fll_desc_table_entry = { 0 };
239 u8 *fll_tbl_entry_ptr = NULL;
240 u32 index = 0;
241 struct fll_device fll_dev_data;
242 struct fll_device *pfll_dev;
243 struct vin_device *pvin_dev;
244 u32 desctablesize;
245 u32 vbios_domain = NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP;
246 struct avfsvinobjs *pvinobjs = &g->clk_pmu.avfs_vinobjs;
247
248 nvgpu_log_info(g, " ");
249
250 fll_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
251 g->bios.clock_token, FLL_TABLE);
252 if (fll_table_ptr == NULL) {
253 status = -1;
254 goto done;
255 }
256
257 memcpy(&fll_desc_table_header_sz, fll_table_ptr,
258 sizeof(struct fll_descriptor_header));
259 if (fll_desc_table_header_sz.size >= FLL_DESCRIPTOR_HEADER_10_SIZE_6) {
260 desctablesize = FLL_DESCRIPTOR_HEADER_10_SIZE_6;
261 } else {
262 desctablesize = FLL_DESCRIPTOR_HEADER_10_SIZE_4;
263 }
264
265 memcpy(&fll_desc_table_header, fll_table_ptr, desctablesize);
266
267 if (desctablesize == FLL_DESCRIPTOR_HEADER_10_SIZE_6) {
268 pfllobjs->max_min_freq_mhz =
269 fll_desc_table_header.max_min_freq_mhz;
270 } else {
271 pfllobjs->max_min_freq_mhz = 0;
272 }
273
274 /* Read table entries*/
275 fll_tbl_entry_ptr = fll_table_ptr + desctablesize;
276 for (index = 0; index < fll_desc_table_header.entry_count; index++) {
277 u32 fll_id;
278
279 memcpy(&fll_desc_table_entry, fll_tbl_entry_ptr,
280 sizeof(struct fll_descriptor_entry_10));
281
282 if (fll_desc_table_entry.fll_device_type == CTRL_CLK_FLL_TYPE_DISABLED) {
283 continue;
284 }
285
286 fll_id = fll_desc_table_entry.fll_device_id;
287
288 if ( (u8)fll_desc_table_entry.vin_idx_logic != CTRL_CLK_VIN_ID_UNDEFINED) {
289 pvin_dev = CLK_GET_VIN_DEVICE(pvinobjs,
290 (u8)fll_desc_table_entry.vin_idx_logic);
291 if (pvin_dev == NULL) {
292 return -EINVAL;
293 } else {
294 pvin_dev->flls_shared_mask |= BIT(fll_id);
295 }
296 } else {
297 /* Return if Logic ADC device index is invalid*/
298 nvgpu_err(g, "Invalid Logic ADC specified for Nafll ID");
299 return -EINVAL;
300 }
301
302 fll_dev_data.lut_device.vselect_mode =
303 (u8)BIOS_GET_FIELD(fll_desc_table_entry.lut_params,
304 NV_FLL_DESC_LUT_PARAMS_VSELECT);
305
306 if ( (u8)fll_desc_table_entry.vin_idx_sram != CTRL_CLK_VIN_ID_UNDEFINED) {
307 pvin_dev = CLK_GET_VIN_DEVICE(pvinobjs,
308 (u8)fll_desc_table_entry.vin_idx_sram);
309 if (pvin_dev == NULL) {
310 return -EINVAL;
311 } else {
312 pvin_dev->flls_shared_mask |= BIT(fll_id);
313 }
314 } else {
315 /* Make sure VSELECT mode is set correctly to _LOGIC*/
316 if (fll_dev_data.lut_device.vselect_mode != CTRL_CLK_FLL_LUT_VSELECT_LOGIC) {
317 return -EINVAL;
318 }
319 }
320
321 fll_dev_data.super.type =
322 (u8)fll_desc_table_entry.fll_device_type;
323 fll_dev_data.id = (u8)fll_desc_table_entry.fll_device_id;
324 fll_dev_data.mdiv = (u8)BIOS_GET_FIELD(
325 fll_desc_table_entry.fll_params,
326 NV_FLL_DESC_FLL_PARAMS_MDIV);
327 fll_dev_data.input_freq_mhz =
328 (u16)fll_desc_table_entry.ref_freq_mhz;
329 fll_dev_data.min_freq_vfe_idx =
330 (u8)fll_desc_table_entry.min_freq_vfe_idx;
331 fll_dev_data.freq_ctrl_idx = CTRL_BOARDOBJ_IDX_INVALID;
332
333 vbios_domain = (u32)(fll_desc_table_entry.clk_domain &
334 NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK);
335 fll_dev_data.clk_domain =
336 g->ops.pmu_ver.clk.get_vbios_clk_domain(vbios_domain);
337
338 fll_dev_data.rail_idx_for_lut = 0;
339 fll_dev_data.vin_idx_logic =
340 (u8)fll_desc_table_entry.vin_idx_logic;
341 fll_dev_data.vin_idx_sram =
342 (u8)fll_desc_table_entry.vin_idx_sram;
343 fll_dev_data.b_skip_pldiv_below_dvco_min =
344 (bool)BIOS_GET_FIELD(fll_desc_table_entry.fll_params,
345 NV_FLL_DESC_FLL_PARAMS_SKIP_PLDIV_BELOW_DVCO_MIN);
346 fll_dev_data.lut_device.hysteresis_threshold =
347 (u8)BIOS_GET_FIELD(fll_desc_table_entry.lut_params,
348 NV_FLL_DESC_LUT_PARAMS_HYSTERISIS_THRESHOLD);
349 fll_dev_data.regime_desc.regime_id =
350 CTRL_CLK_FLL_REGIME_ID_FFR;
351 fll_dev_data.regime_desc.fixed_freq_regime_limit_mhz =
352 (u16)fll_desc_table_entry.ffr_cutoff_freq_mhz;
353 fll_dev_data.regime_desc.target_regime_id_override=0;
354
355 /*construct fll device*/
356 pfll_dev = construct_fll_device(g, (void *)&fll_dev_data);
357
358 status = boardobjgrp_objinsert(&pfllobjs->super.super,
359 (struct boardobj *)pfll_dev, index);
360 fll_tbl_entry_ptr += fll_desc_table_header.entry_size;
361 }
362
363done:
364 nvgpu_log_info(g, " done status %x", status);
365 return status;
366}
367
368u32 nvgpu_clk_get_vbios_clk_domain_gv10x( u32 vbios_domain)
369{
370 if (vbios_domain == 0) {
371 return CTRL_CLK_DOMAIN_GPCCLK;
372 } else if (vbios_domain == 1) {
373 return CTRL_CLK_DOMAIN_XBARCLK;
374 } else if (vbios_domain == 3) {
375 return CTRL_CLK_DOMAIN_SYSCLK;
376 } else if (vbios_domain == 5) {
377 return CTRL_CLK_DOMAIN_NVDCLK;
378 }
379 return 0;
380}
381
382u32 nvgpu_clk_get_vbios_clk_domain_gp10x( u32 vbios_domain)
383{
384 if (vbios_domain == 0) {
385 return CTRL_CLK_DOMAIN_GPC2CLK;
386 } else if (vbios_domain == 1) {
387 return CTRL_CLK_DOMAIN_XBAR2CLK;
388 } else if (vbios_domain == 3) {
389 return CTRL_CLK_DOMAIN_SYS2CLK;
390 }
391 return 0;
392}
393
394static u32 lutbroadcastslaveregister(struct gk20a *g,
395 struct avfsfllobjs *pfllobjs,
396 struct fll_device *pfll,
397 struct fll_device *pfll_slave)
398{
399 if (pfll->clk_domain != pfll_slave->clk_domain) {
400 return -EINVAL;
401 }
402
403 return boardobjgrpmask_bitset(&pfll->
404 lut_prog_broadcast_slave_mask.super,
405 BOARDOBJ_GET_IDX(pfll_slave));
406}
407
408static struct fll_device *construct_fll_device(struct gk20a *g,
409 void *pargs)
410{
411 struct boardobj *board_obj_ptr = NULL;
412 struct fll_device *pfll_dev;
413 struct fll_device *board_obj_fll_ptr = NULL;
414 int status;
415
416 nvgpu_log_info(g, " ");
417 status = boardobj_construct_super(g, &board_obj_ptr,
418 sizeof(struct fll_device), pargs);
419 if (status) {
420 return NULL;
421 }
422
423 pfll_dev = (struct fll_device *)pargs;
424 board_obj_fll_ptr = (struct fll_device *)board_obj_ptr;
425 board_obj_ptr->pmudatainit = fll_device_init_pmudata_super;
426 board_obj_fll_ptr->lut_broadcast_slave_register =
427 lutbroadcastslaveregister;
428 board_obj_fll_ptr->id = pfll_dev->id;
429 board_obj_fll_ptr->mdiv = pfll_dev->mdiv;
430 board_obj_fll_ptr->rail_idx_for_lut = pfll_dev->rail_idx_for_lut;
431 board_obj_fll_ptr->input_freq_mhz = pfll_dev->input_freq_mhz;
432 board_obj_fll_ptr->clk_domain = pfll_dev->clk_domain;
433 board_obj_fll_ptr->vin_idx_logic = pfll_dev->vin_idx_logic;
434 board_obj_fll_ptr->vin_idx_sram = pfll_dev->vin_idx_sram;
435 board_obj_fll_ptr->min_freq_vfe_idx =
436 pfll_dev->min_freq_vfe_idx;
437 board_obj_fll_ptr->freq_ctrl_idx = pfll_dev->freq_ctrl_idx;
438 board_obj_fll_ptr->b_skip_pldiv_below_dvco_min =
439 pfll_dev->b_skip_pldiv_below_dvco_min;
440 memcpy(&board_obj_fll_ptr->lut_device, &pfll_dev->lut_device,
441 sizeof(struct nv_pmu_clk_lut_device_desc));
442 memcpy(&board_obj_fll_ptr->regime_desc, &pfll_dev->regime_desc,
443 sizeof(struct nv_pmu_clk_regime_desc));
444 boardobjgrpmask_e32_init(
445 &board_obj_fll_ptr->lut_prog_broadcast_slave_mask, NULL);
446
447 nvgpu_log_info(g, " Done");
448
449 return (struct fll_device *)board_obj_ptr;
450}
451
452static int fll_device_init_pmudata_super(struct gk20a *g,
453 struct boardobj *board_obj_ptr,
454 struct nv_pmu_boardobj *ppmudata)
455{
456 int status = 0;
457 struct fll_device *pfll_dev;
458 struct nv_pmu_clk_clk_fll_device_boardobj_set *perf_pmu_data;
459
460 nvgpu_log_info(g, " ");
461
462 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
463 if (status != 0) {
464 return status;
465 }
466
467 pfll_dev = (struct fll_device *)board_obj_ptr;
468 perf_pmu_data = (struct nv_pmu_clk_clk_fll_device_boardobj_set *)
469 ppmudata;
470
471 perf_pmu_data->id = pfll_dev->id;
472 perf_pmu_data->mdiv = pfll_dev->mdiv;
473 perf_pmu_data->rail_idx_for_lut = pfll_dev->rail_idx_for_lut;
474 perf_pmu_data->input_freq_mhz = pfll_dev->input_freq_mhz;
475 perf_pmu_data->vin_idx_logic = pfll_dev->vin_idx_logic;
476 perf_pmu_data->vin_idx_sram = pfll_dev->vin_idx_sram;
477 perf_pmu_data->clk_domain = pfll_dev->clk_domain;
478 perf_pmu_data->min_freq_vfe_idx =
479 pfll_dev->min_freq_vfe_idx;
480 perf_pmu_data->freq_ctrl_idx = pfll_dev->freq_ctrl_idx;
481 perf_pmu_data->b_skip_pldiv_below_dvco_min = pfll_dev->b_skip_pldiv_below_dvco_min;
482 memcpy(&perf_pmu_data->lut_device, &pfll_dev->lut_device,
483 sizeof(struct nv_pmu_clk_lut_device_desc));
484 memcpy(&perf_pmu_data->regime_desc, &pfll_dev->regime_desc,
485 sizeof(struct nv_pmu_clk_regime_desc));
486
487 status = boardobjgrpmask_export(
488 &pfll_dev->lut_prog_broadcast_slave_mask.super,
489 pfll_dev->lut_prog_broadcast_slave_mask.super.bitcount,
490 &perf_pmu_data->lut_prog_broadcast_slave_mask.super);
491
492 nvgpu_log_info(g, " Done");
493
494 return status;
495}