From 8d3427633f867c5d4d079f0c2de076ae81482031 Mon Sep 17 00:00:00 2001 From: Abdul Salam Date: Thu, 7 Nov 2019 12:19:34 +0530 Subject: [PATCH] gpu: nvgpu: Provide ability to select dgpu freq cap from DT Add support in nvgpu to parse and get the freq cap from DT. The patch does below Parse the DT and gets the freq cap value during probe. During clk_arb init compare this with P0.Max and takes the lowest. Send change_seq with the new value and set dgpu freq. Use the lowest for "get points","get default","set VF". Bug 200556366 Change-Id: Ie10243f9bf83cb5ae07ebcc4cdc8efaffa56c309 Signed-off-by: Abdul Salam Reviewed-on: https://git-master.nvidia.com/r/2204644 Reviewed-by: mobile promotions Tested-by: mobile promotions --- .../gpu/nvgpu/common/clk_arb/clk_arb_gv100.c | 31 +++++++++++++++++-- drivers/gpu/nvgpu/common/pmu/clk/clk_prog.h | 1 - drivers/gpu/nvgpu/include/nvgpu/clk_arb.h | 7 +++-- drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 2 ++ .../nvgpu/include/nvgpu/pmu/clk/clk_prog.h | 1 + drivers/gpu/nvgpu/os/linux/pci.c | 25 +++++++++++++++ 6 files changed, 62 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gv100.c b/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gv100.c index 7e69950de..43b7ea560 100644 --- a/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gv100.c +++ b/drivers/gpu/nvgpu/common/clk_arb/clk_arb_gv100.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "clk_arb_gv100.h" @@ -61,6 +62,7 @@ int gv100_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, struct clk_set_info *p0_info; struct nvgpu_avfsfllobjs *pfllobjs = g->pmu->clk_pmu->avfs_fllobjs; u16 limit_min_mhz; + u16 gpcclk_cap_mhz; bool error_status = false; switch (api_domain) { @@ -88,15 +90,21 @@ int gv100_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, } limit_min_mhz = p0_info->min_mhz; + gpcclk_cap_mhz = p0_info->max_mhz; + /* WAR for DVCO min */ if (api_domain == CTRL_CLK_DOMAIN_GPCCLK) { if ((pfllobjs->max_min_freq_mhz != 0U) && (pfllobjs->max_min_freq_mhz >= limit_min_mhz)) { limit_min_mhz = pfllobjs->max_min_freq_mhz + 1U; } + if ((g->clk_arb->gpc_cap_clkmhz != 0U) && + (p0_info->max_mhz > g->clk_arb->gpc_cap_clkmhz )) { + gpcclk_cap_mhz = g->clk_arb->gpc_cap_clkmhz; + } } *min_mhz = limit_min_mhz; - *max_mhz = p0_info->max_mhz; + *max_mhz = gpcclk_cap_mhz; return 0; } @@ -107,6 +115,7 @@ int gv100_get_arbiter_clk_default(struct gk20a *g, u32 api_domain, u32 clkwhich; struct clk_set_info *p0_info; bool error_status = false; + u16 gpcclk_cap_mhz; switch (api_domain) { case CTRL_CLK_DOMAIN_MCLK: @@ -132,7 +141,15 @@ int gv100_get_arbiter_clk_default(struct gk20a *g, u32 api_domain, return -EINVAL; } - *default_mhz = p0_info->max_mhz; + gpcclk_cap_mhz = p0_info->max_mhz; + if (api_domain == CTRL_CLK_DOMAIN_GPCCLK) { + if ((g->clk_arb->gpc_cap_clkmhz != 0U) && + (p0_info->max_mhz > g->clk_arb->gpc_cap_clkmhz )) { + gpcclk_cap_mhz = g->clk_arb->gpc_cap_clkmhz; + } + } + *default_mhz = gpcclk_cap_mhz; + return 0; } @@ -239,6 +256,11 @@ int gv100_init_clk_arbiter(struct gk20a *g) goto init_fail; } + if (g->dgpu_max_clk != 0U) { + g->dgpu_max_clk = (g->dgpu_max_clk / + FREQ_STEP_SIZE_MHZ) * FREQ_STEP_SIZE_MHZ; + arb->gpc_cap_clkmhz = g->dgpu_max_clk; + } #ifdef CONFIG_DEBUG_FS arb->debug = &arb->debug_pool[0]; @@ -391,6 +413,11 @@ void gv100_clk_arb_run_arbiter_cb(struct nvgpu_clk_arb *arb) mclk_target = arb->mclk_max; } + if ((arb->gpc_cap_clkmhz != 0U) && + (gpc2clk_target > arb->gpc_cap_clkmhz)) { + gpc2clk_target = arb->gpc_cap_clkmhz; + } + vf_point.gpc_mhz = gpc2clk_target; (void)nvgpu_clk_arb_find_slave_points(arb, &vf_point); if (status != 0) { diff --git a/drivers/gpu/nvgpu/common/pmu/clk/clk_prog.h b/drivers/gpu/nvgpu/common/pmu/clk/clk_prog.h index e1a417529..382608966 100644 --- a/drivers/gpu/nvgpu/common/pmu/clk/clk_prog.h +++ b/drivers/gpu/nvgpu/common/pmu/clk/clk_prog.h @@ -33,7 +33,6 @@ #include struct clk_prog_1x_master; -#define FREQ_STEP_SIZE_MHZ 15U typedef int vf_flatten(struct gk20a *g, struct nvgpu_clk_pmupstate *pclk, struct clk_prog_1x_master *p1xmaster, diff --git a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h index 0938e51f0..e8424fde2 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h +++ b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h @@ -201,8 +201,11 @@ struct nvgpu_clk_arb { u16 mclk_default_mhz; u32 voltuv_actual; - u16 gpc2clk_min, gpc2clk_max; - u16 mclk_min, mclk_max; + u16 gpc2clk_min; + u16 gpc2clk_max; + u16 gpc_cap_clkmhz; + u16 mclk_min; + u16 mclk_max; struct nvgpu_clk_arb_work_item update_vf_table_work_item; struct nvgpu_clk_arb_work_item update_arb_work_item; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 18357b98f..b6b5281bd 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -989,6 +989,8 @@ struct gk20a { struct nvgpu_mem pdb_cache_war_mem; /** @endcond */ + + u16 dgpu_max_clk; }; /** diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_prog.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_prog.h index 890231221..faa9842b5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_prog.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_prog.h @@ -27,6 +27,7 @@ #include +#define FREQ_STEP_SIZE_MHZ 15U struct gk20a; struct boardobjgrp_e255; diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index 2da7d77ad..dc37efbba 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c @@ -429,6 +429,26 @@ static int nvgpu_pci_pm_deinit(struct device *dev) return 0; } +static int nvgpu_get_dt_clock_limit(struct gk20a *g, u16 *gpuclk_clkmhz) +{ + struct device_node *np; + u32 gpuclk_dt_cap = 0U; + + np = of_find_node_by_name(NULL, "nvgpu"); + if (!np) { + return -ENOENT; + } + + if (of_property_read_u32(np, "dgpuclk-max-mhz", &gpuclk_dt_cap)) { + nvgpu_info(g, "dgpuclk-max-mhz not defined," + "P-state will be used"); + } + + *gpuclk_clkmhz = (u16)gpuclk_dt_cap; + + return 0; +} + static int nvgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { @@ -597,6 +617,11 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, } } + err = nvgpu_get_dt_clock_limit(g, &g->dgpu_max_clk); + if (err != 0) { + nvgpu_info(g, "Missing nvgpu node"); + } + err = nvgpu_pci_add_pci_power(pdev); if (err) { nvgpu_err(g, "add pci power failed (%d).", err);