aboutsummaryrefslogtreecommitdiffstats
path: root/include/clk/clk_vf_point.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/clk/clk_vf_point.c')
-rw-r--r--include/clk/clk_vf_point.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/include/clk/clk_vf_point.c b/include/clk/clk_vf_point.c
new file mode 100644
index 0000000..96413c8
--- /dev/null
+++ b/include/clk/clk_vf_point.c
@@ -0,0 +1,433 @@
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/gk20a.h>
24
25#include "clk.h"
26#include "clk_vf_point.h"
27#include "boardobj/boardobjgrp.h"
28#include "boardobj/boardobjgrp_e32.h"
29#include "ctrl/ctrlclk.h"
30#include "ctrl/ctrlvolt.h"
31
32static int _clk_vf_point_pmudatainit_super(struct gk20a *g, struct boardobj
33 *board_obj_ptr, struct nv_pmu_boardobj *ppmudata);
34
35static int _clk_vf_points_pmudatainit(struct gk20a *g,
36 struct boardobjgrp *pboardobjgrp,
37 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
38{
39 u32 status = 0;
40
41 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
42 if (status) {
43 nvgpu_err(g,
44 "error updating pmu boardobjgrp for clk vfpoint 0x%x",
45 status);
46 goto done;
47 }
48
49done:
50 return status;
51}
52
53static int _clk_vf_points_pmudata_instget(struct gk20a *g,
54 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
55 struct nv_pmu_boardobj **ppboardobjpmudata,
56 u8 idx)
57{
58 struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *pgrp_set =
59 (struct nv_pmu_clk_clk_vf_point_boardobj_grp_set *)
60 pmuboardobjgrp;
61
62 nvgpu_log_info(g, " ");
63
64 /*check whether pmuboardobjgrp has a valid boardobj in index*/
65 if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) {
66 return -EINVAL;
67 }
68
69 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
70 &pgrp_set->objects[idx].data.board_obj;
71 nvgpu_log_info(g, " Done");
72 return 0;
73}
74
75static int _clk_vf_points_pmustatus_instget(struct gk20a *g,
76 void *pboardobjgrppmu,
77 struct nv_pmu_boardobj_query **ppboardobjpmustatus,
78 u8 idx)
79{
80 struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *pgrp_get_status =
81 (struct nv_pmu_clk_clk_vf_point_boardobj_grp_get_status *)
82 pboardobjgrppmu;
83
84 /*check whether pmuboardobjgrp has a valid boardobj in index*/
85 if (idx >= CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) {
86 return -EINVAL;
87 }
88
89 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
90 &pgrp_get_status->objects[idx].data.board_obj;
91 return 0;
92}
93
94int clk_vf_point_sw_setup(struct gk20a *g)
95{
96 int status;
97 struct boardobjgrp *pboardobjgrp = NULL;
98
99 nvgpu_log_info(g, " ");
100
101 status = boardobjgrpconstruct_e255(g, &g->clk_pmu.clk_vf_pointobjs.super);
102 if (status) {
103 nvgpu_err(g,
104 "error creating boardobjgrp for clk vfpoint, status - 0x%x",
105 status);
106 goto done;
107 }
108
109 pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super;
110
111 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_VF_POINT);
112
113 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
114 clk, CLK, clk_vf_point, CLK_VF_POINT);
115 if (status) {
116 nvgpu_err(g,
117 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
118 status);
119 goto done;
120 }
121
122 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
123 &g->clk_pmu.clk_vf_pointobjs.super.super,
124 clk, CLK, clk_vf_point, CLK_VF_POINT);
125 if (status) {
126 nvgpu_err(g,
127 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
128 status);
129 goto done;
130 }
131
132 pboardobjgrp->pmudatainit = _clk_vf_points_pmudatainit;
133 pboardobjgrp->pmudatainstget = _clk_vf_points_pmudata_instget;
134 pboardobjgrp->pmustatusinstget = _clk_vf_points_pmustatus_instget;
135
136done:
137 nvgpu_log_info(g, " done status %x", status);
138 return status;
139}
140
141int clk_vf_point_pmu_setup(struct gk20a *g)
142{
143 int status;
144 struct boardobjgrp *pboardobjgrp = NULL;
145
146 nvgpu_log_info(g, " ");
147
148 pboardobjgrp = &g->clk_pmu.clk_vf_pointobjs.super.super;
149
150 if (!pboardobjgrp->bconstructed) {
151 return -EINVAL;
152 }
153
154 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
155
156 nvgpu_log_info(g, "Done");
157 return status;
158}
159
160static int clk_vf_point_construct_super(struct gk20a *g,
161 struct boardobj **ppboardobj,
162 u16 size, void *pargs)
163{
164 struct clk_vf_point *pclkvfpoint;
165 struct clk_vf_point *ptmpvfpoint =
166 (struct clk_vf_point *)pargs;
167 int status = 0;
168
169 status = boardobj_construct_super(g, ppboardobj,
170 size, pargs);
171 if (status) {
172 return -EINVAL;
173 }
174
175 pclkvfpoint = (struct clk_vf_point *)*ppboardobj;
176
177 pclkvfpoint->super.pmudatainit =
178 _clk_vf_point_pmudatainit_super;
179
180 pclkvfpoint->vfe_equ_idx = ptmpvfpoint->vfe_equ_idx;
181 pclkvfpoint->volt_rail_idx = ptmpvfpoint->volt_rail_idx;
182
183 return status;
184}
185
186static int _clk_vf_point_pmudatainit_volt(struct gk20a *g,
187 struct boardobj *board_obj_ptr,
188 struct nv_pmu_boardobj *ppmudata)
189{
190 int status = 0;
191 struct clk_vf_point_volt *pclk_vf_point_volt;
192 struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *pset;
193
194 nvgpu_log_info(g, " ");
195
196 status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata);
197 if (status != 0) {
198 return status;
199 }
200
201 pclk_vf_point_volt =
202 (struct clk_vf_point_volt *)board_obj_ptr;
203
204 pset = (struct nv_pmu_clk_clk_vf_point_volt_boardobj_set *)
205 ppmudata;
206
207 pset->source_voltage_uv = pclk_vf_point_volt->source_voltage_uv;
208 pset->freq_delta.data = pclk_vf_point_volt->freq_delta.data;
209 pset->freq_delta.type = pclk_vf_point_volt->freq_delta.type;
210
211 return status;
212}
213
214static int _clk_vf_point_pmudatainit_freq(struct gk20a *g,
215 struct boardobj *board_obj_ptr,
216 struct nv_pmu_boardobj *ppmudata)
217{
218 int status = 0;
219 struct clk_vf_point_freq *pclk_vf_point_freq;
220 struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *pset;
221
222 nvgpu_log_info(g, " ");
223
224 status = _clk_vf_point_pmudatainit_super(g, board_obj_ptr, ppmudata);
225 if (status != 0) {
226 return status;
227 }
228
229 pclk_vf_point_freq =
230 (struct clk_vf_point_freq *)board_obj_ptr;
231
232 pset = (struct nv_pmu_clk_clk_vf_point_freq_boardobj_set *)
233 ppmudata;
234
235 pset->freq_mhz =
236 clkvfpointfreqmhzget(g, &pclk_vf_point_freq->super);
237
238 pset->volt_delta_uv = pclk_vf_point_freq->volt_delta_uv;
239
240 return status;
241}
242
243static int clk_vf_point_construct_volt(struct gk20a *g,
244 struct boardobj **ppboardobj,
245 u16 size, void *pargs)
246{
247 struct boardobj *ptmpobj = (struct boardobj *)pargs;
248 struct clk_vf_point_volt *pclkvfpoint;
249 struct clk_vf_point_volt *ptmpvfpoint =
250 (struct clk_vf_point_volt *)pargs;
251 int status = 0;
252
253 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_VOLT) {
254 return -EINVAL;
255 }
256
257 ptmpobj->type_mask = BIT(CTRL_CLK_CLK_VF_POINT_TYPE_VOLT);
258 status = clk_vf_point_construct_super(g, ppboardobj, size, pargs);
259 if (status) {
260 return -EINVAL;
261 }
262
263 pclkvfpoint = (struct clk_vf_point_volt *)*ppboardobj;
264
265 pclkvfpoint->super.super.pmudatainit =
266 _clk_vf_point_pmudatainit_volt;
267
268 pclkvfpoint->source_voltage_uv = ptmpvfpoint->source_voltage_uv;
269 pclkvfpoint->freq_delta = ptmpvfpoint->freq_delta;
270
271 return status;
272}
273
274static int clk_vf_point_construct_freq(struct gk20a *g,
275 struct boardobj **ppboardobj,
276 u16 size, void *pargs)
277{
278 struct boardobj *ptmpobj = (struct boardobj *)pargs;
279 struct clk_vf_point_freq *pclkvfpoint;
280 struct clk_vf_point_freq *ptmpvfpoint =
281 (struct clk_vf_point_freq *)pargs;
282 int status = 0;
283
284 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_VF_POINT_TYPE_FREQ) {
285 return -EINVAL;
286 }
287
288 ptmpobj->type_mask = BIT(CTRL_CLK_CLK_VF_POINT_TYPE_FREQ);
289 status = clk_vf_point_construct_super(g, ppboardobj, size, pargs);
290 if (status) {
291 return -EINVAL;
292 }
293
294 pclkvfpoint = (struct clk_vf_point_freq *)*ppboardobj;
295
296 pclkvfpoint->super.super.pmudatainit =
297 _clk_vf_point_pmudatainit_freq;
298
299 clkvfpointfreqmhzset(g, &pclkvfpoint->super,
300 clkvfpointfreqmhzget(g, &ptmpvfpoint->super));
301
302 return status;
303}
304
305struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs)
306{
307 struct boardobj *board_obj_ptr = NULL;
308 int status;
309
310 nvgpu_log_info(g, " ");
311 switch (BOARDOBJ_GET_TYPE(pargs)) {
312 case CTRL_CLK_CLK_VF_POINT_TYPE_FREQ:
313 status = clk_vf_point_construct_freq(g, &board_obj_ptr,
314 sizeof(struct clk_vf_point_freq), pargs);
315 break;
316
317 case CTRL_CLK_CLK_VF_POINT_TYPE_VOLT:
318 status = clk_vf_point_construct_volt(g, &board_obj_ptr,
319 sizeof(struct clk_vf_point_volt), pargs);
320 break;
321
322 default:
323 return NULL;
324 }
325
326 if (status) {
327 return NULL;
328 }
329
330 nvgpu_log_info(g, " Done");
331
332 return (struct clk_vf_point *)board_obj_ptr;
333}
334
335static int _clk_vf_point_pmudatainit_super(struct gk20a *g,
336 struct boardobj *board_obj_ptr,
337 struct nv_pmu_boardobj *ppmudata)
338{
339 int status = 0;
340 struct clk_vf_point *pclk_vf_point;
341 struct nv_pmu_clk_clk_vf_point_boardobj_set *pset;
342
343 nvgpu_log_info(g, " ");
344
345 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
346 if (status != 0) {
347 return status;
348 }
349
350 pclk_vf_point =
351 (struct clk_vf_point *)board_obj_ptr;
352
353 pset = (struct nv_pmu_clk_clk_vf_point_boardobj_set *)
354 ppmudata;
355
356
357 pset->vfe_equ_idx = pclk_vf_point->vfe_equ_idx;
358 pset->volt_rail_idx = pclk_vf_point->volt_rail_idx;
359 return status;
360}
361
362
363static int clk_vf_point_update(struct gk20a *g,
364 struct boardobj *board_obj_ptr,
365 struct nv_pmu_boardobj *ppmudata)
366{
367 struct clk_vf_point *pclk_vf_point;
368 struct nv_pmu_clk_clk_vf_point_boardobj_get_status *pstatus;
369
370 nvgpu_log_info(g, " ");
371
372
373 pclk_vf_point =
374 (struct clk_vf_point *)board_obj_ptr;
375
376 pstatus = (struct nv_pmu_clk_clk_vf_point_boardobj_get_status *)
377 ppmudata;
378
379 if (pstatus->super.type != pclk_vf_point->super.type) {
380 nvgpu_err(g,
381 "pmu data and boardobj type not matching");
382 return -EINVAL;
383 }
384 /* now copy VF pair */
385 memcpy(&pclk_vf_point->pair, &pstatus->pair,
386 sizeof(struct ctrl_clk_vf_pair));
387 return 0;
388}
389
390/*get latest vf point data from PMU */
391int clk_vf_point_cache(struct gk20a *g)
392{
393
394 struct clk_vf_points *pclk_vf_points;
395 struct boardobjgrp *pboardobjgrp;
396 struct boardobjgrpmask *pboardobjgrpmask;
397 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu;
398 struct boardobj *pboardobj = NULL;
399 struct nv_pmu_boardobj_query *pboardobjpmustatus = NULL;
400 int status;
401 u8 index;
402
403 nvgpu_log_info(g, " ");
404 pclk_vf_points = &g->clk_pmu.clk_vf_pointobjs;
405 pboardobjgrp = &pclk_vf_points->super.super;
406 pboardobjgrpmask = &pclk_vf_points->super.mask.super;
407
408 status = pboardobjgrp->pmugetstatus(g, pboardobjgrp, pboardobjgrpmask);
409 if (status) {
410 nvgpu_err(g, "err getting boardobjs from pmu");
411 return status;
412 }
413 pboardobjgrppmu = pboardobjgrp->pmu.getstatus.buf;
414
415 BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
416 status = pboardobjgrp->pmustatusinstget(g,
417 (struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
418 &pboardobjpmustatus, index);
419 if (status) {
420 nvgpu_err(g, "could not get status object instance");
421 return status;
422 }
423
424 status = clk_vf_point_update(g, pboardobj,
425 (struct nv_pmu_boardobj *)pboardobjpmustatus);
426 if (status) {
427 nvgpu_err(g, "invalid data from pmu at %d", index);
428 return status;
429 }
430 }
431
432 return 0;
433}