From 054546525571dde1117376176f00511f13168f07 Mon Sep 17 00:00:00 2001 From: Vaikundanathan S Date: Mon, 23 Apr 2018 17:21:58 +0530 Subject: 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 Signed-off-by: Mahantesh Kumbar Reviewed-on: https://git-master.nvidia.com/r/1700788 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/clk/clk.c | 151 ++++++++++++++++++++++ drivers/gpu/nvgpu/clk/clk.h | 10 ++ drivers/gpu/nvgpu/common/pmu/pmu_fw.c | 4 +- drivers/gpu/nvgpu/gk20a/gk20a.c | 12 +- drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h | 7 + 6 files changed, 179 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index 28f08cb6..5d6ae19d 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c @@ -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, diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h index 019a1c11..70b04fc4 100644 --- a/drivers/gpu/nvgpu/clk/clk.h +++ b/drivers/gpu/nvgpu/clk/clk.h @@ -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 diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c index 1e33ecc2..a1e3dfd0 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c @@ -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; diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index c48d7cf8..9ce2ef53 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -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); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 8f35e2c9..07ff28f6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -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 { diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h index 471892ca..fe9a70db 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifclk.h @@ -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; }; -- cgit v1.2.2