From 4c8a320f2c42f7856da61b26dc3ff40324ad89dc Mon Sep 17 00:00:00 2001 From: Abdul Salam Date: Tue, 26 Feb 2019 14:26:53 +0530 Subject: [PATCH] gpu: nvgpu: Add support for guaranteed frequency 1. Check for volt margin and freq margin in VBIOS. 2. If it is valid (!255) send RPC to get margin, else ignore. 3. Get freq margin followed by volt margin. 4. Add this to requested voltage/freq based on output type. Bug 200492048 Change-Id: I513c6cdebcc7c2db348e3be37258e7657b48eb7e Signed-off-by: Abdul Salam Reviewed-on: https://git-master.nvidia.com/r/2021974 Reviewed-by: svc-mobile-coverity Reviewed-by: Deepak Nibade GVS: Gerrit_Virtual_Submit Reviewed-by: Vijayakumar Subbu Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/pmu/clk/clk_fll.c | 2 + .../gpu/nvgpu/common/pmu/clk/clk_vf_point.c | 17 +++++- drivers/gpu/nvgpu/common/pmu/perf/vfe_equ.c | 58 +++++++++++++++++++ drivers/gpu/nvgpu/common/pmu/pmu_fw.c | 2 + drivers/gpu/nvgpu/common/pmu/volt/volt_pmu.c | 18 ++++++ drivers/gpu/nvgpu/include/nvgpu/bios.h | 1 + drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 1 + .../gpu/nvgpu/include/nvgpu/pmu/clk/clk_fll.h | 1 + drivers/gpu/nvgpu/include/nvgpu/pmu/perf.h | 2 + drivers/gpu/nvgpu/include/nvgpu/pmu/volt.h | 1 + .../nvgpu/include/nvgpu/pmuif/gpmuifperf.h | 11 +++- 11 files changed, 111 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nvgpu/common/pmu/clk/clk_fll.c b/drivers/gpu/nvgpu/common/pmu/clk/clk_fll.c index 6d1e483f6..7828f559c 100644 --- a/drivers/gpu/nvgpu/common/pmu/clk/clk_fll.c +++ b/drivers/gpu/nvgpu/common/pmu/clk/clk_fll.c @@ -273,6 +273,8 @@ static int devinit_get_fll_device_table(struct gk20a *g, if (desctablesize >= FLL_DESCRIPTOR_HEADER_10_SIZE_6) { pfllobjs->max_min_freq_mhz = fll_desc_table_header.max_min_freq_mhz; + pfllobjs->freq_margin_vfe_idx = + fll_desc_table_header.freq_margin_vfe_idx; } else { pfllobjs->max_min_freq_mhz = 0; } diff --git a/drivers/gpu/nvgpu/common/pmu/clk/clk_vf_point.c b/drivers/gpu/nvgpu/common/pmu/clk/clk_vf_point.c index 8bf8f3cdd..06dedc6bd 100644 --- a/drivers/gpu/nvgpu/common/pmu/clk/clk_vf_point.c +++ b/drivers/gpu/nvgpu/common/pmu/clk/clk_vf_point.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "clk.h" #include "clk_vf_point.h" @@ -475,7 +476,7 @@ int nvgpu_clk_set_req_fll_clk_ps35(struct gk20a *g, struct nvgpu_clk_slave_freq u32 max_clkmhz; u16 max_ratio; struct clk_set_info *p0_info; - u32 vmin_uv = 0; + u32 vmin_uv = 0, vmargin_uv = 0U, fmargin_mhz = 0U; (void) memset(&change_input, 0, sizeof(struct ctrl_perf_change_seq_change_input)); @@ -604,9 +605,23 @@ int nvgpu_clk_set_req_fll_clk_ps35(struct gk20a *g, struct nvgpu_clk_slave_freq change_input.flags = (u32)CTRL_PERF_CHANGE_SEQ_CHANGE_FORCE; change_input.vf_points_cache_counter = 0xFFFFFFFFU; + status = nvgpu_vfe_get_freq_margin_limit(g, &fmargin_mhz); + if (status != 0) { + nvgpu_err(g, "Failed to fetch Fmargin status=0x%x", status); + return status; + } + + gpcclk_clkmhz += fmargin_mhz; status = clk_domain_freq_to_volt(g, gpcclk_domain, &gpcclk_clkmhz, &gpcclk_voltuv, CTRL_VOLT_DOMAIN_LOGIC); + status = nvgpu_vfe_get_volt_margin_limit(g, &vmargin_uv); + if (status != 0) { + nvgpu_err(g, "Failed to fetch Vmargin status=0x%x", status); + return status; + } + + gpcclk_voltuv += vmargin_uv; status = g->ops.pmu_ver.volt.volt_get_vmin(g, &vmin_uv); if (status != 0) { nvgpu_err(g, "Failed to execute Vmin get_status status=0x%x", diff --git a/drivers/gpu/nvgpu/common/pmu/perf/vfe_equ.c b/drivers/gpu/nvgpu/common/pmu/perf/vfe_equ.c index 0505d0fca..d57b0d2cc 100644 --- a/drivers/gpu/nvgpu/common/pmu/perf/vfe_equ.c +++ b/drivers/gpu/nvgpu/common/pmu/perf/vfe_equ.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "pmu_perf.h" #include "vfe_equ.h" @@ -738,3 +739,60 @@ static struct vfe_equ *construct_vfe_equ(struct gk20a *g, void *pargs) return (struct vfe_equ *)board_obj_ptr; } + +int nvgpu_vfe_get_volt_margin_limit(struct gk20a *g, u32 *vmargin_uv) +{ + struct nvgpu_pmu *pmu = &g->pmu; + struct nv_pmu_rpc_struct_perf_vfe_eval rpc; + int status = 0; + u8 vmargin_idx; + + vmargin_idx = g->ops.pmu_ver.volt.volt_get_vmargin(g); + if (vmargin_idx == 0U) { + nvgpu_info(g, "Skipping volt margin idx"); + return 0; + } + + (void) memset(&rpc, 0, sizeof(rpc)); + rpc.data.equ_idx = vmargin_idx; + rpc.data.output_type = CTRL_PERF_VFE_EQU_OUTPUT_TYPE_VOLT_DELTA_UV; + rpc.data.var_count = 0U; + PMU_RPC_EXECUTE_CPB(status, pmu, PERF, VFE_EQU_EVAL, &rpc, 0); + if (status != 0) { + nvgpu_err(g, "Failed to execute RPC status=0x%x", + status); + return status; + } + + *vmargin_uv = rpc.data.result.voltu_v; + return status; +} + +int nvgpu_vfe_get_freq_margin_limit(struct gk20a *g, u32 *fmargin_mhz) +{ + struct nvgpu_pmu *pmu = &g->pmu; + struct nv_pmu_rpc_struct_perf_vfe_eval rpc; + int status = 0; + u8 fmargin_idx; + struct nvgpu_avfsfllobjs *pfllobjs = &(g->clk_pmu->avfs_fllobjs); + + fmargin_idx = pfllobjs->freq_margin_vfe_idx; + if (fmargin_idx == 255U) { + nvgpu_info(g, "Skipping freq margin idx"); + return 0; + } + + (void) memset(&rpc, 0, sizeof(rpc)); + rpc.data.equ_idx = fmargin_idx; + rpc.data.output_type = CTRL_PERF_VFE_EQU_OUTPUT_TYPE_FREQ_MHZ; + rpc.data.var_count = 0U; + PMU_RPC_EXECUTE_CPB(status, pmu, PERF, VFE_EQU_EVAL, &rpc, 0); + if (status != 0) { + nvgpu_err(g, "Failed to execute RPC status=0x%x", + status); + return status; + } + + *fmargin_mhz = rpc.data.result.voltu_v; + return status; +} diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c index 477e62edb..5ca174c6a 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c @@ -1333,6 +1333,8 @@ static int init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu, u32 app_version) g->ops.pmu_ver.clk.clk_set_boot_clk = NULL; g->ops.pmu_ver.volt.volt_get_vmin = nvgpu_volt_get_vmin_tu10x; + g->ops.pmu_ver.volt.volt_get_vmargin = + nvgpu_volt_get_vmargin_tu10x; } } else { g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params = diff --git a/drivers/gpu/nvgpu/common/pmu/volt/volt_pmu.c b/drivers/gpu/nvgpu/common/pmu/volt/volt_pmu.c index 80df27dba..d679d81f2 100644 --- a/drivers/gpu/nvgpu/common/pmu/volt/volt_pmu.c +++ b/drivers/gpu/nvgpu/common/pmu/volt/volt_pmu.c @@ -413,3 +413,21 @@ int nvgpu_volt_get_vmin_tu10x(struct gk20a *g, u32 *vmin_uv) return status; } +u8 nvgpu_volt_get_vmargin_tu10x(struct gk20a *g) +{ + struct boardobjgrp *pboardobjgrp; + struct boardobj *pboardobj = NULL; + struct voltage_rail *volt_rail = NULL; + u8 index, vmargin_uv; + + pboardobjgrp = &g->perf_pmu->volt.volt_rail_metadata.volt_rails.super; + + BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj *, pboardobj, index) { + volt_rail = (struct voltage_rail *)(void *)pboardobj; + if (volt_rail->volt_margin_limit_vfe_equ_idx != 255U) { + vmargin_uv = volt_rail->volt_margin_limit_vfe_equ_idx; + return vmargin_uv; + } + } + return 0U; +} diff --git a/drivers/gpu/nvgpu/include/nvgpu/bios.h b/drivers/gpu/nvgpu/include/nvgpu/bios.h index 389647b03..94c776f23 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/bios.h +++ b/drivers/gpu/nvgpu/include/nvgpu/bios.h @@ -98,6 +98,7 @@ struct fll_descriptor_header_10 { u8 entry_size; u8 entry_count; u16 max_min_freq_mhz; + u8 freq_margin_vfe_idx; } __packed; #define FLL_DESCRIPTOR_ENTRY_10_SIZE 15U diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index cc809274f..7054ea75b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -1045,6 +1045,7 @@ struct gpu_ops { u8 volt_domain, u32 *pvoltage_uv); int (*volt_send_load_cmd_to_pmu)(struct gk20a *g); int (*volt_get_vmin)(struct gk20a *g, u32 *vmin_uv); + u8 (*volt_get_vmargin)(struct gk20a *g); } volt; struct { u32 (*get_vbios_clk_domain)(u32 vbios_domain); diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_fll.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_fll.h index 2407b881d..28601813e 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_fll.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/clk/clk_fll.h @@ -38,6 +38,7 @@ struct nvgpu_avfsfllobjs { u32 lut_min_voltage_uv; u8 lut_num_entries; u16 max_min_freq_mhz; + u8 freq_margin_vfe_idx; }; struct nvgpu_set_fll_clk { diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/perf.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/perf.h index 537fb2936..1af51d656 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu/perf.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/perf.h @@ -99,6 +99,8 @@ int vfe_equ_pmu_setup(struct gk20a *g); int vfe_var_sw_setup(struct gk20a *g); int vfe_var_pmu_setup(struct gk20a *g); +int nvgpu_vfe_get_volt_margin_limit(struct gk20a *g, u32 *vmargin_uv); +int nvgpu_vfe_get_freq_margin_limit(struct gk20a *g, u32 *fmargin_mhz); int nvgpu_perf_change_seq_sw_setup(struct gk20a *g); int nvgpu_perf_change_seq_pmu_setup(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/volt.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/volt.h index 93ccb0035..6343e2689 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu/volt.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/volt.h @@ -82,5 +82,6 @@ int volt_policy_sw_setup(struct gk20a *g); int volt_policy_pmu_setup(struct gk20a *g); int nvgpu_volt_rail_boardobj_grp_get_status(struct gk20a *g); int nvgpu_volt_get_vmin_tu10x(struct gk20a *g, u32 *vmin_uv); +u8 nvgpu_volt_get_vmargin_tu10x(struct gk20a *g); #endif /* NVGPU_PMU_VOLT_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifperf.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifperf.h index f7fe176e4..589835e62 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifperf.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuifperf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -59,7 +59,7 @@ * used to execute LOAD RPC. */ struct nv_pmu_rpc_struct_perf_load { - /*[IN/OUT] Must be first field in RPC structure */ + /* [IN/OUT] Must be first field in RPC structure */ struct nv_pmu_rpc_header hdr; bool b_load; u32 scratch[1]; @@ -215,4 +215,11 @@ struct perf_change_seq_pmu_script { steps[CTRL_PERF_CHANGE_SEQ_PMU_STEP_ID_MAX_STEPS]; }; +struct nv_pmu_rpc_struct_perf_vfe_eval { + /*[IN/OUT] Must be first field in RPC structure */ + struct nv_pmu_rpc_header hdr; + struct nv_pmu_perf_rpc_vfe_equ_eval data; + u32 scratch[1]; +}; + #endif /* NVGPU_PMUIF_GPMUIFPERF_H*/