From 1b1090512020369df18dbe36336ac5a85d2cd693 Mon Sep 17 00:00:00 2001 From: Vijayakumar Date: Wed, 31 Aug 2016 17:40:24 +0530 Subject: 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 Reviewed-on: http://git-master/r/1211234 (cherry-picked from commit 5b83b03f2454fbec8d49a064ed09b09c92d3e9fa) Reviewed-on: http://git-master/r/1235054 Reviewed-by: Thomas Fleury Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/clk/clk_domain.c | 125 ++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/nvgpu/clk/clk_domain.c') 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) struct boardobjgrp *pboardobjgrp = NULL; struct clk_domains *pclkdomainobjs; struct clk_domain *pdomain; + struct clk_domain_3x_master *pdomain_master; + struct clk_domain_3x_slave *pdomain_slave; u8 i; gk20a_dbg_info(""); @@ -186,6 +188,7 @@ u32 clk_domain_sw_setup(struct gk20a *g) BOARDOBJGRP_FOR_EACH(&(pclkdomainobjs->super.super), struct clk_domain *, pdomain, i) { + pdomain_master = NULL; if (pdomain->super.implements(g, &pdomain->super, CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG)) { status = boardobjgrpmask_bitset( @@ -201,6 +204,18 @@ u32 clk_domain_sw_setup(struct gk20a *g) if (status) goto done; } + + if (pdomain->super.implements(g, &pdomain->super, + CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { + pdomain_slave = + (struct clk_domain_3x_slave *)pdomain; + pdomain_master = + (struct clk_domain_3x_master *) + (CLK_CLK_DOMAIN_GET((&g->clk_pmu), + pdomain_slave->master_idx)); + pdomain_master->slave_idxs_mask |= BIT(i); + } + } done: @@ -407,6 +422,20 @@ static u32 clkdomainclkproglink_not_supported(struct gk20a *g, return -EINVAL; } +static u32 clkdomainvfsearch_stub( + struct gk20a *g, + struct clk_pmupstate *pclk, + struct clk_domain *pdomain, + u16 *clkmhz, + u32 *voltuv, + u8 rail +) +{ + gk20a_dbg_info(""); + return -EINVAL; +} + + static u32 clk_domain_construct_super(struct gk20a *g, struct boardobj **ppboardobj, u16 size, void *pargs) @@ -429,6 +458,9 @@ static u32 clk_domain_construct_super(struct gk20a *g, pdomain->clkdomainclkproglink = clkdomainclkproglink_not_supported; + pdomain->clkdomainclkvfsearch = + clkdomainvfsearch_stub; + pdomain->api_domain = ptmpdomain->api_domain; pdomain->domain = ptmpdomain->domain; pdomain->perf_domain_grp_idx = @@ -508,6 +540,92 @@ static u32 clkdomainclkproglink_3x_prog(struct gk20a *g, return status; } +static u32 clkdomainvfsearch +( + struct gk20a *g, + struct clk_pmupstate *pclk, + struct clk_domain *pdomain, + u16 *pclkmhz, + u32 *pvoltuv, + u8 rail +) +{ + u32 status = 0; + struct clk_domain_3x_master *p3xmaster = + (struct clk_domain_3x_master *)pdomain; + struct clk_prog *pprog = NULL; + struct clk_prog_1x_master *pprog1xmaster = NULL; + u8 i; + u8 *pslaveidx = NULL; + u8 slaveidx; + u16 clkmhz; + u32 voltuv; + u16 bestclkmhz; + u32 bestvoltuv; + + gk20a_dbg_info(""); + if ((*pclkmhz != 0) && (*pvoltuv != 0)) + return -EINVAL; + + bestclkmhz = *pclkmhz; + bestvoltuv = *pvoltuv; + + if (pdomain->super.implements(g, &pdomain->super, + CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) { + slaveidx = BOARDOBJ_GET_IDX(pdomain); + pslaveidx = &slaveidx; + p3xmaster = (struct clk_domain_3x_master *) + CLK_CLK_DOMAIN_GET(pclk, + ((struct clk_domain_3x_slave *) + pdomain)->master_idx); + } + + /* Iterate over the set of CLK_PROGs pointed at by this domain.*/ + for (i = p3xmaster->super.clk_prog_idx_first; + i <= p3xmaster->super.clk_prog_idx_last; + i++) { + clkmhz = *pclkmhz; + voltuv = *pvoltuv; + pprog = CLK_CLK_PROG_GET(pclk, i); + + /* MASTER CLK_DOMAINs must point to MASTER CLK_PROGs.*/ + if (!pprog->super.implements(g, &pprog->super, + CTRL_CLK_CLK_PROG_TYPE_1X_MASTER)) { + status = -EINVAL; + goto done; + } + + pprog1xmaster = (struct clk_prog_1x_master *)pprog; + status = pprog1xmaster->vflookup(g, pclk, pprog1xmaster, + pslaveidx, &clkmhz, &voltuv, rail); + /* if look up has found the V or F value matching to other + exit */ + if (status == 0) { + if (*pclkmhz == 0) { + bestclkmhz = clkmhz; + } else { + bestvoltuv = voltuv; + break; + } + } + } + /* clk and volt sent as zero to pring vf table */ + if ((*pclkmhz == 0) && (*pvoltuv == 0)) { + status = 0; + goto done; + } + /* atleast one search found a matching value? */ + if ((bestvoltuv != 0) && (bestclkmhz != 0)) { + *pclkmhz = bestclkmhz; + *pvoltuv = bestvoltuv; + status = 0; + goto done; + } +done: + gk20a_dbg_info("done status %x", status); + return status; +} + static u32 _clk_domain_pmudatainit_3x_prog(struct gk20a *g, struct boardobj *board_obj_ptr, struct nv_pmu_boardobj *ppmudata) @@ -568,6 +686,9 @@ static u32 clk_domain_construct_3x_prog(struct gk20a *g, pdomain->super.super.clkdomainclkproglink = clkdomainclkproglink_3x_prog; + pdomain->super.super.clkdomainclkvfsearch = + clkdomainvfsearch; + pdomain->clk_prog_idx_first = ptmpdomain->clk_prog_idx_first; pdomain->clk_prog_idx_last = ptmpdomain->clk_prog_idx_last; pdomain->noise_unaware_ordering_index = @@ -707,8 +828,6 @@ static u32 clk_domain_construct_3x_master(struct gk20a *g, { struct boardobj *ptmpobj = (struct boardobj *)pargs; struct clk_domain_3x_master *pdomain; - struct clk_domain_3x_master *ptmpdomain = - (struct clk_domain_3x_master *)pargs; u32 status = 0; 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, pdomain->super.super.super.clkdomainclkproglink = clkdomainclkproglink_3x_master; - pdomain->slave_idxs_mask = ptmpdomain->slave_idxs_mask; + pdomain->slave_idxs_mask = 0; return status; } -- cgit v1.2.2