diff options
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.c | 136 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.h | 11 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 426 |
3 files changed, 397 insertions, 176 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index bec5fad1..07c80e22 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "volt/volt.h" | 20 | #include "volt/volt.h" |
21 | #include "gk20a/pmu_gk20a.h" | 21 | #include "gk20a/pmu_gk20a.h" |
22 | 22 | ||
23 | #define BOOT_GPC2CLK_MHZ 2581 | ||
23 | #define BOOT_MCLK_MHZ 3003 | 24 | #define BOOT_MCLK_MHZ 3003 |
24 | 25 | ||
25 | struct clkrpc_pmucmdhandler_params { | 26 | struct clkrpc_pmucmdhandler_params { |
@@ -255,7 +256,61 @@ static int get_regime_id(struct gk20a *g, u32 domain, u32 *regimeid) | |||
255 | return -EINVAL; | 256 | return -EINVAL; |
256 | } | 257 | } |
257 | 258 | ||
258 | int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | 259 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) |
260 | { | ||
261 | int status = -EINVAL; | ||
262 | |||
263 | /*set regime ids */ | ||
264 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
265 | &setfllclk->current_regime_id_gpc); | ||
266 | if (status) | ||
267 | goto done; | ||
268 | |||
269 | setfllclk->target_regime_id_gpc = find_regime_id(g, | ||
270 | CTRL_CLK_DOMAIN_GPC2CLK, setfllclk->gpc2clkmhz); | ||
271 | |||
272 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
273 | &setfllclk->current_regime_id_sys); | ||
274 | if (status) | ||
275 | goto done; | ||
276 | |||
277 | setfllclk->target_regime_id_sys = find_regime_id(g, | ||
278 | CTRL_CLK_DOMAIN_SYS2CLK, setfllclk->sys2clkmhz); | ||
279 | |||
280 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
281 | &setfllclk->current_regime_id_xbar); | ||
282 | if (status) | ||
283 | goto done; | ||
284 | |||
285 | setfllclk->target_regime_id_xbar = find_regime_id(g, | ||
286 | CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk->xbar2clkmhz); | ||
287 | |||
288 | status = clk_pmu_vf_inject(g, setfllclk); | ||
289 | |||
290 | if (status) | ||
291 | gk20a_err(dev_from_gk20a(g), | ||
292 | "vf inject to change clk failed"); | ||
293 | |||
294 | /* save regime ids */ | ||
295 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
296 | setfllclk->target_regime_id_xbar); | ||
297 | if (status) | ||
298 | goto done; | ||
299 | |||
300 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
301 | setfllclk->target_regime_id_gpc); | ||
302 | if (status) | ||
303 | goto done; | ||
304 | |||
305 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
306 | setfllclk->target_regime_id_sys); | ||
307 | if (status) | ||
308 | goto done; | ||
309 | done: | ||
310 | return status; | ||
311 | } | ||
312 | |||
313 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *setfllclk) | ||
259 | { | 314 | { |
260 | int status = -EINVAL; | 315 | int status = -EINVAL; |
261 | struct clk_domain *pdomain; | 316 | struct clk_domain *pdomain; |
@@ -265,25 +320,14 @@ int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | |||
265 | struct clk_domain_3x_master *p3xmaster; | 320 | struct clk_domain_3x_master *p3xmaster; |
266 | struct clk_domain_3x_slave *p3xslave; | 321 | struct clk_domain_3x_slave *p3xslave; |
267 | unsigned long slaveidxmask; | 322 | unsigned long slaveidxmask; |
268 | struct set_fll_clk setfllclk; | ||
269 | bool foundxbar2clk = false; | ||
270 | bool foundsys2clk = false; | ||
271 | 323 | ||
272 | memset(&setfllclk, 0, sizeof(setfllclk)); | 324 | if (setfllclk->gpc2clkmhz == 0) |
273 | if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPC2CLK) | ||
274 | return -EINVAL; | ||
275 | if (fllclk->voltuv == 0) | ||
276 | return -EINVAL; | 325 | return -EINVAL; |
277 | if (fllclk->clkmhz == 0) | ||
278 | return -EINVAL; | ||
279 | |||
280 | setfllclk.voltuv = fllclk->voltuv; | ||
281 | setfllclk.gpc2clkmhz = fllclk->clkmhz; | ||
282 | 326 | ||
283 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | 327 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), |
284 | struct clk_domain *, pdomain, i) { | 328 | struct clk_domain *, pdomain, i) { |
285 | 329 | ||
286 | if (pdomain->api_domain == fllclk->api_clk_domain) { | 330 | if (pdomain->api_domain == CTRL_CLK_DOMAIN_GPC2CLK) { |
287 | 331 | ||
288 | if (!pdomain->super.implements(g, &pdomain->super, | 332 | if (!pdomain->super.implements(g, &pdomain->super, |
289 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { | 333 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) { |
@@ -305,74 +349,20 @@ int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk) | |||
305 | pclk, | 349 | pclk, |
306 | (struct clk_domain *)p3xslave, | 350 | (struct clk_domain *)p3xslave, |
307 | &clkmhz, | 351 | &clkmhz, |
308 | fllclk->clkmhz); | 352 | setfllclk->gpc2clkmhz); |
309 | if (status) { | 353 | if (status) { |
310 | status = -EINVAL; | 354 | status = -EINVAL; |
311 | goto done; | 355 | goto done; |
312 | } | 356 | } |
313 | if (p3xslave->super.super.super.api_domain == | 357 | if (p3xslave->super.super.super.api_domain == |
314 | CTRL_CLK_DOMAIN_XBAR2CLK) { | 358 | CTRL_CLK_DOMAIN_XBAR2CLK) |
315 | setfllclk.xbar2clkmhz = clkmhz; | 359 | setfllclk->xbar2clkmhz = clkmhz; |
316 | foundxbar2clk = true; | ||
317 | } | ||
318 | if (p3xslave->super.super.super.api_domain == | 360 | if (p3xslave->super.super.super.api_domain == |
319 | CTRL_CLK_DOMAIN_SYS2CLK) { | 361 | CTRL_CLK_DOMAIN_SYS2CLK) |
320 | setfllclk.sys2clkmhz = clkmhz; | 362 | setfllclk->sys2clkmhz = clkmhz; |
321 | foundsys2clk = true; | ||
322 | } | ||
323 | } | 363 | } |
324 | } | 364 | } |
325 | } | 365 | } |
326 | if (!(foundxbar2clk && foundsys2clk)) { | ||
327 | status = -EINVAL; | ||
328 | goto done; | ||
329 | } | ||
330 | /*set regime ids */ | ||
331 | status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
332 | &setfllclk.current_regime_id_gpc); | ||
333 | if (status) | ||
334 | goto done; | ||
335 | |||
336 | setfllclk.target_regime_id_gpc = find_regime_id(g, | ||
337 | CTRL_CLK_DOMAIN_GPC2CLK, setfllclk.gpc2clkmhz); | ||
338 | |||
339 | status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
340 | &setfllclk.current_regime_id_sys); | ||
341 | if (status) | ||
342 | goto done; | ||
343 | |||
344 | setfllclk.target_regime_id_sys = find_regime_id(g, | ||
345 | CTRL_CLK_DOMAIN_SYS2CLK, setfllclk.sys2clkmhz); | ||
346 | |||
347 | status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
348 | &setfllclk.current_regime_id_xbar); | ||
349 | if (status) | ||
350 | goto done; | ||
351 | |||
352 | setfllclk.target_regime_id_xbar = find_regime_id(g, | ||
353 | CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk.xbar2clkmhz); | ||
354 | |||
355 | status = clk_pmu_vf_inject(g, &setfllclk); | ||
356 | |||
357 | if (status) | ||
358 | gk20a_err(dev_from_gk20a(g), | ||
359 | "vf inject to change clk failed"); | ||
360 | |||
361 | /* save regime ids */ | ||
362 | status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK, | ||
363 | setfllclk.target_regime_id_xbar); | ||
364 | if (status) | ||
365 | goto done; | ||
366 | |||
367 | status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
368 | setfllclk.target_regime_id_gpc); | ||
369 | if (status) | ||
370 | goto done; | ||
371 | |||
372 | status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK, | ||
373 | setfllclk.target_regime_id_sys); | ||
374 | if (status) | ||
375 | goto done; | ||
376 | done: | 366 | done: |
377 | return status; | 367 | return status; |
378 | } | 368 | } |
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h index d0e82173..42cb9f7d 100644 --- a/drivers/gpu/nvgpu/clk/clk.h +++ b/drivers/gpu/nvgpu/clk/clk.h | |||
@@ -35,7 +35,6 @@ struct clk_pmupstate { | |||
35 | struct clk_progs clk_progobjs; | 35 | struct clk_progs clk_progobjs; |
36 | struct clk_vf_points clk_vf_pointobjs; | 36 | struct clk_vf_points clk_vf_pointobjs; |
37 | struct clk_mclk_state clk_mclk; | 37 | struct clk_mclk_state clk_mclk; |
38 | struct mutex changeclkmutex; | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | struct clockentry { | 40 | struct clockentry { |
@@ -45,12 +44,6 @@ struct clockentry { | |||
45 | u32 api_clk_domain; | 44 | u32 api_clk_domain; |
46 | }; | 45 | }; |
47 | 46 | ||
48 | struct change_fll_clk { | ||
49 | u32 api_clk_domain; | ||
50 | u16 clkmhz; | ||
51 | u32 voltuv; | ||
52 | }; | ||
53 | |||
54 | struct set_fll_clk { | 47 | struct set_fll_clk { |
55 | u32 voltuv; | 48 | u32 voltuv; |
56 | u16 gpc2clkmhz; | 49 | u16 gpc2clkmhz; |
@@ -119,5 +112,7 @@ u32 clk_domain_get_f_points( | |||
119 | u32 *fpointscount, | 112 | u32 *fpointscount, |
120 | u16 *freqpointsinmhz | 113 | u16 *freqpointsinmhz |
121 | ); | 114 | ); |
122 | int clk_program_fll_clks(struct gk20a *g, struct change_fll_clk *fllclk); | 115 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); |
116 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); | ||
117 | |||
123 | #endif | 118 | #endif |
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index f3d6cfab..b816a570 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c | |||
@@ -41,14 +41,32 @@ static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work); | |||
41 | static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb); | 41 | static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb); |
42 | static void nvgpu_clk_arb_free_fd(struct kref *refcount); | 42 | static void nvgpu_clk_arb_free_fd(struct kref *refcount); |
43 | static void nvgpu_clk_arb_free_session(struct kref *refcount); | 43 | static void nvgpu_clk_arb_free_session(struct kref *refcount); |
44 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk, | 44 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, |
45 | u16 mclk, u32 voltuv, u32 voltuv_sram); | 45 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, |
46 | static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | 46 | u32 voltuv_sram); |
47 | u16 *gpc2clk_target, u16 *mclk_target, u32 *voltuv, | 47 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, |
48 | u32 *voltuv_sram); | 48 | u16 *gpc2clk_target, u16 *sys2clk_target, u16 *xbar2clk_target, |
49 | u16 *mclk_target, u32 *voltuv, u32 *voltuv_sram); | ||
50 | |||
51 | #define VF_POINT_INVALID_PSTATE ~0U | ||
52 | #define VF_POINT_SET_PSTATE_SUPPORTED(a, b) ((a)->pstates |= (1UL << (b))) | ||
53 | #define VF_POINT_GET_PSTATE(a) (((a)->pstates) ?\ | ||
54 | __fls((a)->pstates) :\ | ||
55 | VF_POINT_INVALID_PSTATE) | ||
56 | #define VF_POINT_COMMON_PSTATE(a, b) (((a)->pstates & (b)->pstates) ?\ | ||
57 | __fls((a)->pstates & (b)->pstates) :\ | ||
58 | VF_POINT_INVALID_PSTATE) | ||
49 | 59 | ||
50 | struct nvgpu_clk_vf_point { | 60 | struct nvgpu_clk_vf_point { |
51 | u16 mhz; | 61 | u16 pstates; |
62 | union { | ||
63 | struct { | ||
64 | u16 gpc_mhz; | ||
65 | u16 sys_mhz; | ||
66 | u16 xbar_mhz; | ||
67 | }; | ||
68 | u16 mem_mhz; | ||
69 | }; | ||
52 | u32 uvolt; | 70 | u32 uvolt; |
53 | u32 uvolt_sram; | 71 | u32 uvolt_sram; |
54 | }; | 72 | }; |
@@ -72,6 +90,7 @@ struct nvgpu_clk_arb_debug { | |||
72 | struct nvgpu_clk_arb_target { | 90 | struct nvgpu_clk_arb_target { |
73 | u16 mclk; | 91 | u16 mclk; |
74 | u16 gpc2clk; | 92 | u16 gpc2clk; |
93 | u32 pstate; | ||
75 | }; | 94 | }; |
76 | 95 | ||
77 | struct nvgpu_clk_arb { | 96 | struct nvgpu_clk_arb { |
@@ -362,9 +381,12 @@ int nvgpu_clk_arb_init_session(struct gk20a *g, | |||
362 | kref_init(&session->refcount); | 381 | kref_init(&session->refcount); |
363 | 382 | ||
364 | session->zombie = false; | 383 | session->zombie = false; |
384 | session->target_pool[0].pstate = CTRL_PERF_PSTATE_P8; | ||
385 | /* make sure that the initialization of the pool is visible | ||
386 | * before the update */ | ||
387 | smp_wmb(); | ||
365 | session->target = &session->target_pool[0]; | 388 | session->target = &session->target_pool[0]; |
366 | session->target->mclk = arb->mclk_default_mhz; | 389 | |
367 | session->target->gpc2clk = arb->gpc2clk_default_mhz; | ||
368 | init_llist_head(&session->targets); | 390 | init_llist_head(&session->targets); |
369 | 391 | ||
370 | spin_lock(&arb->sessions_lock); | 392 | spin_lock(&arb->sessions_lock); |
@@ -464,13 +486,15 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
464 | struct nvgpu_clk_vf_table *table; | 486 | struct nvgpu_clk_vf_table *table; |
465 | 487 | ||
466 | u32 i, j; | 488 | u32 i, j; |
467 | int status = 0; | 489 | int status = -EINVAL; |
468 | u32 gpc2clk_voltuv = 0, mclk_voltuv = 0; | 490 | u32 gpc2clk_voltuv = 0, mclk_voltuv = 0; |
469 | u32 gpc2clk_voltuv_sram = 0, mclk_voltuv_sram = 0; | 491 | u32 gpc2clk_voltuv_sram = 0, mclk_voltuv_sram = 0; |
470 | u16 gpc2clk_min, gpc2clk_max, clk_cur; | 492 | u16 gpc2clk_min, gpc2clk_max, clk_cur; |
471 | u16 mclk_min, mclk_max; | 493 | u16 mclk_min, mclk_max; |
472 | u32 num_points; | 494 | u32 num_points; |
473 | 495 | ||
496 | struct clk_set_info *p5_info, *p0_info; | ||
497 | |||
474 | table = ACCESS_ONCE(arb->current_vf_table); | 498 | table = ACCESS_ONCE(arb->current_vf_table); |
475 | /* make flag visible when all data has resolved in the tables */ | 499 | /* make flag visible when all data has resolved in the tables */ |
476 | smp_rmb(); | 500 | smp_rmb(); |
@@ -504,17 +528,28 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
504 | memset(table->gpc2clk_points, 0, | 528 | memset(table->gpc2clk_points, 0, |
505 | table->gpc2clk_num_points*sizeof(struct nvgpu_clk_vf_point)); | 529 | table->gpc2clk_num_points*sizeof(struct nvgpu_clk_vf_point)); |
506 | 530 | ||
531 | p5_info = pstate_get_clk_set_info(g, | ||
532 | CTRL_PERF_PSTATE_P5, clkwhich_mclk); | ||
533 | if (!p5_info) | ||
534 | goto exit_vf_table; | ||
535 | |||
536 | p0_info = pstate_get_clk_set_info(g, | ||
537 | CTRL_PERF_PSTATE_P0, clkwhich_mclk); | ||
538 | if (!p0_info) | ||
539 | goto exit_vf_table; | ||
540 | |||
507 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; | 541 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; |
508 | i < table->mclk_num_points; i++) { | 542 | i < table->mclk_num_points; i++) { |
543 | |||
509 | if ((arb->mclk_f_points[i] >= mclk_min) && | 544 | if ((arb->mclk_f_points[i] >= mclk_min) && |
510 | (arb->mclk_f_points[i] <= mclk_max) && | 545 | (arb->mclk_f_points[i] <= mclk_max) && |
511 | (arb->mclk_f_points[i] != clk_cur)) { | 546 | (arb->mclk_f_points[i] != clk_cur)) { |
512 | 547 | ||
513 | table->mclk_points[j].mhz = arb->mclk_f_points[i]; | 548 | table->mclk_points[j].mem_mhz = arb->mclk_f_points[i]; |
514 | mclk_voltuv = mclk_voltuv_sram = 0; | 549 | mclk_voltuv = mclk_voltuv_sram = 0; |
515 | 550 | ||
516 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, | 551 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, |
517 | &table->mclk_points[j].mhz, &mclk_voltuv, | 552 | &table->mclk_points[j].mem_mhz, &mclk_voltuv, |
518 | CTRL_VOLT_DOMAIN_LOGIC); | 553 | CTRL_VOLT_DOMAIN_LOGIC); |
519 | if (status < 0) { | 554 | if (status < 0) { |
520 | gk20a_err(dev_from_gk20a(g), | 555 | gk20a_err(dev_from_gk20a(g), |
@@ -522,7 +557,8 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
522 | goto exit_vf_table; | 557 | goto exit_vf_table; |
523 | } | 558 | } |
524 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, | 559 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_MCLK, |
525 | &table->mclk_points[j].mhz, &mclk_voltuv_sram, | 560 | &table->mclk_points[j].mem_mhz, |
561 | &mclk_voltuv_sram, | ||
526 | CTRL_VOLT_DOMAIN_SRAM); | 562 | CTRL_VOLT_DOMAIN_SRAM); |
527 | if (status < 0) { | 563 | if (status < 0) { |
528 | gk20a_err(dev_from_gk20a(g), | 564 | gk20a_err(dev_from_gk20a(g), |
@@ -532,7 +568,19 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
532 | 568 | ||
533 | table->mclk_points[j].uvolt = mclk_voltuv; | 569 | table->mclk_points[j].uvolt = mclk_voltuv; |
534 | table->mclk_points[j].uvolt_sram = mclk_voltuv_sram; | 570 | table->mclk_points[j].uvolt_sram = mclk_voltuv_sram; |
535 | clk_cur = table->mclk_points[j].mhz; | 571 | clk_cur = table->mclk_points[j].mem_mhz; |
572 | |||
573 | if ((clk_cur >= p5_info->min_mhz) && | ||
574 | (clk_cur <= p5_info->max_mhz)) | ||
575 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
576 | &table->mclk_points[j], | ||
577 | CTRL_PERF_PSTATE_P5); | ||
578 | if ((clk_cur >= p0_info->min_mhz) && | ||
579 | (clk_cur <= p0_info->max_mhz)) | ||
580 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
581 | &table->mclk_points[j], | ||
582 | CTRL_PERF_PSTATE_P0); | ||
583 | |||
536 | j++; | 584 | j++; |
537 | num_points++; | 585 | num_points++; |
538 | 586 | ||
@@ -540,45 +588,187 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
540 | } | 588 | } |
541 | table->mclk_num_points = num_points; | 589 | table->mclk_num_points = num_points; |
542 | 590 | ||
591 | p5_info = pstate_get_clk_set_info(g, | ||
592 | CTRL_PERF_PSTATE_P5, clkwhich_gpc2clk); | ||
593 | if (!p5_info) { | ||
594 | status = -EINVAL; | ||
595 | goto exit_vf_table; | ||
596 | } | ||
597 | |||
598 | p0_info = pstate_get_clk_set_info(g, | ||
599 | CTRL_PERF_PSTATE_P0, clkwhich_gpc2clk); | ||
600 | if (!p0_info) { | ||
601 | status = -EINVAL; | ||
602 | goto exit_vf_table; | ||
603 | } | ||
604 | |||
605 | /* GPC2CLK needs to be checked in two passes. The first determines the | ||
606 | * relationships between GPC2CLK, SYS2CLK and XBAR2CLK, while the | ||
607 | * second verifies that the clocks minimum DVCO is satisfied and sets | ||
608 | * the voltages | ||
609 | */ | ||
543 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; | 610 | for (i = 0, j = 0, num_points = 0, clk_cur = 0; |
544 | i < table->gpc2clk_num_points; i++) { | 611 | i < table->gpc2clk_num_points; i++) { |
612 | struct set_fll_clk setfllclk; | ||
613 | |||
545 | if ((arb->gpc2clk_f_points[i] >= gpc2clk_min) && | 614 | if ((arb->gpc2clk_f_points[i] >= gpc2clk_min) && |
546 | (arb->gpc2clk_f_points[i] <= gpc2clk_max) && | 615 | (arb->gpc2clk_f_points[i] <= gpc2clk_max) && |
547 | (arb->gpc2clk_f_points[i] != clk_cur)) { | 616 | (arb->gpc2clk_f_points[i] != clk_cur)) { |
548 | 617 | ||
549 | table->gpc2clk_points[j].mhz = arb->gpc2clk_f_points[i]; | 618 | table->gpc2clk_points[j].gpc_mhz = |
550 | gpc2clk_voltuv = gpc2clk_voltuv_sram = 0; | 619 | arb->gpc2clk_f_points[i]; |
551 | 620 | ||
552 | status = clk_domain_get_f_or_v(g, | 621 | setfllclk.gpc2clkmhz = arb->gpc2clk_f_points[i]; |
553 | CTRL_CLK_DOMAIN_GPC2CLK, | 622 | status = clk_get_fll_clks(g, &setfllclk); |
554 | &table->gpc2clk_points[j].mhz, &gpc2clk_voltuv, | ||
555 | CTRL_VOLT_DOMAIN_LOGIC); | ||
556 | if (status < 0) { | 623 | if (status < 0) { |
557 | gk20a_err(dev_from_gk20a(g), | 624 | gk20a_err(dev_from_gk20a(g), |
558 | "failed to get GPC2CLK LOGIC voltage"); | 625 | "failed to get GPC2CLK slave clocks"); |
559 | goto exit_vf_table; | 626 | goto exit_vf_table; |
560 | } | 627 | } |
561 | 628 | ||
562 | status = clk_domain_get_f_or_v(g, | 629 | |
563 | CTRL_CLK_DOMAIN_GPC2CLK, | 630 | table->gpc2clk_points[j].sys_mhz = |
564 | &table->gpc2clk_points[j].mhz, | 631 | setfllclk.sys2clkmhz; |
565 | &gpc2clk_voltuv_sram, | 632 | table->gpc2clk_points[j].xbar_mhz = |
566 | CTRL_VOLT_DOMAIN_SRAM); | 633 | setfllclk.xbar2clkmhz; |
634 | |||
635 | clk_cur = table->gpc2clk_points[j].gpc_mhz; | ||
636 | |||
637 | if ((clk_cur >= p5_info->min_mhz) && | ||
638 | (clk_cur <= p5_info->max_mhz)) | ||
639 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
640 | &table->gpc2clk_points[j], | ||
641 | CTRL_PERF_PSTATE_P5); | ||
642 | if ((clk_cur >= p0_info->min_mhz) && | ||
643 | (clk_cur <= p0_info->max_mhz)) | ||
644 | VF_POINT_SET_PSTATE_SUPPORTED( | ||
645 | &table->gpc2clk_points[j], | ||
646 | CTRL_PERF_PSTATE_P0); | ||
647 | |||
648 | j++; | ||
649 | num_points++; | ||
650 | } | ||
651 | } | ||
652 | table->gpc2clk_num_points = num_points; | ||
653 | |||
654 | /* Second pass */ | ||
655 | for (i = 0, j = 0; i < table->gpc2clk_num_points; i++) { | ||
656 | struct set_fll_clk setfllclk; | ||
657 | |||
658 | u16 alt_gpc2clk = table->gpc2clk_points[i].gpc_mhz; | ||
659 | gpc2clk_voltuv = gpc2clk_voltuv_sram = 0; | ||
660 | |||
661 | /* Check sysclk */ | ||
662 | p5_info = pstate_get_clk_set_info(g, | ||
663 | VF_POINT_GET_PSTATE(&table->gpc2clk_points[i]), | ||
664 | clkwhich_sys2clk); | ||
665 | if (!p5_info) { | ||
666 | status = -EINVAL; | ||
667 | goto exit_vf_table; | ||
668 | } | ||
669 | /* sys2clk below DVCO min, need to find correct clock */ | ||
670 | if (table->gpc2clk_points[i].sys_mhz < p5_info->min_mhz) { | ||
671 | for (j = i + 1; j < table->gpc2clk_num_points; j++) { | ||
672 | |||
673 | if (table->gpc2clk_points[j].sys_mhz >= | ||
674 | p5_info->min_mhz) { | ||
675 | |||
676 | table->gpc2clk_points[i].sys_mhz = | ||
677 | table->gpc2clk_points[j]. | ||
678 | sys_mhz; | ||
679 | |||
680 | alt_gpc2clk = alt_gpc2clk < | ||
681 | table->gpc2clk_points[j]. | ||
682 | gpc_mhz ? | ||
683 | table->gpc2clk_points[j]. | ||
684 | gpc_mhz: | ||
685 | alt_gpc2clk; | ||
686 | break; | ||
687 | } | ||
688 | } | ||
689 | /* no VF exists that satisfies condition */ | ||
690 | if (j == table->gpc2clk_num_points) { | ||
691 | status = -EINVAL; | ||
692 | goto exit_vf_table; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* Check xbarclk */ | ||
697 | p5_info = pstate_get_clk_set_info(g, | ||
698 | VF_POINT_GET_PSTATE(&table->gpc2clk_points[i]), | ||
699 | clkwhich_xbar2clk); | ||
700 | if (!p5_info) { | ||
701 | status = -EINVAL; | ||
702 | goto exit_vf_table; | ||
703 | } | ||
704 | |||
705 | /* xbar2clk below DVCO min, need to find correct clock */ | ||
706 | if (table->gpc2clk_points[i].xbar_mhz < p5_info->min_mhz) { | ||
707 | for (j = i; j < table->gpc2clk_num_points; j++) { | ||
708 | if (table->gpc2clk_points[j].xbar_mhz >= | ||
709 | p5_info->min_mhz) { | ||
710 | |||
711 | table->gpc2clk_points[i].xbar_mhz = | ||
712 | table->gpc2clk_points[j]. | ||
713 | xbar_mhz; | ||
714 | alt_gpc2clk = alt_gpc2clk < | ||
715 | table->gpc2clk_points[j]. | ||
716 | gpc_mhz ? | ||
717 | table->gpc2clk_points[j]. | ||
718 | gpc_mhz: | ||
719 | alt_gpc2clk; | ||
720 | break; | ||
721 | } | ||
722 | } | ||
723 | /* no VF exists that satisfies condition */ | ||
724 | if (j == table->gpc2clk_num_points) { | ||
725 | status = -EINVAL; | ||
726 | |||
727 | goto exit_vf_table; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /* alternate gpc2clk clock has been requested, we need to | ||
732 | * calculate new ratios */ | ||
733 | if (alt_gpc2clk != table->gpc2clk_points[i].gpc_mhz) { | ||
734 | setfllclk.gpc2clkmhz = alt_gpc2clk; | ||
735 | |||
736 | status = clk_get_fll_clks(g, &setfllclk); | ||
567 | if (status < 0) { | 737 | if (status < 0) { |
568 | gk20a_err(dev_from_gk20a(g), | 738 | gk20a_err(dev_from_gk20a(g), |
569 | "failed to get GPC2CLK SRAM voltage"); | 739 | "failed to get GPC2CLK slave clocks"); |
570 | goto exit_vf_table; | 740 | goto exit_vf_table; |
571 | } | 741 | } |
572 | 742 | ||
573 | table->gpc2clk_points[j].uvolt = gpc2clk_voltuv; | 743 | table->gpc2clk_points[i].sys_mhz = |
574 | table->gpc2clk_points[j].uvolt_sram = | 744 | setfllclk.sys2clkmhz; |
575 | gpc2clk_voltuv_sram; | 745 | table->gpc2clk_points[i].xbar_mhz = |
576 | clk_cur = table->gpc2clk_points[j].mhz; | 746 | setfllclk.xbar2clkmhz; |
577 | j++; | 747 | } |
578 | num_points++; | 748 | |
749 | /* Calculate voltages */ | ||
750 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
751 | &alt_gpc2clk, &gpc2clk_voltuv, | ||
752 | CTRL_VOLT_DOMAIN_LOGIC); | ||
753 | if (status < 0) { | ||
754 | gk20a_err(dev_from_gk20a(g), | ||
755 | "failed to get GPC2CLK LOGIC voltage"); | ||
756 | goto exit_vf_table; | ||
757 | } | ||
758 | |||
759 | status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPC2CLK, | ||
760 | &alt_gpc2clk, | ||
761 | &gpc2clk_voltuv_sram, | ||
762 | CTRL_VOLT_DOMAIN_SRAM); | ||
763 | if (status < 0) { | ||
764 | gk20a_err(dev_from_gk20a(g), | ||
765 | "failed to get GPC2CLK SRAM voltage"); | ||
766 | goto exit_vf_table; | ||
579 | } | 767 | } |
768 | |||
769 | table->gpc2clk_points[i].uvolt = gpc2clk_voltuv; | ||
770 | table->gpc2clk_points[i].uvolt_sram = gpc2clk_voltuv_sram; | ||
580 | } | 771 | } |
581 | table->gpc2clk_num_points = num_points; | ||
582 | 772 | ||
583 | /* make table visible when all data has resolved in the tables */ | 773 | /* make table visible when all data has resolved in the tables */ |
584 | smp_wmb(); | 774 | smp_wmb(); |
@@ -625,13 +815,14 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
625 | struct gk20a *g = arb->g; | 815 | struct gk20a *g = arb->g; |
626 | struct llist_node *head; | 816 | struct llist_node *head; |
627 | 817 | ||
818 | u32 pstate = VF_POINT_INVALID_PSTATE; | ||
628 | u32 voltuv, voltuv_sram; | 819 | u32 voltuv, voltuv_sram; |
629 | bool mclk_set, gpc2clk_set; | 820 | bool mclk_set, gpc2clk_set; |
630 | 821 | ||
631 | int status = 0; | 822 | int status = 0; |
632 | 823 | ||
633 | /* Temporary variables for checking target frequency */ | 824 | /* Temporary variables for checking target frequency */ |
634 | u16 gpc2clk_target, mclk_target; | 825 | u16 gpc2clk_target, sys2clk_target, xbar2clk_target, mclk_target; |
635 | 826 | ||
636 | #ifdef CONFIG_DEBUG_FS | 827 | #ifdef CONFIG_DEBUG_FS |
637 | u64 t0, t1; | 828 | u64 t0, t1; |
@@ -699,29 +890,25 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
699 | rcu_read_unlock(); | 890 | rcu_read_unlock(); |
700 | 891 | ||
701 | gpc2clk_target = (gpc2clk_target > 0) ? gpc2clk_target : | 892 | gpc2clk_target = (gpc2clk_target > 0) ? gpc2clk_target : |
702 | arb->actual->gpc2clk ? gpc2clk_target : | 893 | arb->gpc2clk_default_mhz; |
703 | arb->gpc2clk_default_mhz; | ||
704 | |||
705 | mclk_target = (mclk_target > 0) ? mclk_target : | ||
706 | arb->actual->mclk ? mclk_target : | ||
707 | arb->mclk_default_mhz; | ||
708 | |||
709 | if (!gpc2clk_target && !mclk_target) { | ||
710 | mclk_target = arb->mclk_default_mhz; | ||
711 | gpc2clk_target = arb->gpc2clk_default_mhz; | ||
712 | } | ||
713 | |||
714 | if (!gpc2clk_target) | ||
715 | gpc2clk_target = arb->actual->mclk; | ||
716 | |||
717 | if (!mclk_target) | ||
718 | mclk_target = arb->actual->mclk; | ||
719 | 894 | ||
895 | mclk_target = (mclk_target > 0) ? mclk_target: | ||
896 | arb->mclk_default_mhz; | ||
720 | 897 | ||
898 | sys2clk_target = 0; | ||
899 | xbar2clk_target = 0; | ||
721 | /* Query the table for the closest vf point to program */ | 900 | /* Query the table for the closest vf point to program */ |
722 | nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target, &mclk_target, &voltuv, | 901 | pstate = nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target, |
902 | &sys2clk_target, &xbar2clk_target, &mclk_target, &voltuv, | ||
723 | &voltuv_sram); | 903 | &voltuv_sram); |
724 | 904 | ||
905 | if (pstate == VF_POINT_INVALID_PSTATE) { | ||
906 | arb->status = -EINVAL; | ||
907 | /* make status visible */ | ||
908 | smp_mb(); | ||
909 | goto exit_arb; | ||
910 | } | ||
911 | |||
725 | if ((arb->actual->gpc2clk == gpc2clk_target) && | 912 | if ((arb->actual->gpc2clk == gpc2clk_target) && |
726 | (arb->actual->mclk == mclk_target) && | 913 | (arb->actual->mclk == mclk_target) && |
727 | (arb->voltuv_actual == voltuv)) { | 914 | (arb->voltuv_actual == voltuv)) { |
@@ -731,12 +918,17 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
731 | /* Program clocks */ | 918 | /* Program clocks */ |
732 | /* A change in both mclk of gpc2clk may require a change in voltage */ | 919 | /* A change in both mclk of gpc2clk may require a change in voltage */ |
733 | 920 | ||
734 | status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target, mclk_target, | 921 | status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target, |
735 | voltuv, voltuv_sram); | 922 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, |
923 | voltuv_sram); | ||
736 | 924 | ||
737 | if (status < 0) | 925 | if (status < 0) { |
738 | goto exit_arb; | 926 | arb->status = status; |
927 | /* make status visible */ | ||
928 | smp_mb(); | ||
739 | 929 | ||
930 | goto exit_arb; | ||
931 | } | ||
740 | actual = ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ? | 932 | actual = ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ? |
741 | &arb->actual_pool[1] : &arb->actual_pool[0]; | 933 | &arb->actual_pool[1] : &arb->actual_pool[0]; |
742 | 934 | ||
@@ -745,6 +937,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
745 | actual->gpc2clk = gpc2clk_target; | 937 | actual->gpc2clk = gpc2clk_target; |
746 | actual->mclk = mclk_target; | 938 | actual->mclk = mclk_target; |
747 | arb->voltuv_actual = voltuv; | 939 | arb->voltuv_actual = voltuv; |
940 | actual->pstate = pstate; | ||
748 | arb->status = status; | 941 | arb->status = status; |
749 | 942 | ||
750 | /* Make changes visible to other threads */ | 943 | /* Make changes visible to other threads */ |
@@ -1015,15 +1208,17 @@ int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, | |||
1015 | return (int)clk_domain_get_f_points(g, api_domain, max_points, fpoints); | 1208 | return (int)clk_domain_get_f_points(g, api_domain, max_points, fpoints); |
1016 | } | 1209 | } |
1017 | 1210 | ||
1018 | static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | 1211 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, |
1019 | u16 *gpc2clk, u16 *mclk, u32 *voltuv, | 1212 | u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk, |
1020 | u32 *voltuv_sram) | 1213 | u32 *voltuv, u32 *voltuv_sram) |
1021 | { | 1214 | { |
1022 | u16 gpc2clk_target, mclk_target; | 1215 | u16 gpc2clk_target, mclk_target; |
1023 | u32 gpc2clk_voltuv, gpc2clk_voltuv_sram; | 1216 | u32 gpc2clk_voltuv, gpc2clk_voltuv_sram; |
1024 | u32 mclk_voltuv, mclk_voltuv_sram; | 1217 | u32 mclk_voltuv, mclk_voltuv_sram; |
1218 | u32 pstate = VF_POINT_INVALID_PSTATE; | ||
1025 | struct nvgpu_clk_vf_table *table; | 1219 | struct nvgpu_clk_vf_table *table; |
1026 | u32 index; | 1220 | u32 index, index_mclk; |
1221 | struct nvgpu_clk_vf_point *mclk_vf = NULL; | ||
1027 | 1222 | ||
1028 | do { | 1223 | do { |
1029 | gpc2clk_target = *gpc2clk; | 1224 | gpc2clk_target = *gpc2clk; |
@@ -1042,12 +1237,39 @@ static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | |||
1042 | if ((!table->gpc2clk_num_points) || (!table->mclk_num_points)) | 1237 | if ((!table->gpc2clk_num_points) || (!table->mclk_num_points)) |
1043 | goto find_exit; | 1238 | goto find_exit; |
1044 | 1239 | ||
1240 | /* First we check MCLK to find out which PSTATE we are | ||
1241 | * are requesting, and from there try to find the minimum | ||
1242 | * GPC2CLK on the same PSTATE that satisfies the request. | ||
1243 | * If no GPC2CLK can be found, then we need to up the PSTATE | ||
1244 | */ | ||
1245 | |||
1246 | recalculate_vf_point: | ||
1247 | for (index = 0; index < table->mclk_num_points; index++) { | ||
1248 | if (table->mclk_points[index].mem_mhz >= mclk_target) { | ||
1249 | mclk_vf = &table->mclk_points[index]; | ||
1250 | break; | ||
1251 | } | ||
1252 | } | ||
1253 | if (index == table->mclk_num_points) { | ||
1254 | mclk_vf = &table->mclk_points[index-1]; | ||
1255 | } | ||
1256 | index_mclk = index; | ||
1257 | |||
1045 | /* round up the freq requests */ | 1258 | /* round up the freq requests */ |
1046 | for (index = 0; index < table->gpc2clk_num_points; index++) { | 1259 | for (index = 0; index < table->gpc2clk_num_points; index++) { |
1047 | if (table->gpc2clk_points[index].mhz >= | 1260 | pstate = VF_POINT_COMMON_PSTATE( |
1048 | gpc2clk_target) { | 1261 | &table->gpc2clk_points[index], mclk_vf); |
1262 | |||
1263 | if ((table->gpc2clk_points[index].gpc_mhz >= | ||
1264 | gpc2clk_target) && | ||
1265 | (pstate != VF_POINT_INVALID_PSTATE)){ | ||
1049 | gpc2clk_target = | 1266 | gpc2clk_target = |
1050 | table->gpc2clk_points[index].mhz; | 1267 | table->gpc2clk_points[index].gpc_mhz; |
1268 | *sys2clk = | ||
1269 | table->gpc2clk_points[index].sys_mhz; | ||
1270 | *xbar2clk = | ||
1271 | table->gpc2clk_points[index].xbar_mhz; | ||
1272 | |||
1051 | gpc2clk_voltuv = | 1273 | gpc2clk_voltuv = |
1052 | table->gpc2clk_points[index].uvolt; | 1274 | table->gpc2clk_points[index].uvolt; |
1053 | gpc2clk_voltuv_sram = | 1275 | gpc2clk_voltuv_sram = |
@@ -1057,27 +1279,42 @@ static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | |||
1057 | } | 1279 | } |
1058 | 1280 | ||
1059 | if (index == table->gpc2clk_num_points) { | 1281 | if (index == table->gpc2clk_num_points) { |
1060 | gpc2clk_target = table->gpc2clk_points[index-1].mhz; | 1282 | pstate = VF_POINT_COMMON_PSTATE( |
1061 | gpc2clk_voltuv = table->gpc2clk_points[index-1].uvolt; | 1283 | &table->gpc2clk_points[index-1], mclk_vf); |
1062 | gpc2clk_voltuv_sram = | 1284 | if (pstate != VF_POINT_INVALID_PSTATE) { |
1063 | table->gpc2clk_points[index-1].uvolt_sram; | 1285 | gpc2clk_target = |
1064 | } | 1286 | table->gpc2clk_points[index-1].gpc_mhz; |
1287 | *sys2clk = | ||
1288 | table->gpc2clk_points[index-1].sys_mhz; | ||
1289 | *xbar2clk = | ||
1290 | table->gpc2clk_points[index-1].xbar_mhz; | ||
1065 | 1291 | ||
1066 | for (index = 0; index < table->mclk_num_points; index++) { | 1292 | gpc2clk_voltuv = |
1067 | if (table->mclk_points[index].mhz >= mclk_target) { | 1293 | table->gpc2clk_points[index-1].uvolt; |
1068 | mclk_target = table->mclk_points[index].mhz; | 1294 | gpc2clk_voltuv_sram = |
1069 | mclk_voltuv = table->mclk_points[index].uvolt; | 1295 | table->gpc2clk_points[index-1]. |
1070 | mclk_voltuv_sram = | 1296 | uvolt_sram; |
1071 | table->mclk_points[index].uvolt_sram; | 1297 | } else if (index_mclk == table->mclk_num_points - 1) { |
1072 | break; | 1298 | /* There is no available combination of MCLK |
1299 | * and GPC2CLK, we need to fail this | ||
1300 | */ | ||
1301 | gpc2clk_target = 0; | ||
1302 | mclk_target = 0; | ||
1303 | pstate = VF_POINT_INVALID_PSTATE; | ||
1304 | goto find_exit; | ||
1305 | } else { | ||
1306 | /* recalculate with higher PSTATE */ | ||
1307 | gpc2clk_target = *gpc2clk; | ||
1308 | mclk_target = table->mclk_points[index_mclk+1]. | ||
1309 | mem_mhz; | ||
1310 | goto recalculate_vf_point; | ||
1073 | } | 1311 | } |
1074 | } | 1312 | } |
1075 | if (index == table->mclk_num_points) { | 1313 | |
1076 | mclk_target = table->mclk_points[index-1].mhz; | 1314 | mclk_target = mclk_vf->mem_mhz; |
1077 | mclk_voltuv = table->mclk_points[index-1].uvolt; | 1315 | mclk_voltuv = mclk_vf->uvolt; |
1078 | mclk_voltuv_sram = | 1316 | mclk_voltuv_sram = mclk_vf->uvolt_sram; |
1079 | table->mclk_points[index-1].uvolt_sram; | 1317 | |
1080 | } | ||
1081 | } while (!table || | 1318 | } while (!table || |
1082 | (ACCESS_ONCE(arb->current_vf_table) != table)); | 1319 | (ACCESS_ONCE(arb->current_vf_table) != table)); |
1083 | 1320 | ||
@@ -1088,15 +1325,23 @@ find_exit: | |||
1088 | 1325 | ||
1089 | *gpc2clk = gpc2clk_target; | 1326 | *gpc2clk = gpc2clk_target; |
1090 | *mclk = mclk_target; | 1327 | *mclk = mclk_target; |
1328 | return pstate; | ||
1091 | } | 1329 | } |
1092 | 1330 | ||
1093 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | 1331 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, |
1094 | u16 mclk_target, u32 voltuv, u32 voltuv_sram) | 1332 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, |
1333 | u32 voltuv_sram) | ||
1095 | { | 1334 | { |
1096 | struct change_fll_clk fllclk; | 1335 | struct set_fll_clk fllclk; |
1097 | struct nvgpu_clk_arb *arb = g->clk_arb; | 1336 | struct nvgpu_clk_arb *arb = g->clk_arb; |
1098 | int status; | 1337 | int status; |
1099 | 1338 | ||
1339 | fllclk.gpc2clkmhz = gpc2clk_target; | ||
1340 | fllclk.sys2clkmhz = sys2clk_target; | ||
1341 | fllclk.xbar2clkmhz = xbar2clk_target; | ||
1342 | |||
1343 | fllclk.voltuv = voltuv; | ||
1344 | |||
1100 | /* if voltage ascends we do: | 1345 | /* if voltage ascends we do: |
1101 | * (1) FLL change | 1346 | * (1) FLL change |
1102 | * (2) Voltage change | 1347 | * (2) Voltage change |
@@ -1117,17 +1362,11 @@ static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | |||
1117 | if (status < 0) | 1362 | if (status < 0) |
1118 | return status; | 1363 | return status; |
1119 | 1364 | ||
1120 | fllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; | 1365 | status = clk_set_fll_clks(g, &fllclk); |
1121 | fllclk.clkmhz = gpc2clk_target; | ||
1122 | fllclk.voltuv = voltuv; | ||
1123 | status = clk_program_fll_clks(g, &fllclk); | ||
1124 | if (status < 0) | 1366 | if (status < 0) |
1125 | return status; | 1367 | return status; |
1126 | } else if (voltuv > arb->voltuv_actual) { | 1368 | } else if (voltuv > arb->voltuv_actual) { |
1127 | fllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; | 1369 | status = clk_set_fll_clks(g, &fllclk); |
1128 | fllclk.clkmhz = gpc2clk_target; | ||
1129 | fllclk.voltuv = voltuv; | ||
1130 | status = clk_program_fll_clks(g, &fllclk); | ||
1131 | if (status < 0) | 1370 | if (status < 0) |
1132 | return status; | 1371 | return status; |
1133 | 1372 | ||
@@ -1143,10 +1382,7 @@ static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | |||
1143 | if (status < 0) | 1382 | if (status < 0) |
1144 | return status; | 1383 | return status; |
1145 | 1384 | ||
1146 | fllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; | 1385 | status = clk_set_fll_clks(g, &fllclk); |
1147 | fllclk.clkmhz = gpc2clk_target; | ||
1148 | fllclk.voltuv = voltuv; | ||
1149 | status = clk_program_fll_clks(g, &fllclk); | ||
1150 | if (status < 0) | 1386 | if (status < 0) |
1151 | return status; | 1387 | return status; |
1152 | } | 1388 | } |