diff options
author | Joshua Bakita <bakitajoshua@gmail.com> | 2024-09-25 16:09:09 -0400 |
---|---|---|
committer | Joshua Bakita <bakitajoshua@gmail.com> | 2024-09-25 16:09:09 -0400 |
commit | f347fde22f1297e4f022600d201780d5ead78114 (patch) | |
tree | 76be305d6187003a1e0486ff6e91efb1062ae118 /include/clk/clk_domain.c | |
parent | 8340d234d78a7d0f46c11a584de538148b78b7cb (diff) |
Delete no-longer-needed nvgpu headersHEADmasterjbakita-wip
The dependency on these was removed in commit 8340d234.
Diffstat (limited to 'include/clk/clk_domain.c')
-rw-r--r-- | include/clk/clk_domain.c | 1666 |
1 files changed, 0 insertions, 1666 deletions
diff --git a/include/clk/clk_domain.c b/include/clk/clk_domain.c deleted file mode 100644 index 3b64f51..0000000 --- a/include/clk/clk_domain.c +++ /dev/null | |||
@@ -1,1666 +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/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 | |||
34 | static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs); | ||
35 | |||
36 | static int devinit_get_clocks_table(struct gk20a *g, | ||
37 | struct clk_domains *pdomainobjs); | ||
38 | |||
39 | static int clk_domain_pmudatainit_super(struct gk20a *g, struct boardobj | ||
40 | *board_obj_ptr, struct nv_pmu_boardobj *ppmudata); | ||
41 | |||
42 | static struct vbios_clocks_table_1x_hal_clock_entry | ||
43 | vbiosclktbl1xhalentry_gp[] = { | ||
44 | { clkwhich_gpc2clk, true, 1, }, | ||
45 | { clkwhich_xbar2clk, true, 1, }, | ||
46 | { clkwhich_mclk, false, 1, }, | ||
47 | { clkwhich_sys2clk, true, 1, }, | ||
48 | { clkwhich_hub2clk, false, 1, }, | ||
49 | { clkwhich_nvdclk, false, 1, }, | ||
50 | { clkwhich_pwrclk, false, 1, }, | ||
51 | { clkwhich_dispclk, false, 1, }, | ||
52 | { clkwhich_pciegenclk, false, 1, } | ||
53 | }; | ||
54 | /* | ||
55 | * Updated from RM devinit_clock.c | ||
56 | * GV100 is 0x03 and | ||
57 | * GP10x is 0x02 in clocks_hal. | ||
58 | */ | ||
59 | static struct vbios_clocks_table_1x_hal_clock_entry | ||
60 | vbiosclktbl1xhalentry_gv[] = { | ||
61 | { clkwhich_gpcclk, true, 2, }, | ||
62 | { clkwhich_xbarclk, true, 1, }, | ||
63 | { clkwhich_mclk, false, 1, }, | ||
64 | { clkwhich_sysclk, true, 1, }, | ||
65 | { clkwhich_hubclk, false, 1, }, | ||
66 | { clkwhich_nvdclk, true, 1, }, | ||
67 | { clkwhich_pwrclk, false, 1, }, | ||
68 | { clkwhich_dispclk, false, 1, }, | ||
69 | { clkwhich_pciegenclk, false, 1, }, | ||
70 | { clkwhich_hostclk, true, 1, } | ||
71 | }; | ||
72 | |||
73 | static u32 clktranslatehalmumsettoapinumset(u32 clkhaldomains) | ||
74 | { | ||
75 | u32 clkapidomains = 0; | ||
76 | |||
77 | if (clkhaldomains & BIT(clkwhich_gpcclk)) { | ||
78 | clkapidomains |= CTRL_CLK_DOMAIN_GPCCLK; | ||
79 | } | ||
80 | if (clkhaldomains & BIT(clkwhich_xbarclk)) { | ||
81 | clkapidomains |= CTRL_CLK_DOMAIN_XBARCLK; | ||
82 | } | ||
83 | if (clkhaldomains & BIT(clkwhich_sysclk)) { | ||
84 | clkapidomains |= CTRL_CLK_DOMAIN_SYSCLK; | ||
85 | } | ||
86 | if (clkhaldomains & BIT(clkwhich_hubclk)) { | ||
87 | clkapidomains |= CTRL_CLK_DOMAIN_HUBCLK; | ||
88 | } | ||
89 | if (clkhaldomains & BIT(clkwhich_hostclk)) { | ||
90 | clkapidomains |= CTRL_CLK_DOMAIN_HOSTCLK; | ||
91 | } | ||
92 | if (clkhaldomains & BIT(clkwhich_gpc2clk)) { | ||
93 | clkapidomains |= CTRL_CLK_DOMAIN_GPC2CLK; | ||
94 | } | ||
95 | if (clkhaldomains & BIT(clkwhich_xbar2clk)) { | ||
96 | clkapidomains |= CTRL_CLK_DOMAIN_XBAR2CLK; | ||
97 | } | ||
98 | if (clkhaldomains & BIT(clkwhich_sys2clk)) { | ||
99 | clkapidomains |= CTRL_CLK_DOMAIN_SYS2CLK; | ||
100 | } | ||
101 | if (clkhaldomains & BIT(clkwhich_hub2clk)) { | ||
102 | clkapidomains |= CTRL_CLK_DOMAIN_HUB2CLK; | ||
103 | } | ||
104 | if (clkhaldomains & BIT(clkwhich_pwrclk)) { | ||
105 | clkapidomains |= CTRL_CLK_DOMAIN_PWRCLK; | ||
106 | } | ||
107 | if (clkhaldomains & BIT(clkwhich_pciegenclk)) { | ||
108 | clkapidomains |= CTRL_CLK_DOMAIN_PCIEGENCLK; | ||
109 | } | ||
110 | if (clkhaldomains & BIT(clkwhich_mclk)) { | ||
111 | clkapidomains |= CTRL_CLK_DOMAIN_MCLK; | ||
112 | } | ||
113 | if (clkhaldomains & BIT(clkwhich_nvdclk)) { | ||
114 | clkapidomains |= CTRL_CLK_DOMAIN_NVDCLK; | ||
115 | } | ||
116 | if (clkhaldomains & BIT(clkwhich_dispclk)) { | ||
117 | clkapidomains |= CTRL_CLK_DOMAIN_DISPCLK; | ||
118 | } | ||
119 | |||
120 | return clkapidomains; | ||
121 | } | ||
122 | |||
123 | static int _clk_domains_pmudatainit_3x(struct gk20a *g, | ||
124 | struct boardobjgrp *pboardobjgrp, | ||
125 | struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
126 | { | ||
127 | struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *pset = | ||
128 | (struct nv_pmu_clk_clk_domain_boardobjgrp_set_header *) | ||
129 | pboardobjgrppmu; | ||
130 | struct clk_domains *pdomains = (struct clk_domains *)pboardobjgrp; | ||
131 | int status = 0; | ||
132 | |||
133 | status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu); | ||
134 | if (status) { | ||
135 | nvgpu_err(g, | ||
136 | "error updating pmu boardobjgrp for clk domain 0x%x", | ||
137 | status); | ||
138 | goto done; | ||
139 | } | ||
140 | |||
141 | pset->vbios_domains = pdomains->vbios_domains; | ||
142 | pset->cntr_sampling_periodms = pdomains->cntr_sampling_periodms; | ||
143 | pset->version = CLK_DOMAIN_BOARDOBJGRP_VERSION; | ||
144 | pset->b_override_o_v_o_c = false; | ||
145 | pset->b_debug_mode = false; | ||
146 | pset->b_enforce_vf_monotonicity = pdomains->b_enforce_vf_monotonicity; | ||
147 | pset->b_enforce_vf_smoothening = pdomains->b_enforce_vf_smoothening; | ||
148 | if (g->ops.clk.split_rail_support) { | ||
149 | pset->volt_rails_max = 2; | ||
150 | } else { | ||
151 | pset->volt_rails_max = 1; | ||
152 | } | ||
153 | status = boardobjgrpmask_export( | ||
154 | &pdomains->master_domains_mask.super, | ||
155 | pdomains->master_domains_mask.super.bitcount, | ||
156 | &pset->master_domains_mask.super); | ||
157 | |||
158 | memcpy(&pset->deltas, &pdomains->deltas, | ||
159 | (sizeof(struct ctrl_clk_clk_delta))); | ||
160 | |||
161 | done: | ||
162 | return status; | ||
163 | } | ||
164 | |||
165 | static int _clk_domains_pmudata_instget(struct gk20a *g, | ||
166 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
167 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
168 | u8 idx) | ||
169 | { | ||
170 | struct nv_pmu_clk_clk_domain_boardobj_grp_set *pgrp_set = | ||
171 | (struct nv_pmu_clk_clk_domain_boardobj_grp_set *) | ||
172 | pmuboardobjgrp; | ||
173 | |||
174 | nvgpu_log_info(g, " "); | ||
175 | |||
176 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
177 | if (((u32)BIT(idx) & | ||
178 | pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0) { | ||
179 | return -EINVAL; | ||
180 | } | ||
181 | |||
182 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
183 | &pgrp_set->objects[idx].data.board_obj; | ||
184 | nvgpu_log_info(g, " Done"); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | int clk_domain_sw_setup(struct gk20a *g) | ||
189 | { | ||
190 | int status; | ||
191 | struct boardobjgrp *pboardobjgrp = NULL; | ||
192 | struct clk_domains *pclkdomainobjs; | ||
193 | struct clk_domain *pdomain; | ||
194 | struct clk_domain_3x_master *pdomain_master; | ||
195 | struct clk_domain_3x_slave *pdomain_slave; | ||
196 | u8 i; | ||
197 | |||
198 | nvgpu_log_info(g, " "); | ||
199 | |||
200 | status = boardobjgrpconstruct_e32(g, &g->clk_pmu.clk_domainobjs.super); | ||
201 | if (status) { | ||
202 | nvgpu_err(g, | ||
203 | "error creating boardobjgrp for clk domain, status - 0x%x", | ||
204 | status); | ||
205 | goto done; | ||
206 | } | ||
207 | |||
208 | pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super; | ||
209 | pclkdomainobjs = &(g->clk_pmu.clk_domainobjs); | ||
210 | |||
211 | BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_DOMAIN); | ||
212 | |||
213 | status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp, | ||
214 | clk, CLK, clk_domain, CLK_DOMAIN); | ||
215 | if (status) { | ||
216 | nvgpu_err(g, | ||
217 | "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x", | ||
218 | status); | ||
219 | goto done; | ||
220 | } | ||
221 | |||
222 | pboardobjgrp->pmudatainit = _clk_domains_pmudatainit_3x; | ||
223 | pboardobjgrp->pmudatainstget = _clk_domains_pmudata_instget; | ||
224 | |||
225 | /* Initialize mask to zero.*/ | ||
226 | boardobjgrpmask_e32_init(&pclkdomainobjs->prog_domains_mask, NULL); | ||
227 | boardobjgrpmask_e32_init(&pclkdomainobjs->master_domains_mask, NULL); | ||
228 | pclkdomainobjs->b_enforce_vf_monotonicity = true; | ||
229 | pclkdomainobjs->b_enforce_vf_smoothening = true; | ||
230 | |||
231 | memset(&pclkdomainobjs->ordered_noise_aware_list, 0, | ||
232 | sizeof(pclkdomainobjs->ordered_noise_aware_list)); | ||
233 | |||
234 | memset(&pclkdomainobjs->ordered_noise_unaware_list, 0, | ||
235 | sizeof(pclkdomainobjs->ordered_noise_unaware_list)); | ||
236 | |||
237 | memset(&pclkdomainobjs->deltas, 0, | ||
238 | sizeof(struct ctrl_clk_clk_delta)); | ||
239 | |||
240 | status = devinit_get_clocks_table(g, pclkdomainobjs); | ||
241 | if (status) { | ||
242 | goto done; | ||
243 | } | ||
244 | |||
245 | BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super), | ||
246 | struct clk_domain *, pdomain, i) { | ||
247 | pdomain_master = NULL; | ||
248 | if (pdomain->super.implements(g, &pdomain->super, | ||
249 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) { | ||
250 | status = boardobjgrpmask_bitset( | ||
251 | &pclkdomainobjs->prog_domains_mask.super, i); | ||
252 | if (status) { | ||
253 | goto done; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | if (pdomain->super.implements(g, &pdomain->super, | ||
258 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | ||
259 | status = boardobjgrpmask_bitset( | ||
260 | &pclkdomainobjs->master_domains_mask.super, i); | ||
261 | if (status) { | ||
262 | goto done; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | if (pdomain->super.implements(g, &pdomain->super, | ||
267 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
268 | pdomain_slave = | ||
269 | (struct clk_domain_3x_slave *)pdomain; | ||
270 | pdomain_master = | ||
271 | (struct clk_domain_3x_master *) | ||
272 | (CLK_CLK_DOMAIN_GET((&g->clk_pmu), | ||
273 | pdomain_slave->master_idx)); | ||
274 | pdomain_master->slave_idxs_mask |= BIT(i); | ||
275 | } | ||
276 | |||
277 | } | ||
278 | |||
279 | done: | ||
280 | nvgpu_log_info(g, " done status %x", status); | ||
281 | return status; | ||
282 | } | ||
283 | |||
284 | int clk_domain_pmu_setup(struct gk20a *g) | ||
285 | { | ||
286 | int status; | ||
287 | struct boardobjgrp *pboardobjgrp = NULL; | ||
288 | |||
289 | nvgpu_log_info(g, " "); | ||
290 | |||
291 | pboardobjgrp = &g->clk_pmu.clk_domainobjs.super.super; | ||
292 | |||
293 | if (!pboardobjgrp->bconstructed) { | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | |||
297 | status = pboardobjgrp->pmuinithandle(g, pboardobjgrp); | ||
298 | |||
299 | nvgpu_log_info(g, "Done"); | ||
300 | return status; | ||
301 | } | ||
302 | |||
303 | static int devinit_get_clocks_table_35(struct gk20a *g, | ||
304 | struct clk_domains *pclkdomainobjs, u8 *clocks_table_ptr) | ||
305 | { | ||
306 | int status = 0; | ||
307 | struct vbios_clocks_table_35_header clocks_table_header = { 0 }; | ||
308 | struct vbios_clocks_table_35_entry clocks_table_entry = { 0 }; | ||
309 | struct vbios_clocks_table_1x_hal_clock_entry *vbiosclktbl1xhalentry; | ||
310 | u8 *clocks_tbl_entry_ptr = NULL; | ||
311 | u32 index = 0; | ||
312 | struct clk_domain *pclkdomain_dev; | ||
313 | union { | ||
314 | struct boardobj boardobj; | ||
315 | struct clk_domain clk_domain; | ||
316 | struct clk_domain_3x v3x; | ||
317 | struct clk_domain_3x_fixed v3x_fixed; | ||
318 | struct clk_domain_35_prog v35_prog; | ||
319 | struct clk_domain_35_master v35_master; | ||
320 | struct clk_domain_35_slave v35_slave; | ||
321 | } clk_domain_data; | ||
322 | |||
323 | nvgpu_log_info(g, " "); | ||
324 | |||
325 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
326 | VBIOS_CLOCKS_TABLE_35_HEADER_SIZE_09); | ||
327 | if (clocks_table_header.header_size < | ||
328 | (u8) VBIOS_CLOCKS_TABLE_35_HEADER_SIZE_09) { | ||
329 | status = -EINVAL; | ||
330 | goto done; | ||
331 | } | ||
332 | |||
333 | if (clocks_table_header.entry_size < | ||
334 | (u8) VBIOS_CLOCKS_TABLE_35_ENTRY_SIZE_11) { | ||
335 | status = -EINVAL; | ||
336 | goto done; | ||
337 | } | ||
338 | |||
339 | switch (clocks_table_header.clocks_hal) { | ||
340 | case CLK_TABLE_HAL_ENTRY_GP: | ||
341 | { | ||
342 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gp; | ||
343 | break; | ||
344 | } | ||
345 | case CLK_TABLE_HAL_ENTRY_GV: | ||
346 | { | ||
347 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gv; | ||
348 | break; | ||
349 | } | ||
350 | default: | ||
351 | { | ||
352 | status = -EINVAL; | ||
353 | goto done; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | pclkdomainobjs->cntr_sampling_periodms = | ||
358 | (u16)clocks_table_header.cntr_sampling_periodms; | ||
359 | |||
360 | /* Read table entries*/ | ||
361 | clocks_tbl_entry_ptr = clocks_table_ptr + | ||
362 | clocks_table_header.header_size; | ||
363 | for (index = 0; index < clocks_table_header.entry_count; index++) { | ||
364 | memcpy((void*) &clocks_table_entry, (void*) clocks_tbl_entry_ptr, | ||
365 | clocks_table_header.entry_size); | ||
366 | clk_domain_data.clk_domain.domain = | ||
367 | (u8) vbiosclktbl1xhalentry[index].domain; | ||
368 | clk_domain_data.clk_domain.api_domain = | ||
369 | clktranslatehalmumsettoapinumset( | ||
370 | (u32) BIT(clk_domain_data.clk_domain.domain)); | ||
371 | clk_domain_data.v3x.b_noise_aware_capable = | ||
372 | vbiosclktbl1xhalentry[index].b_noise_aware_capable; | ||
373 | |||
374 | switch (BIOS_GET_FIELD(clocks_table_entry.flags0, | ||
375 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE)) { | ||
376 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_FIXED: | ||
377 | { | ||
378 | clk_domain_data.boardobj.type = | ||
379 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED; | ||
380 | clk_domain_data.v3x_fixed.freq_mhz = (u16)BIOS_GET_FIELD( | ||
381 | clocks_table_entry.param1, | ||
382 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_FIXED_FREQUENCY_MHZ); | ||
383 | break; | ||
384 | } | ||
385 | |||
386 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_MASTER: | ||
387 | { | ||
388 | clk_domain_data.boardobj.type = | ||
389 | CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER; | ||
390 | clk_domain_data.v35_prog.super.clk_prog_idx_first = | ||
391 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
392 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
393 | clk_domain_data.v35_prog.super.clk_prog_idx_last = | ||
394 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
395 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
396 | clk_domain_data.v35_prog.super.noise_unaware_ordering_index = | ||
397 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
398 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
399 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
400 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = | ||
401 | (bool)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
402 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
403 | |||
404 | } else { | ||
405 | clk_domain_data.v35_prog.super.noise_aware_ordering_index = | ||
406 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
407 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = false; | ||
408 | } | ||
409 | clk_domain_data.v35_prog.pre_volt_ordering_index = | ||
410 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
411 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_PRE_VOLT_ORDERING_IDX)); | ||
412 | |||
413 | clk_domain_data.v35_prog.post_volt_ordering_index = | ||
414 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
415 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_POST_VOLT_ORDERING_IDX)); | ||
416 | |||
417 | clk_domain_data.v35_prog.super.factory_delta.data.delta_khz = 0; | ||
418 | clk_domain_data.v35_prog.super.factory_delta.type = 0; | ||
419 | |||
420 | clk_domain_data.v35_prog.super.freq_delta_min_mhz = | ||
421 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
422 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MIN_MHZ)); | ||
423 | |||
424 | clk_domain_data.v35_prog.super.freq_delta_max_mhz = | ||
425 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
426 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MAX_MHZ)); | ||
427 | clk_domain_data.v35_prog.clk_vf_curve_count = | ||
428 | vbiosclktbl1xhalentry[index].clk_vf_curve_count; | ||
429 | break; | ||
430 | } | ||
431 | |||
432 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_SLAVE: | ||
433 | { | ||
434 | clk_domain_data.boardobj.type = | ||
435 | CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE; | ||
436 | clk_domain_data.v35_prog.super.clk_prog_idx_first = | ||
437 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
438 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
439 | clk_domain_data.v35_prog.super.clk_prog_idx_last = | ||
440 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
441 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
442 | clk_domain_data.v35_prog.super.noise_unaware_ordering_index = | ||
443 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
444 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
445 | |||
446 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
447 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = | ||
448 | (bool)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
449 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
450 | |||
451 | } else { | ||
452 | clk_domain_data.v35_prog.super.noise_aware_ordering_index = | ||
453 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
454 | clk_domain_data.v35_prog.super.b_force_noise_unaware_ordering = false; | ||
455 | } | ||
456 | clk_domain_data.v35_prog.pre_volt_ordering_index = | ||
457 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
458 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_PRE_VOLT_ORDERING_IDX)); | ||
459 | |||
460 | clk_domain_data.v35_prog.post_volt_ordering_index = | ||
461 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
462 | NV_VBIOS_CLOCKS_TABLE_35_ENTRY_PARAM2_PROG_POST_VOLT_ORDERING_IDX)); | ||
463 | |||
464 | clk_domain_data.v35_prog.super.factory_delta.data.delta_khz = 0; | ||
465 | clk_domain_data.v35_prog.super.factory_delta.type = 0; | ||
466 | clk_domain_data.v35_prog.super.freq_delta_min_mhz = 0; | ||
467 | clk_domain_data.v35_prog.super.freq_delta_max_mhz = 0; | ||
468 | clk_domain_data.v35_slave.slave.master_idx = | ||
469 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
470 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_SLAVE_MASTER_DOMAIN)); | ||
471 | break; | ||
472 | } | ||
473 | |||
474 | default: | ||
475 | { | ||
476 | nvgpu_err(g, | ||
477 | "error reading clock domain entry %d", index); | ||
478 | status = -EINVAL; | ||
479 | goto done; | ||
480 | } | ||
481 | |||
482 | } | ||
483 | pclkdomain_dev = construct_clk_domain(g, | ||
484 | (void *)&clk_domain_data); | ||
485 | if (pclkdomain_dev == NULL) { | ||
486 | nvgpu_err(g, | ||
487 | "unable to construct clock domain boardobj for %d", | ||
488 | index); | ||
489 | status = -EINVAL; | ||
490 | goto done; | ||
491 | } | ||
492 | status = boardobjgrp_objinsert( | ||
493 | &pclkdomainobjs->super.super, | ||
494 | (struct boardobj *)(void*) pclkdomain_dev, index); | ||
495 | if (status != 0UL) { | ||
496 | nvgpu_err(g, | ||
497 | "unable to insert clock domain boardobj for %d", index); | ||
498 | status = (u32) -EINVAL; | ||
499 | goto done; | ||
500 | } | ||
501 | clocks_tbl_entry_ptr += clocks_table_header.entry_size; | ||
502 | } | ||
503 | |||
504 | done: | ||
505 | nvgpu_log_info(g, " done status %x", status); | ||
506 | return status; | ||
507 | } | ||
508 | |||
509 | static int devinit_get_clocks_table_1x(struct gk20a *g, | ||
510 | struct clk_domains *pclkdomainobjs, u8 *clocks_table_ptr) | ||
511 | { | ||
512 | int status = 0; | ||
513 | struct vbios_clocks_table_1x_header clocks_table_header = { 0 }; | ||
514 | struct vbios_clocks_table_1x_entry clocks_table_entry = { 0 }; | ||
515 | struct vbios_clocks_table_1x_hal_clock_entry *vbiosclktbl1xhalentry; | ||
516 | u8 *clocks_tbl_entry_ptr = NULL; | ||
517 | u32 index = 0; | ||
518 | struct clk_domain *pclkdomain_dev; | ||
519 | union { | ||
520 | struct boardobj boardobj; | ||
521 | struct clk_domain clk_domain; | ||
522 | struct clk_domain_3x v3x; | ||
523 | struct clk_domain_3x_fixed v3x_fixed; | ||
524 | struct clk_domain_3x_prog v3x_prog; | ||
525 | struct clk_domain_3x_master v3x_master; | ||
526 | struct clk_domain_3x_slave v3x_slave; | ||
527 | } clk_domain_data; | ||
528 | |||
529 | nvgpu_log_info(g, " "); | ||
530 | |||
531 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
532 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07); | ||
533 | if (clocks_table_header.header_size < | ||
534 | (u8) VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07) { | ||
535 | status = -EINVAL; | ||
536 | goto done; | ||
537 | } | ||
538 | |||
539 | if (clocks_table_header.entry_size < | ||
540 | (u8) VBIOS_CLOCKS_TABLE_1X_ENTRY_SIZE_09) { | ||
541 | status = -EINVAL; | ||
542 | goto done; | ||
543 | } | ||
544 | |||
545 | switch (clocks_table_header.clocks_hal) { | ||
546 | case CLK_TABLE_HAL_ENTRY_GP: | ||
547 | { | ||
548 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gp; | ||
549 | break; | ||
550 | } | ||
551 | case CLK_TABLE_HAL_ENTRY_GV: | ||
552 | { | ||
553 | vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gv; | ||
554 | break; | ||
555 | } | ||
556 | default: | ||
557 | { | ||
558 | status = -EINVAL; | ||
559 | goto done; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | pclkdomainobjs->cntr_sampling_periodms = | ||
564 | (u16)clocks_table_header.cntr_sampling_periodms; | ||
565 | |||
566 | /* Read table entries*/ | ||
567 | clocks_tbl_entry_ptr = clocks_table_ptr + | ||
568 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07; | ||
569 | for (index = 0; index < clocks_table_header.entry_count; index++) { | ||
570 | memcpy((void*) &clocks_table_entry, (void*) clocks_tbl_entry_ptr, | ||
571 | clocks_table_header.entry_size); | ||
572 | clk_domain_data.clk_domain.domain = | ||
573 | (u8) vbiosclktbl1xhalentry[index].domain; | ||
574 | clk_domain_data.clk_domain.api_domain = | ||
575 | clktranslatehalmumsettoapinumset( | ||
576 | BIT(clk_domain_data.clk_domain.domain)); | ||
577 | clk_domain_data.v3x.b_noise_aware_capable = | ||
578 | vbiosclktbl1xhalentry[index].b_noise_aware_capable; | ||
579 | |||
580 | switch (BIOS_GET_FIELD(clocks_table_entry.flags0, | ||
581 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE)) { | ||
582 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_FIXED: | ||
583 | { | ||
584 | clk_domain_data.boardobj.type = | ||
585 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED; | ||
586 | clk_domain_data.v3x_fixed.freq_mhz = (u16)BIOS_GET_FIELD( | ||
587 | clocks_table_entry.param1, | ||
588 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_FIXED_FREQUENCY_MHZ); | ||
589 | break; | ||
590 | } | ||
591 | |||
592 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_MASTER: | ||
593 | { | ||
594 | clk_domain_data.boardobj.type = | ||
595 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER; | ||
596 | clk_domain_data.v3x_prog.clk_prog_idx_first = | ||
597 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
598 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
599 | clk_domain_data.v3x_prog.clk_prog_idx_last = | ||
600 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
601 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
602 | clk_domain_data.v3x_prog.noise_unaware_ordering_index = | ||
603 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
604 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
605 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
606 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
607 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
608 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX)); | ||
609 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = | ||
610 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
611 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
612 | } else { | ||
613 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
614 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
615 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false; | ||
616 | } | ||
617 | |||
618 | clk_domain_data.v3x_prog.factory_delta.data.delta_khz = 0; | ||
619 | clk_domain_data.v3x_prog.factory_delta.type = 0; | ||
620 | |||
621 | clk_domain_data.v3x_prog.freq_delta_min_mhz = | ||
622 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
623 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MIN_MHZ)); | ||
624 | |||
625 | clk_domain_data.v3x_prog.freq_delta_max_mhz = | ||
626 | (u16)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
627 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_MASTER_FREQ_OC_DELTA_MAX_MHZ)); | ||
628 | break; | ||
629 | } | ||
630 | |||
631 | case NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_FLAGS0_USAGE_SLAVE: | ||
632 | { | ||
633 | clk_domain_data.boardobj.type = | ||
634 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE; | ||
635 | clk_domain_data.v3x_prog.clk_prog_idx_first = | ||
636 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
637 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_FIRST)); | ||
638 | clk_domain_data.v3x_prog.clk_prog_idx_last = | ||
639 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param0, | ||
640 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM0_PROG_CLK_PROG_IDX_LAST)); | ||
641 | clk_domain_data.v3x_prog.noise_unaware_ordering_index = | ||
642 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
643 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_UNAWARE_ORDERING_IDX)); | ||
644 | |||
645 | if (clk_domain_data.v3x.b_noise_aware_capable) { | ||
646 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
647 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
648 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_NOISE_AWARE_ORDERING_IDX)); | ||
649 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = | ||
650 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param2, | ||
651 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM2_PROG_FORCE_NOISE_UNAWARE_ORDERING)); | ||
652 | } else { | ||
653 | clk_domain_data.v3x_prog.noise_aware_ordering_index = | ||
654 | CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID; | ||
655 | clk_domain_data.v3x_prog.b_force_noise_unaware_ordering = false; | ||
656 | } | ||
657 | clk_domain_data.v3x_prog.factory_delta.data.delta_khz = 0; | ||
658 | clk_domain_data.v3x_prog.factory_delta.type = 0; | ||
659 | clk_domain_data.v3x_prog.freq_delta_min_mhz = 0; | ||
660 | clk_domain_data.v3x_prog.freq_delta_max_mhz = 0; | ||
661 | clk_domain_data.v3x_slave.master_idx = | ||
662 | (u8)(BIOS_GET_FIELD(clocks_table_entry.param1, | ||
663 | NV_VBIOS_CLOCKS_TABLE_1X_ENTRY_PARAM1_SLAVE_MASTER_DOMAIN)); | ||
664 | break; | ||
665 | } | ||
666 | |||
667 | default: | ||
668 | { | ||
669 | nvgpu_err(g, | ||
670 | "error reading clock domain entry %d", index); | ||
671 | status = (u32) -EINVAL; | ||
672 | goto done; | ||
673 | } | ||
674 | |||
675 | } | ||
676 | pclkdomain_dev = construct_clk_domain(g, | ||
677 | (void *)&clk_domain_data); | ||
678 | if (pclkdomain_dev == NULL) { | ||
679 | nvgpu_err(g, | ||
680 | "unable to construct clock domain boardobj for %d", | ||
681 | index); | ||
682 | status = (u32) -EINVAL; | ||
683 | goto done; | ||
684 | } | ||
685 | status = boardobjgrp_objinsert(&pclkdomainobjs->super.super, | ||
686 | (struct boardobj *)(void *)pclkdomain_dev, index); | ||
687 | if (status != 0UL) { | ||
688 | nvgpu_err(g, | ||
689 | "unable to insert clock domain boardobj for %d", index); | ||
690 | status = (u32) -EINVAL; | ||
691 | goto done; | ||
692 | } | ||
693 | clocks_tbl_entry_ptr += clocks_table_header.entry_size; | ||
694 | } | ||
695 | |||
696 | done: | ||
697 | nvgpu_log_info(g, " done status %x", status); | ||
698 | return status; | ||
699 | } | ||
700 | |||
701 | static int devinit_get_clocks_table(struct gk20a *g, | ||
702 | struct clk_domains *pclkdomainobjs) | ||
703 | { | ||
704 | int status = 0; | ||
705 | u8 *clocks_table_ptr = NULL; | ||
706 | struct vbios_clocks_table_1x_header clocks_table_header = { 0 }; | ||
707 | nvgpu_log_info(g, " "); | ||
708 | |||
709 | clocks_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
710 | g->bios.clock_token, CLOCKS_TABLE); | ||
711 | if (clocks_table_ptr == NULL) { | ||
712 | status = -EINVAL; | ||
713 | goto done; | ||
714 | } | ||
715 | memcpy(&clocks_table_header, clocks_table_ptr, | ||
716 | VBIOS_CLOCKS_TABLE_1X_HEADER_SIZE_07); | ||
717 | if (clocks_table_header.version == 0x35U) { | ||
718 | devinit_get_clocks_table_35(g, pclkdomainobjs, clocks_table_ptr); | ||
719 | } | ||
720 | else { | ||
721 | devinit_get_clocks_table_1x(g, pclkdomainobjs, clocks_table_ptr); | ||
722 | } | ||
723 | done: | ||
724 | return status; | ||
725 | |||
726 | } | ||
727 | |||
728 | static int clkdomainclkproglink_not_supported(struct gk20a *g, | ||
729 | struct clk_pmupstate *pclk, | ||
730 | struct clk_domain *pdomain) | ||
731 | { | ||
732 | nvgpu_log_info(g, " "); | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | |||
736 | static int clkdomainvfsearch_stub( | ||
737 | struct gk20a *g, | ||
738 | struct clk_pmupstate *pclk, | ||
739 | struct clk_domain *pdomain, | ||
740 | u16 *clkmhz, | ||
741 | u32 *voltuv, | ||
742 | u8 rail) | ||
743 | |||
744 | { | ||
745 | nvgpu_log_info(g, " "); | ||
746 | return -EINVAL; | ||
747 | } | ||
748 | |||
749 | static u32 clkdomaingetfpoints_stub( | ||
750 | struct gk20a *g, | ||
751 | struct clk_pmupstate *pclk, | ||
752 | struct clk_domain *pdomain, | ||
753 | u32 *pfpointscount, | ||
754 | u16 *pfreqpointsinmhz, | ||
755 | u8 rail) | ||
756 | { | ||
757 | nvgpu_log_info(g, " "); | ||
758 | return -EINVAL; | ||
759 | } | ||
760 | |||
761 | |||
762 | static int clk_domain_construct_super(struct gk20a *g, | ||
763 | struct boardobj **ppboardobj, | ||
764 | u16 size, void *pargs) | ||
765 | { | ||
766 | struct clk_domain *pdomain; | ||
767 | struct clk_domain *ptmpdomain = (struct clk_domain *)pargs; | ||
768 | int status = 0; | ||
769 | |||
770 | status = boardobj_construct_super(g, ppboardobj, | ||
771 | size, pargs); | ||
772 | |||
773 | if (status) { | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | |||
777 | pdomain = (struct clk_domain *)*ppboardobj; | ||
778 | |||
779 | pdomain->super.pmudatainit = | ||
780 | clk_domain_pmudatainit_super; | ||
781 | |||
782 | pdomain->clkdomainclkproglink = | ||
783 | clkdomainclkproglink_not_supported; | ||
784 | |||
785 | pdomain->clkdomainclkvfsearch = | ||
786 | clkdomainvfsearch_stub; | ||
787 | |||
788 | pdomain->clkdomainclkgetfpoints = | ||
789 | clkdomaingetfpoints_stub; | ||
790 | |||
791 | pdomain->api_domain = ptmpdomain->api_domain; | ||
792 | pdomain->domain = ptmpdomain->domain; | ||
793 | pdomain->perf_domain_grp_idx = | ||
794 | ptmpdomain->perf_domain_grp_idx; | ||
795 | |||
796 | return status; | ||
797 | } | ||
798 | |||
799 | static int _clk_domain_pmudatainit_3x(struct gk20a *g, | ||
800 | struct boardobj *board_obj_ptr, | ||
801 | struct nv_pmu_boardobj *ppmudata) | ||
802 | { | ||
803 | int status = 0; | ||
804 | struct clk_domain_3x *pclk_domain_3x; | ||
805 | struct nv_pmu_clk_clk_domain_3x_boardobj_set *pset; | ||
806 | |||
807 | nvgpu_log_info(g, " "); | ||
808 | |||
809 | status = clk_domain_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
810 | if (status != 0) { | ||
811 | return status; | ||
812 | } | ||
813 | |||
814 | pclk_domain_3x = (struct clk_domain_3x *)board_obj_ptr; | ||
815 | |||
816 | pset = (struct nv_pmu_clk_clk_domain_3x_boardobj_set *)ppmudata; | ||
817 | |||
818 | pset->b_noise_aware_capable = pclk_domain_3x->b_noise_aware_capable; | ||
819 | |||
820 | return status; | ||
821 | } | ||
822 | |||
823 | static int clk_domain_construct_3x(struct gk20a *g, | ||
824 | struct boardobj **ppboardobj, | ||
825 | u16 size, void *pargs) | ||
826 | { | ||
827 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
828 | struct clk_domain_3x *pdomain; | ||
829 | struct clk_domain_3x *ptmpdomain = | ||
830 | (struct clk_domain_3x *)pargs; | ||
831 | int status = 0; | ||
832 | |||
833 | ptmpobj->type_mask = BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X); | ||
834 | status = clk_domain_construct_super(g, ppboardobj, | ||
835 | size, pargs); | ||
836 | if (status) { | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | |||
840 | pdomain = (struct clk_domain_3x *)*ppboardobj; | ||
841 | |||
842 | pdomain->super.super.pmudatainit = | ||
843 | _clk_domain_pmudatainit_3x; | ||
844 | |||
845 | pdomain->b_noise_aware_capable = ptmpdomain->b_noise_aware_capable; | ||
846 | |||
847 | return status; | ||
848 | } | ||
849 | |||
850 | static int clkdomainclkproglink_3x_prog(struct gk20a *g, | ||
851 | struct clk_pmupstate *pclk, | ||
852 | struct clk_domain *pdomain) | ||
853 | { | ||
854 | int status = 0; | ||
855 | struct clk_domain_3x_prog *p3xprog = | ||
856 | (struct clk_domain_3x_prog *)pdomain; | ||
857 | struct clk_prog *pprog = NULL; | ||
858 | u8 i; | ||
859 | |||
860 | nvgpu_log_info(g, " "); | ||
861 | |||
862 | for (i = p3xprog->clk_prog_idx_first; | ||
863 | i <= p3xprog->clk_prog_idx_last; | ||
864 | i++) { | ||
865 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
866 | if (pprog == NULL) { | ||
867 | status = -EINVAL; | ||
868 | } | ||
869 | } | ||
870 | return status; | ||
871 | } | ||
872 | |||
873 | static int clkdomaingetslaveclk(struct gk20a *g, | ||
874 | struct clk_pmupstate *pclk, | ||
875 | struct clk_domain *pdomain, | ||
876 | u16 *pclkmhz, | ||
877 | u16 masterclkmhz) | ||
878 | { | ||
879 | int status = 0; | ||
880 | struct clk_prog *pprog = NULL; | ||
881 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
882 | u8 slaveidx; | ||
883 | struct clk_domain_3x_master *p3xmaster; | ||
884 | |||
885 | nvgpu_log_info(g, " "); | ||
886 | |||
887 | if (pclkmhz == NULL) { | ||
888 | return -EINVAL; | ||
889 | } | ||
890 | |||
891 | if (masterclkmhz == 0) { | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | |||
895 | slaveidx = BOARDOBJ_GET_IDX(pdomain); | ||
896 | p3xmaster = (struct clk_domain_3x_master *) | ||
897 | CLK_CLK_DOMAIN_GET(pclk, | ||
898 | ((struct clk_domain_3x_slave *) | ||
899 | pdomain)->master_idx); | ||
900 | pprog = CLK_CLK_PROG_GET(pclk, p3xmaster->super.clk_prog_idx_first); | ||
901 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
902 | |||
903 | status = pprog1xmaster->getslaveclk(g, pclk, pprog1xmaster, | ||
904 | slaveidx, pclkmhz, masterclkmhz); | ||
905 | return status; | ||
906 | } | ||
907 | |||
908 | static int clkdomainvfsearch(struct gk20a *g, | ||
909 | struct clk_pmupstate *pclk, | ||
910 | struct clk_domain *pdomain, | ||
911 | u16 *pclkmhz, | ||
912 | u32 *pvoltuv, | ||
913 | u8 rail) | ||
914 | { | ||
915 | int status = 0; | ||
916 | struct clk_domain_3x_master *p3xmaster = | ||
917 | (struct clk_domain_3x_master *)pdomain; | ||
918 | struct clk_prog *pprog = NULL; | ||
919 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
920 | u8 i; | ||
921 | u8 *pslaveidx = NULL; | ||
922 | u8 slaveidx; | ||
923 | u16 clkmhz; | ||
924 | u32 voltuv; | ||
925 | u16 bestclkmhz; | ||
926 | u32 bestvoltuv; | ||
927 | |||
928 | nvgpu_log_info(g, " "); | ||
929 | |||
930 | if ((pclkmhz == NULL) || (pvoltuv == NULL)) { | ||
931 | return -EINVAL; | ||
932 | } | ||
933 | |||
934 | if ((*pclkmhz != 0) && (*pvoltuv != 0)) { | ||
935 | return -EINVAL; | ||
936 | } | ||
937 | |||
938 | bestclkmhz = *pclkmhz; | ||
939 | bestvoltuv = *pvoltuv; | ||
940 | |||
941 | if (pdomain->super.implements(g, &pdomain->super, | ||
942 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
943 | slaveidx = BOARDOBJ_GET_IDX(pdomain); | ||
944 | pslaveidx = &slaveidx; | ||
945 | p3xmaster = (struct clk_domain_3x_master *) | ||
946 | CLK_CLK_DOMAIN_GET(pclk, | ||
947 | ((struct clk_domain_3x_slave *) | ||
948 | pdomain)->master_idx); | ||
949 | } | ||
950 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
951 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
952 | i <= p3xmaster->super.clk_prog_idx_last; | ||
953 | i++) { | ||
954 | clkmhz = *pclkmhz; | ||
955 | voltuv = *pvoltuv; | ||
956 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
957 | |||
958 | /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ | ||
959 | if (!pprog->super.implements(g, &pprog->super, | ||
960 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { | ||
961 | status = -EINVAL; | ||
962 | goto done; | ||
963 | } | ||
964 | |||
965 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
966 | status = pprog1xmaster->vflookup(g, pclk, pprog1xmaster, | ||
967 | pslaveidx, &clkmhz, &voltuv, rail); | ||
968 | /* if look up has found the V or F value matching to other | ||
969 | exit */ | ||
970 | if (status == 0) { | ||
971 | if (*pclkmhz == 0) { | ||
972 | bestclkmhz = clkmhz; | ||
973 | } else { | ||
974 | bestvoltuv = voltuv; | ||
975 | break; | ||
976 | } | ||
977 | } | ||
978 | } | ||
979 | /* clk and volt sent as zero to print vf table */ | ||
980 | if ((*pclkmhz == 0) && (*pvoltuv == 0)) { | ||
981 | status = 0; | ||
982 | goto done; | ||
983 | } | ||
984 | /* atleast one search found a matching value? */ | ||
985 | if ((bestvoltuv != 0) && (bestclkmhz != 0)) { | ||
986 | *pclkmhz = bestclkmhz; | ||
987 | *pvoltuv = bestvoltuv; | ||
988 | status = 0; | ||
989 | goto done; | ||
990 | } | ||
991 | done: | ||
992 | nvgpu_log_info(g, "done status %x", status); | ||
993 | return status; | ||
994 | } | ||
995 | |||
996 | static u32 clkdomaingetfpoints | ||
997 | ( | ||
998 | struct gk20a *g, | ||
999 | struct clk_pmupstate *pclk, | ||
1000 | struct clk_domain *pdomain, | ||
1001 | u32 *pfpointscount, | ||
1002 | u16 *pfreqpointsinmhz, | ||
1003 | u8 rail | ||
1004 | ) | ||
1005 | { | ||
1006 | u32 status = 0; | ||
1007 | struct clk_domain_3x_master *p3xmaster = | ||
1008 | (struct clk_domain_3x_master *)pdomain; | ||
1009 | struct clk_prog *pprog = NULL; | ||
1010 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
1011 | u32 fpointscount = 0; | ||
1012 | u32 remainingcount; | ||
1013 | u32 totalcount; | ||
1014 | u16 *freqpointsdata; | ||
1015 | u8 i; | ||
1016 | |||
1017 | nvgpu_log_info(g, " "); | ||
1018 | |||
1019 | if (pfpointscount == NULL) { | ||
1020 | return -EINVAL; | ||
1021 | } | ||
1022 | |||
1023 | if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) { | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1026 | |||
1027 | if (pdomain->super.implements(g, &pdomain->super, | ||
1028 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | freqpointsdata = pfreqpointsinmhz; | ||
1033 | totalcount = 0; | ||
1034 | fpointscount = *pfpointscount; | ||
1035 | remainingcount = fpointscount; | ||
1036 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
1037 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
1038 | i <= p3xmaster->super.clk_prog_idx_last; | ||
1039 | i++) { | ||
1040 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
1041 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
1042 | status = pprog1xmaster->getfpoints(g, pclk, pprog1xmaster, | ||
1043 | &fpointscount, &freqpointsdata, rail); | ||
1044 | if (status) { | ||
1045 | *pfpointscount = 0; | ||
1046 | goto done; | ||
1047 | } | ||
1048 | totalcount += fpointscount; | ||
1049 | if (*pfpointscount) { | ||
1050 | remainingcount -= fpointscount; | ||
1051 | fpointscount = remainingcount; | ||
1052 | } else { | ||
1053 | fpointscount = 0; | ||
1054 | } | ||
1055 | |||
1056 | } | ||
1057 | |||
1058 | *pfpointscount = totalcount; | ||
1059 | done: | ||
1060 | nvgpu_log_info(g, "done status %x", status); | ||
1061 | return status; | ||
1062 | } | ||
1063 | |||
1064 | static int clk_domain_pmudatainit_35_prog(struct gk20a *g, | ||
1065 | struct boardobj *board_obj_ptr, | ||
1066 | struct nv_pmu_boardobj *ppmudata) | ||
1067 | { | ||
1068 | int status = 0; | ||
1069 | struct clk_domain_35_prog *pclk_domain_35_prog; | ||
1070 | struct clk_domain_3x_prog *pclk_domain_3x_prog; | ||
1071 | struct nv_pmu_clk_clk_domain_35_prog_boardobj_set *pset; | ||
1072 | struct clk_domains *pdomains = &(g->clk_pmu.clk_domainobjs); | ||
1073 | |||
1074 | nvgpu_log_info(g, " "); | ||
1075 | |||
1076 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
1077 | if (status != 0UL) { | ||
1078 | return status; | ||
1079 | } | ||
1080 | |||
1081 | pclk_domain_35_prog = (struct clk_domain_35_prog *)(void*)board_obj_ptr; | ||
1082 | pclk_domain_3x_prog = &pclk_domain_35_prog->super; | ||
1083 | |||
1084 | pset = (struct nv_pmu_clk_clk_domain_35_prog_boardobj_set *) | ||
1085 | (void*) ppmudata; | ||
1086 | |||
1087 | pset->super.clk_prog_idx_first = pclk_domain_3x_prog->clk_prog_idx_first; | ||
1088 | pset->super.clk_prog_idx_last = pclk_domain_3x_prog->clk_prog_idx_last; | ||
1089 | pset->super.b_force_noise_unaware_ordering = | ||
1090 | pclk_domain_3x_prog->b_force_noise_unaware_ordering; | ||
1091 | pset->super.factory_delta = pclk_domain_3x_prog->factory_delta; | ||
1092 | pset->super.freq_delta_min_mhz = pclk_domain_3x_prog->freq_delta_min_mhz; | ||
1093 | pset->super.freq_delta_max_mhz = pclk_domain_3x_prog->freq_delta_max_mhz; | ||
1094 | memcpy(&pset->super.deltas, &pdomains->deltas, | ||
1095 | (sizeof(struct ctrl_clk_clk_delta))); | ||
1096 | pset->pre_volt_ordering_index = pclk_domain_35_prog->pre_volt_ordering_index; | ||
1097 | pset->post_volt_ordering_index = pclk_domain_35_prog->post_volt_ordering_index; | ||
1098 | pset->clk_pos = pclk_domain_35_prog->clk_pos; | ||
1099 | pset->clk_vf_curve_count = pclk_domain_35_prog->clk_vf_curve_count; | ||
1100 | |||
1101 | return status; | ||
1102 | } | ||
1103 | |||
1104 | static int _clk_domain_pmudatainit_3x_prog(struct gk20a *g, | ||
1105 | struct boardobj *board_obj_ptr, | ||
1106 | struct nv_pmu_boardobj *ppmudata) | ||
1107 | { | ||
1108 | int status = 0; | ||
1109 | struct clk_domain_3x_prog *pclk_domain_3x_prog; | ||
1110 | struct nv_pmu_clk_clk_domain_30_prog_boardobj_set *pset; | ||
1111 | struct clk_domains *pdomains = &(g->clk_pmu.clk_domainobjs); | ||
1112 | |||
1113 | nvgpu_log_info(g, " "); | ||
1114 | |||
1115 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
1116 | if (status != 0) { | ||
1117 | return status; | ||
1118 | } | ||
1119 | |||
1120 | pclk_domain_3x_prog = (struct clk_domain_3x_prog *)board_obj_ptr; | ||
1121 | |||
1122 | pset = (struct nv_pmu_clk_clk_domain_30_prog_boardobj_set *) | ||
1123 | ppmudata; | ||
1124 | |||
1125 | pset->super.clk_prog_idx_first = pclk_domain_3x_prog->clk_prog_idx_first; | ||
1126 | pset->super.clk_prog_idx_last = pclk_domain_3x_prog->clk_prog_idx_last; | ||
1127 | pset->noise_unaware_ordering_index = | ||
1128 | pclk_domain_3x_prog->noise_unaware_ordering_index; | ||
1129 | pset->noise_aware_ordering_index = | ||
1130 | pclk_domain_3x_prog->noise_aware_ordering_index; | ||
1131 | pset->super.b_force_noise_unaware_ordering = | ||
1132 | pclk_domain_3x_prog->b_force_noise_unaware_ordering; | ||
1133 | pset->super.factory_delta = pclk_domain_3x_prog->factory_delta; | ||
1134 | pset->super.freq_delta_min_mhz = pclk_domain_3x_prog->freq_delta_min_mhz; | ||
1135 | pset->super.freq_delta_max_mhz = pclk_domain_3x_prog->freq_delta_max_mhz; | ||
1136 | memcpy(&pset->super.deltas, &pdomains->deltas, | ||
1137 | (sizeof(struct ctrl_clk_clk_delta))); | ||
1138 | |||
1139 | return status; | ||
1140 | } | ||
1141 | |||
1142 | static int clk_domain_construct_35_prog(struct gk20a *g, | ||
1143 | struct boardobj **ppboardobj, | ||
1144 | u16 size, void *pargs) | ||
1145 | { | ||
1146 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1147 | struct clk_domain_35_prog *pdomain; | ||
1148 | struct clk_domain_35_prog *ptmpdomain = | ||
1149 | (struct clk_domain_35_prog *)pargs; | ||
1150 | int status = 0; | ||
1151 | |||
1152 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG); | ||
1153 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
1154 | if (status != 0UL) | ||
1155 | { | ||
1156 | return (u32) -EINVAL; | ||
1157 | } | ||
1158 | |||
1159 | pdomain = (struct clk_domain_35_prog *)(void*) *ppboardobj; | ||
1160 | |||
1161 | pdomain->super.super.super.super.pmudatainit = | ||
1162 | clk_domain_pmudatainit_35_prog; | ||
1163 | |||
1164 | pdomain->super.super.super.clkdomainclkproglink = | ||
1165 | clkdomainclkproglink_3x_prog; | ||
1166 | |||
1167 | pdomain->super.super.super.clkdomainclkvfsearch = | ||
1168 | clkdomainvfsearch; | ||
1169 | |||
1170 | pdomain->super.super.super.clkdomainclkgetfpoints = | ||
1171 | clkdomaingetfpoints; | ||
1172 | |||
1173 | pdomain->super.clk_prog_idx_first = ptmpdomain->super.clk_prog_idx_first; | ||
1174 | pdomain->super.clk_prog_idx_last = ptmpdomain->super.clk_prog_idx_last; | ||
1175 | pdomain->super.noise_unaware_ordering_index = | ||
1176 | ptmpdomain->super.noise_unaware_ordering_index; | ||
1177 | pdomain->super.noise_aware_ordering_index = | ||
1178 | ptmpdomain->super.noise_aware_ordering_index; | ||
1179 | pdomain->super.b_force_noise_unaware_ordering = | ||
1180 | ptmpdomain->super.b_force_noise_unaware_ordering; | ||
1181 | pdomain->super.factory_delta = ptmpdomain->super.factory_delta; | ||
1182 | pdomain->super.freq_delta_min_mhz = ptmpdomain->super.freq_delta_min_mhz; | ||
1183 | pdomain->super.freq_delta_max_mhz = ptmpdomain->super.freq_delta_max_mhz; | ||
1184 | pdomain->pre_volt_ordering_index = ptmpdomain->pre_volt_ordering_index; | ||
1185 | pdomain->post_volt_ordering_index = ptmpdomain->post_volt_ordering_index; | ||
1186 | pdomain->clk_pos = ptmpdomain->clk_pos; | ||
1187 | pdomain->clk_vf_curve_count = ptmpdomain->clk_vf_curve_count; | ||
1188 | |||
1189 | return status; | ||
1190 | } | ||
1191 | |||
1192 | static int clk_domain_construct_3x_prog(struct gk20a *g, | ||
1193 | struct boardobj **ppboardobj, | ||
1194 | u16 size, void *pargs) | ||
1195 | { | ||
1196 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1197 | struct clk_domain_3x_prog *pdomain; | ||
1198 | struct clk_domain_3x_prog *ptmpdomain = | ||
1199 | (struct clk_domain_3x_prog *)pargs; | ||
1200 | int status = 0; | ||
1201 | |||
1202 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG); | ||
1203 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
1204 | if (status) { | ||
1205 | return -EINVAL; | ||
1206 | } | ||
1207 | |||
1208 | pdomain = (struct clk_domain_3x_prog *)*ppboardobj; | ||
1209 | |||
1210 | pdomain->super.super.super.pmudatainit = | ||
1211 | _clk_domain_pmudatainit_3x_prog; | ||
1212 | |||
1213 | pdomain->super.super.clkdomainclkproglink = | ||
1214 | clkdomainclkproglink_3x_prog; | ||
1215 | |||
1216 | pdomain->super.super.clkdomainclkvfsearch = | ||
1217 | clkdomainvfsearch; | ||
1218 | |||
1219 | pdomain->super.super.clkdomainclkgetfpoints = | ||
1220 | clkdomaingetfpoints; | ||
1221 | |||
1222 | pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first; | ||
1223 | pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last; | ||
1224 | pdomain->noise_unaware_ordering_index = | ||
1225 | ptmpdomain->noise_unaware_ordering_index; | ||
1226 | pdomain->noise_aware_ordering_index = | ||
1227 | ptmpdomain->noise_aware_ordering_index; | ||
1228 | pdomain->b_force_noise_unaware_ordering = | ||
1229 | ptmpdomain->b_force_noise_unaware_ordering; | ||
1230 | pdomain->factory_delta = ptmpdomain->factory_delta; | ||
1231 | pdomain->freq_delta_min_mhz = ptmpdomain->freq_delta_min_mhz; | ||
1232 | pdomain->freq_delta_max_mhz = ptmpdomain->freq_delta_max_mhz; | ||
1233 | |||
1234 | return status; | ||
1235 | } | ||
1236 | |||
1237 | static int _clk_domain_pmudatainit_35_slave(struct gk20a *g, | ||
1238 | struct boardobj *board_obj_ptr, | ||
1239 | struct nv_pmu_boardobj *ppmudata) | ||
1240 | { | ||
1241 | int status = 0; | ||
1242 | struct clk_domain_35_slave *pclk_domain_35_slave; | ||
1243 | struct nv_pmu_clk_clk_domain_35_slave_boardobj_set *pset; | ||
1244 | |||
1245 | nvgpu_log_info(g, " "); | ||
1246 | |||
1247 | status = clk_domain_pmudatainit_35_prog(g, board_obj_ptr, ppmudata); | ||
1248 | if (status != 0UL) { | ||
1249 | return status; | ||
1250 | } | ||
1251 | |||
1252 | pclk_domain_35_slave = (struct clk_domain_35_slave *)(void*)board_obj_ptr; | ||
1253 | |||
1254 | pset = (struct nv_pmu_clk_clk_domain_35_slave_boardobj_set *) | ||
1255 | (void*) ppmudata; | ||
1256 | |||
1257 | pset->slave.master_idx = pclk_domain_35_slave->slave.master_idx; | ||
1258 | |||
1259 | return status; | ||
1260 | } | ||
1261 | |||
1262 | static int clk_domain_pmudatainit_3x_slave(struct gk20a *g, | ||
1263 | struct boardobj *board_obj_ptr, | ||
1264 | struct nv_pmu_boardobj *ppmudata) | ||
1265 | { | ||
1266 | int status = 0; | ||
1267 | struct clk_domain_3x_slave *pclk_domain_3x_slave; | ||
1268 | struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *pset; | ||
1269 | |||
1270 | nvgpu_log_info(g, " "); | ||
1271 | |||
1272 | status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata); | ||
1273 | if (status != 0) { | ||
1274 | return status; | ||
1275 | } | ||
1276 | |||
1277 | pclk_domain_3x_slave = (struct clk_domain_3x_slave *)board_obj_ptr; | ||
1278 | |||
1279 | pset = (struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set *) | ||
1280 | ppmudata; | ||
1281 | |||
1282 | pset->master_idx = pclk_domain_3x_slave->master_idx; | ||
1283 | |||
1284 | return status; | ||
1285 | } | ||
1286 | |||
1287 | static int clk_domain_construct_35_slave(struct gk20a *g, | ||
1288 | struct boardobj **ppboardobj, | ||
1289 | u16 size, void *pargs) | ||
1290 | { | ||
1291 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1292 | struct clk_domain_35_slave *pdomain; | ||
1293 | struct clk_domain_35_slave *ptmpdomain = | ||
1294 | (struct clk_domain_35_slave *)pargs; | ||
1295 | int status = 0; | ||
1296 | |||
1297 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE) { | ||
1298 | return (u32) -EINVAL; | ||
1299 | } | ||
1300 | |||
1301 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE); | ||
1302 | status = clk_domain_construct_35_prog(g, ppboardobj, size, pargs); | ||
1303 | if (status != 0UL) { | ||
1304 | return (u32) -EINVAL; | ||
1305 | } | ||
1306 | |||
1307 | pdomain = (struct clk_domain_35_slave *)(void*)*ppboardobj; | ||
1308 | |||
1309 | pdomain->super.super.super.super.super.pmudatainit = | ||
1310 | _clk_domain_pmudatainit_35_slave; | ||
1311 | |||
1312 | pdomain->slave.master_idx = ptmpdomain->slave.master_idx; | ||
1313 | |||
1314 | pdomain->slave.clkdomainclkgetslaveclk = | ||
1315 | clkdomaingetslaveclk; | ||
1316 | |||
1317 | return status; | ||
1318 | } | ||
1319 | |||
1320 | static int clk_domain_construct_3x_slave(struct gk20a *g, | ||
1321 | struct boardobj **ppboardobj, | ||
1322 | u16 size, void *pargs) | ||
1323 | { | ||
1324 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1325 | struct clk_domain_3x_slave *pdomain; | ||
1326 | struct clk_domain_3x_slave *ptmpdomain = | ||
1327 | (struct clk_domain_3x_slave *)pargs; | ||
1328 | int status = 0; | ||
1329 | |||
1330 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE) { | ||
1331 | return -EINVAL; | ||
1332 | } | ||
1333 | |||
1334 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE); | ||
1335 | status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs); | ||
1336 | if (status != 0UL) { | ||
1337 | return -EINVAL; | ||
1338 | } | ||
1339 | |||
1340 | pdomain = (struct clk_domain_3x_slave *)*ppboardobj; | ||
1341 | |||
1342 | pdomain->super.super.super.super.pmudatainit = | ||
1343 | clk_domain_pmudatainit_3x_slave; | ||
1344 | |||
1345 | pdomain->master_idx = ptmpdomain->master_idx; | ||
1346 | |||
1347 | pdomain->clkdomainclkgetslaveclk = | ||
1348 | clkdomaingetslaveclk; | ||
1349 | |||
1350 | return status; | ||
1351 | } | ||
1352 | |||
1353 | static int clkdomainclkproglink_3x_master(struct gk20a *g, | ||
1354 | struct clk_pmupstate *pclk, | ||
1355 | struct clk_domain *pdomain) | ||
1356 | { | ||
1357 | int status = 0; | ||
1358 | struct clk_domain_3x_master *p3xmaster = | ||
1359 | (struct clk_domain_3x_master *)pdomain; | ||
1360 | struct clk_prog *pprog = NULL; | ||
1361 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
1362 | u16 freq_max_last_mhz = 0; | ||
1363 | u8 i; | ||
1364 | |||
1365 | nvgpu_log_info(g, " "); | ||
1366 | |||
1367 | status = clkdomainclkproglink_3x_prog(g, pclk, pdomain); | ||
1368 | if (status) { | ||
1369 | goto done; | ||
1370 | } | ||
1371 | |||
1372 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
1373 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
1374 | i <= p3xmaster->super.clk_prog_idx_last; | ||
1375 | i++) { | ||
1376 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
1377 | |||
1378 | /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ | ||
1379 | if (!pprog->super.implements(g, &pprog->super, | ||
1380 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { | ||
1381 | status = -EINVAL; | ||
1382 | goto done; | ||
1383 | } | ||
1384 | |||
1385 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
1386 | status = pprog1xmaster->vfflatten(g, pclk, pprog1xmaster, | ||
1387 | BOARDOBJ_GET_IDX(p3xmaster), &freq_max_last_mhz); | ||
1388 | if (status) { | ||
1389 | goto done; | ||
1390 | } | ||
1391 | } | ||
1392 | done: | ||
1393 | nvgpu_log_info(g, "done status %x", status); | ||
1394 | return status; | ||
1395 | } | ||
1396 | |||
1397 | static int clk_domain_pmudatainit_35_master(struct gk20a *g, | ||
1398 | struct boardobj *board_obj_ptr, | ||
1399 | struct nv_pmu_boardobj *ppmudata) | ||
1400 | { | ||
1401 | int status = 0; | ||
1402 | struct clk_domain_35_master *pclk_domain_35_master; | ||
1403 | struct nv_pmu_clk_clk_domain_35_master_boardobj_set *pset; | ||
1404 | |||
1405 | nvgpu_log_info(g, " "); | ||
1406 | |||
1407 | status = clk_domain_pmudatainit_35_prog(g, board_obj_ptr, ppmudata); | ||
1408 | if (status != 0UL) { | ||
1409 | return status; | ||
1410 | } | ||
1411 | |||
1412 | pclk_domain_35_master = (struct clk_domain_35_master *) | ||
1413 | (void*) board_obj_ptr; | ||
1414 | |||
1415 | pset = (struct nv_pmu_clk_clk_domain_35_master_boardobj_set *) | ||
1416 | (void*) ppmudata; | ||
1417 | |||
1418 | pset->master.slave_idxs_mask = pclk_domain_35_master->master.slave_idxs_mask; | ||
1419 | |||
1420 | return status; | ||
1421 | } | ||
1422 | |||
1423 | static int _clk_domain_pmudatainit_3x_master(struct gk20a *g, | ||
1424 | struct boardobj *board_obj_ptr, | ||
1425 | struct nv_pmu_boardobj *ppmudata) | ||
1426 | { | ||
1427 | int status = 0; | ||
1428 | struct clk_domain_3x_master *pclk_domain_3x_master; | ||
1429 | struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *pset; | ||
1430 | |||
1431 | nvgpu_log_info(g, " "); | ||
1432 | |||
1433 | status = _clk_domain_pmudatainit_3x_prog(g, board_obj_ptr, ppmudata); | ||
1434 | if (status != 0) { | ||
1435 | return status; | ||
1436 | } | ||
1437 | |||
1438 | pclk_domain_3x_master = (struct clk_domain_3x_master *)board_obj_ptr; | ||
1439 | |||
1440 | pset = (struct nv_pmu_clk_clk_domain_3x_master_boardobj_set *) | ||
1441 | ppmudata; | ||
1442 | |||
1443 | pset->slave_idxs_mask = pclk_domain_3x_master->slave_idxs_mask; | ||
1444 | |||
1445 | return status; | ||
1446 | } | ||
1447 | |||
1448 | static int clk_domain_construct_35_master(struct gk20a *g, | ||
1449 | struct boardobj **ppboardobj, | ||
1450 | u16 size, void *pargs) | ||
1451 | { | ||
1452 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1453 | struct clk_domain_35_master *pdomain; | ||
1454 | int status = 0; | ||
1455 | |||
1456 | if (BOARDOBJ_GET_TYPE(pargs) != (u8) CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER) { | ||
1457 | return -EINVAL; | ||
1458 | } | ||
1459 | |||
1460 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER); | ||
1461 | status = clk_domain_construct_35_prog(g, ppboardobj, size, pargs); | ||
1462 | if (status != 0UL) { | ||
1463 | return (u32) -EINVAL; | ||
1464 | } | ||
1465 | |||
1466 | pdomain = (struct clk_domain_35_master *)(void*) *ppboardobj; | ||
1467 | |||
1468 | pdomain->super.super.super.super.super.pmudatainit = | ||
1469 | clk_domain_pmudatainit_35_master; | ||
1470 | pdomain->super.super.super.super.clkdomainclkproglink = | ||
1471 | clkdomainclkproglink_3x_master; | ||
1472 | |||
1473 | pdomain->master.slave_idxs_mask = 0; | ||
1474 | |||
1475 | return status; | ||
1476 | } | ||
1477 | |||
1478 | static int clk_domain_construct_3x_master(struct gk20a *g, | ||
1479 | struct boardobj **ppboardobj, | ||
1480 | u16 size, void *pargs) | ||
1481 | { | ||
1482 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1483 | struct clk_domain_3x_master *pdomain; | ||
1484 | int status = 0; | ||
1485 | |||
1486 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER) { | ||
1487 | return -EINVAL; | ||
1488 | } | ||
1489 | |||
1490 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER); | ||
1491 | status = clk_domain_construct_3x_prog(g, ppboardobj, size, pargs); | ||
1492 | if (status) { | ||
1493 | return -EINVAL; | ||
1494 | } | ||
1495 | |||
1496 | pdomain = (struct clk_domain_3x_master *)*ppboardobj; | ||
1497 | |||
1498 | pdomain->super.super.super.super.pmudatainit = | ||
1499 | _clk_domain_pmudatainit_3x_master; | ||
1500 | pdomain->super.super.super.clkdomainclkproglink = | ||
1501 | clkdomainclkproglink_3x_master; | ||
1502 | |||
1503 | pdomain->slave_idxs_mask = 0; | ||
1504 | |||
1505 | return status; | ||
1506 | } | ||
1507 | |||
1508 | static int clkdomainclkproglink_fixed(struct gk20a *g, | ||
1509 | struct clk_pmupstate *pclk, | ||
1510 | struct clk_domain *pdomain) | ||
1511 | { | ||
1512 | nvgpu_log_info(g, " "); | ||
1513 | return 0; | ||
1514 | } | ||
1515 | |||
1516 | static int _clk_domain_pmudatainit_3x_fixed(struct gk20a *g, | ||
1517 | struct boardobj *board_obj_ptr, | ||
1518 | struct nv_pmu_boardobj *ppmudata) | ||
1519 | { | ||
1520 | int status = 0; | ||
1521 | struct clk_domain_3x_fixed *pclk_domain_3x_fixed; | ||
1522 | struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *pset; | ||
1523 | |||
1524 | nvgpu_log_info(g, " "); | ||
1525 | |||
1526 | status = _clk_domain_pmudatainit_3x(g, board_obj_ptr, ppmudata); | ||
1527 | if (status != 0) { | ||
1528 | return status; | ||
1529 | } | ||
1530 | |||
1531 | pclk_domain_3x_fixed = (struct clk_domain_3x_fixed *)board_obj_ptr; | ||
1532 | |||
1533 | pset = (struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set *) | ||
1534 | ppmudata; | ||
1535 | |||
1536 | pset->freq_mhz = pclk_domain_3x_fixed->freq_mhz; | ||
1537 | |||
1538 | return status; | ||
1539 | } | ||
1540 | |||
1541 | static int clk_domain_construct_3x_fixed(struct gk20a *g, | ||
1542 | struct boardobj **ppboardobj, | ||
1543 | u16 size, void *pargs) | ||
1544 | { | ||
1545 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | ||
1546 | struct clk_domain_3x_fixed *pdomain; | ||
1547 | struct clk_domain_3x_fixed *ptmpdomain = | ||
1548 | (struct clk_domain_3x_fixed *)pargs; | ||
1549 | int status = 0; | ||
1550 | |||
1551 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED) { | ||
1552 | return -EINVAL; | ||
1553 | } | ||
1554 | |||
1555 | ptmpobj->type_mask |= BIT(CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED); | ||
1556 | status = clk_domain_construct_3x(g, ppboardobj, size, pargs); | ||
1557 | if (status) { | ||
1558 | return -EINVAL; | ||
1559 | } | ||
1560 | |||
1561 | pdomain = (struct clk_domain_3x_fixed *)*ppboardobj; | ||
1562 | |||
1563 | pdomain->super.super.super.pmudatainit = | ||
1564 | _clk_domain_pmudatainit_3x_fixed; | ||
1565 | |||
1566 | pdomain->super.super.clkdomainclkproglink = | ||
1567 | clkdomainclkproglink_fixed; | ||
1568 | |||
1569 | pdomain->freq_mhz = ptmpdomain->freq_mhz; | ||
1570 | |||
1571 | return status; | ||
1572 | } | ||
1573 | |||
1574 | static struct clk_domain *construct_clk_domain(struct gk20a *g, void *pargs) | ||
1575 | { | ||
1576 | struct boardobj *board_obj_ptr = NULL; | ||
1577 | u32 status; | ||
1578 | |||
1579 | nvgpu_log_info(g, " %d", BOARDOBJ_GET_TYPE(pargs)); | ||
1580 | switch (BOARDOBJ_GET_TYPE(pargs)) { | ||
1581 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED: | ||
1582 | status = clk_domain_construct_3x_fixed(g, &board_obj_ptr, | ||
1583 | sizeof(struct clk_domain_3x_fixed), pargs); | ||
1584 | break; | ||
1585 | |||
1586 | case CTRL_CLK_CLK_DOMAIN_TYPE_35_MASTER: | ||
1587 | status = clk_domain_construct_35_master(g, &board_obj_ptr, | ||
1588 | sizeof(struct clk_domain_35_master), pargs); | ||
1589 | break; | ||
1590 | |||
1591 | |||
1592 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER: | ||
1593 | status = clk_domain_construct_3x_master(g, &board_obj_ptr, | ||
1594 | sizeof(struct clk_domain_3x_master), pargs); | ||
1595 | break; | ||
1596 | |||
1597 | case CTRL_CLK_CLK_DOMAIN_TYPE_35_SLAVE: | ||
1598 | status = clk_domain_construct_35_slave(g, &board_obj_ptr, | ||
1599 | sizeof(struct clk_domain_35_slave), pargs); | ||
1600 | break; | ||
1601 | |||
1602 | case CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE: | ||
1603 | status = clk_domain_construct_3x_slave(g, &board_obj_ptr, | ||
1604 | sizeof(struct clk_domain_3x_slave), pargs); | ||
1605 | break; | ||
1606 | |||
1607 | default: | ||
1608 | return NULL; | ||
1609 | } | ||
1610 | |||
1611 | if (status) { | ||
1612 | return NULL; | ||
1613 | } | ||
1614 | |||
1615 | nvgpu_log_info(g, " Done"); | ||
1616 | |||
1617 | return (struct clk_domain *)board_obj_ptr; | ||
1618 | } | ||
1619 | |||
1620 | static int clk_domain_pmudatainit_super(struct gk20a *g, | ||
1621 | struct boardobj *board_obj_ptr, | ||
1622 | struct nv_pmu_boardobj *ppmudata) | ||
1623 | { | ||
1624 | int status = 0; | ||
1625 | struct clk_domain *pclk_domain; | ||
1626 | struct nv_pmu_clk_clk_domain_boardobj_set *pset; | ||
1627 | |||
1628 | nvgpu_log_info(g, " "); | ||
1629 | |||
1630 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
1631 | if (status != 0) { | ||
1632 | return status; | ||
1633 | } | ||
1634 | |||
1635 | pclk_domain = (struct clk_domain *)board_obj_ptr; | ||
1636 | |||
1637 | pset = (struct nv_pmu_clk_clk_domain_boardobj_set *)ppmudata; | ||
1638 | |||
1639 | pset->domain = pclk_domain->domain; | ||
1640 | pset->api_domain = pclk_domain->api_domain; | ||
1641 | pset->perf_domain_grp_idx = pclk_domain->perf_domain_grp_idx; | ||
1642 | |||
1643 | return status; | ||
1644 | } | ||
1645 | |||
1646 | int clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk) | ||
1647 | { | ||
1648 | int status = 0; | ||
1649 | struct clk_domain *pdomain; | ||
1650 | u8 i; | ||
1651 | |||
1652 | /* Iterate over all CLK_DOMAINs and flatten their VF curves.*/ | ||
1653 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
1654 | struct clk_domain *, pdomain, i) { | ||
1655 | status = pdomain->clkdomainclkproglink(g, pclk, pdomain); | ||
1656 | if (status) { | ||
1657 | nvgpu_err(g, | ||
1658 | "error flattening VF for CLK DOMAIN - 0x%x", | ||
1659 | pdomain->domain); | ||
1660 | goto done; | ||
1661 | } | ||
1662 | } | ||
1663 | |||
1664 | done: | ||
1665 | return status; | ||
1666 | } | ||