mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 11:04:51 +03:00
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>
This commit is contained in:
committed by
Deepak Nibade
parent
e28ef73ec9
commit
1b10905120
@@ -29,6 +29,7 @@ static struct clk_prog *construct_clk_prog(struct gk20a *g, void *pargs);
|
||||
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 u32 _clk_progs_pmudatainit(struct gk20a *g,
|
||||
struct boardobjgrp *pboardobjgrp,
|
||||
@@ -603,6 +604,9 @@ static u32 clk_prog_construct_1x_master(struct gk20a *g,
|
||||
pclkprog->vfflatten =
|
||||
vfflatten_prog_1x_master;
|
||||
|
||||
pclkprog->vflookup =
|
||||
vflookup_prog_1x_master;
|
||||
|
||||
pclkprog->p_vf_entries = (struct ctrl_clk_clk_prog_1x_master_vf_entry *)
|
||||
kzalloc(vfsize, GFP_KERNEL);
|
||||
|
||||
@@ -831,3 +835,152 @@ done:
|
||||
gk20a_dbg_info("done status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static u32 vflookup_prog_1x_master
|
||||
(
|
||||
struct gk20a *g,
|
||||
struct clk_pmupstate *pclk,
|
||||
struct clk_prog_1x_master *p1xmaster,
|
||||
u8 *slave_clk_domain,
|
||||
u16 *pclkmhz,
|
||||
u32 *pvoltuv,
|
||||
u8 rail
|
||||
)
|
||||
{
|
||||
u8 j;
|
||||
struct ctrl_clk_clk_prog_1x_master_vf_entry
|
||||
*pvfentry;
|
||||
struct clk_vf_point *pvfpoint;
|
||||
struct clk_progs *pclkprogobjs;
|
||||
struct clk_prog_1x_master_ratio *p1xmasterratio;
|
||||
u16 clkmhz;
|
||||
u32 voltuv;
|
||||
u8 slaveentrycount;
|
||||
u8 i;
|
||||
struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry *pslaveents;
|
||||
|
||||
if ((*pclkmhz != 0) && (*pvoltuv != 0))
|
||||
return -EINVAL;
|
||||
|
||||
pclkprogobjs = &(pclk->clk_progobjs);
|
||||
|
||||
slaveentrycount = pclkprogobjs->slave_entry_count;
|
||||
|
||||
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)));
|
||||
|
||||
clkmhz = *pclkmhz;
|
||||
voltuv = *pvoltuv;
|
||||
|
||||
/*if domain is slave domain and freq is input
|
||||
then derive master clk */
|
||||
if ((slave_clk_domain != NULL) && (*pclkmhz != 0)) {
|
||||
if (p1xmaster->super.super.super.implements(g,
|
||||
&p1xmaster->super.super.super,
|
||||
CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) {
|
||||
|
||||
p1xmasterratio =
|
||||
(struct clk_prog_1x_master_ratio *)p1xmaster;
|
||||
pslaveents = p1xmasterratio->p_slave_entries;
|
||||
for (i = 0; i < slaveentrycount; i++) {
|
||||
if (pslaveents->clk_dom_idx ==
|
||||
*slave_clk_domain)
|
||||
break;
|
||||
pslaveents++;
|
||||
}
|
||||
if (i == slaveentrycount)
|
||||
return -EINVAL;
|
||||
clkmhz = (clkmhz * 100)/pslaveents->ratio;
|
||||
} else {
|
||||
/* only support ratio for now */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* if both volt and clks are zero simply print*/
|
||||
if ((*pvoltuv == 0) && (*pclkmhz == 0)) {
|
||||
for (j = pvfentry->vf_point_idx_first;
|
||||
j <= pvfentry->vf_point_idx_last; j++) {
|
||||
pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
|
||||
gk20a_err(dev_from_gk20a(g), "v %x c %x",
|
||||
clkvfpointvoltageuvget(g, pvfpoint),
|
||||
clkvfpointfreqmhzget(g, pvfpoint));
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
/* start looking up f for v for v for f */
|
||||
/* looking for volt? */
|
||||
if (*pvoltuv == 0) {
|
||||
pvfpoint = CLK_CLK_VF_POINT_GET(pclk,
|
||||
pvfentry->vf_point_idx_last);
|
||||
/* above range? */
|
||||
if (clkmhz > clkvfpointfreqmhzget(g, pvfpoint))
|
||||
return -EINVAL;
|
||||
|
||||
for (j = pvfentry->vf_point_idx_last;
|
||||
j >= pvfentry->vf_point_idx_first; j--) {
|
||||
pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
|
||||
if (clkmhz <= clkvfpointfreqmhzget(g, pvfpoint))
|
||||
voltuv = clkvfpointvoltageuvget(g, pvfpoint);
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else { /* looking for clk? */
|
||||
|
||||
pvfpoint = CLK_CLK_VF_POINT_GET(pclk,
|
||||
pvfentry->vf_point_idx_first);
|
||||
/* below range? */
|
||||
if (voltuv < clkvfpointvoltageuvget(g, pvfpoint))
|
||||
return -EINVAL;
|
||||
|
||||
for (j = pvfentry->vf_point_idx_first;
|
||||
j <= pvfentry->vf_point_idx_last; j++) {
|
||||
pvfpoint = CLK_CLK_VF_POINT_GET(pclk, j);
|
||||
if (voltuv >= clkvfpointvoltageuvget(g, pvfpoint))
|
||||
clkmhz = clkvfpointfreqmhzget(g, pvfpoint);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*if domain is slave domain and freq was looked up
|
||||
then derive slave clk */
|
||||
if ((slave_clk_domain != NULL) && (*pclkmhz == 0)) {
|
||||
if (p1xmaster->super.super.super.implements(g,
|
||||
&p1xmaster->super.super.super,
|
||||
CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO)) {
|
||||
|
||||
p1xmasterratio =
|
||||
(struct clk_prog_1x_master_ratio *)p1xmaster;
|
||||
pslaveents = p1xmasterratio->p_slave_entries;
|
||||
for (i = 0; i < slaveentrycount; i++) {
|
||||
if (pslaveents->clk_dom_idx ==
|
||||
*slave_clk_domain)
|
||||
break;
|
||||
pslaveents++;
|
||||
}
|
||||
if (i == slaveentrycount)
|
||||
return -EINVAL;
|
||||
clkmhz = (clkmhz * pslaveents->ratio)/100;
|
||||
} else {
|
||||
/* only support ratio for now */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
*pclkmhz = clkmhz;
|
||||
*pvoltuv = voltuv;
|
||||
if ((clkmhz == 0) || (voltuv == 0))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user