gpu: nvgpu: set gv10x boot clock

- Set gv10x boot gpcclk to 952 MHz
- Created ops to set gv10x boot gpcclk instead
of using clk arbiter to set clocks

Bug 200399373

Change-Id: Ice5956f79d4a52abf455506a798cf7b914f3d3ed
Signed-off-by: Vaikundanathan S <vaikuns@nvidia.com>
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1700788
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Vaikundanathan S
2018-04-23 17:21:58 +05:30
committed by Tejal Kudav
parent 14d8430697
commit 0545465255
6 changed files with 179 additions and 6 deletions

View File

@@ -182,6 +182,7 @@ u32 clk_pmu_vin_load(struct gk20a *g)
(u32)sizeof(struct pmu_hdr);
cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC;
cmd.cmd.clk.generic.b_perf_daemon_cmd =false;
payload.in.buf = (u8 *)&rpccall;
payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc);
@@ -547,6 +548,156 @@ u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain)
return status;
}
static int clk_program_fllclks(struct gk20a *g, struct change_fll_clk *fllclk)
{
int status = -EINVAL;
struct clk_domain *pdomain;
u8 i;
struct clk_pmupstate *pclk = &g->clk_pmu;
u16 clkmhz = 0;
struct clk_domain_3x_master *p3xmaster;
struct clk_domain_3x_slave *p3xslave;
unsigned long slaveidxmask;
struct set_fll_clk setfllclk;
if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPCCLK)
return -EINVAL;
if (fllclk->voltuv == 0)
return -EINVAL;
if (fllclk->clkmhz == 0)
return -EINVAL;
setfllclk.voltuv = fllclk->voltuv;
setfllclk.gpc2clkmhz = fllclk->clkmhz;
BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
struct clk_domain *, pdomain, i) {
if (pdomain->api_domain == fllclk->api_clk_domain) {
if (!pdomain->super.implements(g, &pdomain->super,
CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) {
status = -EINVAL;
goto done;
}
p3xmaster = (struct clk_domain_3x_master *)pdomain;
slaveidxmask = p3xmaster->slave_idxs_mask;
for_each_set_bit(i, &slaveidxmask, 32) {
p3xslave = (struct clk_domain_3x_slave *)
CLK_CLK_DOMAIN_GET(pclk, i);
if ((p3xslave->super.super.super.api_domain !=
CTRL_CLK_DOMAIN_XBARCLK) &&
(p3xslave->super.super.super.api_domain !=
CTRL_CLK_DOMAIN_SYSCLK))
continue;
clkmhz = 0;
status = p3xslave->clkdomainclkgetslaveclk(g,
pclk,
(struct clk_domain *)p3xslave,
&clkmhz,
fllclk->clkmhz);
if (status) {
status = -EINVAL;
goto done;
}
if (p3xslave->super.super.super.api_domain ==
CTRL_CLK_DOMAIN_XBARCLK)
setfllclk.xbar2clkmhz = clkmhz;
if (p3xslave->super.super.super.api_domain ==
CTRL_CLK_DOMAIN_SYSCLK)
setfllclk.sys2clkmhz = clkmhz;
}
}
}
/*set regime ids */
status = get_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK,
&setfllclk.current_regime_id_gpc);
if (status)
goto done;
setfllclk.target_regime_id_gpc = find_regime_id(g,
CTRL_CLK_DOMAIN_GPCCLK, setfllclk.gpc2clkmhz);
status = get_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK,
&setfllclk.current_regime_id_sys);
if (status)
goto done;
setfllclk.target_regime_id_sys = find_regime_id(g,
CTRL_CLK_DOMAIN_SYSCLK, setfllclk.sys2clkmhz);
status = get_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK,
&setfllclk.current_regime_id_xbar);
if (status)
goto done;
setfllclk.target_regime_id_xbar = find_regime_id(g,
CTRL_CLK_DOMAIN_XBARCLK, setfllclk.xbar2clkmhz);
status = clk_pmu_vf_inject(g, &setfllclk);
if (status)
nvgpu_err(g,
"vf inject to change clk failed");
/* save regime ids */
status = set_regime_id(g, CTRL_CLK_DOMAIN_XBARCLK,
setfllclk.target_regime_id_xbar);
if (status)
goto done;
status = set_regime_id(g, CTRL_CLK_DOMAIN_GPCCLK,
setfllclk.target_regime_id_gpc);
if (status)
goto done;
status = set_regime_id(g, CTRL_CLK_DOMAIN_SYSCLK,
setfllclk.target_regime_id_sys);
if (status)
goto done;
done:
return status;
}
u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g)
{
int status;
struct change_fll_clk bootfllclk;
u16 gpcclk_clkmhz = BOOT_GPCCLK_MHZ;
u32 gpcclk_voltuv = 0;
u32 voltuv = 0;
status = clk_vf_point_cache(g);
if (status) {
nvgpu_err(g,"caching failed");
return status;
}
status = clk_domain_get_f_or_v(g, CTRL_CLK_DOMAIN_GPCCLK,
&gpcclk_clkmhz, &gpcclk_voltuv, CTRL_VOLT_DOMAIN_LOGIC);
if (status) {
nvgpu_err(g,"failed 1");
return status;
}
voltuv = gpcclk_voltuv;
status = volt_set_voltage(g, voltuv, 0);
if (status)
nvgpu_err(g,
"attempt to set boot voltage failed %d",
voltuv);
bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPCCLK;
bootfllclk.clkmhz = gpcclk_clkmhz;
bootfllclk.voltuv = voltuv;
status = clk_program_fllclks(g, &bootfllclk);
if (status)
nvgpu_err(g, "attempt to set boot gpcclk failed");
return status;
}
u32 clk_domain_get_f_or_v(
struct gk20a *g,
u32 clkapidomain,

View File

@@ -35,9 +35,12 @@
#define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10
#define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_MASK 0x1F
#define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SHIFT 0
#define BOOT_GPCCLK_MHZ 952
struct gk20a;
int clk_set_boot_fll_clk(struct gk20a *g);
/* clock related defines for GPUs supporting clock control from pmu*/
struct clk_pmupstate {
struct avfsvinobjs avfs_vinobjs;
@@ -56,6 +59,12 @@ struct clockentry {
u32 api_clk_domain;
};
struct change_fll_clk {
u32 api_clk_domain;
u16 clkmhz;
u32 voltuv;
};
struct set_fll_clk {
u32 voltuv;
u16 gpc2clkmhz;
@@ -133,4 +142,5 @@ u32 nvgpu_clk_vf_change_inject_data_fill_gv10x(struct gk20a *g,
u32 nvgpu_clk_vf_change_inject_data_fill_gp10x(struct gk20a *g,
struct nv_pmu_clk_rpc *rpccall,
struct set_fll_clk *setfllclk);
u32 nvgpu_clk_set_boot_fll_clk_gv10x(struct gk20a *g);
#endif

View File

@@ -1313,6 +1313,8 @@ static int nvgpu_init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu)
nvgpu_clk_vf_change_inject_data_fill_gv10x;
g->ops.pmu_ver.clk.perf_pmu_vfe_load =
perf_pmu_vfe_load_gv10x;
g->ops.pmu_ver.clk.clk_set_boot_clk =
nvgpu_clk_set_boot_fll_clk_gv10x;
} else {
g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params =
get_pmu_init_msg_pmu_queue_params_v4;
@@ -1484,8 +1486,6 @@ static int nvgpu_init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu)
clk_avfs_get_vin_cal_fuse_v10;
g->ops.pmu_ver.clk.clk_vf_change_inject_data_fill =
nvgpu_clk_vf_change_inject_data_fill_gp10x;
g->ops.pmu_ver.clk.clk_set_boot_clk =
nvgpu_clk_set_boot_fll_clk_gv10x;
g->ops.pmu_ver.clk.perf_pmu_vfe_load =
perf_pmu_vfe_load;
break;

View File

@@ -281,10 +281,14 @@ int gk20a_finalize_poweron(struct gk20a *g)
}
}
err = nvgpu_clk_arb_init_arbiter(g);
if (err) {
nvgpu_err(g, "failed to init clk arb");
goto done;
if (g->ops.pmu_ver.clk.clk_set_boot_clk && nvgpu_is_enabled(g, NVGPU_PMU_PSTATE))
g->ops.pmu_ver.clk.clk_set_boot_clk(g);
else {
err = nvgpu_clk_arb_init_arbiter(g);
if (err) {
nvgpu_err(g, "failed to init clk arb");
goto done;
}
}
err = gk20a_init_therm_support(g);

View File

@@ -820,6 +820,7 @@ struct gpu_ops {
struct nv_pmu_clk_rpc *rpccall,
struct set_fll_clk *setfllclk);
u32 (*perf_pmu_vfe_load)(struct gk20a *g);
u32 (*clk_set_boot_clk)(struct gk20a *g);
}clk;
} pmu_ver;
struct {

View File

@@ -448,6 +448,12 @@ struct nv_pmu_clk_cmd_rpc {
struct nv_pmu_allocation request;
};
struct nv_pmu_clk_cmd_generic {
u8 cmd_type;
bool b_perf_daemon_cmd;
u8 pad[2];
};
#define NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET \
(offsetof(struct nv_pmu_clk_cmd_rpc, request))
@@ -455,6 +461,7 @@ struct nv_pmu_clk_cmd {
union {
u8 cmd_type;
struct nv_pmu_boardobj_cmd_grp grp_set;
struct nv_pmu_clk_cmd_generic generic;
struct nv_pmu_clk_cmd_rpc rpc;
struct nv_pmu_boardobj_cmd_grp grp_get_status;
};