aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_vin.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/clk/clk_vin.c')
-rw-r--r--include/clk/clk_vin.c573
1 files changed, 0 insertions, 573 deletions
diff --git a/include/clk/clk_vin.c b/include/clk/clk_vin.c
deleted file mode 100644
index e0a4a5b..0000000
--- a/include/clk/clk_vin.c
+++ /dev/null
@@ -1,573 +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/pmuif/nvgpu_gpmu_cmdif.h>
25#include <nvgpu/io.h>
26#include <nvgpu/gk20a.h>
27
28#include "boardobj/boardobjgrp.h"
29#include "boardobj/boardobjgrp_e32.h"
30
31#include "ctrl/ctrlvolt.h"
32
33#include "gp106/bios_gp106.h"
34
35#include "clk.h"
36#include "clk_vin.h"
37
38static int devinit_get_vin_device_table(struct gk20a *g,
39 struct avfsvinobjs *pvinobjs);
40
41static int vin_device_construct_v10(struct gk20a *g,
42 struct boardobj **ppboardobj,
43 u16 size, void *pargs);
44static int vin_device_construct_v20(struct gk20a *g,
45 struct boardobj **ppboardobj,
46 u16 size, void *pargs);
47static int vin_device_construct_super(struct gk20a *g,
48 struct boardobj **ppboardobj,
49 u16 size, void *pargs);
50static struct vin_device *construct_vin_device(struct gk20a *g, void *pargs);
51
52static int vin_device_init_pmudata_v10(struct gk20a *g,
53 struct boardobj *board_obj_ptr,
54 struct nv_pmu_boardobj *ppmudata);
55static int vin_device_init_pmudata_v20(struct gk20a *g,
56 struct boardobj *board_obj_ptr,
57 struct nv_pmu_boardobj *ppmudata);
58static int vin_device_init_pmudata_super(struct gk20a *g,
59 struct boardobj *board_obj_ptr,
60 struct nv_pmu_boardobj *ppmudata);
61
62u32 clk_avfs_get_vin_cal_fuse_v10(struct gk20a *g,
63 struct avfsvinobjs *pvinobjs,
64 struct vin_device_v20 *pvindev)
65{
66 u32 status = 0;
67 u32 slope, intercept;
68 u8 i;
69
70 if (pvinobjs->calibration_rev_vbios == g->ops.fuse.read_vin_cal_fuse_rev(g)) {
71 BOARDOBJGRP_FOR_EACH(&(pvinobjs->super.super),
72 struct vin_device_v20 *, pvindev, i) {
73 slope = 0;
74 intercept = 0;
75 pvindev = (struct vin_device_v20 *)CLK_GET_VIN_DEVICE(pvinobjs, i);
76 status = g->ops.fuse.read_vin_cal_slope_intercept_fuse(g,
77 pvindev->super.id, &slope, &intercept);
78 if (status) {
79 nvgpu_err(g,
80 "err reading vin cal for id %x", pvindev->super.id);
81 return status;
82 }
83 pvindev->data.vin_cal.cal_v10.slope = slope;
84 pvindev->data.vin_cal.cal_v10.intercept = intercept;
85 }
86 }
87 return status;
88
89}
90
91u32 clk_avfs_get_vin_cal_fuse_v20(struct gk20a *g,
92 struct avfsvinobjs *pvinobjs,
93 struct vin_device_v20 *pvindev)
94{
95 u32 status = 0;
96 s8 gain, offset;
97 u8 i;
98
99 if (pvinobjs->calibration_rev_vbios == g->ops.fuse.read_vin_cal_fuse_rev(g)) {
100 BOARDOBJGRP_FOR_EACH(&(pvinobjs->super.super),
101 struct vin_device_v20 *, pvindev, i) {
102 gain = '\0';
103 offset = '\0';
104 pvindev = (struct vin_device_v20 *)CLK_GET_VIN_DEVICE(pvinobjs, i);
105 status = g->ops.fuse.read_vin_cal_gain_offset_fuse(g,
106 pvindev->super.id, &gain, &offset);
107 if (status) {
108 nvgpu_err(g,
109 "err reading vin cal for id %x", pvindev->super.id);
110 return status;
111 }
112 pvindev->data.vin_cal.cal_v20.gain = gain;
113 pvindev->data.vin_cal.cal_v20.offset = offset;
114 }
115 }
116 return status;
117
118}
119
120static int _clk_vin_devgrp_pmudatainit_super(struct gk20a *g,
121 struct boardobjgrp *pboardobjgrp,
122 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
123{
124 struct nv_pmu_clk_clk_vin_device_boardobjgrp_set_header *pset =
125 (struct nv_pmu_clk_clk_vin_device_boardobjgrp_set_header *)
126 pboardobjgrppmu;
127 struct avfsvinobjs *pvin_obbj = (struct avfsvinobjs *)pboardobjgrp;
128 int status = 0;
129
130 nvgpu_log_info(g, " ");
131
132 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
133
134 pset->b_vin_is_disable_allowed = pvin_obbj->vin_is_disable_allowed;
135
136 nvgpu_log_info(g, " Done");
137 return status;
138}
139
140static int _clk_vin_devgrp_pmudata_instget(struct gk20a *g,
141 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
142 struct nv_pmu_boardobj **ppboardobjpmudata,
143 u8 idx)
144{
145 struct nv_pmu_clk_clk_vin_device_boardobj_grp_set *pgrp_set =
146 (struct nv_pmu_clk_clk_vin_device_boardobj_grp_set *)
147 pmuboardobjgrp;
148
149 nvgpu_log_info(g, " ");
150
151 /*check whether pmuboardobjgrp has a valid boardobj in index*/
152 if (((u32)BIT(idx) &
153 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) {
154 return -EINVAL;
155 }
156
157 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
158 &pgrp_set->objects[idx].data.board_obj;
159 nvgpu_log_info(g, " Done");
160 return 0;
161}
162
163static int _clk_vin_devgrp_pmustatus_instget(struct gk20a *g,
164 void *pboardobjgrppmu,
165 struct nv_pmu_boardobj_query **ppboardobjpmustatus,
166 u8 idx)
167{
168 struct nv_pmu_clk_clk_vin_device_boardobj_grp_get_status *pgrp_get_status =
169 (struct nv_pmu_clk_clk_vin_device_boardobj_grp_get_status *)
170 pboardobjgrppmu;
171
172 /*check whether pmuboardobjgrp has a valid boardobj in index*/
173 if (((u32)BIT(idx) &
174 pgrp_get_status->hdr.data.super.obj_mask.super.data[0]) == 0) {
175 return -EINVAL;
176 }
177
178 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
179 &pgrp_get_status->objects[idx].data.board_obj;
180 return 0;
181}
182
183int clk_vin_sw_setup(struct gk20a *g)
184{
185 int status;
186 struct boardobjgrp *pboardobjgrp = NULL;
187 struct vin_device_v20 *pvindev = NULL;
188 struct avfsvinobjs *pvinobjs;
189
190 nvgpu_log_info(g, " ");
191
192 status = boardobjgrpconstruct_e32(g, &g->clk_pmu.avfs_vinobjs.super);
193 if (status) {
194 nvgpu_err(g,
195 "error creating boardobjgrp for clk vin, statu - 0x%x",
196 status);
197 goto done;
198 }
199
200 pboardobjgrp = &g->clk_pmu.avfs_vinobjs.super.super;
201 pvinobjs = &g->clk_pmu.avfs_vinobjs;
202
203 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, VIN_DEVICE);
204
205 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
206 clk, CLK, clk_vin_device, CLK_VIN_DEVICE);
207 if (status) {
208 nvgpu_err(g,
209 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
210 status);
211 goto done;
212 }
213
214 pboardobjgrp->pmudatainit = _clk_vin_devgrp_pmudatainit_super;
215 pboardobjgrp->pmudatainstget = _clk_vin_devgrp_pmudata_instget;
216 pboardobjgrp->pmustatusinstget = _clk_vin_devgrp_pmustatus_instget;
217
218 status = devinit_get_vin_device_table(g, &g->clk_pmu.avfs_vinobjs);
219 if (status) {
220 goto done;
221 }
222
223 /*update vin calibration to fuse */
224 g->ops.pmu_ver.clk.clk_avfs_get_vin_cal_data(g, pvinobjs, pvindev);
225
226 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
227 &g->clk_pmu.avfs_vinobjs.super.super,
228 clk, CLK, clk_vin_device, CLK_VIN_DEVICE);
229 if (status) {
230 nvgpu_err(g,
231 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
232 status);
233 goto done;
234 }
235
236done:
237 nvgpu_log_info(g, " done status %x", status);
238 return status;
239}
240
241int clk_vin_pmu_setup(struct gk20a *g)
242{
243 int status;
244 struct boardobjgrp *pboardobjgrp = NULL;
245
246 nvgpu_log_info(g, " ");
247
248 pboardobjgrp = &g->clk_pmu.avfs_vinobjs.super.super;
249
250 if (!pboardobjgrp->bconstructed) {
251 return -EINVAL;
252 }
253
254 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
255
256 nvgpu_log_info(g, "Done");
257 return status;
258}
259
260static int devinit_get_vin_device_table(struct gk20a *g,
261 struct avfsvinobjs *pvinobjs)
262{
263 int status = 0;
264 u8 *vin_table_ptr = NULL;
265 struct vin_descriptor_header_10 vin_desc_table_header = { 0 };
266 struct vin_descriptor_entry_10 vin_desc_table_entry = { 0 };
267 u8 *vin_tbl_entry_ptr = NULL;
268 u32 index = 0;
269 u32 slope=0, intercept=0;
270 s8 offset='\0', gain='\0';
271 struct vin_device *pvin_dev;
272 u32 cal_type;
273
274 union {
275 struct boardobj boardobj;
276 struct vin_device vin_device;
277 struct vin_device_v10 vin_device_v10;
278 struct vin_device_v20 vin_device_v20;
279 } vin_device_data;
280
281 nvgpu_log_info(g, " ");
282
283 vin_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
284 g->bios.clock_token, VIN_TABLE);
285 if (vin_table_ptr == NULL) {
286 status = -1;
287 goto done;
288 }
289
290 memcpy(&vin_desc_table_header, vin_table_ptr,
291 sizeof(struct vin_descriptor_header_10));
292
293 pvinobjs->calibration_rev_vbios =
294 BIOS_GET_FIELD(vin_desc_table_header.flags0,
295 NV_VIN_DESC_FLAGS0_VIN_CAL_REVISION);
296 pvinobjs->vin_is_disable_allowed =
297 BIOS_GET_FIELD(vin_desc_table_header.flags0,
298 NV_VIN_DESC_FLAGS0_DISABLE_CONTROL);
299 cal_type = BIOS_GET_FIELD(vin_desc_table_header.flags0,
300 NV_VIN_DESC_FLAGS0_VIN_CAL_TYPE);
301 if (!cal_type) {
302 cal_type = CTRL_CLK_VIN_CAL_TYPE_V10;
303 }
304
305 switch (cal_type) {
306 case CTRL_CLK_VIN_CAL_TYPE_V10:
307 /* VIN calibration slope: XX.YYY mV/code => XXYYY uV/code*/
308 slope = ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
309 NV_VIN_DESC_VIN_CAL_SLOPE_INTEGER) * 1000)) +
310 ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
311 NV_VIN_DESC_VIN_CAL_SLOPE_FRACTION)));
312
313 /* VIN calibration intercept: ZZZ.W mV => ZZZW00 uV */
314 intercept = ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
315 NV_VIN_DESC_VIN_CAL_INTERCEPT_INTEGER) * 1000)) +
316 ((BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
317 NV_VIN_DESC_VIN_CAL_INTERCEPT_FRACTION) * 100));
318
319 break;
320 case CTRL_CLK_VIN_CAL_TYPE_V20:
321 offset = BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
322 NV_VIN_DESC_VIN_CAL_OFFSET);
323 gain = BIOS_GET_FIELD(vin_desc_table_header.vin_cal,
324 NV_VIN_DESC_VIN_CAL_GAIN);
325 break;
326 default:
327 status = -1;
328 goto done;
329 }
330 /* Read table entries*/
331 vin_tbl_entry_ptr = vin_table_ptr + vin_desc_table_header.header_sizee;
332 for (index = 0; index < vin_desc_table_header.entry_count; index++) {
333 memcpy(&vin_desc_table_entry, vin_tbl_entry_ptr,
334 sizeof(struct vin_descriptor_entry_10));
335
336 if (vin_desc_table_entry.vin_device_type == CTRL_CLK_VIN_TYPE_DISABLED) {
337 continue;
338 }
339
340 vin_device_data.boardobj.type =
341 (u8)vin_desc_table_entry.vin_device_type;
342 vin_device_data.vin_device.id = (u8)vin_desc_table_entry.vin_device_id;
343 vin_device_data.vin_device.volt_domain_vbios =
344 (u8)vin_desc_table_entry.volt_domain_vbios;
345 vin_device_data.vin_device.flls_shared_mask = 0;
346
347 switch (vin_device_data.boardobj.type) {
348 case CTRL_CLK_VIN_TYPE_V10:
349 vin_device_data.vin_device_v10.data.vin_cal.slope = slope;
350 vin_device_data.vin_device_v10.data.vin_cal.intercept = intercept;
351 break;
352 case CTRL_CLK_VIN_TYPE_V20:
353 vin_device_data.vin_device_v20.data.cal_type = (u8) cal_type;
354 vin_device_data.vin_device_v20.data.vin_cal.cal_v20.offset = offset;
355 vin_device_data.vin_device_v20.data.vin_cal.cal_v20.gain = gain;
356 break;
357 default:
358 status = -1;
359 goto done;
360 };
361
362 pvin_dev = construct_vin_device(g, (void *)&vin_device_data);
363
364 status = boardobjgrp_objinsert(&pvinobjs->super.super,
365 (struct boardobj *)pvin_dev, index);
366
367 vin_tbl_entry_ptr += vin_desc_table_header.entry_size;
368 }
369
370done:
371 nvgpu_log_info(g, " done status %x", status);
372 return status;
373}
374
375static int vin_device_construct_v10(struct gk20a *g,
376 struct boardobj **ppboardobj,
377 u16 size, void *pargs)
378{
379 struct boardobj *ptmpobj = (struct boardobj *)pargs;
380 struct vin_device_v10 *pvin_device_v10;
381 struct vin_device_v10 *ptmpvin_device_v10 = (struct vin_device_v10 *)pargs;
382 int status = 0;
383
384 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_VIN_TYPE_V10) {
385 return -EINVAL;
386 }
387
388 ptmpobj->type_mask |= BIT(CTRL_CLK_VIN_TYPE_V10);
389 status = vin_device_construct_super(g, ppboardobj, size, pargs);
390 if (status) {
391 return -EINVAL;
392 }
393
394 pvin_device_v10 = (struct vin_device_v10 *)*ppboardobj;
395
396 pvin_device_v10->super.super.pmudatainit =
397 vin_device_init_pmudata_v10;
398
399 pvin_device_v10->data.vin_cal.slope = ptmpvin_device_v10->data.vin_cal.slope;
400 pvin_device_v10->data.vin_cal.intercept = ptmpvin_device_v10->data.vin_cal.intercept;
401
402 return status;
403}
404
405static int vin_device_construct_v20(struct gk20a *g,
406 struct boardobj **ppboardobj,
407 u16 size, void *pargs)
408{
409 struct boardobj *ptmpobj = (struct boardobj *)pargs;
410 struct vin_device_v20 *pvin_device_v20;
411 struct vin_device_v20 *ptmpvin_device_v20 = (struct vin_device_v20 *)pargs;
412 int status = 0;
413
414 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_VIN_TYPE_V20) {
415 return -EINVAL;
416 }
417
418 ptmpobj->type_mask |= BIT(CTRL_CLK_VIN_TYPE_V20);
419 status = vin_device_construct_super(g, ppboardobj, size, pargs);
420 if (status) {
421 return -EINVAL;
422 }
423
424 pvin_device_v20 = (struct vin_device_v20 *)*ppboardobj;
425
426 pvin_device_v20->super.super.pmudatainit =
427 vin_device_init_pmudata_v20;
428
429 pvin_device_v20->data.cal_type = ptmpvin_device_v20->data.cal_type;
430 pvin_device_v20->data.vin_cal.cal_v20.offset = ptmpvin_device_v20->data.vin_cal.cal_v20.offset;
431 pvin_device_v20->data.vin_cal.cal_v20.gain = ptmpvin_device_v20->data.vin_cal.cal_v20.gain;
432
433 return status;
434}
435static int vin_device_construct_super(struct gk20a *g,
436 struct boardobj **ppboardobj,
437 u16 size, void *pargs)
438{
439 struct vin_device *pvin_device;
440 struct vin_device *ptmpvin_device = (struct vin_device *)pargs;
441 int status = 0;
442 status = boardobj_construct_super(g, ppboardobj, size, pargs);
443
444 if (status) {
445 return -EINVAL;
446 }
447
448 pvin_device = (struct vin_device *)*ppboardobj;
449
450 pvin_device->super.pmudatainit =
451 vin_device_init_pmudata_super;
452
453 pvin_device->id = ptmpvin_device->id;
454 pvin_device->volt_domain_vbios = ptmpvin_device->volt_domain_vbios;
455 pvin_device->flls_shared_mask = ptmpvin_device->flls_shared_mask;
456 pvin_device->volt_domain = CTRL_VOLT_DOMAIN_LOGIC;
457
458 return status;
459}
460static struct vin_device *construct_vin_device(struct gk20a *g, void *pargs)
461{
462 struct boardobj *board_obj_ptr = NULL;
463 int status;
464
465 nvgpu_log_info(g, " %d", BOARDOBJ_GET_TYPE(pargs));
466 switch (BOARDOBJ_GET_TYPE(pargs)) {
467 case CTRL_CLK_VIN_TYPE_V10:
468 status = vin_device_construct_v10(g, &board_obj_ptr,
469 sizeof(struct vin_device_v10), pargs);
470 break;
471
472 case CTRL_CLK_VIN_TYPE_V20:
473 status = vin_device_construct_v20(g, &board_obj_ptr,
474 sizeof(struct vin_device_v20), pargs);
475 break;
476
477 default:
478 return NULL;
479 };
480
481 if (status) {
482 return NULL;
483 }
484
485 nvgpu_log_info(g, " Done");
486
487 return (struct vin_device *)board_obj_ptr;
488}
489
490
491
492static int vin_device_init_pmudata_v10(struct gk20a *g,
493 struct boardobj *board_obj_ptr,
494 struct nv_pmu_boardobj *ppmudata)
495{
496 int status = 0;
497 struct vin_device_v20 *pvin_dev_v20;
498 struct nv_pmu_clk_clk_vin_device_v10_boardobj_set *perf_pmu_data;
499
500 nvgpu_log_info(g, " ");
501
502 status = vin_device_init_pmudata_super(g, board_obj_ptr, ppmudata);
503 if (status != 0) {
504 return status;
505 }
506
507 pvin_dev_v20 = (struct vin_device_v20 *)board_obj_ptr;
508 perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_v10_boardobj_set *)
509 ppmudata;
510
511 perf_pmu_data->data.vin_cal.intercept = pvin_dev_v20->data.vin_cal.cal_v10.intercept;
512 perf_pmu_data->data.vin_cal.slope = pvin_dev_v20->data.vin_cal.cal_v10.slope;
513
514 nvgpu_log_info(g, " Done");
515
516 return status;
517}
518
519static int vin_device_init_pmudata_v20(struct gk20a *g,
520 struct boardobj *board_obj_ptr,
521 struct nv_pmu_boardobj *ppmudata)
522{
523 int status = 0;
524 struct vin_device_v20 *pvin_dev_v20;
525 struct nv_pmu_clk_clk_vin_device_v20_boardobj_set *perf_pmu_data;
526
527 nvgpu_log_info(g, " ");
528
529 status = vin_device_init_pmudata_super(g, board_obj_ptr, ppmudata);
530 if (status != 0) {
531 return status;
532 }
533
534 pvin_dev_v20 = (struct vin_device_v20 *)board_obj_ptr;
535 perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_v20_boardobj_set *)
536 ppmudata;
537
538 perf_pmu_data->data.cal_type = pvin_dev_v20->data.cal_type;
539 perf_pmu_data->data.vin_cal.cal_v20.offset = pvin_dev_v20->data.vin_cal.cal_v20.offset;
540 perf_pmu_data->data.vin_cal.cal_v20.gain = pvin_dev_v20->data.vin_cal.cal_v20.gain;
541
542 nvgpu_log_info(g, " Done");
543
544 return status;
545}
546
547static int vin_device_init_pmudata_super(struct gk20a *g,
548 struct boardobj *board_obj_ptr,
549 struct nv_pmu_boardobj *ppmudata)
550{
551 int status = 0;
552 struct vin_device *pvin_dev;
553 struct nv_pmu_clk_clk_vin_device_boardobj_set *perf_pmu_data;
554
555 nvgpu_log_info(g, " ");
556
557 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
558 if (status != 0) {
559 return status;
560 }
561
562 pvin_dev = (struct vin_device *)board_obj_ptr;
563 perf_pmu_data = (struct nv_pmu_clk_clk_vin_device_boardobj_set *)
564 ppmudata;
565
566 perf_pmu_data->id = pvin_dev->id;
567 perf_pmu_data->volt_domain = pvin_dev->volt_domain;
568 perf_pmu_data->flls_shared_mask = pvin_dev->flls_shared_mask;
569
570 nvgpu_log_info(g, " Done");
571
572 return status;
573}