summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/clk/clk_domain.c
diff options
context:
space:
mode:
authorVijayakumar Subbu <vsubbu@nvidia.com>2016-07-30 13:44:30 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:49 -0500
commit432017248e432df0619dc2df30f915a52634338f (patch)
tree40bb7a77983fb2753271bc46b346a44ebd6121cf /drivers/gpu/nvgpu/clk/clk_domain.c
parent38ad90b4840434df4650c617a236e1b01f8a43c6 (diff)
gpu: nvgpu: Add dGPU clocks support
JIRA DNVGPU-42 Change-Id: Ic2fca9d0cf82f2823654ac5e8f0772a1eec7b3b5 Signed-off-by: Vijayakumar Subbu <vsubbu@nvidia.com> Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1205850 (cherry picked from commit b9f5c6bc4e649162d63e33d65b725872340ca114) Reviewed-on: http://git-master/r/1227257 GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk_domain.c')
-rw-r--r--drivers/gpu/nvgpu/clk/clk_domain.c874
1 files changed, 874 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_domain.c b/drivers/gpu/nvgpu/clk/clk_domain.c
new file mode 100644
index 00000000..dc485e6b
--- /dev/null
+++ b/drivers/gpu/nvgpu/clk/clk_domain.c
@@ -0,0 +1,874 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include "gk20a/gk20a.h"
15#include "clk.h"
16#include "clk_fll.h"
17#include "clk_domain.h"
18#include "include/bios.h"
19#include "boardobj/boardobjgrp.h"
20#include "boardobj/boardobjgrp_e32.h"
21#include "pmuif/gpmuifboardobj.h"
22#include "pmuif/gpmuifclk.h"
23#include "gm206/bios_gm206.h"
24#include "ctrl/ctrlclk.h"
25#include "ctrl/ctrlvolt.h"
26#include "gk20a/pmu_gk20a.h"
27
28static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs);
29
30static u32 devinit_get_clocks_table(struct gk20a *g,
31 struct clk_domains *pdomainobjs);
32
33static u32 clk_domain_pmudatainit_super(struct gk20a *g, struct boardobj
34 *board_obj_ptr, struct nv_pmu_boardobj *ppmudata);
35
36const struct vbios_clocks_table_1x_hal_clock_entry vbiosclktbl1xhalentry[] = {
37 { clkwhich_gpc2clk, true, },
38 { clkwhich_xbar2clk, true, },
39 { clkwhich_mclk, false, },
40 { clkwhich_sys2clk, true, },
41 { clkwhich_hub2clk, false, },
42 { clkwhich_nvdclk, false, },
43 { clkwhich_pwrclk, false, },
44 { clkwhich_dispclk, false, },
45 { clkwhich_pciegenclk, false, }
46};
47
48static u32 clktranslatehalmumsettoapinumset(u32 clkhaldomains)
49{
50 u32 clkapidomains = 0;
51
52 if (clkhaldomains & BIT(clkwhich_gpc2clk))
53 clkapidomains |= CTRL_CLK_DOMAIN_GPC2CLK;
54 if (clkhaldomains & BIT(clkwhich_xbar2clk))
55 clkapidomains |= CTRL_CLK_DOMAIN_XBAR2CLK;
56 if (clkhaldomains & BIT(clkwhich_sys2clk))
57 clkapidomains |= CTRL_CLK_DOMAIN_SYS2CLK;
58 if (clkhaldomains & BIT(clkwhich_hub2clk))
59 clkapidomains |= CTRL_CLK_DOMAIN_HUB2CLK;
60 if (clkhaldomains & BIT(clkwhich_pwrclk))
61 clkapidomains |= CTRL_CLK_DOMAIN_PWRCLK;
62 if (clkhaldomains & BIT(clkwhich_pciegenclk))
63 clkapidomains |= CTRL_CLK_DOMAIN_PCIEGENCLK;
64 if (clkhaldomains & BIT(clkwhich_mclk))
65 clkapidomains |= CTRL_CLK_DOMAIN_MCLK;
66 if (clkhaldomains & BIT(clkwhich_nvdclk))
67 clkapidomains |= CTRL_CLK_DOMAIN_NVDCLK;
68 if (clkhaldomains & BIT(clkwhich_dispclk))
69 clkapidomains |= CTRL_CLK_DOMAIN_DISPCLK;
70
71 return clkapidomains;
72}
73
74static u32 _clk_domains_pmudatainit_3x(struct gk20a *g,
75 struct boardobjgrp *pboardobjgrp,
76 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
77{
78 struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *pset =
79 (struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *)
80 pboardobjgrppmu;
81 struct clk_domains *pdomains = (struct clk_domains *)pboardobjgrp;
82 u32 status = 0;
83
84 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
85 if (status) {
86 gk20a_err(dev_from_gk20a(g),
87 "error updating pmu boardobjgrp for clk domain 0x%x",
88 status);
89 goto done;
90 }
91
92 pset->vbios_domains = pdomains->vbios_domains;
93 pset->cntr_sampling_periodms = pdomains->cntr_sampling_periodms;
94 pset->b_override_o_v_o_c = false;
95 pset->b_debug_mode = false;
96 pset->b_enforce_vf_monotonicity = pdomains->b_enforce_vf_monotonicity;
97 pset->volt_rails_max = 2;
98 status = boardobjgrpmask_export(
99 &pdomains->master_domains_mask.super,
100 pdomains->master_domains_mask.super.bitcount,
101 &pset->master_domains_mask.super);
102
103 memcpy(&pset->deltas, &pdomains->deltas,
104 (sizeof(struct ctrl_clk_clk_delta)));
105
106done:
107 return status;
108}
109
110static u32 _clk_domains_pmudata_instget(struct gk20a *g,
111 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
112 struct nv_pmu_boardobj **ppboardobjpmudata,
113 u8 idx)
114{
115 struct nv_pmu_clk_clk_domain_boardobj_grp_set *pgrp_set =
116 (struct nv_pmu_clk_clk_domain_boardobj_grp_set *)
117 pmuboardobjgrp;
118
119 gk20a_dbg_info("");
120
121 /*check whether pmuboardobjgrp has a valid boardobj in index*/
122 if (((u32)BIT(idx) &
123 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0)
124 return -EINVAL;
125
126 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
127 &pgrp_set->objects[idx].data.board_obj;
128 gk20a_dbg_info(" Done");
129 return 0;
130}
131
132u32 clk_domain_sw_setup(struct gk20a *g)
133{
134 u32 status;
135 struct boardobjgrp *pboardobjgrp = NULL;
136 struct clk_domains *pclkdomainobjs;
137 struct clk_domain *pdomain;
138 u8 i;
139
140 gk20a_dbg_info("");
141
142 status = boardobjgrpconstruct_e32(&g->clk_pmu.clk_domainobjs.super);
143 if (status) {
144 gk20a_err(dev_from_gk20a(g),
145 "error creating boardobjgrp for clk domain, status - 0x%x",
146 status);
147 goto done;
148 }
149
150 pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super;
151 pclkdomainobjs = &(g->clk_pmu.clk_domainobjs);
152
153 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_DOMAIN);
154
155 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
156 clk, CLK, clk_domain, CLK_DOMAIN);
157 if (status) {
158 gk20a_err(dev_from_gk20a(g),
159 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
160 status);
161 goto done;
162 }
163
164 pboardobjgrp->pmudatainit = _clk_domains_pmudatainit_3x;
165 pboardobjgrp->pmudatainstget = _clk_domains_pmudata_instget;
166
167 /* Initialize mask to zero.*/
168 boardobjgrpmask_e32_init(&pclkdomainobjs->prog_domains_mask, NULL);
169 boardobjgrpmask_e32_init(&pclkdomainobjs->master_domains_mask, NULL);
170 pclkdomainobjs->b_enforce_vf_monotonicity = true;
171
172 memset(&pclkdomainobjs->ordered_noise_aware_list, 0,
173 sizeof(pclkdomainobjs->ordered_noise_aware_list));
174
175 memset(&pclkdomainobjs->ordered_noise_unaware_list, 0,
176 sizeof(pclkdomainobjs->ordered_noise_unaware_list));
177
178 memset(&pclkdomainobjs->deltas, 0,
179 sizeof(struct ctrl_clk_clk_delta));
180
181 status = devinit_get_clocks_table(g, pclkdomainobjs);
182 if (status)
183 goto done;
184
185 BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super),
186 struct clk_domain *, pdomain, i) {
187 if (pdomain->super.implements(g, &pdomain->super,
188 CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) {
189 status = boardobjgrpmask_bitset(
190 &pclkdomainobjs->prog_domains_mask.super, i);
191 if (status)
192 goto done;
193 }
194
195 if (pdomain->super.implements(g, &pdomain->super,
196 CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) {
197 status = boardobjgrpmask_bitset(
198 &pclkdomainobjs->master_domains_mask.super, i);
199 if (status)
200 goto done;
201 }
202 }
203
204done:
205 gk20a_dbg_info(" done status %x", status);
206 return status;
207}
208
209u32 clk_domain_pmu_setup(struct gk20a *g)
210{
211 u32 status;
212 struct boardobjgrp *pboardobjgrp = NULL;
213
214 gk20a_dbg_info("");
215
216 pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super;
217
218 if (!pboardobjgrp->bconstructed)
219 return -EINVAL;
220
221 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
222
223 gk20a_dbg_info("Done");
224 return status;
225}
226
227static u32 devinit_get_clocks_table(struct gk20a *g,
228 struct clk_domains *pclkdomainobjs)
229{
230 u32 status = 0;
231 u8 *clocks_table_ptr = NULL;
232 struct vbios_clocks_table_1x_header clocks_table_header = { 0 };
233 struct vbios_clocks_table_1x_entry clocks_table_entry = { 0 };
234 u8 *clocks_tbl_entry_ptr = NULL;
235 u32 index = 0;
236 struct clk_domain *pclkdomain_dev;
237 union {
238 struct boardobj boardobj;
239 struct clk_domain clk_domain;
240 struct clk_domain_3x v3x;
241 struct clk_domain_3x_fixed v3x_fixed;
242 struct clk_domain_3x_prog v3x_prog;
243 struct clk_domain_3x_master v3x_master;
244 struct clk_domain_3x_slave v3x_slave;
245 } clk_domain_data;
246
247 gk20a_dbg_info("");
248
249 if (g->ops.bios.get_perf_table_ptrs) {
250 clocks_table_ptr = (u8 *)g->ops.bios.get_perf_table_ptrs(g,
251 g->bios.clock_token, CLOCKS_TABLE);
252 if (clocks_table_ptr == NULL) {
253 status = -EINVAL;
254 goto done;
255 }
256 }
257
258 memcpy(&clocks_table_header, clocks_table_ptr,
259 VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07);
260 if (clocks_table_header.header_size <
261 VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07) {
262 status = -EINVAL;
263 goto done;
264 }
265
266 if (clocks_table_header.entry_size <
267 VBIOS_CLOCKS_TABLE_1X_ENTRY_SIZE_09) {
268 status = -EINVAL;
269 goto done;
270 }
271
272 pclkdomainobjs->cntr_sampling_periodms =
273 (u16)clocks_table_header.cntr_sampling_periodms;
274
275 /* Read table entries*/
276 clocks_tbl_entry_ptr = clocks_table_ptr +
277 VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07;
278 for (index = 0; index < clocks_table_header.entry_count; index++) {
279 memcpy(&clocks_table_entry, clocks_tbl_entry_ptr,
280 clocks_table_header.entry_size);
281 clk_domain_data.clk_domain.domain =
282 vbiosclktbl1xhalentry[index].domain;
283 clk_domain_data.clk_domain.api_domain =
284 clktranslatehalmumsettoapinumset(
285 BIT(clk_domain_data.clk_domain.domain));
286 clk_domain_data.v3x.b_noise_aware_capable =
287 vbiosclktbl1xhalentry[index].b_noise_aware_capable;
288
289 switch (BIOS_GET_FIELD(clocks_table_entry.flags0,
290 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE)) {
291 case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_FIXED:
292 clk_domain_data.boardobj.type =
293 CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED;
294 clk_domain_data.v3x_fixed.freq_mhz = (u16)BIOS_GET_FIELD(
295 clocks_table_entry.param1,
296 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_FIXED_FREQUENCY_MHZ);
297 break;
298
299 case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_MASTER:
300 clk_domain_data.boardobj.type =
301 CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER;
302 clk_domain_data.v3x_prog.clk_prog_idx_first =
303 (u8)(BIOS_GET_FIELD(clocks_table_entry.param0,
304 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST));
305 clk_domain_data.v3x_prog.clk_prog_idx_last =
306 (u8)(BIOS_GET_FIELD(clocks_table_entry.param0,
307 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST));
308 clk_domain_data.v3x_prog.noise_unaware_ordering_index =
309 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
310 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX));
311
312 if (clk_domain_data.v3x.b_noise_aware_capable) {
313 clk_domain_data.v3x_prog.noise_aware_ordering_index =
314 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
315 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX));
316 clk_domain_data.v3x_prog.b_force_noise_unaware_ordering =
317 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
318 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING));
319 } else {
320 clk_domain_data.v3x_prog.noise_aware_ordering_index =
321 CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID;
322 clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false;
323 }
324 clk_domain_data.v3x_prog.factory_offset_khz = 0;
325
326 clk_domain_data.v3x_prog.freq_delta_min_mhz =
327 (u16)(BIOS_GET_FIELD(clocks_table_entry.param1,
328 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MIN_MHZ));
329
330 clk_domain_data.v3x_prog.freq_delta_max_mhz =
331 (u16)(BIOS_GET_FIELD(clocks_table_entry.param1,
332 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MAX_MHZ));
333 break;
334
335 case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_SLAVE:
336 clk_domain_data.boardobj.type =
337 CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE;
338 clk_domain_data.v3x_prog.clk_prog_idx_first =
339 (u8)(BIOS_GET_FIELD(clocks_table_entry.param0,
340 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST));
341 clk_domain_data.v3x_prog.clk_prog_idx_last =
342 (u8)(BIOS_GET_FIELD(clocks_table_entry.param0,
343 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST));
344 clk_domain_data.v3x_prog.noise_unaware_ordering_index =
345 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
346 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX));
347
348 if (clk_domain_data.v3x.b_noise_aware_capable) {
349 clk_domain_data.v3x_prog.noise_aware_ordering_index =
350 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
351 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX));
352 clk_domain_data.v3x_prog.b_force_noise_unaware_ordering =
353 (u8)(BIOS_GET_FIELD(clocks_table_entry.param2,
354 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING));
355 } else {
356 clk_domain_data.v3x_prog.noise_aware_ordering_index =
357 CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID;
358 clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false;
359 }
360 clk_domain_data.v3x_prog.factory_offset_khz = 0;
361 clk_domain_data.v3x_prog.freq_delta_min_mhz = 0;
362 clk_domain_data.v3x_prog.freq_delta_max_mhz = 0;
363 clk_domain_data.v3x_slave.master_idx =
364 (u8)(BIOS_GET_FIELD(clocks_table_entry.param1,
365 NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_SLAVE_MASTER_DOMAIN));
366 break;
367
368 default:
369 gk20a_err(dev_from_gk20a(g),
370 "error reading clock domain entry %d", index);
371 status = -EINVAL;
372 goto done;
373
374 }
375 pclkdomain_dev = construct_clk_domain(g,
376 (void *)&clk_domain_data);
377 if (pclkdomain_dev == NULL) {
378 gk20a_err(dev_from_gk20a(g),
379 "unable to construct clock domain boardobj for %d",
380 index);
381 status = -EINVAL;
382 goto done;
383 }
384 status = boardobjgrp_objinsert(&pclkdomainobjs->super.super,
385 (struct boardobj *)pclkdomain_dev, index);
386 if (status) {
387 gk20a_err(dev_from_gk20a(g),
388 "unable to insert clock domain boardobj for %d", index);
389 status = -EINVAL;
390 goto done;
391 }
392 clocks_tbl_entry_ptr += clocks_table_header.entry_size;
393 }
394
395done:
396 gk20a_dbg_info(" done status %x", status);
397 return status;
398}
399
400static u32 clkdomainclkproglink_not_supported(struct gk20a *g,
401 struct clk_pmupstate *pclk,
402 struct clk_domain *pdomain)
403{
404 gk20a_dbg_info("");
405 return -EINVAL;
406}
407
408static u32 clk_domain_construct_super(struct gk20a *g,
409 struct boardobj **ppboardobj,
410 u16 size, void *pargs)
411{
412 struct clk_domain *pdomain;
413 struct clk_domain *ptmpdomain = (struct clk_domain *)pargs;
414 u32 status = 0;
415
416 status = boardobj_construct_super(g, ppboardobj,
417 size, pargs);
418
419 if (status)
420 return -EINVAL;
421
422 pdomain = (struct clk_domain *)*ppboardobj;
423
424 pdomain->super.pmudatainit =
425 clk_domain_pmudatainit_super;
426
427 pdomain->clkdomainclkproglink =
428 clkdomainclkproglink_not_supported;
429
430 pdomain->api_domain = ptmpdomain->api_domain;
431 pdomain->domain = ptmpdomain->domain;
432 pdomain->perf_domain_grp_idx =
433 ptmpdomain->perf_domain_grp_idx;
434
435 return status;
436}
437
438static u32 _clk_domain_pmudatainit_3x(struct gk20a *g,
439 struct boardobj *board_obj_ptr,
440 struct nv_pmu_boardobj *ppmudata)
441{
442 u32 status = 0;
443 struct clk_domain_3x *pclk_domain_3x;
444 struct nv_pmu_clk_clk_domain_3x_boardobj_set *pset;
445
446 gk20a_dbg_info("");
447
448 status = clk_domain_pmudatainit_super(g, board_obj_ptr, ppmudata);
449 if (status != 0)
450 return status;
451
452 pclk_domain_3x = (struct clk_domain_3x *)board_obj_ptr;
453
454 pset = (struct nv_pmu_clk_clk_domain_3x_boardobj_set *)ppmudata;
455
456 pset->b_noise_aware_capable = pclk_domain_3x->b_noise_aware_capable;
457
458 return status;
459}
460
461static u32 clk_domain_construct_3x(struct gk20a *g,
462 struct boardobj **ppboardobj,
463 u16 size, void *pargs)
464{
465 struct boardobj *ptmpobj = (struct boardobj *)pargs;
466 struct clk_domain_3x *pdomain;
467 struct clk_domain_3x *ptmpdomain =
468 (struct clk_domain_3x *)pargs;
469 u32 status = 0;
470
471 ptmpobj->type_mask = BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X);
472 status = clk_domain_construct_super(g, ppboardobj,
473 size, pargs);
474 if (status)
475 return -EINVAL;
476
477 pdomain = (struct clk_domain_3x *)*ppboardobj;
478
479 pdomain->super.super.pmudatainit =
480 _clk_domain_pmudatainit_3x;
481
482 pdomain->b_noise_aware_capable = ptmpdomain->b_noise_aware_capable;
483
484 return status;
485}
486
487static u32 clkdomainclkproglink_3x_prog(struct gk20a *g,
488 struct clk_pmupstate *pclk,
489 struct clk_domain *pdomain)
490{
491 u32 status = 0;
492 struct clk_domain_3x_prog *p3xprog =
493 (struct clk_domain_3x_prog *)pdomain;
494 struct clk_prog *pprog = NULL;
495 u8 i;
496
497 gk20a_dbg_info("");
498
499 for (i = p3xprog->clk_prog_idx_first;
500 i <= p3xprog->clk_prog_idx_last;
501 i++) {
502 pprog = CLK_CLK_PROG_GET(pclk, i);
503 if (pprog == NULL)
504 status = -EINVAL;
505 }
506 return status;
507}
508
509static u32 _clk_domain_pmudatainit_3x_prog(struct gk20a *g,
510 struct boardobj *board_obj_ptr,
511 struct nv_pmu_boardobj *ppmudata)
512{
513 u32 status = 0;
514 struct clk_domain_3x_prog *pclk_domain_3x_prog;
515 struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set *pset;
516 struct clk_domains *pdomains = &(g->clk_pmu.clk_domainobjs);
517
518 gk20a_dbg_info("");
519
520 status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata);
521 if (status != 0)
522 return status;
523
524 pclk_domain_3x_prog = (struct clk_domain_3x_prog *)board_obj_ptr;
525
526 pset = (struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set *)
527 ppmudata;
528
529 pset->clk_prog_idx_first = pclk_domain_3x_prog->clk_prog_idx_first;
530 pset->clk_prog_idx_last = pclk_domain_3x_prog->clk_prog_idx_last;
531 pset->noise_unaware_ordering_index =
532 pclk_domain_3x_prog->noise_unaware_ordering_index;
533 pset->noise_aware_ordering_index =
534 pclk_domain_3x_prog->noise_aware_ordering_index;
535 pset->b_force_noise_unaware_ordering =
536 pclk_domain_3x_prog->b_force_noise_unaware_ordering;
537 pset->factory_offset_khz = pclk_domain_3x_prog->factory_offset_khz;
538 pset->freq_delta_min_mhz = pclk_domain_3x_prog->freq_delta_min_mhz;
539 pset->freq_delta_max_mhz = pclk_domain_3x_prog->freq_delta_max_mhz;
540 memcpy(&pset->deltas, &pdomains->deltas,
541 (sizeof(struct ctrl_clk_clk_delta)));
542
543 return status;
544}
545
546static u32 clk_domain_construct_3x_prog(struct gk20a *g,
547 struct boardobj **ppboardobj,
548 u16 size, void *pargs)
549{
550 struct boardobj *ptmpobj = (struct boardobj *)pargs;
551 struct clk_domain_3x_prog *pdomain;
552 struct clk_domain_3x_prog *ptmpdomain =
553 (struct clk_domain_3x_prog *)pargs;
554 u32 status = 0;
555
556 ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG);
557 status = clk_domain_construct_3x(g, ppboardobj, size, pargs);
558 if (status)
559 return -EINVAL;
560
561 pdomain = (struct clk_domain_3x_prog *)*ppboardobj;
562
563 pdomain->super.super.super.pmudatainit =
564 _clk_domain_pmudatainit_3x_prog;
565
566 pdomain->super.super.clkdomainclkproglink =
567 clkdomainclkproglink_3x_prog;
568
569 pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first;
570 pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last;
571 pdomain->noise_unaware_ordering_index =
572 ptmpdomain->noise_unaware_ordering_index;
573 pdomain->noise_aware_ordering_index =
574 ptmpdomain->noise_aware_ordering_index;
575 pdomain->b_force_noise_unaware_ordering =
576 ptmpdomain->b_force_noise_unaware_ordering;
577 pdomain->factory_offset_khz = ptmpdomain->factory_offset_khz;
578 pdomain->freq_delta_min_mhz = ptmpdomain->freq_delta_min_mhz;
579 pdomain->freq_delta_max_mhz = ptmpdomain->freq_delta_max_mhz;
580
581 return status;
582}
583
584static u32 _clk_domain_pmudatainit_3x_slave(struct gk20a *g,
585 struct boardobj *board_obj_ptr,
586 struct nv_pmu_boardobj *ppmudata)
587{
588 u32 status = 0;
589 struct clk_domain_3x_slave *pclk_domain_3x_slave;
590 struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *pset;
591
592 gk20a_dbg_info("");
593
594 status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata);
595 if (status != 0)
596 return status;
597
598 pclk_domain_3x_slave = (struct clk_domain_3x_slave *)board_obj_ptr;
599
600 pset = (struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *)
601 ppmudata;
602
603 pset->master_idx = pclk_domain_3x_slave->master_idx;
604
605 return status;
606}
607
608static u32 clk_domain_construct_3x_slave(struct gk20a *g,
609 struct boardobj **ppboardobj,
610 u16 size, void *pargs)
611{
612 struct boardobj *ptmpobj = (struct boardobj *)pargs;
613 struct clk_domain_3x_slave *pdomain;
614 struct clk_domain_3x_slave *ptmpdomain =
615 (struct clk_domain_3x_slave *)pargs;
616 u32 status = 0;
617
618 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)
619 return -EINVAL;
620
621 ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE);
622 status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs);
623 if (status)
624 return -EINVAL;
625
626 pdomain = (struct clk_domain_3x_slave *)*ppboardobj;
627
628 pdomain->super.super.super.super.pmudatainit =
629 _clk_domain_pmudatainit_3x_slave;
630
631 pdomain->master_idx = ptmpdomain->master_idx;
632
633 return status;
634}
635
636static u32 clkdomainclkproglink_3x_master(struct gk20a *g,
637 struct clk_pmupstate *pclk,
638 struct clk_domain *pdomain)
639{
640 u32 status = 0;
641 struct clk_domain_3x_master *p3xmaster =
642 (struct clk_domain_3x_master *)pdomain;
643 struct clk_prog *pprog = NULL;
644 struct clk_prog_1x_master *pprog1xmaster = NULL;
645 u16 freq_max_last_mhz = 0;
646 u8 i;
647
648 gk20a_dbg_info("");
649
650 status = clkdomainclkproglink_3x_prog(g, pclk, pdomain);
651 if (status)
652 goto done;
653
654 /* Iterate over the set of CLK_PROGs pointed at by this domain.*/
655 for (i = p3xmaster->super.clk_prog_idx_first;
656 i <= p3xmaster->super.clk_prog_idx_last;
657 i++) {
658 pprog = CLK_CLK_PROG_GET(pclk, i);
659
660 /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/
661 if (!pprog->super.implements(g, &pprog->super,
662 CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) {
663 status = -EINVAL;
664 goto done;
665 }
666
667 pprog1xmaster = (struct clk_prog_1x_master *)pprog;
668 status = pprog1xmaster->vfflatten(g, pclk, pprog1xmaster,
669 BOARDOBJ_GET_IDX(p3xmaster), &freq_max_last_mhz);
670 if (status)
671 goto done;
672 }
673done:
674 gk20a_dbg_info("done status %x", status);
675 return status;
676}
677
678static u32 _clk_domain_pmudatainit_3x_master(struct gk20a *g,
679 struct boardobj *board_obj_ptr,
680 struct nv_pmu_boardobj *ppmudata)
681{
682 u32 status = 0;
683 struct clk_domain_3x_master *pclk_domain_3x_master;
684 struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *pset;
685
686 gk20a_dbg_info("");
687
688 status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata);
689 if (status != 0)
690 return status;
691
692 pclk_domain_3x_master = (struct clk_domain_3x_master *)board_obj_ptr;
693
694 pset = (struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *)
695 ppmudata;
696
697 pset->slave_idxs_mask = pclk_domain_3x_master->slave_idxs_mask;
698
699 return status;
700}
701
702static u32 clk_domain_construct_3x_master(struct gk20a *g,
703 struct boardobj **ppboardobj,
704 u16 size, void *pargs)
705{
706 struct boardobj *ptmpobj = (struct boardobj *)pargs;
707 struct clk_domain_3x_master *pdomain;
708 struct clk_domain_3x_master *ptmpdomain =
709 (struct clk_domain_3x_master *)pargs;
710 u32 status = 0;
711
712 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)
713 return -EINVAL;
714
715 ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER);
716 status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs);
717 if (status)
718 return -EINVAL;
719
720 pdomain = (struct clk_domain_3x_master *)*ppboardobj;
721
722 pdomain->super.super.super.super.pmudatainit =
723 _clk_domain_pmudatainit_3x_master;
724 pdomain->super.super.super.clkdomainclkproglink =
725 clkdomainclkproglink_3x_master;
726
727 pdomain->slave_idxs_mask = ptmpdomain->slave_idxs_mask;
728
729 return status;
730}
731
732static u32 clkdomainclkproglink_fixed(struct gk20a *g,
733 struct clk_pmupstate *pclk,
734 struct clk_domain *pdomain)
735{
736 gk20a_dbg_info("");
737 return 0;
738}
739
740static u32 _clk_domain_pmudatainit_3x_fixed(struct gk20a *g,
741 struct boardobj *board_obj_ptr,
742 struct nv_pmu_boardobj *ppmudata)
743{
744 u32 status = 0;
745 struct clk_domain_3x_fixed *pclk_domain_3x_fixed;
746 struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *pset;
747
748 gk20a_dbg_info("");
749
750 status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata);
751 if (status != 0)
752 return status;
753
754 pclk_domain_3x_fixed = (struct clk_domain_3x_fixed *)board_obj_ptr;
755
756 pset = (struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *)
757 ppmudata;
758
759 pset->freq_mhz = pclk_domain_3x_fixed->freq_mhz;
760
761 return status;
762}
763
764static u32 clk_domain_construct_3x_fixed(struct gk20a *g,
765 struct boardobj **ppboardobj,
766 u16 size, void *pargs)
767{
768 struct boardobj *ptmpobj = (struct boardobj *)pargs;
769 struct clk_domain_3x_fixed *pdomain;
770 struct clk_domain_3x_fixed *ptmpdomain =
771 (struct clk_domain_3x_fixed *)pargs;
772 u32 status = 0;
773
774 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED)
775 return -EINVAL;
776
777 ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED);
778 status = clk_domain_construct_3x(g, ppboardobj, size, pargs);
779 if (status)
780 return -EINVAL;
781
782 pdomain = (struct clk_domain_3x_fixed *)*ppboardobj;
783
784 pdomain->super.super.super.pmudatainit =
785 _clk_domain_pmudatainit_3x_fixed;
786
787 pdomain->super.super.clkdomainclkproglink =
788 clkdomainclkproglink_fixed;
789
790 pdomain->freq_mhz = ptmpdomain->freq_mhz;
791
792 return status;
793}
794
795static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs)
796{
797 struct boardobj *board_obj_ptr = NULL;
798 u32 status;
799
800 gk20a_dbg_info(" %d", BOARDOBJ_GET_TYPE(pargs));
801 switch (BOARDOBJ_GET_TYPE(pargs)) {
802 case CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED:
803 status = clk_domain_construct_3x_fixed(g, &board_obj_ptr,
804 sizeof(struct clk_domain_3x_fixed), pargs);
805 break;
806
807 case CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER:
808 status = clk_domain_construct_3x_master(g, &board_obj_ptr,
809 sizeof(struct clk_domain_3x_master), pargs);
810 break;
811
812 case CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE:
813 status = clk_domain_construct_3x_slave(g, &board_obj_ptr,
814 sizeof(struct clk_domain_3x_slave), pargs);
815 break;
816
817 default:
818 return NULL;
819 }
820
821 if (status)
822 return NULL;
823
824 gk20a_dbg_info(" Done");
825
826 return (struct clk_domain *)board_obj_ptr;
827}
828
829static u32 clk_domain_pmudatainit_super(struct gk20a *g,
830 struct boardobj *board_obj_ptr,
831 struct nv_pmu_boardobj *ppmudata)
832{
833 u32 status = 0;
834 struct clk_domain *pclk_domain;
835 struct nv_pmu_clk_clk_domain_boardobj_set *pset;
836
837 gk20a_dbg_info("");
838
839 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
840 if (status != 0)
841 return status;
842
843 pclk_domain = (struct clk_domain *)board_obj_ptr;
844
845 pset = (struct nv_pmu_clk_clk_domain_boardobj_set *)ppmudata;
846
847 pset->domain = pclk_domain->domain;
848 pset->api_domain = pclk_domain->api_domain;
849 pset->perf_domain_grp_idx = pclk_domain->perf_domain_grp_idx;
850
851 return status;
852}
853
854u32 clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk)
855{
856 u32 status = 0;
857 struct clk_domain *pdomain;
858 u8 i;
859
860 /* Iterate over all CLK_DOMAINs and flatten their VF curves.*/
861 BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
862 struct clk_domain *, pdomain, i) {
863 status = pdomain->clkdomainclkproglink(g, pclk, pdomain);
864 if (status) {
865 gk20a_err(dev_from_gk20a(g),
866 "error flattening VF for CLK DOMAIN - 0x%x",
867 pdomain->domain);
868 goto done;
869 }
870 }
871
872done:
873 return status;
874}