From 3c351f5bb2d04c1f70c72f3f2fd758bbb340877c Mon Sep 17 00:00:00 2001 From: Vijayakumar Date: Mon, 12 Sep 2016 22:36:33 +0530 Subject: gpu: nvgpu: add function to retrieve clk points JIRA DNVGPU-123 Function will copy possible clock points for a given master clock domain to pointer passed. pointer with NULL value and count of zero can be passed to query number of clock points for a given domain so that memory can be allocated and function called again to fill clock points Change-Id: Iec6206f23789980036be99793599e934bd221035 Reviewed-on: http://git-master/r/1218912 (cherry picked from commit 9219697bff1e12deb605325055a02a7b387996e9) Signed-off-by: Vijayakumar Reviewed-on: http://git-master/r/1235055 Reviewed-by: Thomas Fleury GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/clk/clk.c | 31 ++++++++++++++ drivers/gpu/nvgpu/clk/clk.h | 6 +++ drivers/gpu/nvgpu/clk/clk_domain.c | 83 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/clk/clk_domain.h | 6 +++ drivers/gpu/nvgpu/clk/clk_prog.c | 61 ++++++++++++++++++++++++++++ drivers/gpu/nvgpu/clk/clk_prog.h | 7 ++++ 6 files changed, 194 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index 34b344c8..7ee4f283 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c @@ -236,3 +236,34 @@ u32 clk_domain_get_f_or_v( } return status; } + +u32 clk_domain_get_f_points( + struct gk20a *g, + u32 clkapidomain, + u32 *pfpointscount, + u16 *pfreqpointsinmhz +) +{ + u32 status = -EINVAL; + struct clk_domain *pdomain; + u8 i; + struct clk_pmupstate *pclk = &g->clk_pmu; + + if (pfpointscount == NULL) + return -EINVAL; + + if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) + return -EINVAL; + + BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), + struct clk_domain *, pdomain, i) { + if (pdomain->api_domain == clkapidomain) { + status = pdomain->clkdomainclkgetfpoints(g, pclk, + pdomain, pfpointscount, + pfreqpointsinmhz, + CLK_PROG_VFE_ENTRY_LOGIC); + return status; + } + } + return status; +} diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h index 0d12ba7d..1f25fa4e 100644 --- a/drivers/gpu/nvgpu/clk/clk.h +++ b/drivers/gpu/nvgpu/clk/clk.h @@ -92,5 +92,11 @@ u32 clk_domain_get_f_or_v u16 *pclkmhz, u32 *pvoltuv ); +u32 clk_domain_get_f_points( + struct gk20a *g, + u32 clkapidomain, + u32 *fpointscount, + u16 *freqpointsinmhz +); #endif diff --git a/drivers/gpu/nvgpu/clk/clk_domain.c b/drivers/gpu/nvgpu/clk/clk_domain.c index c8da851a..f87530dc 100644 --- a/drivers/gpu/nvgpu/clk/clk_domain.c +++ b/drivers/gpu/nvgpu/clk/clk_domain.c @@ -435,6 +435,19 @@ static u32 clkdomainvfsearch_stub( return -EINVAL; } +static u32 clkdomaingetfpoints_stub( + struct gk20a *g, + struct clk_pmupstate *pclk, + struct clk_domain *pdomain, + u32 *pfpointscount, + u16 *pfreqpointsinmhz, + u8 rail +) +{ + gk20a_dbg_info(""); + return -EINVAL; +} + static u32 clk_domain_construct_super(struct gk20a *g, struct boardobj **ppboardobj, @@ -461,6 +474,9 @@ static u32 clk_domain_construct_super(struct gk20a *g, pdomain->clkdomainclkvfsearch = clkdomainvfsearch_stub; + pdomain->clkdomainclkgetfpoints = + clkdomaingetfpoints_stub; + pdomain->api_domain = ptmpdomain->api_domain; pdomain->domain = ptmpdomain->domain; pdomain->perf_domain_grp_idx = @@ -626,6 +642,70 @@ done: return status; } +static u32 clkdomaingetfpoints +( + struct gk20a *g, + struct clk_pmupstate *pclk, + struct clk_domain *pdomain, + u32 *pfpointscount, + u16 *pfreqpointsinmhz, + 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; + u32 fpointscount = 0; + u32 remainingcount; + u32 totalcount; + u16 *freqpointsdata; + u8 i; + + gk20a_dbg_info(""); + + if (pfpointscount == NULL) + return -EINVAL; + + if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) + return -EINVAL; + + if (pdomain->super.implements(g, &pdomain->super, + CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE)) + return -EINVAL; + + freqpointsdata = pfreqpointsinmhz; + totalcount = 0; + fpointscount = *pfpointscount; + remainingcount = fpointscount; + /* 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++) { + pprog = CLK_CLK_PROG_GET(pclk, i); + pprog1xmaster = (struct clk_prog_1x_master *)pprog; + status = pprog1xmaster->getfpoints(g, pclk, pprog1xmaster, + &fpointscount, &freqpointsdata, rail); + if (status) { + *pfpointscount = 0; + goto done; + } + totalcount += fpointscount; + if (*pfpointscount) { + remainingcount -= fpointscount; + fpointscount = remainingcount; + } else + fpointscount = 0; + + } + + *pfpointscount = totalcount; +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) @@ -689,6 +769,9 @@ static u32 clk_domain_construct_3x_prog(struct gk20a *g, pdomain->super.super.clkdomainclkvfsearch = clkdomainvfsearch; + pdomain->super.super.clkdomainclkgetfpoints = + clkdomaingetfpoints; + 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 = diff --git a/drivers/gpu/nvgpu/clk/clk_domain.h b/drivers/gpu/nvgpu/clk/clk_domain.h index 07976a2a..eeb7c256 100644 --- a/drivers/gpu/nvgpu/clk/clk_domain.h +++ b/drivers/gpu/nvgpu/clk/clk_domain.h @@ -33,6 +33,11 @@ typedef u32 clkproglink(struct gk20a *g, struct clk_pmupstate *pclk, typedef u32 clkvfsearch(struct gk20a *g, struct clk_pmupstate *pclk, struct clk_domain *pdomain, u16 *clkmhz, u32 *voltuv, u8 rail); + +typedef u32 clkgetfpoints(struct gk20a *g, struct clk_pmupstate *pclk, + struct clk_domain *pdomain, u32 *pfpointscount, + u16 *pfreqpointsinmhz, u8 rail); + struct clk_domains { struct boardobjgrp_e32 super; u8 n_num_entries; @@ -61,6 +66,7 @@ struct clk_domain { u8 usage; clkproglink *clkdomainclkproglink; clkvfsearch *clkdomainclkvfsearch; + clkgetfpoints *clkdomainclkgetfpoints; }; struct clk_domain_3x { diff --git a/drivers/gpu/nvgpu/clk/clk_prog.c b/drivers/gpu/nvgpu/clk/clk_prog.c index 5e4700a0..cb9a0e8d 100644 --- a/drivers/gpu/nvgpu/clk/clk_prog.c +++ b/drivers/gpu/nvgpu/clk/clk_prog.c @@ -30,6 +30,7 @@ static u32 devinit_get_clk_prog_table(struct gk20a *g, struct clk_progs *pprogobjs); static vf_flatten vfflatten_prog_1x_master; static vf_lookup vflookup_prog_1x_master; +static get_fpoints getfpoints_prog_1x_master; static u32 _clk_progs_pmudatainit(struct gk20a *g, struct boardobjgrp *pboardobjgrp, @@ -607,6 +608,9 @@ static u32 clk_prog_construct_1x_master(struct gk20a *g, pclkprog->vflookup = vflookup_prog_1x_master; + pclkprog->getfpoints = + getfpoints_prog_1x_master; + pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *) kzalloc(vfsize, GFP_KERNEL); @@ -984,3 +988,60 @@ static u32 vflookup_prog_1x_master return -EINVAL; return 0; } + +static u32 getfpoints_prog_1x_master +( + struct gk20a *g, + struct clk_pmupstate *pclk, + struct clk_prog_1x_master *p1xmaster, + u32 *pfpointscount, + u16 **ppfreqpointsinmhz, + u8 rail +) +{ + + struct ctrl_clk_clk_prog_1x_master_vf_entry + *pvfentry; + struct clk_vf_point *pvfpoint; + struct clk_progs *pclkprogobjs; + u8 j; + u32 fpointscount = 0; + + if (pfpointscount == NULL) + return -EINVAL; + + pclkprogobjs = &(pclk->clk_progobjs); + + if (pclkprogobjs->vf_entry_count > + CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES) + return -EINVAL; + + if (rail >= pclkprogobjs->vf_entry_count) + return -EINVAL; + + pvfentry = p1xmaster->p_vf_entries; + + pvfentry = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)( + (u8 *)pvfentry + + (sizeof(struct ctrl_clk_clk_prog_1x_master_vf_entry) * + (rail+1))); + + fpointscount = pvfentry->vf_point_idx_last - + pvfentry->vf_point_idx_first + 1; + + /* if pointer for freq data is NULL simply return count */ + if (*ppfreqpointsinmhz == NULL) + goto done; + + if (fpointscount > *pfpointscount) + return -ENOMEM; + for (j = pvfentry->vf_point_idx_first; + j <= pvfentry->vf_point_idx_last; j++) { + pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j); + **ppfreqpointsinmhz = clkvfpointfreqmhzget(g, pvfpoint); + (*ppfreqpointsinmhz)++; + } +done: + *pfpointscount = fpointscount; + return 0; +} diff --git a/drivers/gpu/nvgpu/clk/clk_prog.h b/drivers/gpu/nvgpu/clk/clk_prog.h index 979d327d..be92b3fc 100644 --- a/drivers/gpu/nvgpu/clk/clk_prog.h +++ b/drivers/gpu/nvgpu/clk/clk_prog.h @@ -32,6 +32,12 @@ typedef u32 vf_lookup(struct gk20a *g, struct clk_pmupstate *pclk, u8 *slave_clk_domain_idx, u16 *pclkmhz, u32 *pvoltuv, u8 rail); +typedef u32 get_fpoints(struct gk20a *g, struct clk_pmupstate *pclk, + struct clk_prog_1x_master *p1xmaster, + u32 *pfpointscount, + u16 **ppfreqpointsinmhz, u8 rail); + + struct clk_progs { struct boardobjgrp_e255 super; u8 slave_entry_count; @@ -58,6 +64,7 @@ struct clk_prog_1x_master { union ctrl_clk_clk_prog_1x_master_source_data source_data; vf_flatten *vfflatten; vf_lookup *vflookup; + get_fpoints *getfpoints; }; struct clk_prog_1x_master_ratio { -- cgit v1.2.2