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);