diff options
author | Vijayakumar <vsubbu@nvidia.com> | 2016-08-31 08:10:24 -0400 |
---|---|---|
committer | Deepak Nibade <dnibade@nvidia.com> | 2016-12-27 04:56:50 -0500 |
commit | 1b1090512020369df18dbe36336ac5a85d2cd693 (patch) | |
tree | 41f3a11dbdff21815545e0e69734c60416783e5e /drivers/gpu/nvgpu/clk/clk_domain.c | |
parent | e28ef73ec9baea7df631606298f8c210dc8f31a8 (diff) |
gpu: nvgpu: support to parse VF table
JIRA DNVGPU-123
function was added to retrieve V for F or
F for V for a given clock domain.
Clock domain can be master or slave.
F or V can be intermediate point between two
successive V or F values in VF table.
VF table should be cached before calling this function.
A F value below Fmin will return Vmin.
F > Fmax will return error
A V value above Vmax wil return F max.
A V value below Vmin will return error.
Change-Id: I28b4e8647510c6933e9e1204cfff31d74616e11a
Signed-off-by: Vijayakumar <vsubbu@nvidia.com>
Reviewed-on: http://git-master/r/1211234
(cherry-picked from commit 5b83b03f2454fbec8d49a064ed09b09c92d3e9fa)
Reviewed-on: http://git-master/r/1235054
Reviewed-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk_domain.c')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_domain.c | 125 |
1 files changed, 122 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_domain.c b/drivers/gpu/nvgpu/clk/clk_domain.c index 7371946c..c8da851a 100644 --- a/drivers/gpu/nvgpu/clk/clk_domain.c +++ b/drivers/gpu/nvgpu/clk/clk_domain.c | |||
@@ -136,6 +136,8 @@ u32 clk_domain_sw_setup(struct gk20a *g) | |||
136 | struct boardobjgrp *pboardobjgrp = NULL; | 136 | struct boardobjgrp *pboardobjgrp = NULL; |
137 | struct clk_domains *pclkdomainobjs; | 137 | struct clk_domains *pclkdomainobjs; |
138 | struct clk_domain *pdomain; | 138 | struct clk_domain *pdomain; |
139 | struct clk_domain_3x_master *pdomain_master; | ||
140 | struct clk_domain_3x_slave *pdomain_slave; | ||
139 | u8 i; | 141 | u8 i; |
140 | 142 | ||
141 | gk20a_dbg_info(""); | 143 | gk20a_dbg_info(""); |
@@ -186,6 +188,7 @@ u32 clk_domain_sw_setup(struct gk20a *g) | |||
186 | 188 | ||
187 | BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super), | 189 | BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super), |
188 | struct clk_domain *, pdomain, i) { | 190 | struct clk_domain *, pdomain, i) { |
191 | pdomain_master = NULL; | ||
189 | if (pdomain->super.implements(g, &pdomain->super, | 192 | if (pdomain->super.implements(g, &pdomain->super, |
190 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) { | 193 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) { |
191 | status = boardobjgrpmask_bitset( | 194 | status = boardobjgrpmask_bitset( |
@@ -201,6 +204,18 @@ u32 clk_domain_sw_setup(struct gk20a *g) | |||
201 | if (status) | 204 | if (status) |
202 | goto done; | 205 | goto done; |
203 | } | 206 | } |
207 | |||
208 | if (pdomain->super.implements(g, &pdomain->super, | ||
209 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
210 | pdomain_slave = | ||
211 | (struct clk_domain_3x_slave *)pdomain; | ||
212 | pdomain_master = | ||
213 | (struct clk_domain_3x_master *) | ||
214 | (CLK_CLK_DOMAIN_GET((&g->clk_pmu), | ||
215 | pdomain_slave->master_idx)); | ||
216 | pdomain_master->slave_idxs_mask |= BIT(i); | ||
217 | } | ||
218 | |||
204 | } | 219 | } |
205 | 220 | ||
206 | done: | 221 | done: |
@@ -407,6 +422,20 @@ static u32 clkdomainclkproglink_not_supported(struct gk20a *g, | |||
407 | return -EINVAL; | 422 | return -EINVAL; |
408 | } | 423 | } |
409 | 424 | ||
425 | static u32 clkdomainvfsearch_stub( | ||
426 | struct gk20a *g, | ||
427 | struct clk_pmupstate *pclk, | ||
428 | struct clk_domain *pdomain, | ||
429 | u16 *clkmhz, | ||
430 | u32 *voltuv, | ||
431 | u8 rail | ||
432 | ) | ||
433 | { | ||
434 | gk20a_dbg_info(""); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | |||
410 | static u32 clk_domain_construct_super(struct gk20a *g, | 439 | static u32 clk_domain_construct_super(struct gk20a *g, |
411 | struct boardobj **ppboardobj, | 440 | struct boardobj **ppboardobj, |
412 | u16 size, void *pargs) | 441 | u16 size, void *pargs) |
@@ -429,6 +458,9 @@ static u32 clk_domain_construct_super(struct gk20a *g, | |||
429 | pdomain->clkdomainclkproglink = | 458 | pdomain->clkdomainclkproglink = |
430 | clkdomainclkproglink_not_supported; | 459 | clkdomainclkproglink_not_supported; |
431 | 460 | ||
461 | pdomain->clkdomainclkvfsearch = | ||
462 | clkdomainvfsearch_stub; | ||
463 | |||
432 | pdomain->api_domain = ptmpdomain->api_domain; | 464 | pdomain->api_domain = ptmpdomain->api_domain; |
433 | pdomain->domain = ptmpdomain->domain; | 465 | pdomain->domain = ptmpdomain->domain; |
434 | pdomain->perf_domain_grp_idx = | 466 | pdomain->perf_domain_grp_idx = |
@@ -508,6 +540,92 @@ static u32 clkdomainclkproglink_3x_prog(struct gk20a *g, | |||
508 | return status; | 540 | return status; |
509 | } | 541 | } |
510 | 542 | ||
543 | static u32 clkdomainvfsearch | ||
544 | ( | ||
545 | struct gk20a *g, | ||
546 | struct clk_pmupstate *pclk, | ||
547 | struct clk_domain *pdomain, | ||
548 | u16 *pclkmhz, | ||
549 | u32 *pvoltuv, | ||
550 | u8 rail | ||
551 | ) | ||
552 | { | ||
553 | u32 status = 0; | ||
554 | struct clk_domain_3x_master *p3xmaster = | ||
555 | (struct clk_domain_3x_master *)pdomain; | ||
556 | struct clk_prog *pprog = NULL; | ||
557 | struct clk_prog_1x_master *pprog1xmaster = NULL; | ||
558 | u8 i; | ||
559 | u8 *pslaveidx = NULL; | ||
560 | u8 slaveidx; | ||
561 | u16 clkmhz; | ||
562 | u32 voltuv; | ||
563 | u16 bestclkmhz; | ||
564 | u32 bestvoltuv; | ||
565 | |||
566 | gk20a_dbg_info(""); | ||
567 | if ((*pclkmhz != 0) && (*pvoltuv != 0)) | ||
568 | return -EINVAL; | ||
569 | |||
570 | bestclkmhz = *pclkmhz; | ||
571 | bestvoltuv = *pvoltuv; | ||
572 | |||
573 | if (pdomain->super.implements(g, &pdomain->super, | ||
574 | CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { | ||
575 | slaveidx = BOARDOBJ_GET_IDX(pdomain); | ||
576 | pslaveidx = &slaveidx; | ||
577 | p3xmaster = (struct clk_domain_3x_master *) | ||
578 | CLK_CLK_DOMAIN_GET(pclk, | ||
579 | ((struct clk_domain_3x_slave *) | ||
580 | pdomain)->master_idx); | ||
581 | } | ||
582 | |||
583 | /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ | ||
584 | for (i = p3xmaster->super.clk_prog_idx_first; | ||
585 | i <= p3xmaster->super.clk_prog_idx_last; | ||
586 | i++) { | ||
587 | clkmhz = *pclkmhz; | ||
588 | voltuv = *pvoltuv; | ||
589 | pprog = CLK_CLK_PROG_GET(pclk, i); | ||
590 | |||
591 | /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ | ||
592 | if (!pprog->super.implements(g, &pprog->super, | ||
593 | CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { | ||
594 | status = -EINVAL; | ||
595 | goto done; | ||
596 | } | ||
597 | |||
598 | pprog1xmaster = (struct clk_prog_1x_master *)pprog; | ||
599 | status = pprog1xmaster->vflookup(g, pclk, pprog1xmaster, | ||
600 | pslaveidx, &clkmhz, &voltuv, rail); | ||
601 | /* if look up has found the V or F value matching to other | ||
602 | exit */ | ||
603 | if (status == 0) { | ||
604 | if (*pclkmhz == 0) { | ||
605 | bestclkmhz = clkmhz; | ||
606 | } else { | ||
607 | bestvoltuv = voltuv; | ||
608 | break; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | /* clk and volt sent as zero to pring vf table */ | ||
613 | if ((*pclkmhz == 0) && (*pvoltuv == 0)) { | ||
614 | status = 0; | ||
615 | goto done; | ||
616 | } | ||
617 | /* atleast one search found a matching value? */ | ||
618 | if ((bestvoltuv != 0) && (bestclkmhz != 0)) { | ||
619 | *pclkmhz = bestclkmhz; | ||
620 | *pvoltuv = bestvoltuv; | ||
621 | status = 0; | ||
622 | goto done; | ||
623 | } | ||
624 | done: | ||
625 | gk20a_dbg_info("done status %x", status); | ||
626 | return status; | ||
627 | } | ||
628 | |||
511 | static u32 _clk_domain_pmudatainit_3x_prog(struct gk20a *g, | 629 | static u32 _clk_domain_pmudatainit_3x_prog(struct gk20a *g, |
512 | struct boardobj *board_obj_ptr, | 630 | struct boardobj *board_obj_ptr, |
513 | struct nv_pmu_boardobj *ppmudata) | 631 | struct nv_pmu_boardobj *ppmudata) |
@@ -568,6 +686,9 @@ static u32 clk_domain_construct_3x_prog(struct gk20a *g, | |||
568 | pdomain->super.super.clkdomainclkproglink = | 686 | pdomain->super.super.clkdomainclkproglink = |
569 | clkdomainclkproglink_3x_prog; | 687 | clkdomainclkproglink_3x_prog; |
570 | 688 | ||
689 | pdomain->super.super.clkdomainclkvfsearch = | ||
690 | clkdomainvfsearch; | ||
691 | |||
571 | pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first; | 692 | pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first; |
572 | pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last; | 693 | pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last; |
573 | pdomain->noise_unaware_ordering_index = | 694 | pdomain->noise_unaware_ordering_index = |
@@ -707,8 +828,6 @@ static u32 clk_domain_construct_3x_master(struct gk20a *g, | |||
707 | { | 828 | { |
708 | struct boardobj *ptmpobj = (struct boardobj *)pargs; | 829 | struct boardobj *ptmpobj = (struct boardobj *)pargs; |
709 | struct clk_domain_3x_master *pdomain; | 830 | struct clk_domain_3x_master *pdomain; |
710 | struct clk_domain_3x_master *ptmpdomain = | ||
711 | (struct clk_domain_3x_master *)pargs; | ||
712 | u32 status = 0; | 831 | u32 status = 0; |
713 | 832 | ||
714 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER) | 833 | if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER) |
@@ -726,7 +845,7 @@ static u32 clk_domain_construct_3x_master(struct gk20a *g, | |||
726 | pdomain->super.super.super.clkdomainclkproglink = | 845 | pdomain->super.super.super.clkdomainclkproglink = |
727 | clkdomainclkproglink_3x_master; | 846 | clkdomainclkproglink_3x_master; |
728 | 847 | ||
729 | pdomain->slave_idxs_mask = ptmpdomain->slave_idxs_mask; | 848 | pdomain->slave_idxs_mask = 0; |
730 | 849 | ||
731 | return status; | 850 | return status; |
732 | } | 851 | } |