summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijayakumar <vsubbu@nvidia.com>2016-08-31 08:10:24 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commit1b1090512020369df18dbe36336ac5a85d2cd693 (patch)
tree41f3a11dbdff21815545e0e69734c60416783e5e
parente28ef73ec9baea7df631606298f8c210dc8f31a8 (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>
-rw-r--r--drivers/gpu/nvgpu/clk/clk.c48
-rw-r--r--drivers/gpu/nvgpu/clk/clk.h8
-rw-r--r--drivers/gpu/nvgpu/clk/clk_domain.c125
-rw-r--r--drivers/gpu/nvgpu/clk/clk_domain.h10
-rw-r--r--drivers/gpu/nvgpu/clk/clk_prog.c153
-rw-r--r--drivers/gpu/nvgpu/clk/clk_prog.h6
-rw-r--r--drivers/gpu/nvgpu/clk/clk_vf_point.h7
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.c4
8 files changed, 356 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c
index 0679efc0..34b344c8 100644
--- a/drivers/gpu/nvgpu/clk/clk.c
+++ b/drivers/gpu/nvgpu/clk/clk.c
@@ -188,3 +188,51 @@ u32 clk_pmu_vf_inject(struct gk20a *g)
188done: 188done:
189 return status; 189 return status;
190} 190}
191
192u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain)
193{
194 u32 status = -EINVAL;
195 struct clk_domain *pdomain;
196 u8 i;
197 struct clk_pmupstate *pclk = &g->clk_pmu;
198 u16 clkmhz = 0;
199 u32 volt = 0;
200
201 BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
202 struct clk_domain *, pdomain, i) {
203 if (pdomain->api_domain == clkapidomain) {
204 status = pdomain->clkdomainclkvfsearch(g, pclk,
205 pdomain, &clkmhz, &volt,
206 CLK_PROG_VFE_ENTRY_LOGIC);
207 return status;
208 }
209 }
210 return status;
211}
212
213u32 clk_domain_get_f_or_v(
214 struct gk20a *g,
215 u32 clkapidomain,
216 u16 *pclkmhz,
217 u32 *pvoltuv
218)
219{
220 u32 status = -EINVAL;
221 struct clk_domain *pdomain;
222 u8 i;
223 struct clk_pmupstate *pclk = &g->clk_pmu;
224
225 if ((pclkmhz == NULL) || (pvoltuv == NULL))
226 return -EINVAL;
227
228 BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
229 struct clk_domain *, pdomain, i) {
230 if (pdomain->api_domain == clkapidomain) {
231 status = pdomain->clkdomainclkvfsearch(g, pclk,
232 pdomain, pclkmhz, pvoltuv,
233 CLK_PROG_VFE_ENTRY_LOGIC);
234 return status;
235 }
236 }
237 return status;
238}
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h
index e24aada2..0d12ba7d 100644
--- a/drivers/gpu/nvgpu/clk/clk.h
+++ b/drivers/gpu/nvgpu/clk/clk.h
@@ -84,5 +84,13 @@ struct vbios_clocks_table_1x_hal_clock_entry {
84 84
85u32 clk_pmu_vf_inject(struct gk20a *g); 85u32 clk_pmu_vf_inject(struct gk20a *g);
86u32 clk_pmu_vin_load(struct gk20a *g); 86u32 clk_pmu_vin_load(struct gk20a *g);
87u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain);
88u32 clk_domain_get_f_or_v
89(
90 struct gk20a *g,
91 u32 clkapidomain,
92 u16 *pclkmhz,
93 u32 *pvoltuv
94);
87 95
88#endif 96#endif
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
206done: 221done:
@@ -407,6 +422,20 @@ static u32 clkdomainclkproglink_not_supported(struct gk20a *g,
407 return -EINVAL; 422 return -EINVAL;
408} 423}
409 424
425static 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
410static u32 clk_domain_construct_super(struct gk20a *g, 439static 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
543static 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 }
624done:
625 gk20a_dbg_info("done status %x", status);
626 return status;
627}
628
511static u32 _clk_domain_pmudatainit_3x_prog(struct gk20a *g, 629static 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}
diff --git a/drivers/gpu/nvgpu/clk/clk_domain.h b/drivers/gpu/nvgpu/clk/clk_domain.h
index 2670a066..07976a2a 100644
--- a/drivers/gpu/nvgpu/clk/clk_domain.h
+++ b/drivers/gpu/nvgpu/clk/clk_domain.h
@@ -26,8 +26,13 @@ struct clk_domain;
26/*data and function definition to talk to driver*/ 26/*data and function definition to talk to driver*/
27u32 clk_domain_sw_setup(struct gk20a *g); 27u32 clk_domain_sw_setup(struct gk20a *g);
28u32 clk_domain_pmu_setup(struct gk20a *g); 28u32 clk_domain_pmu_setup(struct gk20a *g);
29
29typedef u32 clkproglink(struct gk20a *g, struct clk_pmupstate *pclk, 30typedef u32 clkproglink(struct gk20a *g, struct clk_pmupstate *pclk,
30 struct clk_domain *pdomain); 31 struct clk_domain *pdomain);
32
33typedef u32 clkvfsearch(struct gk20a *g, struct clk_pmupstate *pclk,
34 struct clk_domain *pdomain, u16 *clkmhz,
35 u32 *voltuv, u8 rail);
31struct clk_domains { 36struct clk_domains {
32 struct boardobjgrp_e32 super; 37 struct boardobjgrp_e32 super;
33 u8 n_num_entries; 38 u8 n_num_entries;
@@ -55,6 +60,7 @@ struct clk_domain {
55 u8 ratio_domain; 60 u8 ratio_domain;
56 u8 usage; 61 u8 usage;
57 clkproglink *clkdomainclkproglink; 62 clkproglink *clkdomainclkproglink;
63 clkvfsearch *clkdomainclkvfsearch;
58}; 64};
59 65
60struct clk_domain_3x { 66struct clk_domain_3x {
@@ -92,4 +98,8 @@ struct clk_domain_3x_slave {
92 98
93u32 clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk); 99u32 clk_domain_clk_prog_link(struct gk20a *g, struct clk_pmupstate *pclk);
94 100
101#define CLK_CLK_DOMAIN_GET(pclk, idx) \
102 ((struct clk_domain *)BOARDOBJGRP_OBJ_GET_BY_IDX( \
103 &pclk->clk_domainobjs.super.super, (u8)(idx)))
104
95#endif 105#endif
diff --git a/drivers/gpu/nvgpu/clk/clk_prog.c b/drivers/gpu/nvgpu/clk/clk_prog.c
index 4bf473ac..5e4700a0 100644
--- a/drivers/gpu/nvgpu/clk/clk_prog.c
+++ b/drivers/gpu/nvgpu/clk/clk_prog.c
@@ -29,6 +29,7 @@ static struct clk_prog *construct_clk_prog(struct gk20a *g, void *pargs);
29static u32 devinit_get_clk_prog_table(struct gk20a *g, 29static u32 devinit_get_clk_prog_table(struct gk20a *g,
30 struct clk_progs *pprogobjs); 30 struct clk_progs *pprogobjs);
31static vf_flatten vfflatten_prog_1x_master; 31static vf_flatten vfflatten_prog_1x_master;
32static vf_lookup vflookup_prog_1x_master;
32 33
33static u32 _clk_progs_pmudatainit(struct gk20a *g, 34static u32 _clk_progs_pmudatainit(struct gk20a *g,
34 struct boardobjgrp *pboardobjgrp, 35 struct boardobjgrp *pboardobjgrp,
@@ -603,6 +604,9 @@ static u32 clk_prog_construct_1x_master(struct gk20a *g,
603 pclkprog->vfflatten = 604 pclkprog->vfflatten =
604 vfflatten_prog_1x_master; 605 vfflatten_prog_1x_master;
605 606
607 pclkprog->vflookup =
608 vflookup_prog_1x_master;
609
606 pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *) 610 pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)
607 kzalloc(vfsize, GFP_KERNEL); 611 kzalloc(vfsize, GFP_KERNEL);
608 612
@@ -831,3 +835,152 @@ done:
831 gk20a_dbg_info("done status %x", status); 835 gk20a_dbg_info("done status %x", status);
832 return status; 836 return status;
833} 837}
838
839static u32 vflookup_prog_1x_master
840(
841 struct gk20a *g,
842 struct clk_pmupstate *pclk,
843 struct clk_prog_1x_master *p1xmaster,
844 u8 *slave_clk_domain,
845 u16 *pclkmhz,
846 u32 *pvoltuv,
847 u8 rail
848)
849{
850 u8 j;
851 struct ctrl_clk_clk_prog_1x_master_vf_entry
852 *pvfentry;
853 struct clk_vf_point *pvfpoint;
854 struct clk_progs *pclkprogobjs;
855 struct clk_prog_1x_master_ratio *p1xmasterratio;
856 u16 clkmhz;
857 u32 voltuv;
858 u8 slaveentrycount;
859 u8 i;
860 struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents;
861
862 if ((*pclkmhz != 0) && (*pvoltuv != 0))
863 return -EINVAL;
864
865 pclkprogobjs = &(pclk->clk_progobjs);
866
867 slaveentrycount = pclkprogobjs->slave_entry_count;
868
869 if (pclkprogobjs->vf_entry_count >
870 CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES)
871 return -EINVAL;
872
873 if (rail >= pclkprogobjs->vf_entry_count)
874 return -EINVAL;
875
876 pvfentry = p1xmaster->p_vf_entries;
877
878 pvfentry = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)(
879 (u8 *)pvfentry +
880 (sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) *
881 (rail+1)));
882
883 clkmhz = *pclkmhz;
884 voltuv = *pvoltuv;
885
886 /*if domain is slave domain and freq is input
887 then derive master clk */
888 if ((slave_clk_domain != NULL) && (*pclkmhz != 0)) {
889 if (p1xmaster->super.super.super.implements(g,
890 &p1xmaster->super.super.super,
891 CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) {
892
893 p1xmasterratio =
894 (struct clk_prog_1x_master_ratio *)p1xmaster;
895 pslaveents = p1xmasterratio->p_slave_entries;
896 for (i = 0; i < slaveentrycount; i++) {
897 if (pslaveents->clk_dom_idx ==
898 *slave_clk_domain)
899 break;
900 pslaveents++;
901 }
902 if (i == slaveentrycount)
903 return -EINVAL;
904 clkmhz = (clkmhz * 100)/pslaveents->ratio;
905 } else {
906 /* only support ratio for now */
907 return -EINVAL;
908 }
909 }
910
911 /* if both volt and clks are zero simply print*/
912 if ((*pvoltuv == 0) && (*pclkmhz == 0)) {
913 for (j = pvfentry->vf_point_idx_first;
914 j <= pvfentry->vf_point_idx_last; j++) {
915 pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
916 gk20a_err(dev_from_gk20a(g), "v %x c %x",
917 clkvfpointvoltageuvget(g, pvfpoint),
918 clkvfpointfreqmhzget(g, pvfpoint));
919 }
920 return -EINVAL;
921 }
922 /* start looking up f for v for v for f */
923 /* looking for volt? */
924 if (*pvoltuv == 0) {
925 pvfpoint = CLK_CLK_VF_POINT_GET(pclk,
926 pvfentry->vf_point_idx_last);
927 /* above range? */
928 if (clkmhz > clkvfpointfreqmhzget(g, pvfpoint))
929 return -EINVAL;
930
931 for (j = pvfentry->vf_point_idx_last;
932 j >= pvfentry->vf_point_idx_first; j--) {
933 pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
934 if (clkmhz <= clkvfpointfreqmhzget(g, pvfpoint))
935 voltuv = clkvfpointvoltageuvget(g, pvfpoint);
936 else
937 break;
938 }
939 } else { /* looking for clk? */
940
941 pvfpoint = CLK_CLK_VF_POINT_GET(pclk,
942 pvfentry->vf_point_idx_first);
943 /* below range? */
944 if (voltuv < clkvfpointvoltageuvget(g, pvfpoint))
945 return -EINVAL;
946
947 for (j = pvfentry->vf_point_idx_first;
948 j <= pvfentry->vf_point_idx_last; j++) {
949 pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
950 if (voltuv >= clkvfpointvoltageuvget(g, pvfpoint))
951 clkmhz = clkvfpointfreqmhzget(g, pvfpoint);
952 else
953 break;
954 }
955 }
956
957 /*if domain is slave domain and freq was looked up
958 then derive slave clk */
959 if ((slave_clk_domain != NULL) && (*pclkmhz == 0)) {
960 if (p1xmaster->super.super.super.implements(g,
961 &p1xmaster->super.super.super,
962 CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) {
963
964 p1xmasterratio =
965 (struct clk_prog_1x_master_ratio *)p1xmaster;
966 pslaveents = p1xmasterratio->p_slave_entries;
967 for (i = 0; i < slaveentrycount; i++) {
968 if (pslaveents->clk_dom_idx ==
969 *slave_clk_domain)
970 break;
971 pslaveents++;
972 }
973 if (i == slaveentrycount)
974 return -EINVAL;
975 clkmhz = (clkmhz * pslaveents->ratio)/100;
976 } else {
977 /* only support ratio for now */
978 return -EINVAL;
979 }
980 }
981 *pclkmhz = clkmhz;
982 *pvoltuv = voltuv;
983 if ((clkmhz == 0) || (voltuv == 0))
984 return -EINVAL;
985 return 0;
986}
diff --git a/drivers/gpu/nvgpu/clk/clk_prog.h b/drivers/gpu/nvgpu/clk/clk_prog.h
index 8718bdd6..979d327d 100644
--- a/drivers/gpu/nvgpu/clk/clk_prog.h
+++ b/drivers/gpu/nvgpu/clk/clk_prog.h
@@ -27,6 +27,11 @@ typedef u32 vf_flatten(struct gk20a *g, struct clk_pmupstate *pclk,
27 struct clk_prog_1x_master *p1xmaster, 27 struct clk_prog_1x_master *p1xmaster,
28 u8 clk_domain_idx, u16 *pfreqmaxlastmhz); 28 u8 clk_domain_idx, u16 *pfreqmaxlastmhz);
29 29
30typedef u32 vf_lookup(struct gk20a *g, struct clk_pmupstate *pclk,
31 struct clk_prog_1x_master *p1xmaster,
32 u8 *slave_clk_domain_idx, u16 *pclkmhz,
33 u32 *pvoltuv, u8 rail);
34
30struct clk_progs { 35struct clk_progs {
31 struct boardobjgrp_e255 super; 36 struct boardobjgrp_e255 super;
32 u8 slave_entry_count; 37 u8 slave_entry_count;
@@ -52,6 +57,7 @@ struct clk_prog_1x_master {
52 struct ctrl_clk_clk_delta deltas; 57 struct ctrl_clk_clk_delta deltas;
53 union ctrl_clk_clk_prog_1x_master_source_data source_data; 58 union ctrl_clk_clk_prog_1x_master_source_data source_data;
54 vf_flatten *vfflatten; 59 vf_flatten *vfflatten;
60 vf_lookup *vflookup;
55}; 61};
56 62
57struct clk_prog_1x_master_ratio { 63struct clk_prog_1x_master_ratio {
diff --git a/drivers/gpu/nvgpu/clk/clk_vf_point.h b/drivers/gpu/nvgpu/clk/clk_vf_point.h
index 306bec41..15920066 100644
--- a/drivers/gpu/nvgpu/clk/clk_vf_point.h
+++ b/drivers/gpu/nvgpu/clk/clk_vf_point.h
@@ -46,8 +46,8 @@ struct clk_vf_point_freq {
46}; 46};
47 47
48#define CLK_CLK_VF_POINT_GET(pclk, idx) \ 48#define CLK_CLK_VF_POINT_GET(pclk, idx) \
49 ((struct clk_vf_point)BOARDOBJGRP_OBJ_GET_BY_IDX( \ 49 ((struct clk_vf_point *)BOARDOBJGRP_OBJ_GET_BY_IDX( \
50 &pclk->vfpoints.super.super, (u8)(idx))) 50 &pclk->clk_vf_pointobjs.super.super, (u8)(idx)))
51 51
52#define clkvfpointpairget(pvfpoint) \ 52#define clkvfpointpairget(pvfpoint) \
53 (&((pvfpoint)->pair)) 53 (&((pvfpoint)->pair))
@@ -66,6 +66,9 @@ struct clk_vf_point_freq {
66 CTRL_CLK_VF_PAIR_VOLTAGE_UV_SET(clkvfpointpairget(pvfpoint), \ 66 CTRL_CLK_VF_PAIR_VOLTAGE_UV_SET(clkvfpointpairget(pvfpoint), \
67 _voltageuv) 67 _voltageuv)
68 68
69#define clkvfpointvoltageuvget(pgpu, pvfpoint) \
70 CTRL_CLK_VF_PAIR_VOLTAGE_UV_GET(clkvfpointpairget(pvfpoint)) \
71
69struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs); 72struct clk_vf_point *construct_clk_vf_point(struct gk20a *g, void *pargs);
70 73
71#endif 74#endif
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c
index 83f17937..94ff5010 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.c
+++ b/drivers/gpu/nvgpu/pstate/pstate.c
@@ -96,6 +96,10 @@ int gk20a_init_pstate_pmu_support(struct gk20a *g)
96 return err; 96 return err;
97 97
98 err = clk_pmu_vf_inject(g); 98 err = clk_pmu_vf_inject(g);
99 if (err)
100 return err;
101
102 err = clk_vf_point_cache(g);
99 return err; 103 return err;
100} 104}
101 105